Source file
src/go/types/resolver_test.go
1
2
3
4
5 package types_test
6
7 import (
8 "fmt"
9 "go/ast"
10 "go/importer"
11 "go/token"
12 "internal/testenv"
13 "slices"
14 "testing"
15
16 . "go/types"
17 )
18
19 type resolveTestImporter struct {
20 importer ImporterFrom
21 imported map[string]bool
22 }
23
24 func (imp *resolveTestImporter) Import(string) (*Package, error) {
25 panic("should not be called")
26 }
27
28 func (imp *resolveTestImporter) ImportFrom(path, srcDir string, mode ImportMode) (*Package, error) {
29 if mode != 0 {
30 panic("mode must be 0")
31 }
32 if imp.importer == nil {
33 imp.importer = importer.Default().(ImporterFrom)
34 imp.imported = make(map[string]bool)
35 }
36 pkg, err := imp.importer.ImportFrom(path, srcDir, mode)
37 if err != nil {
38 return nil, err
39 }
40 imp.imported[path] = true
41 return pkg, nil
42 }
43
44 func TestResolveIdents(t *testing.T) {
45 testenv.MustHaveGoBuild(t)
46
47 sources := []string{
48 `
49 package p
50 import "fmt"
51 import "math"
52 const pi = math.Pi
53 func sin(x float64) float64 {
54 return math.Sin(x)
55 }
56 var Println = fmt.Println
57 `,
58 `
59 package p
60 import "fmt"
61 type errorStringer struct { fmt.Stringer; error }
62 func f() string {
63 _ = "foo"
64 return fmt.Sprintf("%d", g())
65 }
66 func g() (x int) { return }
67 `,
68 `
69 package p
70 import . "go/parser"
71 import "sync"
72 func h() Mode { return ImportsOnly }
73 var _, x int = 1, 2
74 func init() {}
75 type T struct{ *sync.Mutex; a, b, c int}
76 type I interface{ m() }
77 var _ = T{a: 1, b: 2, c: 3}
78 func (_ T) m() {}
79 func (T) _() {}
80 var i I
81 var _ = i.m
82 func _(s []int) { for i, x := range s { _, _ = i, x } }
83 func _(x interface{}) {
84 switch x := x.(type) {
85 case int:
86 _ = x
87 }
88 switch {} // implicit 'true' tag
89 }
90 `,
91 `
92 package p
93 type S struct{}
94 func (T) _() {}
95 func (T) _() {}
96 `,
97 `
98 package p
99 func _() {
100 L0:
101 L1:
102 goto L0
103 for {
104 goto L1
105 }
106 if true {
107 goto L2
108 }
109 L2:
110 }
111 `,
112 }
113
114 pkgnames := []string{
115 "fmt",
116 "math",
117 }
118
119
120 fset := token.NewFileSet()
121 var files []*ast.File
122 for _, src := range sources {
123 files = append(files, mustParse(fset, src))
124 }
125
126
127 importer := new(resolveTestImporter)
128 conf := Config{Importer: importer}
129 uses := make(map[*ast.Ident]Object)
130 defs := make(map[*ast.Ident]Object)
131 _, err := conf.Check("testResolveIdents", fset, files, &Info{Defs: defs, Uses: uses})
132 if err != nil {
133 t.Fatal(err)
134 }
135
136
137 for _, name := range pkgnames {
138 if !importer.imported[name] {
139 t.Errorf("package %s not imported", name)
140 }
141 }
142
143
144 for _, f := range files {
145 ast.Inspect(f, func(n ast.Node) bool {
146 if s, ok := n.(*ast.SelectorExpr); ok {
147 if x, ok := s.X.(*ast.Ident); ok {
148 obj := uses[x]
149 if obj == nil {
150 t.Errorf("%s: unresolved qualified identifier %s", fset.Position(x.Pos()), x.Name)
151 return false
152 }
153 if _, ok := obj.(*PkgName); ok && uses[s.Sel] == nil {
154 t.Errorf("%s: unresolved selector %s", fset.Position(s.Sel.Pos()), s.Sel.Name)
155 return false
156 }
157 return false
158 }
159 return true
160 }
161 return true
162 })
163 }
164
165 for id, obj := range uses {
166 if obj == nil {
167 t.Errorf("%s: Uses[%s] == nil", fset.Position(id.Pos()), id.Name)
168 }
169 }
170
171
172 var both []string
173 for _, f := range files {
174 ast.Inspect(f, func(n ast.Node) bool {
175 if x, ok := n.(*ast.Ident); ok {
176 var objects int
177 if _, found := uses[x]; found {
178 objects |= 1
179 delete(uses, x)
180 }
181 if _, found := defs[x]; found {
182 objects |= 2
183 delete(defs, x)
184 }
185 if objects == 0 {
186 t.Errorf("%s: unresolved identifier %s", fset.Position(x.Pos()), x.Name)
187 } else if objects == 3 {
188 both = append(both, x.Name)
189 }
190 return false
191 }
192 return true
193 })
194 }
195
196
197 slices.Sort(both)
198 if got, want := fmt.Sprint(both), "[Mutex Stringer error]"; got != want {
199 t.Errorf("simultaneous uses/defs = %s, want %s", got, want)
200 }
201
202
203 for x := range uses {
204 t.Errorf("%s: identifier %s not present in source", fset.Position(x.Pos()), x.Name)
205 }
206 for x := range defs {
207 t.Errorf("%s: identifier %s not present in source", fset.Position(x.Pos()), x.Name)
208 }
209
210
211 }
212
View as plain text