...

Source file src/golang.org/x/tools/go/ssa/methods_test.go

Documentation: golang.org/x/tools/go/ssa

     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  }
    93  

View as plain text