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