package types_test
import (
+ "bytes"
"fmt"
"go/ast"
"go/importer"
. "go/types"
)
-func TestIssue5770(t *testing.T) {
- src := `package p; type S struct{T}`
+func mustParse(t *testing.T, src string) *ast.File {
f, err := parser.ParseFile(fset, "", src, 0)
if err != nil {
t.Fatal(err)
}
-
+ return f
+}
+func TestIssue5770(t *testing.T) {
+ f := mustParse(t, `package p; type S struct{T}`)
conf := Config{Importer: importer.Default()}
- _, err = conf.Check(f.Name.Name, fset, []*ast.File{f}, nil) // do not crash
+ _, err := conf.Check(f.Name.Name, fset, []*ast.File{f}, nil) // do not crash
want := "undeclared name: T"
if err == nil || !strings.Contains(err.Error(), want) {
t.Errorf("got: %v; want: %s", err, want)
_ = (interface{})("foo")
_ = (interface{})(nil)
)`
- f, err := parser.ParseFile(fset, "", src, 0)
- if err != nil {
- t.Fatal(err)
- }
+ f := mustParse(t, src)
var conf Config
types := make(map[ast.Expr]TypeAndValue)
- _, err = conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Types: types})
+ _, err := conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Types: types})
if err != nil {
t.Fatal(err)
}
return 0
}
`
- f, err := parser.ParseFile(fset, "", src, 0)
- if err != nil {
- t.Fatal(err)
- }
+ f := mustParse(t, src)
var conf Config
types := make(map[ast.Expr]TypeAndValue)
- _, err = conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Types: types})
+ _, err := conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Types: types})
if err != nil {
t.Fatal(err)
}
func (T) m() (res bool) { return }
type T struct{} // receiver type after method declaration
`
- f, err := parser.ParseFile(fset, "", src, 0)
- if err != nil {
- t.Fatal(err)
- }
+ f := mustParse(t, src)
var conf Config
defs := make(map[*ast.Ident]Object)
- _, err = conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Defs: defs})
+ _, err := conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Defs: defs})
if err != nil {
t.Fatal(err)
}
_, _, _ = x, y, z // uses x, y, z
}
`
+ f := mustParse(t, src)
+
const want = `L3 defs func p._()
L4 defs const w untyped int
L5 defs var x int
L7 uses var y int
L7 uses var z int`
- f, err := parser.ParseFile(fset, "", src, 0)
- if err != nil {
- t.Fatal(err)
- }
-
// don't abort at the first error
conf := Config{Error: func(err error) { t.Log(err) }}
defs := make(map[*ast.Ident]Object)
uses := make(map[*ast.Ident]Object)
- _, err = conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Defs: defs, Uses: uses})
+ _, err := conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Defs: defs, Uses: uses})
if s := fmt.Sprint(err); !strings.HasSuffix(s, "cannot assign to w") {
t.Errorf("Check: unexpected error: %s", s)
}
}
`
f := func(test, src string) {
- f, err := parser.ParseFile(fset, "", src, 0)
- if err != nil {
- t.Fatal(err)
- }
+ f := mustParse(t, src)
cfg := Config{Importer: importer.Default()}
info := Info{Uses: make(map[*ast.Ident]Object)}
- _, err = cfg.Check("main", fset, []*ast.File{f}, &info)
+ _, err := cfg.Check("main", fset, []*ast.File{f}, &info)
if err != nil {
t.Fatal(err)
}
}
func TestIssue22525(t *testing.T) {
- src := `package p; func f() { var a, b, c, d, e int }`
- f, err := parser.ParseFile(fset, "", src, 0)
- if err != nil {
- t.Fatal(err)
- }
+ f := mustParse(t, `package p; func f() { var a, b, c, d, e int }`)
got := "\n"
conf := Config{Error: func(err error) { got += err.Error() + "\n" }}
`struct { *I }`,
`struct { a int; b Missing; *Missing }`,
} {
- f, err := parser.ParseFile(fset, "", prefix+src, 0)
- if err != nil {
- t.Fatal(err)
- }
+ f := mustParse(t, prefix+src)
cfg := Config{Importer: importer.Default(), Error: func(err error) {}}
info := &Info{Types: make(map[ast.Expr]TypeAndValue)}
- _, err = cfg.Check(f.Name.Name, fset, []*ast.File{f}, info)
+ _, err := cfg.Check(f.Name.Name, fset, []*ast.File{f}, info)
if err != nil {
if _, ok := err.(Error); !ok {
t.Fatal(err)
// compute original file ASTs
var orig [len(sources)]*ast.File
for i, src := range sources {
- f, err := parser.ParseFile(fset, "", src, 0)
- if err != nil {
- t.Fatal(err)
- }
- orig[i] = f
+ orig[i] = mustParse(t, src)
}
// run the test for all order permutations of the incoming files
t.Fatalf("%s.Lookup: got %q (%p); want %q (%p)", it, obj, obj, want, want)
}
}
+
+func TestIssue29029(t *testing.T) {
+ f1 := mustParse(t, `package p; type A interface { M() }`)
+ f2 := mustParse(t, `package p; var B interface { A }`)
+
+ // printInfo prints the *Func definitions recorded in info, one *Func per line.
+ printInfo := func(info *Info) string {
+ var buf bytes.Buffer
+ for _, obj := range info.Defs {
+ if fn, ok := obj.(*Func); ok {
+ fmt.Fprintln(&buf, fn)
+ }
+ }
+ return buf.String()
+ }
+
+ // The *Func (method) definitions for package p must be the same
+ // independent on whether f1 and f2 are type-checked together, or
+ // incrementally.
+
+ // type-check together
+ var conf Config
+ info := &Info{Defs: make(map[*ast.Ident]Object)}
+ check := NewChecker(&conf, fset, NewPackage("", "p"), info)
+ if err := check.Files([]*ast.File{f1, f2}); err != nil {
+ t.Fatal(err)
+ }
+ want := printInfo(info)
+
+ // type-check incrementally
+ info = &Info{Defs: make(map[*ast.Ident]Object)}
+ check = NewChecker(&conf, fset, NewPackage("", "p"), info)
+ if err := check.Files([]*ast.File{f1}); err != nil {
+ t.Fatal(err)
+ }
+ if err := check.Files([]*ast.File{f2}); err != nil {
+ t.Fatal(err)
+ }
+ got := printInfo(info)
+
+ if got != want {
+ t.Errorf("\ngot : %swant: %s", got, want)
+ }
+}