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