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  }