Colin Cross | d9c6b80 | 2019-03-19 21:10:31 -0700 | [diff] [blame] | 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 | |
Dan Willemsen | bc60c3c | 2021-12-15 01:09:00 -0800 | [diff] [blame] | 7 | import ( |
| 8 | "go/types" |
| 9 | |
| 10 | "golang.org/x/tools/internal/typeparams" |
| 11 | ) |
Colin Cross | d9c6b80 | 2019-03-19 21:10:31 -0700 | [diff] [blame] | 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()) { |
Dan Willemsen | bc60c3c | 2021-12-15 01:09:00 -0800 | [diff] [blame] | 49 | // TODO(taking): Investigate why the Underlying type is not added here. |
Colin Cross | d9c6b80 | 2019-03-19 21:10:31 -0700 | [diff] [blame] | 50 | for i := 0; i < T.NumMethods(); i++ { |
| 51 | addObj(T.Method(i)) |
| 52 | } |
Dan Willemsen | bc60c3c | 2021-12-15 01:09:00 -0800 | [diff] [blame] | 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 | } |
Colin Cross | d9c6b80 | 2019-03-19 21:10:31 -0700 | [diff] [blame] | 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()) |
Dan Willemsen | bc60c3c | 2021-12-15 01:09:00 -0800 | [diff] [blame] | 78 | if tparams := typeparams.ForSignature(T); tparams != nil { |
| 79 | for i := 0; i < tparams.Len(); i++ { |
| 80 | addType(tparams.At(i)) |
| 81 | } |
| 82 | } |
Colin Cross | d9c6b80 | 2019-03-19 21:10:31 -0700 | [diff] [blame] | 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 | } |
Dan Willemsen | bc60c3c | 2021-12-15 01:09:00 -0800 | [diff] [blame] | 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 | } |
Colin Cross | d9c6b80 | 2019-03-19 21:10:31 -0700 | [diff] [blame] | 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 | } |