blob: ade0cc6fab407b54ba4af8875de0c3dc3ba34a28 [file] [log] [blame]
Colin Crossd9c6b802019-03-19 21:10:31 -07001// 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
5package facts
6
Dan Willemsenbc60c3c2021-12-15 01:09:00 -08007import (
8 "go/types"
9
10 "golang.org/x/tools/internal/typeparams"
11)
Colin Crossd9c6b802019-03-19 21:10:31 -070012
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//
24func 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 Willemsenbc60c3c2021-12-15 01:09:00 -080049 // TODO(taking): Investigate why the Underlying type is not added here.
Colin Crossd9c6b802019-03-19 21:10:31 -070050 for i := 0; i < T.NumMethods(); i++ {
51 addObj(T.Method(i))
52 }
Dan Willemsenbc60c3c2021-12-15 01:09:00 -080053 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 Crossd9c6b802019-03-19 21:10:31 -070063 }
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 Willemsenbc60c3c2021-12-15 01:09:00 -080078 if tparams := typeparams.ForSignature(T); tparams != nil {
79 for i := 0; i < tparams.Len(); i++ {
80 addType(tparams.At(i))
81 }
82 }
Colin Crossd9c6b802019-03-19 21:10:31 -070083 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 Willemsenbc60c3c2021-12-15 01:09:00 -080095 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 Crossd9c6b802019-03-19 21:10:31 -0700106 }
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}