...

Source file src/cmd/vendor/golang.org/x/tools/internal/facts/imports.go

Documentation: cmd/vendor/golang.org/x/tools/internal/facts

     1  // Copyright 2018 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package facts
     6  
     7  import (
     8  	"go/types"
     9  )
    10  
    11  // importMap computes the import map for a package by traversing the
    12  // entire exported API each of its imports.
    13  //
    14  // This is a workaround for the fact that we cannot access the map used
    15  // internally by the types.Importer returned by go/importer. The entries
    16  // in this map are the packages and objects that may be relevant to the
    17  // current analysis unit.
    18  //
    19  // Packages in the map that are only indirectly imported may be
    20  // incomplete (!pkg.Complete()).
    21  //
    22  // This function scales very poorly with packages' transitive object
    23  // references, which can be more than a million for each package near
    24  // the top of a large project. (This was a significant contributor to
    25  // #60621.)
    26  // TODO(adonovan): opt: compute this information more efficiently
    27  // by obtaining it from the internals of the gcexportdata decoder.
    28  func importMap(imports []*types.Package) map[string]*types.Package {
    29  	objects := make(map[types.Object]bool)
    30  	typs := make(map[types.Type]bool) // Named and TypeParam
    31  	packages := make(map[string]*types.Package)
    32  
    33  	var addObj func(obj types.Object)
    34  	var addType func(T types.Type)
    35  
    36  	addObj = func(obj types.Object) {
    37  		if !objects[obj] {
    38  			objects[obj] = true
    39  			addType(obj.Type())
    40  			if pkg := obj.Pkg(); pkg != nil {
    41  				packages[pkg.Path()] = pkg
    42  			}
    43  		}
    44  	}
    45  
    46  	addType = func(T types.Type) {
    47  		switch T := T.(type) {
    48  		case *types.Basic:
    49  			// nop
    50  		case *types.Named:
    51  			// Remove infinite expansions of *types.Named by always looking at the origin.
    52  			// Some named types with type parameters [that will not type check] have
    53  			// infinite expansions:
    54  			//     type N[T any] struct { F *N[N[T]] }
    55  			// importMap() is called on such types when Analyzer.RunDespiteErrors is true.
    56  			T = T.Origin()
    57  			if !typs[T] {
    58  				typs[T] = true
    59  				addObj(T.Obj())
    60  				addType(T.Underlying())
    61  				for i := 0; i < T.NumMethods(); i++ {
    62  					addObj(T.Method(i))
    63  				}
    64  				if tparams := T.TypeParams(); tparams != nil {
    65  					for i := 0; i < tparams.Len(); i++ {
    66  						addType(tparams.At(i))
    67  					}
    68  				}
    69  				if targs := T.TypeArgs(); targs != nil {
    70  					for i := 0; i < targs.Len(); i++ {
    71  						addType(targs.At(i))
    72  					}
    73  				}
    74  			}
    75  		case *types.Pointer:
    76  			addType(T.Elem())
    77  		case *types.Slice:
    78  			addType(T.Elem())
    79  		case *types.Array:
    80  			addType(T.Elem())
    81  		case *types.Chan:
    82  			addType(T.Elem())
    83  		case *types.Map:
    84  			addType(T.Key())
    85  			addType(T.Elem())
    86  		case *types.Signature:
    87  			addType(T.Params())
    88  			addType(T.Results())
    89  			if tparams := T.TypeParams(); tparams != nil {
    90  				for i := 0; i < tparams.Len(); i++ {
    91  					addType(tparams.At(i))
    92  				}
    93  			}
    94  		case *types.Struct:
    95  			for i := 0; i < T.NumFields(); i++ {
    96  				addObj(T.Field(i))
    97  			}
    98  		case *types.Tuple:
    99  			for i := 0; i < T.Len(); i++ {
   100  				addObj(T.At(i))
   101  			}
   102  		case *types.Interface:
   103  			for i := 0; i < T.NumMethods(); i++ {
   104  				addObj(T.Method(i))
   105  			}
   106  			for i := 0; i < T.NumEmbeddeds(); i++ {
   107  				addType(T.EmbeddedType(i)) // walk Embedded for implicits
   108  			}
   109  		case *types.Union:
   110  			for i := 0; i < T.Len(); i++ {
   111  				addType(T.Term(i).Type())
   112  			}
   113  		case *types.TypeParam:
   114  			if !typs[T] {
   115  				typs[T] = true
   116  				addObj(T.Obj())
   117  				addType(T.Constraint())
   118  			}
   119  		}
   120  	}
   121  
   122  	for _, imp := range imports {
   123  		packages[imp.Path()] = imp
   124  
   125  		scope := imp.Scope()
   126  		for _, name := range scope.Names() {
   127  			addObj(scope.Lookup(name))
   128  		}
   129  	}
   130  
   131  	return packages
   132  }
   133  

View as plain text