File: methods_test.go

package info (click to toggle)
golang-golang-x-tools 1%3A0.25.0%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 22,724 kB
  • sloc: javascript: 2,027; asm: 1,645; sh: 166; yacc: 155; makefile: 49; ansic: 8
file content (92 lines) | stat: -rw-r--r-- 2,059 bytes parent folder | download | duplicates (2)
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)
		}
	}
}