golang.org/x/tools@v0.21.1-0.20240520172518-788d39e776b1/go/ssa/methods_test.go (about) 1 // Copyright 2022 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. 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 // Tests that MethodValue returns the expected method. 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 // Parse the file. 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 // Build an SSA program from the parsed file. 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 // Collect all of the *types.Selection in the function "selections". 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", // interface 76 "method (p.R[T]) M()": "nil", // parameterized 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 }