@@ -11,20 +11,22 @@ struct ACFieldMethod {
1111 typ string
1212}
1313
14- fn abs (a int ) int {
15- if a < 0 {
16- return - a
17- }
18- return a
19- }
20-
2114pub fn (mut c Checker) run_ac (ast_file & ast.File) {
2215}
2316
2417// Autocomplete for function parameters `os.write_bytes(**path string, bytes []u8***)` etc
2518pub fn (mut c Checker) autocomplete_for_fn_call_expr () {
2619 // println(c.pref.linfo.expr)
27- fn_name := c.pref.linfo.expr.replace ('()' , '' ).trim_space ()
20+ mut fn_name := if c.pref.linfo.expr.ends_with ('(' ) {
21+ c.pref.linfo.expr[..c.pref.linfo.expr.len - 1 ].trim_space ()
22+ } else {
23+ c.pref.linfo.expr.replace ('()' , '' ).trim_space ()
24+ }
25+ mod_name := fn_name.all_before_last ('.' )
26+ resolved_mod_name := c.try_resolve_to_import_mod_name (mod_name)
27+ if resolved_mod_name.len > 0 {
28+ fn_name = resolved_mod_name + '.' + fn_name.all_after_last ('.' )
29+ }
2830 f := c.table.find_fn (fn_name) or {
2931 println ('failed to find fn "${fn_name }"' )
3032 return
@@ -34,12 +36,39 @@ pub fn (mut c Checker) autocomplete_for_fn_call_expr() {
3436}
3537
3638fn (mut c Checker) ident_gotodef () {
37- name := c.pref.linfo.expr.after ('gd^' ).trim_space ()
38- f := c.table.find_fn (name) or {
39- println ('failed to find fn "${name }"' )
39+ mut ident_name := c.pref.linfo.expr.after ('gd^' ).trim_space ()
40+ mod_name := ident_name.all_before_last ('.' )
41+ resolved_mod_name := c.try_resolve_to_import_mod_name (mod_name)
42+ if resolved_mod_name.len > 0 {
43+ ident_name = resolved_mod_name + '.' + ident_name.all_after_last ('.' )
44+ }
45+ if f := c.table.find_fn (ident_name) {
46+ println ('${f .file }:${f .pos .line_nr }:${f .pos .col }' )
4047 return
4148 }
42- println ('${f .file }:${f .pos .line_nr }:${f .pos .col }' )
49+ // TODO: As EnumDecl has no `file` field, we can't goto enum right now
50+ // for name,val in c.table.enum_decls {
51+ // if val.is_pub && name == ident_name {
52+ // println('${val.file}:${val.pos.line_nr}:${val.pos.col}')
53+ // return
54+ // }
55+ // }
56+
57+ // TODO: we need other TypeDecl information here
58+ // for mut sym in c.table.type_symbols {
59+ // if sym.is_pub && sym.name == ident_name {
60+ // match mut sym.info {
61+ // ast.Alias {
62+ // }
63+ // ast.Interface {
64+ // }
65+ // ast.Struct {
66+ // }
67+ // else {
68+ // }
69+ // }
70+ // }
71+ // }
4372}
4473
4574// Autocomplete for `myvar. ...`, `os. ...`
@@ -53,11 +82,11 @@ fn (mut c Checker) ident_autocomplete(node ast.Ident) {
5382 ' pref.linfo.path="${c .pref .linfo .path }" node.name="${node .name }" node.mod="${node .mod }" col="${c .pref .linfo .col }"' )
5483 }
5584 // Make sure this ident is on the same line as requeste, in the same file, and has the same name
56- same_line := node.pos.line_nr in [ c.pref.linfo.line_nr - 1 , c.pref.linfo. line_nr + 1 , c.pref.linfo.line_nr]
85+ same_line := c.pref.linfo.line_nr == node.pos. line_nr
5786 if ! same_line {
5887 return
5988 }
60- same_col := abs ( c.pref.linfo.col - node.pos.col) < 3
89+ same_col := c.pref.linfo.col == node.pos.col + node.pos.len
6190 if ! same_col {
6291 return
6392 }
@@ -67,19 +96,22 @@ fn (mut c Checker) ident_autocomplete(node ast.Ident) {
6796 }
6897 // Module autocomplete
6998 // `os. ...`
70- // println (node)
71- if node. name == '' && node.mod != 'builtin' {
72- c. module_autocomplete (node)
73- return
74- } else if node. name == '' && node. mod == 'builtin' {
75- return
99+ mod_name := c. try_resolve_to_import_mod_name (node.name )
100+ if mod_name.len > 0 {
101+ if node. mod == c.file.mod.name {
102+ c. module_autocomplete (mod_name)
103+ }
104+ exit ( 0 )
76105 }
77106 mut sb := strings.new_builder (10 )
78107 if node.kind == .unresolved {
79108 // println(node)
80109 eprintln ('unresolved type, maybe "${node .name }" was not defined. otherwise this is a bug, should never happen; please report' )
81110 exit (1 )
82111 }
112+ if node.obj.typ == ast.no_type {
113+ exit (0 )
114+ }
83115 sym := c.table.sym (c.unwrap_generic (node.obj.typ))
84116 // sb.writeln('VAR ${node.name}:${sym.name} ${node.pos.line_nr}')
85117 nt := '${node .name }:${sym .name }'
@@ -151,28 +183,15 @@ fn (mut c Checker) ident_autocomplete(node ast.Ident) {
151183 }
152184}
153185
154- fn (mut c Checker) module_autocomplete (node ast.Ident) {
155- mut sb := strings.new_builder (10 )
156- // println(c.table.fns)
157- sb.writeln ('{"methods":[' )
158- prefix := node.mod + '.'
159- mut empty := true
160- for _, f in c.table.fns {
161- mut name := f.name
162- if name.starts_with (prefix) {
163- empty = false
164- if name.contains ('__static__' ) {
165- name = name.replace ('__static__' , '.' )
166- }
167- name = name.after ('.' ) // The user already typed `mod.`, so suggest the name without module
168- sb.writeln ('"${name }:int" ,' )
169- }
170- }
171- if ! empty {
172- sb.go_back (2 ) // remove final ,
173- }
174- sb.writeln (']}' )
175- println (sb.str ().trim_space ())
186+ fn (mut c Checker) module_autocomplete (mod string ) {
187+ println ('{' )
188+ c.write_mod_funcs (mod)
189+ c.write_mod_type_alias (mod)
190+ c.write_mod_interfaces (mod)
191+ c.write_mod_enums (mod)
192+ c.write_mod_consts (mod)
193+ c.write_mod_structs (mod)
194+ println ('}' )
176195}
177196
178197fn build_method_summary (method ast.Fn) string {
@@ -199,3 +218,136 @@ fn (c &Checker) build_fn_summary(method ast.Fn) string {
199218 }
200219 return s + ')'
201220}
221+
222+ fn (c &Checker) try_resolve_to_import_mod_name (name string ) string {
223+ if name in c.file.used_imports {
224+ // resolve alias to mod name
225+ mod_name := c.file.imports.filter (it .alias == name)[0 ].mod
226+ return mod_name
227+ }
228+ return ''
229+ }
230+
231+ fn (c &Checker) write_mod_funcs (mod string ) {
232+ mut sb := strings.new_builder (128 )
233+ sb.writeln ('"functions":[' )
234+ mut empty := true
235+ for _, f in c.table.fns {
236+ mut name := f.name
237+ if f.is_pub && name.all_before_last ('.' ) == mod {
238+ empty = false
239+ if name.contains ('__static__' ) {
240+ name = name.replace ('__static__' , '.' )
241+ }
242+ name = name.all_after_last ('.' ) // The user already typed `mod.`, so suggest the name without module
243+ type_string := if f.return_type != ast.no_type {
244+ c.table.type_to_str (f.return_type)
245+ } else {
246+ 'int'
247+ }
248+ sb.writeln ('"${name }:${type_string }" ,' )
249+ }
250+ }
251+ if ! empty {
252+ sb.go_back (2 ) // remove final ,
253+ }
254+ sb.writeln ('],' )
255+ println (sb.str ().trim_space ())
256+ }
257+
258+ fn (c &Checker) write_mod_type_alias (mod string ) {
259+ mut sb := strings.new_builder (128 )
260+ sb.writeln ('"type_alias":[' )
261+ mut empty := true
262+ for sym in c.table.type_symbols {
263+ if sym.is_pub && sym.info is ast.Alias {
264+ if sym.name.all_before_last ('.' ) == mod {
265+ empty = false
266+ sb.writeln ('"${sym .name .all_after_last ('.')}" ,' )
267+ }
268+ }
269+ }
270+ if ! empty {
271+ sb.go_back (2 ) // remove final ,
272+ }
273+ sb.writeln ('],' )
274+ println (sb.str ().trim_space ())
275+ }
276+
277+ fn (c &Checker) write_mod_interfaces (mod string ) {
278+ mut sb := strings.new_builder (128 )
279+ sb.writeln ('"interfaces":[' )
280+ mut empty := true
281+ for sym in c.table.type_symbols {
282+ if sym.is_pub && sym.info is ast.Interface {
283+ if sym.name.all_before_last ('.' ) == mod {
284+ empty = false
285+ sb.writeln ('"${sym .name .all_after_last ('.')}" ,' )
286+ }
287+ }
288+ }
289+ if ! empty {
290+ sb.go_back (2 ) // remove final ,
291+ }
292+ sb.writeln ('],' )
293+ println (sb.str ().trim_space ())
294+ }
295+
296+ fn (c &Checker) write_mod_enums (mod string ) {
297+ mut sb := strings.new_builder (128 )
298+ sb.writeln ('"enums":[' )
299+ mut empty := true
300+ for name, val in c.table.enum_decls {
301+ if val.is_pub && name.all_before_last ('.' ) == mod {
302+ empty = false
303+ sb.writeln ('"${name .all_after_last ('.')}" ,' )
304+ }
305+ }
306+ if ! empty {
307+ sb.go_back (2 ) // remove final ,
308+ }
309+ sb.writeln ('],' )
310+ println (sb.str ().trim_space ())
311+ }
312+
313+ fn (c &Checker) write_mod_consts (mod string ) {
314+ mut sb := strings.new_builder (128 )
315+ sb.writeln ('"constants":[' )
316+ mut empty := true
317+ for _, obj in c.table.global_scope.objects {
318+ if obj is ast.ConstField && obj.is_pub {
319+ if obj.name.all_before_last ('.' ) == mod {
320+ empty = false
321+ if obj.typ != ast.no_type {
322+ sb.writeln ('"${obj .name .all_after_last ('.')}:${c .table .type_to_str (obj .typ )}" ,' )
323+ } else {
324+ sb.writeln ('"${obj .name .all_after_last ('.')}:int" ,' )
325+ }
326+ }
327+ }
328+ }
329+ if ! empty {
330+ sb.go_back (2 ) // remove final ,
331+ }
332+ sb.writeln ('],' )
333+ println (sb.str ().trim_space ())
334+ }
335+
336+ fn (c &Checker) write_mod_structs (mod string ) {
337+ mut sb := strings.new_builder (128 )
338+ sb.writeln ('"structs":[' )
339+ mut empty := true
340+ for sym in c.table.type_symbols {
341+ if sym.is_pub && sym.info is ast.Struct {
342+ if sym.name.all_before_last ('.' ) == mod {
343+ empty = false
344+ sb.writeln ('"${sym .name .all_after_last ('.')}" ,' )
345+ }
346+ }
347+ }
348+ if ! empty {
349+ sb.go_back (2 ) // remove final ,
350+ }
351+ sb.writeln (']' )
352+ println (sb.str ().trim_space ())
353+ }
0 commit comments