mirror of https://github.com/golang/go.git
go/callgraph/static: adds tests for (instantiated) generics
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>
This commit is contained in:
parent
a37ba1418f
commit
60b4456604
|
|
@ -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
|
||||
|
|
@ -47,42 +49,94 @@ func h()
|
|||
var unknown bool
|
||||
`
|
||||
|
||||
const genericsInput = `package P
|
||||
|
||||
type I interface {
|
||||
F()
|
||||
}
|
||||
|
||||
type A struct{}
|
||||
|
||||
func (a A) F() {}
|
||||
|
||||
type B struct{}
|
||||
|
||||
func (b B) F() {}
|
||||
|
||||
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) {
|
||||
conf := loader.Config{ParserMode: parser.ParseComments}
|
||||
f, err := conf.ParseFile("P.go", input)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
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.CreateFromFiles("P", f)
|
||||
iprog, err := conf.Load()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
conf := loader.Config{ParserMode: parser.ParseComments}
|
||||
f, err := conf.ParseFile("P.go", e.input)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
continue
|
||||
}
|
||||
|
||||
P := iprog.Created[0].Pkg
|
||||
conf.CreateFromFiles("P", f)
|
||||
iprog, err := conf.Load()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
continue
|
||||
}
|
||||
|
||||
prog := ssautil.CreateProgram(iprog, 0)
|
||||
prog.Build()
|
||||
P := iprog.Created[0].Pkg
|
||||
|
||||
cg := static.CallGraph(prog)
|
||||
prog := ssautil.CreateProgram(iprog, ssa.InstantiateGenerics)
|
||||
prog.Build()
|
||||
|
||||
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)
|
||||
cg := static.CallGraph(prog)
|
||||
|
||||
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)
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue