1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
|
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ssa_test
import (
"go/ast"
"go/parser"
"go/token"
"go/types"
"testing"
"golang.org/x/tools/go/ssa"
"golang.org/x/tools/go/ssa/ssautil"
)
// Tests that MethodValue returns the expected method.
func TestMethodValue(t *testing.T) {
input := `
package p
type I interface{ M() }
type S int
func (S) M() {}
type R[T any] struct{ S }
var i I
var s S
var r R[string]
func selections[T any]() {
_ = i.M
_ = s.M
_ = r.M
var v R[T]
_ = v.M
}
`
// Parse the file.
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, "input.go", input, 0)
if err != nil {
t.Error(err)
return
}
// Build an SSA program from the parsed file.
p, info, err := ssautil.BuildPackage(&types.Config{}, fset,
types.NewPackage("p", ""), []*ast.File{f}, ssa.SanityCheckFunctions)
if err != nil {
t.Error(err)
return
}
// Collect all of the *types.Selection in the function "selections".
var selections []*types.Selection
for _, decl := range f.Decls {
if fn, ok := decl.(*ast.FuncDecl); ok && fn.Name.Name == "selections" {
for _, stmt := range fn.Body.List {
if assign, ok := stmt.(*ast.AssignStmt); ok {
sel := assign.Rhs[0].(*ast.SelectorExpr)
selections = append(selections, info.Selections[sel])
}
}
}
}
wants := map[string]string{
"method (p.S) M()": "(p.S).M",
"method (p.R[string]) M()": "(p.R[string]).M",
"method (p.I) M()": "nil", // interface
"method (p.R[T]) M()": "nil", // parameterized
}
if len(wants) != len(selections) {
t.Fatalf("Wanted %d selections. got %d", len(wants), len(selections))
}
for _, selection := range selections {
var got string
if m := p.Prog.MethodValue(selection); m != nil {
got = m.String()
} else {
got = "nil"
}
if want := wants[selection.String()]; want != got {
t.Errorf("p.Prog.MethodValue(%s) expected %q. got %q", selection, want, got)
}
}
}
|