1 // Copyright 2018 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.
16 "golang.org/x/tools/go/types/typeutil"
19 func TestStaticCallee(t *testing.T) {
20 const src = `package p
32 type s struct{ f func(int) }
35 type I interface{ f(int) }
37 var a struct{b struct{c s}}
40 g(x) // a declared func
41 s{}.g(x) // a concrete method
43 fmt.Println(x) // declared func, qualified identifier
49 panic(x) // a built-in
51 I(nil).f(x) // interface method
55 fset := token.NewFileSet()
56 f, err := parser.ParseFile(fset, "p.go", src, 0)
63 Uses: make(map[*ast.Ident]types.Object),
64 Selections: make(map[*ast.SelectorExpr]*types.Selection),
66 cfg := &types.Config{Importer: importer.ForCompiler(fset, "source", nil)}
67 if _, err := cfg.Check("p", fset, []*ast.File{f}, info); err != nil {
71 for _, decl := range f.Decls {
72 if decl, ok := decl.(*ast.FuncDecl); ok && strings.HasSuffix(decl.Name.Name, "calls") {
73 wantCallee := decl.Name.Name == "calls" // false within func noncalls()
74 ast.Inspect(decl.Body, func(n ast.Node) bool {
75 if call, ok := n.(*ast.CallExpr); ok {
76 fn := typeutil.StaticCallee(info, call)
77 if fn == nil && wantCallee {
78 t.Errorf("%s: StaticCallee returned nil",
79 fset.Position(call.Lparen))
80 } else if fn != nil && !wantCallee {
81 t.Errorf("%s: StaticCallee returned %s, want nil",
82 fset.Position(call.Lparen), fn)