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