1 // Copyright 2013 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.
23 func pkgFor(path
, source
string, info
*Info
) (*Package
, error
) {
24 fset
:= token
.NewFileSet()
25 f
, err
:= parser
.ParseFile(fset
, path
, source
, 0)
30 conf
:= Config
{Importer
: importer
.Default()}
31 return conf
.Check(f
.Name
.Name
, fset
, []*ast
.File
{f
}, info
)
34 func mustTypecheck(t
*testing
.T
, path
, source
string, info
*Info
) string {
35 t
.Skip("skipping for gccgo--no importer")
36 pkg
, err
:= pkgFor(path
, source
, info
)
40 name
= "package " + pkg
.Name()
42 t
.Fatalf("%s: didn't type-check (%s)", name
, err
)
47 func TestValuesInfo(t
*testing
.T
) {
48 var tests
= []struct {
50 expr
string // constant expression
51 typ
string // constant type
52 val
string // constant value
54 {`package a0; const _ = false`, `false`, `untyped bool`, `false`},
55 {`package a1; const _ = 0`, `0`, `untyped int`, `0`},
56 {`package a2; const _ = 'A'`, `'A'`, `untyped rune`, `65`},
57 {`package a3; const _ = 0.`, `0.`, `untyped float`, `0`},
58 {`package a4; const _ = 0i`, `0i`, `untyped complex`, `(0 + 0i)`},
59 {`package a5; const _ = "foo"`, `"foo"`, `untyped string`, `"foo"`},
61 {`package b0; var _ = false`, `false`, `bool`, `false`},
62 {`package b1; var _ = 0`, `0`, `int`, `0`},
63 {`package b2; var _ = 'A'`, `'A'`, `rune`, `65`},
64 {`package b3; var _ = 0.`, `0.`, `float64`, `0`},
65 {`package b4; var _ = 0i`, `0i`, `complex128`, `(0 + 0i)`},
66 {`package b5; var _ = "foo"`, `"foo"`, `string`, `"foo"`},
68 {`package c0a; var _ = bool(false)`, `false`, `bool`, `false`},
69 {`package c0b; var _ = bool(false)`, `bool(false)`, `bool`, `false`},
70 {`package c0c; type T bool; var _ = T(false)`, `T(false)`, `c0c.T`, `false`},
72 {`package c1a; var _ = int(0)`, `0`, `int`, `0`},
73 {`package c1b; var _ = int(0)`, `int(0)`, `int`, `0`},
74 {`package c1c; type T int; var _ = T(0)`, `T(0)`, `c1c.T`, `0`},
76 {`package c2a; var _ = rune('A')`, `'A'`, `rune`, `65`},
77 {`package c2b; var _ = rune('A')`, `rune('A')`, `rune`, `65`},
78 {`package c2c; type T rune; var _ = T('A')`, `T('A')`, `c2c.T`, `65`},
80 {`package c3a; var _ = float32(0.)`, `0.`, `float32`, `0`},
81 {`package c3b; var _ = float32(0.)`, `float32(0.)`, `float32`, `0`},
82 {`package c3c; type T float32; var _ = T(0.)`, `T(0.)`, `c3c.T`, `0`},
84 {`package c4a; var _ = complex64(0i)`, `0i`, `complex64`, `(0 + 0i)`},
85 {`package c4b; var _ = complex64(0i)`, `complex64(0i)`, `complex64`, `(0 + 0i)`},
86 {`package c4c; type T complex64; var _ = T(0i)`, `T(0i)`, `c4c.T`, `(0 + 0i)`},
88 {`package c5a; var _ = string("foo")`, `"foo"`, `string`, `"foo"`},
89 {`package c5b; var _ = string("foo")`, `string("foo")`, `string`, `"foo"`},
90 {`package c5c; type T string; var _ = T("foo")`, `T("foo")`, `c5c.T`, `"foo"`},
92 {`package d0; var _ = []byte("foo")`, `"foo"`, `string`, `"foo"`},
93 {`package d1; var _ = []byte(string("foo"))`, `"foo"`, `string`, `"foo"`},
94 {`package d2; var _ = []byte(string("foo"))`, `string("foo")`, `string`, `"foo"`},
95 {`package d3; type T []byte; var _ = T("foo")`, `"foo"`, `string`, `"foo"`},
97 {`package e0; const _ = float32( 1e-200)`, `float32(1e-200)`, `float32`, `0`},
98 {`package e1; const _ = float32(-1e-200)`, `float32(-1e-200)`, `float32`, `0`},
99 {`package e2; const _ = float64( 1e-2000)`, `float64(1e-2000)`, `float64`, `0`},
100 {`package e3; const _ = float64(-1e-2000)`, `float64(-1e-2000)`, `float64`, `0`},
101 {`package e4; const _ = complex64( 1e-200)`, `complex64(1e-200)`, `complex64`, `(0 + 0i)`},
102 {`package e5; const _ = complex64(-1e-200)`, `complex64(-1e-200)`, `complex64`, `(0 + 0i)`},
103 {`package e6; const _ = complex128( 1e-2000)`, `complex128(1e-2000)`, `complex128`, `(0 + 0i)`},
104 {`package e7; const _ = complex128(-1e-2000)`, `complex128(-1e-2000)`, `complex128`, `(0 + 0i)`},
106 {`package f0 ; var _ float32 = 1e-200`, `1e-200`, `float32`, `0`},
107 {`package f1 ; var _ float32 = -1e-200`, `-1e-200`, `float32`, `0`},
108 {`package f2a; var _ float64 = 1e-2000`, `1e-2000`, `float64`, `0`},
109 {`package f3a; var _ float64 = -1e-2000`, `-1e-2000`, `float64`, `0`},
110 {`package f2b; var _ = 1e-2000`, `1e-2000`, `float64`, `0`},
111 {`package f3b; var _ = -1e-2000`, `-1e-2000`, `float64`, `0`},
112 {`package f4 ; var _ complex64 = 1e-200 `, `1e-200`, `complex64`, `(0 + 0i)`},
113 {`package f5 ; var _ complex64 = -1e-200 `, `-1e-200`, `complex64`, `(0 + 0i)`},
114 {`package f6a; var _ complex128 = 1e-2000i`, `1e-2000i`, `complex128`, `(0 + 0i)`},
115 {`package f7a; var _ complex128 = -1e-2000i`, `-1e-2000i`, `complex128`, `(0 + 0i)`},
116 {`package f6b; var _ = 1e-2000i`, `1e-2000i`, `complex128`, `(0 + 0i)`},
117 {`package f7b; var _ = -1e-2000i`, `-1e-2000i`, `complex128`, `(0 + 0i)`},
120 for _
, test
:= range tests
{
122 Types
: make(map[ast
.Expr
]TypeAndValue
),
124 name
:= mustTypecheck(t
, "ValuesInfo", test
.src
, &info
)
126 // look for constant expression
128 for e
:= range info
.Types
{
129 if ExprString(e
) == test
.expr
{
135 t
.Errorf("package %s: no expression found for %s", name
, test
.expr
)
138 tv
:= info
.Types
[expr
]
140 // check that type is correct
141 if got
:= tv
.Type
.String(); got
!= test
.typ
{
142 t
.Errorf("package %s: got type %s; want %s", name
, got
, test
.typ
)
146 // check that value is correct
147 if got
:= tv
.Value
.ExactString(); got
!= test
.val
{
148 t
.Errorf("package %s: got value %s; want %s", name
, got
, test
.val
)
153 func TestTypesInfo(t
*testing
.T
) {
154 var tests
= []struct {
156 expr
string // expression
157 typ
string // value type
159 // single-valued expressions of untyped constants
160 {`package b0; var x interface{} = false`, `false`, `bool`},
161 {`package b1; var x interface{} = 0`, `0`, `int`},
162 {`package b2; var x interface{} = 0.`, `0.`, `float64`},
163 {`package b3; var x interface{} = 0i`, `0i`, `complex128`},
164 {`package b4; var x interface{} = "foo"`, `"foo"`, `string`},
166 // comma-ok expressions
167 {`package p0; var x interface{}; var _, _ = x.(int)`,
171 {`package p1; var x interface{}; func _() { _, _ = x.(int) }`,
175 {`package p2a; type mybool bool; var m map[string]complex128; var b mybool; func _() { _, b = m["foo"] }`,
177 `(complex128, p2a.mybool)`,
179 {`package p2b; var m map[string]complex128; var b bool; func _() { _, b = m["foo"] }`,
181 `(complex128, bool)`,
183 {`package p3; var c chan string; var _, _ = <-c`,
189 {`package issue6796_a; var x interface{}; var _, _ = (x.(int))`,
193 {`package issue6796_b; var c chan string; var _, _ = (<-c)`,
197 {`package issue6796_c; var c chan string; var _, _ = (<-c)`,
201 {`package issue6796_d; var c chan string; var _, _ = ((<-c))`,
205 {`package issue6796_e; func f(c chan string) { _, _ = ((<-c)) }`,
211 {`package issue7060_a; var ( m map[int]string; x, ok = m[0] )`,
215 {`package issue7060_b; var ( m map[int]string; x, ok interface{} = m[0] )`,
219 {`package issue7060_c; func f(x interface{}, ok bool, m map[int]string) { x, ok = m[0] }`,
223 {`package issue7060_d; var ( ch chan string; x, ok = <-ch )`,
227 {`package issue7060_e; var ( ch chan string; x, ok interface{} = <-ch )`,
231 {`package issue7060_f; func f(x interface{}, ok bool, ch chan string) { x, ok = <-ch }`,
237 for _
, test
:= range tests
{
238 info
:= Info
{Types
: make(map[ast
.Expr
]TypeAndValue
)}
239 name
:= mustTypecheck(t
, "TypesInfo", test
.src
, &info
)
241 // look for expression type
243 for e
, tv
:= range info
.Types
{
244 if ExprString(e
) == test
.expr
{
250 t
.Errorf("package %s: no type found for %s", name
, test
.expr
)
254 // check that type is correct
255 if got
:= typ
.String(); got
!= test
.typ
{
256 t
.Errorf("package %s: got %s; want %s", name
, got
, test
.typ
)
261 func predString(tv TypeAndValue
) string {
263 pred
:= func(b
bool, s
string) {
266 buf
.WriteString(", ")
272 pred(tv
.IsVoid(), "void")
273 pred(tv
.IsType(), "type")
274 pred(tv
.IsBuiltin(), "builtin")
275 pred(tv
.IsValue() && tv
.Value
!= nil, "const")
276 pred(tv
.IsValue() && tv
.Value
== nil, "value")
277 pred(tv
.IsNil(), "nil")
278 pred(tv
.Addressable(), "addressable")
279 pred(tv
.Assignable(), "assignable")
280 pred(tv
.HasOk(), "hasOk")
288 func TestPredicatesInfo(t
*testing
.T
) {
289 testenv
.MustHaveGoBuild(t
)
291 var tests
= []struct {
297 {`package n0; func f() { f() }`, `f()`, `void`},
300 {`package t0; type _ int`, `int`, `type`},
301 {`package t1; type _ []int`, `[]int`, `type`},
302 {`package t2; type _ func()`, `func()`, `type`},
305 {`package b0; var _ = len("")`, `len`, `builtin`},
306 {`package b1; var _ = (len)("")`, `(len)`, `builtin`},
309 {`package c0; var _ = 42`, `42`, `const`},
310 {`package c1; var _ = "foo" + "bar"`, `"foo" + "bar"`, `const`},
311 {`package c2; const (i = 1i; _ = i)`, `i`, `const`},
314 {`package v0; var (a, b int; _ = a + b)`, `a + b`, `value`},
315 {`package v1; var _ = &[]int{1}`, `([]int literal)`, `value`},
316 {`package v2; var _ = func(){}`, `(func() literal)`, `value`},
317 {`package v4; func f() { _ = f }`, `f`, `value`},
318 {`package v3; var _ *int = nil`, `nil`, `value, nil`},
319 {`package v3; var _ *int = (nil)`, `(nil)`, `value, nil`},
321 // addressable (and thus assignable) operands
322 {`package a0; var (x int; _ = x)`, `x`, `value, addressable, assignable`},
323 {`package a1; var (p *int; _ = *p)`, `*p`, `value, addressable, assignable`},
324 {`package a2; var (s []int; _ = s[0])`, `s[0]`, `value, addressable, assignable`},
325 {`package a3; var (s struct{f int}; _ = s.f)`, `s.f`, `value, addressable, assignable`},
326 {`package a4; var (a [10]int; _ = a[0])`, `a[0]`, `value, addressable, assignable`},
327 {`package a5; func _(x int) { _ = x }`, `x`, `value, addressable, assignable`},
328 {`package a6; func _()(x int) { _ = x; return }`, `x`, `value, addressable, assignable`},
329 {`package a7; type T int; func (x T) _() { _ = x }`, `x`, `value, addressable, assignable`},
330 // composite literals are not addressable
332 // assignable but not addressable values
333 {`package s0; var (m map[int]int; _ = m[0])`, `m[0]`, `value, assignable, hasOk`},
334 {`package s1; var (m map[int]int; _, _ = m[0])`, `m[0]`, `value, assignable, hasOk`},
337 {`package k0; var (ch chan int; _ = <-ch)`, `<-ch`, `value, hasOk`},
338 {`package k1; var (ch chan int; _, _ = <-ch)`, `<-ch`, `value, hasOk`},
341 // - package names are collected in the Uses map
342 // - identifiers being declared are collected in the Defs map
343 {`package m0; import "os"; func _() { _ = os.Stdout }`, `os`, `<missing>`},
344 {`package m1; import p "os"; func _() { _ = p.Stdout }`, `p`, `<missing>`},
345 {`package m2; const c = 0`, `c`, `<missing>`},
346 {`package m3; type T int`, `T`, `<missing>`},
347 {`package m4; var v int`, `v`, `<missing>`},
348 {`package m5; func f() {}`, `f`, `<missing>`},
349 {`package m6; func _(x int) {}`, `x`, `<missing>`},
350 {`package m6; func _()(x int) { return }`, `x`, `<missing>`},
351 {`package m6; type T int; func (x T) _() {}`, `x`, `<missing>`},
354 for _
, test
:= range tests
{
355 info
:= Info
{Types
: make(map[ast
.Expr
]TypeAndValue
)}
356 name
:= mustTypecheck(t
, "PredicatesInfo", test
.src
, &info
)
358 // look for expression predicates
360 for e
, tv
:= range info
.Types
{
361 //println(name, ExprString(e))
362 if ExprString(e
) == test
.expr
{
368 if got
!= test
.pred
{
369 t
.Errorf("package %s: got %s; want %s", name
, got
, test
.pred
)
374 func TestScopesInfo(t
*testing
.T
) {
375 testenv
.MustHaveGoBuild(t
)
377 var tests
= []struct {
379 scopes
[]string // list of scope descriptors of the form kind:varlist
381 {`package p0`, []string{
384 {`package p1; import ( "fmt"; m "math"; _ "os" ); var ( _ = fmt.Println; _ = m.Pi )`, []string{
387 {`package p2; func _() {}`, []string{
390 {`package p3; func _(x, y int) {}`, []string{
393 {`package p4; func _(x, y int) { x, z := 1, 2; _ = z }`, []string{
394 "file:", "func:x y z", // redeclaration of x
396 {`package p5; func _(x, y int) (u, _ int) { return }`, []string{
397 "file:", "func:u x y",
399 {`package p6; func _() { { var x int; _ = x } }`, []string{
400 "file:", "func:", "block:x",
402 {`package p7; func _() { if true {} }`, []string{
403 "file:", "func:", "if:", "block:",
405 {`package p8; func _() { if x := 0; x < 0 { y := x; _ = y } }`, []string{
406 "file:", "func:", "if:x", "block:y",
408 {`package p9; func _() { switch x := 0; x {} }`, []string{
409 "file:", "func:", "switch:x",
411 {`package p10; func _() { switch x := 0; x { case 1: y := x; _ = y; default: }}`, []string{
412 "file:", "func:", "switch:x", "case:y", "case:",
414 {`package p11; func _(t interface{}) { switch t.(type) {} }`, []string{
415 "file:", "func:t", "type switch:",
417 {`package p12; func _(t interface{}) { switch t := t; t.(type) {} }`, []string{
418 "file:", "func:t", "type switch:t",
420 {`package p13; func _(t interface{}) { switch x := t.(type) { case int: _ = x } }`, []string{
421 "file:", "func:t", "type switch:", "case:x", // x implicitly declared
423 {`package p14; func _() { select{} }`, []string{
426 {`package p15; func _(c chan int) { select{ case <-c: } }`, []string{
427 "file:", "func:c", "comm:",
429 {`package p16; func _(c chan int) { select{ case i := <-c: x := i; _ = x} }`, []string{
430 "file:", "func:c", "comm:i x",
432 {`package p17; func _() { for{} }`, []string{
433 "file:", "func:", "for:", "block:",
435 {`package p18; func _(n int) { for i := 0; i < n; i++ { _ = i } }`, []string{
436 "file:", "func:n", "for:i", "block:",
438 {`package p19; func _(a []int) { for i := range a { _ = i} }`, []string{
439 "file:", "func:a", "range:i", "block:",
441 {`package p20; var s int; func _(a []int) { for i, x := range a { s += x; _ = i } }`, []string{
442 "file:", "func:a", "range:i x", "block:",
446 for _
, test
:= range tests
{
447 info
:= Info
{Scopes
: make(map[ast
.Node
]*Scope
)}
448 name
:= mustTypecheck(t
, "ScopesInfo", test
.src
, &info
)
450 // number of scopes must match
451 if len(info
.Scopes
) != len(test
.scopes
) {
452 t
.Errorf("package %s: got %d scopes; want %d", name
, len(info
.Scopes
), len(test
.scopes
))
455 // scope descriptions must match
456 for node
, scope
:= range info
.Scopes
{
457 kind
:= "<unknown node kind>"
467 case *ast
.SwitchStmt
:
469 case *ast
.TypeSwitchStmt
:
471 case *ast
.CaseClause
:
473 case *ast
.CommClause
:
481 // look for matching scope description
482 desc
:= kind
+ ":" + strings
.Join(scope
.Names(), " ")
484 for _
, d
:= range test
.scopes
{
491 t
.Errorf("package %s: no matching scope found for %s", name
, desc
)
497 func TestInitOrderInfo(t
*testing
.T
) {
498 var tests
= []struct {
502 {`package p0; var (x = 1; y = x)`, []string{
505 {`package p1; var (a = 1; b = 2; c = 3)`, []string{
506 "a = 1", "b = 2", "c = 3",
508 {`package p2; var (a, b, c = 1, 2, 3)`, []string{
509 "a = 1", "b = 2", "c = 3",
511 {`package p3; var _ = f(); func f() int { return 1 }`, []string{
512 "_ = f()", // blank var
514 {`package p4; var (a = 0; x = y; y = z; z = 0)`, []string{
515 "a = 0", "z = 0", "y = z", "x = y",
517 {`package p5; var (a, _ = m[0]; m map[int]string)`, []string{
518 "a, _ = m[0]", // blank var
520 {`package p6; var a, b = f(); func f() (_, _ int) { return z, z }; var z = 0`, []string{
521 "z = 0", "a, b = f()",
523 {`package p7; var (a = func() int { return b }(); b = 1)`, []string{
524 "b = 1", "a = (func() int literal)()",
526 {`package p8; var (a, b = func() (_, _ int) { return c, c }(); c = 1)`, []string{
527 "c = 1", "a, b = (func() (_, _ int) literal)()",
529 {`package p9; type T struct{}; func (T) m() int { _ = y; return 0 }; var x, y = T.m, 1`, []string{
532 {`package p10; var (d = c + b; a = 0; b = 0; c = 0)`, []string{
533 "a = 0", "b = 0", "c = 0", "d = c + b",
535 {`package p11; var (a = e + c; b = d + c; c = 0; d = 0; e = 0)`, []string{
536 "c = 0", "d = 0", "b = d + c", "e = 0", "a = e + c",
538 // emit an initializer for n:1 initializations only once (not for each node
539 // on the lhs which may appear in different order in the dependency graph)
540 {`package p12; var (a = x; b = 0; x, y = m[0]; m map[int]int)`, []string{
541 "b = 0", "x, y = m[0]", "a = x",
543 // test case from spec section on package initialization
557 "d = 3", "b = f()", "c = f()", "a = c + b",
559 // test case for issue 7131
563 func next() int { counter++; return counter }
566 func makeOrder() []int { return []int{f, b, d, e, c, a} }
569 var b, c = next(), next()
570 var d, e, f = next(), next(), next()
572 "a = next()", "b = next()", "c = next()", "d = next()", "e = next()", "f = next()", "_ = makeOrder()",
574 // test case for issue 10709
584 func (T) m() int { return 0 }
586 func makeT(n int) T {
592 "t = makeT(0)", "v = t.m()",
594 // test case for issue 10709: same as test before, but variable decls swapped
604 func (T) m() int { return 0 }
606 func makeT(n int) T {
612 "t = makeT(0)", "v = t.m()",
614 // another candidate possibly causing problems with issue 10709
619 func f1() int { return g1() }
620 func g1() int { f1(); return x1 }
626 func f2() int { return g2() }
627 func g2() int { return x2 }
629 var x2 = 0`, []string{
630 "x1 = 0", "y1 = f1()", "x2 = 0", "y2 = f2()",
634 for _
, test
:= range tests
{
636 name
:= mustTypecheck(t
, "InitOrderInfo", test
.src
, &info
)
638 // number of initializers must match
639 if len(info
.InitOrder
) != len(test
.inits
) {
640 t
.Errorf("package %s: got %d initializers; want %d", name
, len(info
.InitOrder
), len(test
.inits
))
644 // initializers must match
645 for i
, want
:= range test
.inits
{
646 got
:= info
.InitOrder
[i
].String()
648 t
.Errorf("package %s, init %d: got %s; want %s", name
, i
, got
, want
)
655 func TestMultiFileInitOrder(t
*testing
.T
) {
656 fset
:= token
.NewFileSet()
657 mustParse
:= func(src
string) *ast
.File
{
658 f
, err
:= parser
.ParseFile(fset
, "main", src
, 0)
665 fileA
:= mustParse(`package main; var a = 1`)
666 fileB
:= mustParse(`package main; var b = 2`)
668 // The initialization order must not depend on the parse
669 // order of the files, only on the presentation order to
671 for _
, test
:= range []struct {
675 {[]*ast
.File
{fileA
, fileB
}, "[a = 1 b = 2]"},
676 {[]*ast
.File
{fileB
, fileA
}, "[b = 2 a = 1]"},
679 if _
, err
:= new(Config
).Check("main", fset
, test
.files
, &info
); err
!= nil {
682 if got
:= fmt
.Sprint(info
.InitOrder
); got
!= test
.want
{
683 t
.Fatalf("got %s; want %s", got
, test
.want
)
688 func TestFiles(t
*testing
.T
) {
689 var sources
= []string{
690 "package p; type T struct{}; func (T) m1() {}",
691 "package p; func (T) m2() {}; var x interface{ m1(); m2() } = T{}",
692 "package p; func (T) m3() {}; var y interface{ m1(); m2(); m3() } = T{}",
697 fset
:= token
.NewFileSet()
698 pkg
:= NewPackage("p", "p")
700 check
:= NewChecker(&conf
, fset
, pkg
, &info
)
702 for i
, src
:= range sources
{
703 filename
:= fmt
.Sprintf("sources%d", i
)
704 f
, err
:= parser
.ParseFile(fset
, filename
, src
, 0)
708 if err
:= check
.Files([]*ast
.File
{f
}); err
!= nil {
713 // check InitOrder is [x y]
715 for _
, init
:= range info
.InitOrder
{
716 for _
, v
:= range init
.Lhs
{
717 vars
= append(vars
, v
.Name())
720 if got
, want
:= fmt
.Sprint(vars
), "[x y]"; got
!= want
{
721 t
.Errorf("InitOrder == %s, want %s", got
, want
)
725 type testImporter
map[string]*Package
727 func (m testImporter
) Import(path
string) (*Package
, error
) {
728 if pkg
:= m
[path
]; pkg
!= nil {
731 return nil, fmt
.Errorf("package %q not found", path
)
734 func TestSelection(t
*testing
.T
) {
735 selections
:= make(map[*ast
.SelectorExpr
]*Selection
)
737 fset
:= token
.NewFileSet()
738 imports
:= make(testImporter
)
739 conf
:= Config
{Importer
: imports
}
740 makePkg
:= func(path
, src
string) {
741 f
, err
:= parser
.ParseFile(fset
, path
+".go", src
, 0)
745 pkg
, err
:= conf
.Check(path
, fset
, []*ast
.File
{f
}, &Info
{Selections
: selections
})
783 // qualified identifiers
817 // method expressions
824 wantOut
:= map[string][2]string{
825 "lib.T.M": {"method expr (lib.T) M(lib.T)", ".[0]"},
827 "A{}.B": {"field (main.A) B *main.B", ".[0]"},
828 "new(A).B": {"field (*main.A) B *main.B", "->[0]"},
829 "A{}.C": {"field (main.A) C main.C", ".[1]"},
830 "new(A).C": {"field (*main.A) C main.C", "->[1]"},
831 "A{}.b": {"field (main.A) b int", "->[0 0]"},
832 "new(A).b": {"field (*main.A) b int", "->[0 0]"},
833 "A{}.c": {"field (main.A) c int", ".[1 0]"},
834 "new(A).c": {"field (*main.A) c int", "->[1 0]"},
836 "A{}.f": {"method (main.A) f(int)", "->[0 0]"},
837 "new(A).f": {"method (*main.A) f(int)", "->[0 0]"},
838 "A{}.g": {"method (main.A) g()", ".[1 0]"},
839 "new(A).g": {"method (*main.A) g()", "->[1 0]"},
840 "new(A).h": {"method (*main.A) h()", "->[1 1]"}, // TODO(gri) should this report .[1 1] ?
841 "B{}.f": {"method (main.B) f(int)", ".[0]"},
842 "new(B).f": {"method (*main.B) f(int)", "->[0]"},
843 "C{}.g": {"method (main.C) g()", ".[0]"},
844 "new(C).g": {"method (*main.C) g()", "->[0]"},
845 "new(C).h": {"method (*main.C) h()", "->[1]"}, // TODO(gri) should this report .[1] ?
847 "A.f": {"method expr (main.A) f(main.A, int)", "->[0 0]"},
848 "(*A).f": {"method expr (*main.A) f(*main.A, int)", "->[0 0]"},
849 "B.f": {"method expr (main.B) f(main.B, int)", ".[0]"},
850 "(*B).f": {"method expr (*main.B) f(*main.B, int)", "->[0]"},
853 makePkg("lib", libSrc
)
854 makePkg("main", mainSrc
)
856 for e
, sel
:= range selections
{
857 _
= sel
.String() // assertion: must not panic
859 start
:= fset
.Position(e
.Pos()).Offset
860 end
:= fset
.Position(e
.End()).Offset
861 syntax
:= mainSrc
[start
:end
] // (all SelectorExprs are in main, not lib)
869 fmt
.Sprintf("%s%v", direct
, sel
.Index()),
871 want
:= wantOut
[syntax
]
873 t
.Errorf("%s: got %q; want %q", syntax
, got
, want
)
875 delete(wantOut
, syntax
)
877 // We must explicitly assert properties of the
878 // Signature's receiver since it doesn't participate
879 // in Identical() or String().
880 sig
, _
:= sel
.Type().(*Signature
)
881 if sel
.Kind() == MethodVal
{
882 got
:= sig
.Recv().Type()
884 if !Identical(got
, want
) {
885 t
.Errorf("%s: Recv() = %s, want %s", syntax
, got
, want
)
887 } else if sig
!= nil && sig
.Recv() != nil {
888 t
.Errorf("%s: signature has receiver %s", sig
, sig
.Recv().Type())
891 // Assert that all wantOut entries were used exactly once.
892 for syntax
:= range wantOut
{
893 t
.Errorf("no ast.Selection found with syntax %q", syntax
)
897 func TestIssue8518(t
*testing
.T
) {
898 fset
:= token
.NewFileSet()
899 imports
:= make(testImporter
)
901 Error
: func(err error
) { t
.Log(err
) }, // don't exit after first error
904 makePkg
:= func(path
, src
string) {
905 f
, err
:= parser
.ParseFile(fset
, path
, src
, 0)
909 pkg
, _
:= conf
.Check(path
, fset
, []*ast
.File
{f
}, nil) // errors logged via conf.Error
928 makePkg("main", mainSrc
) // don't crash when type-checking this package
931 func TestLookupFieldOrMethod(t
*testing
.T
) {
932 t
.Skip("skipping for gccgo--no importer")
933 // Test cases assume a lookup of the form a.f or x.f, where a stands for an
934 // addressable value, and x for a non-addressable value (even though a variable
935 // for ease of test case writing).
936 var tests
= []struct {
943 {"var x T; type T struct{}", false, nil, false},
944 {"var x T; type T struct{ f int }", true, []int{0}, false},
945 {"var x T; type T struct{ a, b, f, c int }", true, []int{2}, false},
948 {"var a T; type T struct{}; func (T) f() {}", true, []int{0}, false},
949 {"var a *T; type T struct{}; func (T) f() {}", true, []int{0}, true},
950 {"var a T; type T struct{}; func (*T) f() {}", true, []int{0}, false},
951 {"var a *T; type T struct{}; func (*T) f() {}", true, []int{0}, true}, // TODO(gri) should this report indirect = false?
954 {"type ( E1 struct{ f int }; E2 struct{ f int }; x struct{ E1; *E2 })", false, []int{1, 0}, false},
955 {"type ( E1 struct{ f int }; E2 struct{}; x struct{ E1; *E2 }); func (E2) f() {}", false, []int{1, 0}, false},
958 // (*T).f method exists, but value of type T is not addressable
959 {"var x T; type T struct{}; func (*T) f() {}", false, nil, true},
962 for _
, test
:= range tests
{
963 pkg
, err
:= pkgFor("test", "package p;"+test
.src
, nil)
965 t
.Errorf("%s: incorrect test case: %s", test
.src
, err
)
969 obj
:= pkg
.Scope().Lookup("a")
971 if obj
= pkg
.Scope().Lookup("x"); obj
== nil {
972 t
.Errorf("%s: incorrect test case - no object a or x", test
.src
)
977 f
, index
, indirect
:= LookupFieldOrMethod(obj
.Type(), obj
.Name() == "a", pkg
, "f")
978 if (f
!= nil) != test
.found
{
980 t
.Errorf("%s: got no object; want one", test
.src
)
982 t
.Errorf("%s: got object = %v; want none", test
.src
, f
)
985 if !sameSlice(index
, test
.index
) {
986 t
.Errorf("%s: got index = %v; want %v", test
.src
, index
, test
.index
)
988 if indirect
!= test
.indirect
{
989 t
.Errorf("%s: got indirect = %v; want %v", test
.src
, indirect
, test
.indirect
)
994 func sameSlice(a
, b
[]int) bool {
995 if len(a
) != len(b
) {
998 for i
, x
:= range a
{
1006 // TestScopeLookupParent ensures that (*Scope).LookupParent returns
1007 // the correct result at various positions with the source.
1008 func TestScopeLookupParent(t
*testing
.T
) {
1009 fset
:= token
.NewFileSet()
1010 imports
:= make(testImporter
)
1011 conf
:= Config
{Importer
: imports
}
1012 mustParse
:= func(src
string) *ast
.File
{
1013 f
, err
:= parser
.ParseFile(fset
, "dummy.go", src
, parser
.ParseComments
)
1020 makePkg
:= func(path
string, files
...*ast
.File
) {
1022 imports
[path
], err
= conf
.Check(path
, fset
, files
, &info
)
1028 makePkg("lib", mustParse("package lib; var X int"))
1029 // Each /*name=kind:line*/ comment makes the test look up the
1030 // name at that point and checks that it resolves to a decl of
1031 // the specified kind and line number. "undef" means undefined.
1033 /*lib=pkgname:5*/ /*X=var:1*/ /*Pi=const:8*/ /*T=typename:9*/ /*Y=var:10*/ /*F=func:12*/
1044 const pi, e = 3.1415, /*pi=undef*/ 2.71828 /*pi=const:13*/ /*e=const:13*/
1045 type /*t=undef*/ t /*t=typename:14*/ *t
1046 print(Y) /*Y=var:10*/
1047 x, Y := Y, /*x=undef*/ /*Y=var:10*/ Pi /*x=var:16*/ /*Y=var:16*/ ; _ = x; _ = Y
1048 var F = /*F=func:12*/ F /*F=var:17*/ ; _ = F
1051 for i, x := range /*i=undef*/ /*x=var:16*/ a /*i=var:20*/ /*x=var:20*/ { _ = i; _ = x }
1054 switch y := i.(type) { /*y=undef*/
1055 case /*y=undef*/ int /*y=var:23*/ :
1056 case float32, /*y=undef*/ float64 /*y=var:23*/ :
1057 default /*y=var:23*/:
1062 switch int := i.(type) {
1063 case /*int=typename:0*/ int /*int=var:31*/ :
1065 default /*int=var:31*/ :
1071 info
.Uses
= make(map[*ast
.Ident
]Object
)
1072 f
:= mustParse(mainSrc
)
1074 mainScope
:= imports
["main"].Scope()
1075 rx
:= regexp
.MustCompile(`^/\*(\w*)=([\w:]*)\*/$`)
1076 for _
, group
:= range f
.Comments
{
1077 for _
, comment
:= range group
.List
{
1078 // Parse the assertion in the comment.
1079 m
:= rx
.FindStringSubmatch(comment
.Text
)
1081 t
.Errorf("%s: bad comment: %s",
1082 fset
.Position(comment
.Pos()), comment
.Text
)
1085 name
, want
:= m
[1], m
[2]
1087 // Look up the name in the innermost enclosing scope.
1088 inner
:= mainScope
.Innermost(comment
.Pos())
1090 t
.Errorf("%s: at %s: can't find innermost scope",
1091 fset
.Position(comment
.Pos()), comment
.Text
)
1095 if _
, obj
:= inner
.LookupParent(name
, comment
.Pos()); obj
!= nil {
1096 kind
:= strings
.ToLower(strings
.TrimPrefix(reflect
.TypeOf(obj
).String(), "*types."))
1097 got
= fmt
.Sprintf("%s:%d", kind
, fset
.Position(obj
.Pos()).Line
)
1100 t
.Errorf("%s: at %s: %s resolved to %s, want %s",
1101 fset
.Position(comment
.Pos()), comment
.Text
, name
, got
, want
)
1106 // Check that for each referring identifier,
1107 // a lookup of its name on the innermost
1108 // enclosing scope returns the correct object.
1110 for id
, wantObj
:= range info
.Uses
{
1111 inner
:= mainScope
.Innermost(id
.Pos())
1113 t
.Errorf("%s: can't find innermost scope enclosing %q",
1114 fset
.Position(id
.Pos()), id
.Name
)
1118 // Exclude selectors and qualified identifiers---lexical
1119 // refs only. (Ideally, we'd see if the AST parent is a
1120 // SelectorExpr, but that requires PathEnclosingInterval
1121 // from golang.org/x/tools/go/ast/astutil.)
1126 _
, gotObj
:= inner
.LookupParent(id
.Name
, id
.Pos())
1127 if gotObj
!= wantObj
{
1128 t
.Errorf("%s: got %v, want %v",
1129 fset
.Position(id
.Pos()), gotObj
, wantObj
)
1135 func TestIdentical_issue15173(t
*testing
.T
) {
1136 // Identical should allow nil arguments and be symmetric.
1137 for _
, test
:= range []struct {
1141 {Typ
[Int
], Typ
[Int
], true},
1142 {Typ
[Int
], nil, false},
1143 {nil, Typ
[Int
], false},
1146 if got
:= Identical(test
.x
, test
.y
); got
!= test
.want
{
1147 t
.Errorf("Identical(%v, %v) = %t", test
.x
, test
.y
, got
)
1152 func TestIssue15305(t
*testing
.T
) {
1153 const src
= "package p; func f() int16; var _ = f(undef)"
1154 fset
:= token
.NewFileSet()
1155 f
, err
:= parser
.ParseFile(fset
, "issue15305.go", src
, 0)
1160 Error
: func(err error
) {}, // allow errors
1163 Types
: make(map[ast
.Expr
]TypeAndValue
),
1165 conf
.Check("p", fset
, []*ast
.File
{f
}, info
) // ignore result
1166 for e
, tv
:= range info
.Types
{
1167 if _
, ok
:= e
.(*ast
.CallExpr
); ok
{
1168 if tv
.Type
!= Typ
[Int16
] {
1169 t
.Errorf("CallExpr has type %v, want int16", tv
.Type
)
1174 t
.Errorf("CallExpr has no type")
1177 // TestCompositeLitTypes verifies that Info.Types registers the correct
1178 // types for composite literal expressions and composite literal type
1180 func TestCompositeLitTypes(t
*testing
.T
) {
1181 for _
, test
:= range []struct {
1184 {`[16]byte{}`, `[16]byte`},
1185 {`[...]byte{}`, `[0]byte`}, // test for issue #14092
1186 {`[...]int{1, 2, 3}`, `[3]int`}, // test for issue #14092
1187 {`[...]int{90: 0, 98: 1, 2}`, `[100]int`}, // test for issue #14092
1188 {`[]int{}`, `[]int`},
1189 {`map[string]bool{"foo": true}`, `map[string]bool`},
1190 {`struct{}{}`, `struct{}`},
1191 {`struct{x, y int; z complex128}{}`, `struct{x int; y int; z complex128}`},
1193 fset
:= token
.NewFileSet()
1194 f
, err
:= parser
.ParseFile(fset
, test
.lit
, "package p; var _ = "+test
.lit
, 0)
1196 t
.Fatalf("%s: %v", test
.lit
, err
)
1200 Types
: make(map[ast
.Expr
]TypeAndValue
),
1202 if _
, err
= new(Config
).Check("p", fset
, []*ast
.File
{f
}, info
); err
!= nil {
1203 t
.Fatalf("%s: %v", test
.lit
, err
)
1206 cmptype
:= func(x ast
.Expr
, want
string) {
1207 tv
, ok
:= info
.Types
[x
]
1209 t
.Errorf("%s: no Types entry found", test
.lit
)
1213 t
.Errorf("%s: type is nil", test
.lit
)
1216 if got
:= tv
.Type
.String(); got
!= want
{
1217 t
.Errorf("%s: got %v, want %s", test
.lit
, got
, want
)
1221 // test type of composite literal expression
1222 rhs
:= f
.Decls
[0].(*ast
.GenDecl
).Specs
[0].(*ast
.ValueSpec
).Values
[0]
1223 cmptype(rhs
, test
.typ
)
1225 // test type of composite literal type expression
1226 cmptype(rhs
.(*ast
.CompositeLit
).Type
, test
.typ
)
1230 // TestObjectParents verifies that objects have parent scopes or not
1231 // as specified by the Object interface.
1232 func TestObjectParents(t
*testing
.T
) {
1251 func f(x int) { y := x; print(y) }
1254 fset
:= token
.NewFileSet()
1255 f
, err
:= parser
.ParseFile(fset
, "src", src
, 0)
1261 Defs
: make(map[*ast
.Ident
]Object
),
1263 if _
, err
= new(Config
).Check("p", fset
, []*ast
.File
{f
}, info
); err
!= nil {
1267 for ident
, obj
:= range info
.Defs
{
1269 // only package names and implicit vars have a nil object
1270 // (in this test we only need to handle the package name)
1271 if ident
.Name
!= "p" {
1272 t
.Errorf("%v has nil object", ident
)
1277 // struct fields, type-associated and interface methods
1278 // have no parent scope
1280 switch obj
:= obj
.(type) {
1286 if obj
.Type().(*Signature
).Recv() != nil { // method
1291 gotParent
:= obj
.Parent() != nil
1293 case gotParent
&& !wantParent
:
1294 t
.Errorf("%v: want no parent, got %s", ident
, obj
.Parent())
1295 case !gotParent
&& wantParent
:
1296 t
.Errorf("%v: no parent found", ident
)
1301 // TestFailedImport tests that we don't get follow-on errors
1302 // elsewhere in a package due to failing to import a package.
1303 func TestFailedImport(t
*testing
.T
) {
1304 testenv
.MustHaveGoBuild(t
)
1309 import "foo" // should only see an error here
1314 func f(x T) T { return foo.F(x) }
1316 fset
:= token
.NewFileSet()
1317 f
, err
:= parser
.ParseFile(fset
, "src", src
, 0)
1321 files
:= []*ast
.File
{f
}
1323 // type-check using all possible importers
1324 for _
, compiler
:= range []string{"gc", "gccgo", "source"} {
1327 Error
: func(err error
) {
1328 // we should only see the import error
1329 if errcount
> 0 ||
!strings
.Contains(err
.Error(), "could not import foo") {
1330 t
.Errorf("for %s importer, got unexpected error: %v", compiler
, err
)
1334 Importer
: importer
.For(compiler
, nil),
1338 Uses
: make(map[*ast
.Ident
]Object
),
1340 pkg
, _
:= conf
.Check("p", fset
, files
, info
)
1342 t
.Errorf("for %s importer, type-checking failed to return a package", compiler
)
1346 imports
:= pkg
.Imports()
1347 if len(imports
) != 1 {
1348 t
.Errorf("for %s importer, got %d imports, want 1", compiler
, len(imports
))
1352 if imp
.Name() != "foo" {
1353 t
.Errorf(`for %s importer, got %q, want "foo"`, compiler
, imp
.Name())
1357 // verify that all uses of foo refer to the imported package foo (imp)
1358 for ident
, obj
:= range info
.Uses
{
1359 if ident
.Name
== "foo" {
1360 if obj
, ok
:= obj
.(*PkgName
); ok
{
1361 if obj
.Imported() != imp
{
1362 t
.Errorf("%s resolved to %v; want %v", ident
, obj
.Imported(), imp
)
1365 t
.Errorf("%s resolved to %v; want package name", ident
, obj
)