Skip to content

Commit

Permalink
go/callgraph/static: adds tests for (instantiated) generics
Browse files Browse the repository at this point in the history
Updates golang/go#48525

Change-Id: If460999912fecad626ec8cbace251dd6a0358196
Reviewed-on: https://go-review.googlesource.com/c/tools/+/402695
Reviewed-by: Tim King <taking@google.com>
Reviewed-by: Alan Donovan <alan@alandonovan.net>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Zvonimir Pavlinovic <zpavlinovic@google.com>
  • Loading branch information
zpavlinovic committed Apr 28, 2022
1 parent a37ba14 commit 60b4456
Showing 1 changed file with 85 additions and 31 deletions.
116 changes: 85 additions & 31 deletions go/callgraph/static/static_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ import (
"golang.org/x/tools/go/callgraph"
"golang.org/x/tools/go/callgraph/static"
"golang.org/x/tools/go/loader"
"golang.org/x/tools/go/ssa"
"golang.org/x/tools/go/ssa/ssautil"
"golang.org/x/tools/internal/typeparams"
)

const input = `package P
Expand Down Expand Up @@ -47,42 +49,94 @@ func h()
var unknown bool
`

func TestStatic(t *testing.T) {
conf := loader.Config{ParserMode: parser.ParseComments}
f, err := conf.ParseFile("P.go", input)
if err != nil {
t.Fatal(err)
}
const genericsInput = `package P
conf.CreateFromFiles("P", f)
iprog, err := conf.Load()
if err != nil {
t.Fatal(err)
}
type I interface {
F()
}
P := iprog.Created[0].Pkg
type A struct{}
prog := ssautil.CreateProgram(iprog, 0)
prog.Build()
func (a A) F() {}
cg := static.CallGraph(prog)
type B struct{}
var edges []string
callgraph.GraphVisitEdges(cg, func(e *callgraph.Edge) error {
edges = append(edges, fmt.Sprintf("%s -> %s",
e.Caller.Func.RelString(P),
e.Callee.Func.RelString(P)))
return nil
})
sort.Strings(edges)
func (b B) F() {}
want := []string{
"(*C).f -> (C).f",
"f -> (C).f",
"f -> f$1",
"f -> g",
}
if !reflect.DeepEqual(edges, want) {
t.Errorf("Got edges %v, want %v", edges, want)
func instantiated[X I](x X) {
x.F()
}
func Bar() {}
func f(h func(), a A, b B) {
h()
instantiated[A](a)
instantiated[B](b)
}
`

func TestStatic(t *testing.T) {
for _, e := range []struct {
input string
want []string
// typeparams must be true if input uses type parameters
typeparams bool
}{
{input, []string{
"(*C).f -> (C).f",
"f -> (C).f",
"f -> f$1",
"f -> g",
}, false},
{genericsInput, []string{
"(*A).F -> (A).F",
"(*B).F -> (B).F",
"f -> instantiated[[P.A]]",
"f -> instantiated[[P.B]]",
"instantiated[[P.A]] -> (A).F",
"instantiated[[P.B]] -> (B).F",
}, true},
} {
if e.typeparams && !typeparams.Enabled {
// Skip tests with type parameters when the build
// environment is not supporting any.
continue
}

conf := loader.Config{ParserMode: parser.ParseComments}
f, err := conf.ParseFile("P.go", e.input)
if err != nil {
t.Error(err)
continue
}

conf.CreateFromFiles("P", f)
iprog, err := conf.Load()
if err != nil {
t.Error(err)
continue
}

P := iprog.Created[0].Pkg

prog := ssautil.CreateProgram(iprog, ssa.InstantiateGenerics)
prog.Build()

cg := static.CallGraph(prog)

var edges []string
callgraph.GraphVisitEdges(cg, func(e *callgraph.Edge) error {
edges = append(edges, fmt.Sprintf("%s -> %s",
e.Caller.Func.RelString(P),
e.Callee.Func.RelString(P)))
return nil
})
sort.Strings(edges)

if !reflect.DeepEqual(edges, e.want) {
t.Errorf("Got edges %v, want %v", edges, e.want)
}
}
}

0 comments on commit 60b4456

Please sign in to comment.