github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/tools/refactor/lexical/lexical.go (about) 1 // Package lexical computes the structure of the lexical environment, 2 // including the definition of and references to all universal, 3 // package-level, file-level and function-local entities. It does not 4 // record qualified identifiers, labels, struct fields, or methods. 5 // 6 // It is intended for renaming and refactoring tools, which need a more 7 // precise understanding of identifier resolution than is available from 8 // the output of the type-checker alone. 9 // 10 // THIS INTERFACE IS EXPERIMENTAL AND MAY CHANGE OR BE REMOVED IN FUTURE. 11 // 12 package lexical // import "golang.org/x/tools/refactor/lexical" 13 14 // OVERVIEW 15 // 16 // As we traverse the AST, we build a "spaghetti stack" of Blocks, 17 // i.e. a tree with parent edges pointing to the root. Each time we 18 // visit an identifier that's a reference into the lexical environment, 19 // we create and save an Environment, which captures the current mapping 20 // state of the Block; these are saved for the client. 21 // 22 // We don't bother recording non-lexical references. 23 24 // TODO(adonovan): 25 // - make it robust against syntax errors. Audit all type assertions, etc. 26 // - better still, after the Go 1.4 thaw, move this into go/types. 27 // I don't think it need be a big change since the visitor is already there; 28 // we just need to records Environments. lexical.Block is analogous 29 // to types.Scope. 30 31 import ( 32 "fmt" 33 "go/ast" 34 "go/token" 35 "os" 36 "strconv" 37 38 "golang.org/x/tools/go/types" 39 ) 40 41 const trace = false 42 43 var logf = func(format string, args ...interface{}) { 44 fmt.Fprintf(os.Stderr, format, args...) 45 } 46 47 // A Block is a level of the lexical environment, a tree of blocks. 48 // It maps names to objects. 49 // 50 type Block struct { 51 kind string // one of universe package file func block if switch typeswitch case for range 52 syntax ast.Node // syntax declaring the block (nil for universe and package) [needed?] 53 54 parent Environment 55 bindings []types.Object // bindings in lexical order 56 index map[string]int // maps a name to the index of its binding, for fast lookup 57 } 58 59 // An Environment is a snapshot of a Block taken at a certain lexical 60 // position. It may contain bindings for fewer names than the 61 // (completed) block, or different bindings for names that are 62 // re-defined later in the block. 63 // 64 // For example, the lexical Block for the function f below contains a 65 // binding for the local var x, but the Environments captured by at the 66 // two print(x) calls differ: the first contains this binding, the 67 // second does not. The first Environment contains a different binding 68 // for x: the string var defined in the package block, an ancestor. 69 // 70 // var x string 71 // func f() { 72 // print(x) 73 // x := 1 74 // print(x) 75 // } 76 // 77 type Environment struct { 78 block *Block 79 nbindings int // length of prefix of block.bindings that's visible 80 } 81 82 // Depth returns the depth of this block in the block tree. 83 // The universal block has depth 1, a package block 2, a file block 3, etc. 84 func (b *Block) Depth() int { 85 if b == nil { 86 return 0 87 } 88 return 1 + b.parent.block.Depth() 89 } 90 91 // env returns an Environment that is a snapshot of b's current state. 92 func (b *Block) env() Environment { 93 return Environment{b, len(b.bindings)} 94 } 95 96 // Lookup returns the definition of name in the environment specified by 97 // env, and the Block that defines it, which may be an ancestor. 98 func (env Environment) Lookup(name string) (types.Object, *Block) { 99 if env.block == nil { 100 return nil, nil 101 } 102 return lookup(env.block, name, env.nbindings) 103 } 104 105 // nbindings specifies what prefix of b.bindings should be considered visible. 106 func lookup(b *Block, name string, nbindings int) (types.Object, *Block) { 107 if b == nil { 108 return nil, nil 109 } 110 if i, ok := b.index[name]; ok && i < nbindings { 111 return b.bindings[i], b 112 } 113 114 parent := b.parent 115 if parent.block == nil { 116 return nil, nil 117 } 118 return lookup(parent.block, name, parent.nbindings) 119 } 120 121 // Lookup returns the definition of name in the environment specified by 122 // b, and the Block that defines it, which may be an ancestor. 123 func (b *Block) Lookup(name string) (types.Object, *Block) { 124 return b.env().Lookup(name) 125 } 126 127 // Block returns the block of which this environment is a partial view. 128 func (env Environment) Block() *Block { 129 return env.block 130 } 131 132 func (env Environment) String() string { 133 return fmt.Sprintf("%s:%d", env.block, env.nbindings) 134 } 135 136 func (b *Block) String() string { 137 var s string 138 if b.parent.block != nil { 139 s = b.parent.block.String() 140 s += "." 141 } 142 return s + b.kind 143 } 144 145 var universe = &Block{kind: "universe", index: make(map[string]int)} 146 147 func init() { 148 for i, name := range types.Universe.Names() { 149 obj := types.Universe.Lookup(name) 150 universe.bindings = append(universe.bindings, obj) 151 universe.index[name] = i 152 } 153 } 154 155 // -- resolver --------------------------------------------------------- 156 157 // A Reference provides the lexical environment for a given reference to 158 // an object in lexical scope. 159 type Reference struct { 160 Id *ast.Ident 161 Env Environment 162 } 163 164 // resolver holds the state of the identifier resolution visitation: 165 // the package information, the result, and the current block. 166 type resolver struct { 167 fset *token.FileSet 168 imports map[string]*types.Package 169 pkg *types.Package 170 info *types.Info 171 172 // visitor state 173 block *Block 174 175 result *Info 176 } 177 178 func (r *resolver) setBlock(kind string, syntax ast.Node) *Block { 179 b := &Block{ 180 kind: kind, 181 syntax: syntax, 182 parent: r.block.env(), 183 index: make(map[string]int), 184 } 185 if syntax != nil { 186 r.result.Blocks[syntax] = b 187 } 188 r.block = b 189 return b 190 } 191 192 func (r *resolver) use(id *ast.Ident, env Environment) { 193 if id.Name == "_" { 194 return // an error 195 } 196 obj, _ := env.Lookup(id.Name) 197 if obj == nil { 198 logf("%s: lookup of %s failed\n", r.fset.Position(id.Pos()), id.Name) 199 } else if want := r.info.Uses[id]; obj != want { 200 // sanity check against go/types resolver 201 logf("%s: internal error: lookup of %s yielded wrong object: got %v (%s), want %v\n", 202 r.fset.Position(id.Pos()), id.Name, types.ObjectString(r.pkg, obj), 203 r.fset.Position(obj.Pos()), 204 want) 205 } 206 if trace { 207 logf("use %s = %v in %s\n", id.Name, types.ObjectString(r.pkg, obj), env) 208 } 209 210 r.result.Refs[obj] = append(r.result.Refs[obj], Reference{id, env}) 211 } 212 213 func (r *resolver) define(b *Block, id *ast.Ident) { 214 obj := r.info.Defs[id] 215 if obj == nil { 216 logf("%s: internal error: not a defining ident: %s\n", 217 r.fset.Position(id.Pos()), id.Name) 218 panic(id) 219 } 220 r.defineObject(b, id.Name, obj) 221 222 // Objects (other than PkgName) defined at file scope 223 // are also defined in the enclosing package scope. 224 if _, ok := b.syntax.(*ast.File); ok { 225 switch obj.(type) { 226 default: 227 r.defineObject(b.parent.block, id.Name, obj) 228 case nil, *types.PkgName: 229 } 230 } 231 } 232 233 // Used for implicit objects created by some ImportSpecs and CaseClauses. 234 func (r *resolver) defineImplicit(b *Block, n ast.Node, name string) { 235 obj := r.info.Implicits[n] 236 if obj == nil { 237 logf("%s: internal error: not an implicit definition: %T\n", 238 r.fset.Position(n.Pos()), n) 239 } 240 r.defineObject(b, name, obj) 241 } 242 243 func (r *resolver) defineObject(b *Block, name string, obj types.Object) { 244 if obj.Name() == "_" { 245 return 246 } 247 i := len(b.bindings) 248 b.bindings = append(b.bindings, obj) 249 b.index[name] = i 250 if trace { 251 logf("def %s = %s in %s\n", name, types.ObjectString(r.pkg, obj), b) 252 } 253 r.result.Defs[obj] = b 254 } 255 256 func (r *resolver) function(recv *ast.FieldList, typ *ast.FuncType, body *ast.BlockStmt, syntax ast.Node) { 257 // Use all signature types in enclosing block. 258 r.expr(typ) 259 r.fieldList(recv, false) 260 261 savedBlock := r.block // save 262 r.setBlock("func", syntax) 263 264 // Define all parameters/results, and visit the body, within the func block. 265 r.fieldList(typ.Params, true) 266 r.fieldList(typ.Results, true) 267 r.fieldList(recv, true) 268 if body != nil { 269 r.stmtList(body.List) 270 } 271 272 r.block = savedBlock // restore 273 } 274 275 func (r *resolver) fieldList(list *ast.FieldList, def bool) { 276 if list != nil { 277 for _, f := range list.List { 278 if def { 279 for _, id := range f.Names { 280 r.define(r.block, id) 281 } 282 } else { 283 r.expr(f.Type) 284 } 285 } 286 } 287 } 288 289 func (r *resolver) exprList(list []ast.Expr) { 290 for _, x := range list { 291 r.expr(x) 292 } 293 } 294 295 func (r *resolver) expr(n ast.Expr) { 296 switch n := n.(type) { 297 case *ast.BadExpr: 298 case *ast.BasicLit: 299 // no-op 300 301 case *ast.Ident: 302 r.use(n, r.block.env()) 303 304 case *ast.Ellipsis: 305 if n.Elt != nil { 306 r.expr(n.Elt) 307 } 308 309 case *ast.FuncLit: 310 r.function(nil, n.Type, n.Body, n) 311 312 case *ast.CompositeLit: 313 if n.Type != nil { 314 r.expr(n.Type) 315 } 316 tv := r.info.Types[n] 317 if _, ok := deref(tv.Type).Underlying().(*types.Struct); ok { 318 for _, elt := range n.Elts { 319 if kv, ok := elt.(*ast.KeyValueExpr); ok { 320 r.expr(kv.Value) 321 322 // Also uses field kv.Key (non-lexical) 323 // id := kv.Key.(*ast.Ident) 324 // obj := r.info.Uses[id] 325 // logf("use %s = %v (field)\n", 326 // id.Name, types.ObjectString(r.pkg, obj)) 327 // TODO make a fake FieldVal selection? 328 } else { 329 r.expr(elt) 330 } 331 } 332 } else { 333 r.exprList(n.Elts) 334 } 335 336 case *ast.ParenExpr: 337 r.expr(n.X) 338 339 case *ast.SelectorExpr: 340 r.expr(n.X) 341 342 // Non-lexical reference to field/method, or qualified identifier. 343 // if sel, ok := r.info.Selections[n]; ok { // selection 344 // switch sel.Kind() { 345 // case types.FieldVal: 346 // logf("use %s = %v (field)\n", 347 // n.Sel.Name, types.ObjectString(r.pkg, sel.Obj())) 348 // case types.MethodExpr, types.MethodVal: 349 // logf("use %s = %v (method)\n", 350 // n.Sel.Name, types.ObjectString(r.pkg, sel.Obj())) 351 // } 352 // } else { // qualified identifier 353 // obj := r.info.Uses[n.Sel] 354 // logf("use %s = %v (qualified)\n", n.Sel.Name, obj) 355 // } 356 357 case *ast.IndexExpr: 358 r.expr(n.X) 359 r.expr(n.Index) 360 361 case *ast.SliceExpr: 362 r.expr(n.X) 363 if n.Low != nil { 364 r.expr(n.Low) 365 } 366 if n.High != nil { 367 r.expr(n.High) 368 } 369 if n.Max != nil { 370 r.expr(n.Max) 371 } 372 373 case *ast.TypeAssertExpr: 374 r.expr(n.X) 375 if n.Type != nil { 376 r.expr(n.Type) 377 } 378 379 case *ast.CallExpr: 380 r.expr(n.Fun) 381 r.exprList(n.Args) 382 383 case *ast.StarExpr: 384 r.expr(n.X) 385 386 case *ast.UnaryExpr: 387 r.expr(n.X) 388 389 case *ast.BinaryExpr: 390 r.expr(n.X) 391 r.expr(n.Y) 392 393 case *ast.KeyValueExpr: 394 r.expr(n.Key) 395 r.expr(n.Value) 396 397 case *ast.ArrayType: 398 if n.Len != nil { 399 r.expr(n.Len) 400 } 401 r.expr(n.Elt) 402 403 case *ast.StructType: 404 // Use all the type names, but don't define any fields. 405 r.fieldList(n.Fields, false) 406 407 case *ast.FuncType: 408 // Use all the type names, but don't define any vars. 409 r.fieldList(n.Params, false) 410 r.fieldList(n.Results, false) 411 412 case *ast.InterfaceType: 413 // Use all the type names, but don't define any methods. 414 r.fieldList(n.Methods, false) 415 416 case *ast.MapType: 417 r.expr(n.Key) 418 r.expr(n.Value) 419 420 case *ast.ChanType: 421 r.expr(n.Value) 422 423 default: 424 panic(n) 425 } 426 } 427 428 func (r *resolver) stmtList(list []ast.Stmt) { 429 for _, s := range list { 430 r.stmt(s) 431 } 432 } 433 434 func (r *resolver) stmt(n ast.Stmt) { 435 switch n := n.(type) { 436 case *ast.BadStmt: 437 case *ast.EmptyStmt: 438 // nothing to do 439 440 case *ast.DeclStmt: 441 decl := n.Decl.(*ast.GenDecl) 442 for _, spec := range decl.Specs { 443 switch spec := spec.(type) { 444 case *ast.ValueSpec: // const or var 445 if spec.Type != nil { 446 r.expr(spec.Type) 447 } 448 r.exprList(spec.Values) 449 for _, name := range spec.Names { 450 r.define(r.block, name) 451 } 452 453 case *ast.TypeSpec: 454 r.define(r.block, spec.Name) 455 r.expr(spec.Type) 456 } 457 } 458 459 case *ast.LabeledStmt: 460 // Also defines label n.Label (non-lexical) 461 r.stmt(n.Stmt) 462 463 case *ast.ExprStmt: 464 r.expr(n.X) 465 466 case *ast.SendStmt: 467 r.expr(n.Chan) 468 r.expr(n.Value) 469 470 case *ast.IncDecStmt: 471 r.expr(n.X) 472 473 case *ast.AssignStmt: 474 if n.Tok == token.DEFINE { 475 r.exprList(n.Rhs) 476 for _, lhs := range n.Lhs { 477 id := lhs.(*ast.Ident) 478 if _, ok := r.info.Defs[id]; ok { 479 r.define(r.block, id) 480 } else { 481 r.use(id, r.block.env()) 482 } 483 } 484 } else { // ASSIGN 485 r.exprList(n.Lhs) 486 r.exprList(n.Rhs) 487 } 488 489 case *ast.GoStmt: 490 r.expr(n.Call) 491 492 case *ast.DeferStmt: 493 r.expr(n.Call) 494 495 case *ast.ReturnStmt: 496 r.exprList(n.Results) 497 498 case *ast.BranchStmt: 499 if n.Label != nil { 500 // Also uses label n.Label (non-lexical) 501 } 502 503 case *ast.SelectStmt: 504 r.stmtList(n.Body.List) 505 506 case *ast.BlockStmt: // (explicit blocks only) 507 savedBlock := r.block // save 508 r.setBlock("block", n) 509 r.stmtList(n.List) 510 r.block = savedBlock // restore 511 512 case *ast.IfStmt: 513 savedBlock := r.block // save 514 r.setBlock("if", n) 515 if n.Init != nil { 516 r.stmt(n.Init) 517 } 518 r.expr(n.Cond) 519 r.stmt(n.Body) // new block 520 if n.Else != nil { 521 r.stmt(n.Else) 522 } 523 r.block = savedBlock // restore 524 525 case *ast.CaseClause: 526 savedBlock := r.block // save 527 r.setBlock("case", n) 528 if obj, ok := r.info.Implicits[n]; ok { 529 // e.g. 530 // switch y := x.(type) { 531 // case T: // we declare an implicit 'var y T' in this block 532 // } 533 r.defineImplicit(r.block, n, obj.Name()) 534 } 535 r.exprList(n.List) 536 r.stmtList(n.Body) 537 r.block = savedBlock // restore 538 539 case *ast.SwitchStmt: 540 savedBlock := r.block // save 541 r.setBlock("switch", n) 542 if n.Init != nil { 543 r.stmt(n.Init) 544 } 545 if n.Tag != nil { 546 r.expr(n.Tag) 547 } 548 r.stmtList(n.Body.List) 549 r.block = savedBlock // restore 550 551 case *ast.TypeSwitchStmt: 552 savedBlock := r.block // save 553 r.setBlock("typeswitch", n) 554 if n.Init != nil { 555 r.stmt(n.Init) 556 } 557 if assign, ok := n.Assign.(*ast.AssignStmt); ok { // y := x.(type) 558 r.expr(assign.Rhs[0]) // skip y: not a defining ident 559 } else { 560 r.stmt(n.Assign) 561 } 562 r.stmtList(n.Body.List) 563 r.block = savedBlock // restore 564 565 case *ast.CommClause: 566 savedBlock := r.block // save 567 r.setBlock("case", n) 568 if n.Comm != nil { 569 r.stmt(n.Comm) 570 } 571 r.stmtList(n.Body) 572 r.block = savedBlock // restore 573 574 case *ast.ForStmt: 575 savedBlock := r.block // save 576 r.setBlock("for", n) 577 if n.Init != nil { 578 r.stmt(n.Init) 579 } 580 if n.Cond != nil { 581 r.expr(n.Cond) 582 } 583 if n.Post != nil { 584 r.stmt(n.Post) 585 } 586 r.stmt(n.Body) 587 r.block = savedBlock // restore 588 589 case *ast.RangeStmt: 590 r.expr(n.X) 591 savedBlock := r.block // save 592 r.setBlock("range", n) 593 if n.Tok == token.DEFINE { 594 if n.Key != nil { 595 r.define(r.block, n.Key.(*ast.Ident)) 596 } 597 if n.Value != nil { 598 r.define(r.block, n.Value.(*ast.Ident)) 599 } 600 } else { 601 if n.Key != nil { 602 r.expr(n.Key) 603 } 604 if n.Value != nil { 605 r.expr(n.Value) 606 } 607 } 608 r.stmt(n.Body) 609 r.block = savedBlock // restore 610 611 default: 612 panic(n) 613 } 614 } 615 616 func (r *resolver) doImport(s *ast.ImportSpec, fileBlock *Block) { 617 path, _ := strconv.Unquote(s.Path.Value) 618 pkg := r.imports[path] 619 if s.Name == nil { // normal 620 r.defineImplicit(fileBlock, s, pkg.Name()) 621 } else if s.Name.Name == "." { // dot import 622 for _, name := range pkg.Scope().Names() { 623 if ast.IsExported(name) { 624 obj := pkg.Scope().Lookup(name) 625 r.defineObject(fileBlock, name, obj) 626 } 627 } 628 } else { // renaming import 629 r.define(fileBlock, s.Name) 630 } 631 } 632 633 func (r *resolver) doPackage(pkg *types.Package, files []*ast.File) { 634 r.block = universe 635 r.result.Blocks[nil] = universe 636 637 r.result.PackageBlock = r.setBlock("package", nil) 638 639 var fileBlocks []*Block 640 641 // 1. Insert all package-level objects into file and package blocks. 642 // (PkgName objects are only inserted into file blocks.) 643 for _, f := range files { 644 r.block = r.result.PackageBlock 645 fileBlock := r.setBlock("file", f) // package is not yet visible to file 646 fileBlocks = append(fileBlocks, fileBlock) 647 648 for _, d := range f.Decls { 649 switch d := d.(type) { 650 case *ast.GenDecl: 651 for _, s := range d.Specs { 652 switch s := s.(type) { 653 case *ast.ImportSpec: 654 r.doImport(s, fileBlock) 655 656 case *ast.ValueSpec: // const or var 657 for _, name := range s.Names { 658 r.define(r.result.PackageBlock, name) 659 } 660 661 case *ast.TypeSpec: 662 r.define(r.result.PackageBlock, s.Name) 663 } 664 } 665 666 case *ast.FuncDecl: 667 if d.Recv == nil { // function 668 if d.Name.Name != "init" { 669 r.define(r.result.PackageBlock, d.Name) 670 } 671 } 672 } 673 } 674 } 675 676 // 2. Now resolve bodies of GenDecls and FuncDecls. 677 for i, f := range files { 678 fileBlock := fileBlocks[i] 679 fileBlock.parent = r.result.PackageBlock.env() // make entire package visible to this file 680 681 for _, d := range f.Decls { 682 r.block = fileBlock 683 684 switch d := d.(type) { 685 case *ast.GenDecl: 686 for _, s := range d.Specs { 687 switch s := s.(type) { 688 case *ast.ValueSpec: // const or var 689 if s.Type != nil { 690 r.expr(s.Type) 691 } 692 r.exprList(s.Values) 693 694 case *ast.TypeSpec: 695 r.expr(s.Type) 696 } 697 } 698 699 case *ast.FuncDecl: 700 r.function(d.Recv, d.Type, d.Body, d) 701 } 702 } 703 } 704 705 r.block = nil 706 } 707 708 // An Info contains the lexical reference structure of a package. 709 type Info struct { 710 Defs map[types.Object]*Block // maps each object to its defining lexical block 711 Refs map[types.Object][]Reference // maps each object to the set of references to it 712 Blocks map[ast.Node]*Block // maps declaring syntax to block; nil => universe 713 PackageBlock *Block // the package-level lexical block 714 } 715 716 // Structure computes the structure of the lexical environment of the 717 // package specified by (pkg, info, files). 718 // 719 // The info.{Types,Defs,Uses,Implicits} maps must have been populated 720 // by the type-checker 721 // 722 // fset is used for logging. 723 // 724 func Structure(fset *token.FileSet, pkg *types.Package, info *types.Info, files []*ast.File) *Info { 725 r := resolver{ 726 fset: fset, 727 imports: make(map[string]*types.Package), 728 result: &Info{ 729 Defs: make(map[types.Object]*Block), 730 Refs: make(map[types.Object][]Reference), 731 Blocks: make(map[ast.Node]*Block), 732 }, 733 pkg: pkg, 734 info: info, 735 } 736 737 // Build import map for just this package. 738 r.imports["unsafe"] = types.Unsafe 739 for _, imp := range pkg.Imports() { 740 r.imports[imp.Path()] = imp 741 } 742 743 r.doPackage(pkg, files) 744 745 return r.result 746 } 747 748 // -- Plundered from golang.org/x/tools/go/ssa ----------------- 749 750 // deref returns a pointer's element type; otherwise it returns typ. 751 func deref(typ types.Type) types.Type { 752 if p, ok := typ.Underlying().(*types.Pointer); ok { 753 return p.Elem() 754 } 755 return typ 756 }