1package main
2
3import (
4	"bytes"
5	"go/ast"
6	"go/parser"
7	"go/scanner"
8	"go/token"
9	"log"
10)
11
12func parse_decl_list(fset *token.FileSet, data []byte) ([]ast.Decl, error) {
13	var buf bytes.Buffer
14	buf.WriteString("package p;")
15	buf.Write(data)
16	file, err := parser.ParseFile(fset, "", buf.Bytes(), parser.AllErrors)
17	if err != nil {
18		return file.Decls, err
19	}
20	return file.Decls, nil
21}
22
23func log_parse_error(intro string, err error) {
24	if el, ok := err.(scanner.ErrorList); ok {
25		log.Printf("%s:", intro)
26		for _, er := range el {
27			log.Printf(" %s", er)
28		}
29	} else {
30		log.Printf("%s: %s", intro, err)
31	}
32}
33
34//-------------------------------------------------------------------------
35// auto_complete_file
36//-------------------------------------------------------------------------
37
38type auto_complete_file struct {
39	name         string
40	package_name string
41
42	decls     map[string]*decl
43	packages  []package_import
44	filescope *scope
45	scope     *scope
46
47	cursor  int // for current file buffer only
48	fset    *token.FileSet
49	context *package_lookup_context
50}
51
52func new_auto_complete_file(name string, context *package_lookup_context) *auto_complete_file {
53	p := new(auto_complete_file)
54	p.name = name
55	p.cursor = -1
56	p.fset = token.NewFileSet()
57	p.context = context
58	return p
59}
60
61func (f *auto_complete_file) offset(p token.Pos) int {
62	const fixlen = len("package p;")
63	return f.fset.Position(p).Offset - fixlen
64}
65
66// this one is used for current file buffer exclusively
67func (f *auto_complete_file) process_data(data []byte, ctx *auto_complete_context) {
68	// topLevelTok fix rip_off_decl on multi var decl
69	// var (\n jsData  = `{	}`\n 	file2  *File = func() *File {
70	var topLevelTok token.Token
71	if cf, ok := ctx.walker.ParsedFileCache[f.name]; ok {
72		pos := token.Pos(ctx.walker.FileSet.File(cf.Pos()).Base()) + token.Pos(f.cursor)
73		for _, decl := range cf.Decls {
74			if pos >= decl.Pos() && pos <= decl.End() {
75				if decl, ok := decl.(*ast.GenDecl); ok {
76					topLevelTok = decl.Tok
77				}
78				break
79			}
80		}
81	}
82	cur, filedata, block := rip_off_decl(data, f.cursor, topLevelTok)
83	file, err := parser.ParseFile(f.fset, "", filedata, parser.AllErrors)
84	if err != nil && *g_debug {
85		log_parse_error("Error parsing input file (outer block)", err)
86	}
87	f.package_name = package_name(file)
88
89	f.decls = make(map[string]*decl)
90	f.packages = collect_package_imports(f.name, file.Decls, f.context)
91	f.filescope = new_scope(nil)
92	f.scope = f.filescope
93
94	for _, d := range file.Decls {
95		anonymify_ast(d, 0, f.filescope)
96	}
97
98	// process all top-level declarations
99	for _, decl := range file.Decls {
100		append_to_top_decls(f.decls, decl, f.scope)
101	}
102
103	if block != nil {
104		// process local function as top-level declaration
105		decls, err := parse_decl_list(f.fset, block)
106		if err != nil && *g_debug {
107			log_parse_error("Error parsing input file (inner block)", err)
108		}
109
110		for _, d := range decls {
111			anonymify_ast(d, 0, f.filescope)
112		}
113
114		for _, decl := range decls {
115			append_to_top_decls(f.decls, decl, f.scope)
116		}
117
118		// process function internals
119		f.cursor = cur
120		for _, decl := range decls {
121			f.process_decl_locals(decl)
122		}
123	}
124
125}
126
127func (f *auto_complete_file) process_decl_locals(decl ast.Decl) {
128	switch t := decl.(type) {
129	case *ast.FuncDecl:
130		if f.cursor_in(t.Body) {
131			s := f.scope
132			f.scope = new_scope(f.scope)
133
134			f.process_field_list(t.Recv, s)
135			f.process_field_list(t.Type.Params, s)
136			f.process_field_list(t.Type.Results, s)
137			f.process_block_stmt(t.Body)
138		}
139	default:
140		v := new(func_lit_visitor)
141		v.ctx = f
142		ast.Walk(v, decl)
143	}
144}
145
146func (f *auto_complete_file) process_decl(decl ast.Decl) {
147	if t, ok := decl.(*ast.GenDecl); ok && f.offset(t.TokPos) > f.cursor {
148		return
149	}
150	prevscope := f.scope
151	foreach_decl(decl, func(data *foreach_decl_struct) {
152		class := ast_decl_class(data.decl)
153		if class != decl_type {
154			f.scope, prevscope = advance_scope(f.scope)
155		}
156		for i, name := range data.names {
157			typ, v, vi := data.type_value_index(i)
158
159			d := new_decl_full(name.Name, class, ast_decl_flags(data.decl), typ, v, vi, prevscope)
160			if d == nil {
161				continue
162			}
163
164			f.scope.add_named_decl(d)
165		}
166	})
167}
168
169func (f *auto_complete_file) process_block_stmt(block *ast.BlockStmt) {
170	if block != nil && f.cursor_in(block) {
171		f.scope, _ = advance_scope(f.scope)
172
173		for _, stmt := range block.List {
174			f.process_stmt(stmt)
175		}
176
177		// hack to process all func literals
178		v := new(func_lit_visitor)
179		v.ctx = f
180		ast.Walk(v, block)
181	}
182}
183
184type func_lit_visitor struct {
185	ctx *auto_complete_file
186}
187
188func (v *func_lit_visitor) Visit(node ast.Node) ast.Visitor {
189	if t, ok := node.(*ast.FuncLit); ok && v.ctx.cursor_in(t.Body) {
190		s := v.ctx.scope
191		v.ctx.scope = new_scope(v.ctx.scope)
192
193		v.ctx.process_field_list(t.Type.Params, s)
194		v.ctx.process_field_list(t.Type.Results, s)
195		v.ctx.process_block_stmt(t.Body)
196
197		return nil
198	}
199	return v
200}
201
202func (f *auto_complete_file) process_stmt(stmt ast.Stmt) {
203	switch t := stmt.(type) {
204	case *ast.DeclStmt:
205		f.process_decl(t.Decl)
206	case *ast.AssignStmt:
207		f.process_assign_stmt(t)
208	case *ast.IfStmt:
209		if f.cursor_in_if_head(t) {
210			f.process_stmt(t.Init)
211		} else if f.cursor_in_if_stmt(t) {
212			f.scope, _ = advance_scope(f.scope)
213			f.process_stmt(t.Init)
214			f.process_block_stmt(t.Body)
215			f.process_stmt(t.Else)
216		}
217	case *ast.BlockStmt:
218		f.process_block_stmt(t)
219	case *ast.RangeStmt:
220		f.process_range_stmt(t)
221	case *ast.ForStmt:
222		if f.cursor_in_for_head(t) {
223			f.process_stmt(t.Init)
224		} else if f.cursor_in(t.Body) {
225			f.scope, _ = advance_scope(f.scope)
226
227			f.process_stmt(t.Init)
228			f.process_block_stmt(t.Body)
229		}
230	case *ast.SwitchStmt:
231		f.process_switch_stmt(t)
232	case *ast.TypeSwitchStmt:
233		f.process_type_switch_stmt(t)
234	case *ast.SelectStmt:
235		f.process_select_stmt(t)
236	case *ast.LabeledStmt:
237		f.process_stmt(t.Stmt)
238	}
239}
240
241func (f *auto_complete_file) process_select_stmt(a *ast.SelectStmt) {
242	if !f.cursor_in(a.Body) {
243		return
244	}
245	var prevscope *scope
246	f.scope, prevscope = advance_scope(f.scope)
247
248	var last_cursor_after *ast.CommClause
249	for _, s := range a.Body.List {
250		if cc := s.(*ast.CommClause); f.cursor > f.offset(cc.Colon) {
251			last_cursor_after = cc
252		}
253	}
254
255	if last_cursor_after != nil {
256		if last_cursor_after.Comm != nil {
257			//if lastCursorAfter.Lhs != nil && lastCursorAfter.Tok == token.DEFINE {
258			if astmt, ok := last_cursor_after.Comm.(*ast.AssignStmt); ok && astmt.Tok == token.DEFINE {
259				vname := astmt.Lhs[0].(*ast.Ident).Name
260				v := new_decl_var(vname, nil, astmt.Rhs[0], -1, prevscope)
261				if v != nil {
262					f.scope.add_named_decl(v)
263				}
264			}
265		}
266		for _, s := range last_cursor_after.Body {
267			f.process_stmt(s)
268		}
269	}
270}
271
272func (f *auto_complete_file) process_type_switch_stmt(a *ast.TypeSwitchStmt) {
273	if !f.cursor_in(a.Body) {
274		return
275	}
276	var prevscope *scope
277	f.scope, prevscope = advance_scope(f.scope)
278
279	f.process_stmt(a.Init)
280	// type var
281	var tv *decl
282	if a, ok := a.Assign.(*ast.AssignStmt); ok {
283		lhs := a.Lhs
284		rhs := a.Rhs
285		if lhs != nil && len(lhs) == 1 {
286			tvname := lhs[0].(*ast.Ident).Name
287			tv = new_decl_var(tvname, nil, rhs[0], -1, prevscope)
288		}
289	}
290
291	var last_cursor_after *ast.CaseClause
292	for _, s := range a.Body.List {
293		if cc := s.(*ast.CaseClause); f.cursor > f.offset(cc.Colon) {
294			last_cursor_after = cc
295		}
296	}
297
298	if last_cursor_after != nil {
299		if tv != nil {
300			if last_cursor_after.List != nil && len(last_cursor_after.List) == 1 {
301				tv.typ = last_cursor_after.List[0]
302				tv.value = nil
303			}
304			f.scope.add_named_decl(tv)
305		}
306		for _, s := range last_cursor_after.Body {
307			f.process_stmt(s)
308		}
309	}
310}
311
312func (f *auto_complete_file) process_switch_stmt(a *ast.SwitchStmt) {
313	if !f.cursor_in(a.Body) {
314		return
315	}
316	f.scope, _ = advance_scope(f.scope)
317
318	f.process_stmt(a.Init)
319	var last_cursor_after *ast.CaseClause
320	for _, s := range a.Body.List {
321		if cc := s.(*ast.CaseClause); f.cursor > f.offset(cc.Colon) {
322			last_cursor_after = cc
323		}
324	}
325	if last_cursor_after != nil {
326		for _, s := range last_cursor_after.Body {
327			f.process_stmt(s)
328		}
329	}
330}
331
332func (f *auto_complete_file) process_range_stmt(a *ast.RangeStmt) {
333	if !f.cursor_in(a.Body) {
334		return
335	}
336	var prevscope *scope
337	f.scope, prevscope = advance_scope(f.scope)
338
339	if a.Tok == token.DEFINE {
340		if t, ok := a.Key.(*ast.Ident); ok {
341			d := new_decl_var(t.Name, nil, a.X, 0, prevscope)
342			if d != nil {
343				d.flags |= decl_rangevar
344				f.scope.add_named_decl(d)
345			}
346		}
347
348		if a.Value != nil {
349			if t, ok := a.Value.(*ast.Ident); ok {
350				d := new_decl_var(t.Name, nil, a.X, 1, prevscope)
351				if d != nil {
352					d.flags |= decl_rangevar
353					f.scope.add_named_decl(d)
354				}
355			}
356		}
357	}
358
359	f.process_block_stmt(a.Body)
360}
361
362func (f *auto_complete_file) process_assign_stmt(a *ast.AssignStmt) {
363	if a.Tok != token.DEFINE || f.offset(a.TokPos) > f.cursor {
364		return
365	}
366
367	names := make([]*ast.Ident, len(a.Lhs))
368	for i, name := range a.Lhs {
369		id, ok := name.(*ast.Ident)
370		if !ok {
371			// something is wrong, just ignore the whole stmt
372			return
373		}
374		names[i] = id
375	}
376
377	var prevscope *scope
378	f.scope, prevscope = advance_scope(f.scope)
379
380	pack := decl_pack{names, nil, a.Rhs}
381	for i, name := range pack.names {
382		typ, v, vi := pack.type_value_index(i)
383		d := new_decl_var(name.Name, typ, v, vi, prevscope)
384		if d == nil {
385			continue
386		}
387
388		f.scope.add_named_decl(d)
389	}
390}
391
392func (f *auto_complete_file) process_field_list(field_list *ast.FieldList, s *scope) {
393	if field_list != nil {
394		decls := ast_field_list_to_decls(field_list, decl_var, 0, s, false)
395		for _, d := range decls {
396			f.scope.add_named_decl(d)
397		}
398	}
399}
400
401func (f *auto_complete_file) cursor_in_if_head(s *ast.IfStmt) bool {
402	if f.cursor > f.offset(s.If) && f.cursor <= f.offset(s.Body.Lbrace) {
403		return true
404	}
405	return false
406}
407
408func (f *auto_complete_file) cursor_in_if_stmt(s *ast.IfStmt) bool {
409	if f.cursor > f.offset(s.If) {
410		// magic -10 comes from auto_complete_file.offset method, see
411		// len() expr in there
412		if f.offset(s.End()) == -10 || f.cursor < f.offset(s.End()) {
413			return true
414		}
415	}
416	return false
417}
418
419func (f *auto_complete_file) cursor_in_for_head(s *ast.ForStmt) bool {
420	if f.cursor > f.offset(s.For) && f.cursor <= f.offset(s.Body.Lbrace) {
421		return true
422	}
423	return false
424}
425
426func (f *auto_complete_file) cursor_in(block *ast.BlockStmt) bool {
427	if f.cursor == -1 || block == nil {
428		return false
429	}
430
431	// fix block.Rbrace=0 in Go1.14
432	end := block.Rbrace
433	if end < block.Lbrace {
434		end = block.End() - 1
435	}
436
437	if f.cursor > f.offset(block.Lbrace) && f.cursor <= f.offset(end) {
438		return true
439	}
440	return false
441}
442