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