github.com/powerman/golang-tools@v0.1.11-0.20220410185822-5ad214d8d803/go/analysis/internal/facts/imports.go (about)

     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  	"github.com/powerman/golang-tools/internal/typeparams"
    11  )
    12  
    13  // importMap computes the import map for a package by traversing the
    14  // entire exported API each of its imports.
    15  //
    16  // This is a workaround for the fact that we cannot access the map used
    17  // internally by the types.Importer returned by go/importer. The entries
    18  // in this map are the packages and objects that may be relevant to the
    19  // current analysis unit.
    20  //
    21  // Packages in the map that are only indirectly imported may be
    22  // incomplete (!pkg.Complete()).
    23  //
    24  func importMap(imports []*types.Package) map[string]*types.Package {
    25  	objects := make(map[types.Object]bool)
    26  	packages := make(map[string]*types.Package)
    27  
    28  	var addObj func(obj types.Object) bool
    29  	var addType func(T types.Type)
    30  
    31  	addObj = func(obj types.Object) bool {
    32  		if !objects[obj] {
    33  			objects[obj] = true
    34  			addType(obj.Type())
    35  			if pkg := obj.Pkg(); pkg != nil {
    36  				packages[pkg.Path()] = pkg
    37  			}
    38  			return true
    39  		}
    40  		return false
    41  	}
    42  
    43  	addType = func(T types.Type) {
    44  		switch T := T.(type) {
    45  		case *types.Basic:
    46  			// nop
    47  		case *types.Named:
    48  			if addObj(T.Obj()) {
    49  				// TODO(taking): Investigate why the Underlying type is not added here.
    50  				for i := 0; i < T.NumMethods(); i++ {
    51  					addObj(T.Method(i))
    52  				}
    53  				if tparams := typeparams.ForNamed(T); tparams != nil {
    54  					for i := 0; i < tparams.Len(); i++ {
    55  						addType(tparams.At(i))
    56  					}
    57  				}
    58  				if targs := typeparams.NamedTypeArgs(T); targs != nil {
    59  					for i := 0; i < targs.Len(); i++ {
    60  						addType(targs.At(i))
    61  					}
    62  				}
    63  			}
    64  		case *types.Pointer:
    65  			addType(T.Elem())
    66  		case *types.Slice:
    67  			addType(T.Elem())
    68  		case *types.Array:
    69  			addType(T.Elem())
    70  		case *types.Chan:
    71  			addType(T.Elem())
    72  		case *types.Map:
    73  			addType(T.Key())
    74  			addType(T.Elem())
    75  		case *types.Signature:
    76  			addType(T.Params())
    77  			addType(T.Results())
    78  			if tparams := typeparams.ForSignature(T); tparams != nil {
    79  				for i := 0; i < tparams.Len(); i++ {
    80  					addType(tparams.At(i))
    81  				}
    82  			}
    83  		case *types.Struct:
    84  			for i := 0; i < T.NumFields(); i++ {
    85  				addObj(T.Field(i))
    86  			}
    87  		case *types.Tuple:
    88  			for i := 0; i < T.Len(); i++ {
    89  				addObj(T.At(i))
    90  			}
    91  		case *types.Interface:
    92  			for i := 0; i < T.NumMethods(); i++ {
    93  				addObj(T.Method(i))
    94  			}
    95  			for i := 0; i < T.NumEmbeddeds(); i++ {
    96  				addType(T.EmbeddedType(i)) // walk Embedded for implicits
    97  			}
    98  		case *typeparams.Union:
    99  			for i := 0; i < T.Len(); i++ {
   100  				addType(T.Term(i).Type())
   101  			}
   102  		case *typeparams.TypeParam:
   103  			if addObj(T.Obj()) {
   104  				addType(T.Constraint())
   105  			}
   106  		}
   107  	}
   108  
   109  	for _, imp := range imports {
   110  		packages[imp.Path()] = imp
   111  
   112  		scope := imp.Scope()
   113  		for _, name := range scope.Names() {
   114  			addObj(scope.Lookup(name))
   115  		}
   116  	}
   117  
   118  	return packages
   119  }