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 i, src := range sources {
120 f, err := parseSrc(fmt.Sprintf("sources[%d]", i), src)
121 if err != nil {
122 t.Fatal(err)
123 }
124 files = append(files, f)
125 }
126
127
128 importer := new(resolveTestImporter)
129 conf := Config{Importer: importer}
130 uses := make(map[*syntax.Name]Object)
131 defs := make(map[*syntax.Name]Object)
132 _, err := conf.Check("testResolveIdents", files, &Info{Defs: defs, Uses: uses})
133 if err != nil {
134 t.Fatal(err)
135 }
136
137
138 for _, name := range pkgnames {
139 if !importer.imported[name] {
140 t.Errorf("package %s not imported", name)
141 }
142 }
143
144
145 for _, f := range files {
146 syntax.Crawl(f, func(n syntax.Node) bool {
147 if s, ok := n.(*syntax.SelectorExpr); ok {
148 if x, ok := s.X.(*syntax.Name); ok {
149 obj := uses[x]
150 if obj == nil {
151 t.Errorf("%s: unresolved qualified identifier %s", x.Pos(), x.Value)
152 return true
153 }
154 if _, ok := obj.(*PkgName); ok && uses[s.Sel] == nil {
155 t.Errorf("%s: unresolved selector %s", s.Sel.Pos(), s.Sel.Value)
156 return true
157 }
158 return true
159 }
160 return true
161 }
162 return false
163 })
164 }
165
166 for id, obj := range uses {
167 if obj == nil {
168 t.Errorf("%s: Uses[%s] == nil", id.Pos(), id.Value)
169 }
170 }
171
172
173
174
175
176 foundUses := make(map[*syntax.Name]bool)
177 foundDefs := make(map[*syntax.Name]bool)
178 var both []string
179 for _, f := range files {
180 syntax.Crawl(f, func(n syntax.Node) bool {
181 if x, ok := n.(*syntax.Name); ok {
182 var objects int
183 if _, found := uses[x]; found {
184 objects |= 1
185 foundUses[x] = true
186 }
187 if _, found := defs[x]; found {
188 objects |= 2
189 foundDefs[x] = true
190 }
191 switch objects {
192 case 0:
193 t.Errorf("%s: unresolved identifier %s", x.Pos(), x.Value)
194 case 3:
195 both = append(both, x.Value)
196 }
197 return true
198 }
199 return false
200 })
201 }
202
203
204 sort.Strings(both)
205 if got, want := fmt.Sprint(both), "[Mutex Stringer error]"; got != want {
206 t.Errorf("simultaneous uses/defs = %s, want %s", got, want)
207 }
208
209
210 for x := range uses {
211 if !foundUses[x] {
212 t.Errorf("%s: identifier %s not present in source", x.Pos(), x.Value)
213 }
214 }
215 for x := range defs {
216 if !foundDefs[x] {
217 t.Errorf("%s: identifier %s not present in source", x.Pos(), x.Value)
218 }
219 }
220
221
222 }
223
View as plain text