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 | "golang.org/x/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 | // TODO(adonovan): opt: compute this information more efficiently |
25 | // by obtaining it from the internals of the gcexportdata decoder. |
26 | func importMap(imports []*types.Package) map[string]*types.Package { |
27 | objects := make(map[types.Object]bool) |
28 | packages := make(map[string]*types.Package) |
29 | |
30 | var addObj func(obj types.Object) bool |
31 | var addType func(T types.Type) |
32 | |
33 | addObj = func(obj types.Object) bool { |
34 | if !objects[obj] { |
35 | objects[obj] = true |
36 | addType(obj.Type()) |
37 | if pkg := obj.Pkg(); pkg != nil { |
38 | packages[pkg.Path()] = pkg |
39 | } |
40 | return true |
41 | } |
42 | return false |
43 | } |
44 | |
45 | addType = func(T types.Type) { |
46 | switch T := T.(type) { |
47 | case *types.Basic: |
48 | // nop |
49 | case *types.Named: |
50 | if addObj(T.Obj()) { |
51 | // TODO(taking): Investigate why the Underlying type is not added here. |
52 | for i := 0; i < T.NumMethods(); i++ { |
53 | addObj(T.Method(i)) |
54 | } |
55 | if tparams := typeparams.ForNamed(T); tparams != nil { |
56 | for i := 0; i < tparams.Len(); i++ { |
57 | addType(tparams.At(i)) |
58 | } |
59 | } |
60 | if targs := typeparams.NamedTypeArgs(T); targs != nil { |
61 | for i := 0; i < targs.Len(); i++ { |
62 | addType(targs.At(i)) |
63 | } |
64 | } |
65 | } |
66 | case *types.Pointer: |
67 | addType(T.Elem()) |
68 | case *types.Slice: |
69 | addType(T.Elem()) |
70 | case *types.Array: |
71 | addType(T.Elem()) |
72 | case *types.Chan: |
73 | addType(T.Elem()) |
74 | case *types.Map: |
75 | addType(T.Key()) |
76 | addType(T.Elem()) |
77 | case *types.Signature: |
78 | addType(T.Params()) |
79 | addType(T.Results()) |
80 | if tparams := typeparams.ForSignature(T); tparams != nil { |
81 | for i := 0; i < tparams.Len(); i++ { |
82 | addType(tparams.At(i)) |
83 | } |
84 | } |
85 | case *types.Struct: |
86 | for i := 0; i < T.NumFields(); i++ { |
87 | addObj(T.Field(i)) |
88 | } |
89 | case *types.Tuple: |
90 | for i := 0; i < T.Len(); i++ { |
91 | addObj(T.At(i)) |
92 | } |
93 | case *types.Interface: |
94 | for i := 0; i < T.NumMethods(); i++ { |
95 | addObj(T.Method(i)) |
96 | } |
97 | for i := 0; i < T.NumEmbeddeds(); i++ { |
98 | addType(T.EmbeddedType(i)) // walk Embedded for implicits |
99 | } |
100 | case *typeparams.Union: |
101 | for i := 0; i < T.Len(); i++ { |
102 | addType(T.Term(i).Type()) |
103 | } |
104 | case *typeparams.TypeParam: |
105 | if addObj(T.Obj()) { |
106 | addType(T.Constraint()) |
107 | } |
108 | } |
109 | } |
110 | |
111 | for _, imp := range imports { |
112 | packages[imp.Path()] = imp |
113 | |
114 | scope := imp.Scope() |
115 | for _, name := range scope.Names() { |
116 | addObj(scope.Lookup(name)) |
117 | } |
118 | } |
119 | |
120 | return packages |
121 | } |
122 |
Members