mirror of https://github.com/golang/go.git
internal/lsp/source: return all field funcs from outgoing callhierarchy
Outgoing callhierarchy didn't handle different functions defined as field in a struct as separate functions since they were declared by the same AST node. This change adds the identifier name to the key, so that a function must share both declaration node and name to be considered "the same". Fixes golang/go#43456 Change-Id: Ifbced98f2e8fc3a303834f7cefbae66829b68d27 Reviewed-on: https://go-review.googlesource.com/c/tools/+/280618 Trust: Pontus Leitzler <leitzler@gmail.com> Run-TryBot: Pontus Leitzler <leitzler@gmail.com> gopls-CI: kokoro <noreply+kokoro@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Rebecca Stambler <rstambler@golang.org>
This commit is contained in:
parent
6c3993fd31
commit
b8e0803c79
|
|
@ -247,8 +247,14 @@ func collectCallExpressions(fset *token.FileSet, mapper *protocol.ColumnMapper,
|
|||
// toProtocolOutgoingCalls returns an array of protocol.CallHierarchyOutgoingCall for ast call expressions.
|
||||
// Calls to the same function are assigned to the same declaration.
|
||||
func toProtocolOutgoingCalls(ctx context.Context, snapshot Snapshot, fh FileHandle, callRanges []protocol.Range) ([]protocol.CallHierarchyOutgoingCall, error) {
|
||||
// multiple calls could be made to the same function
|
||||
var outgoingCalls = map[ast.Node]*protocol.CallHierarchyOutgoingCall{}
|
||||
// Multiple calls could be made to the same function, defined by "same declaration
|
||||
// AST node & same idenfitier name" to provide a unique identifier key even when
|
||||
// the func is declared in a struct or interface.
|
||||
type key struct {
|
||||
decl ast.Node
|
||||
name string
|
||||
}
|
||||
outgoingCalls := map[key]*protocol.CallHierarchyOutgoingCall{}
|
||||
for _, callRange := range callRanges {
|
||||
identifier, err := Identifier(ctx, snapshot, fh, callRange.Start)
|
||||
if err != nil {
|
||||
|
|
@ -263,7 +269,7 @@ func toProtocolOutgoingCalls(ctx context.Context, snapshot Snapshot, fh FileHand
|
|||
continue
|
||||
}
|
||||
|
||||
if outgoingCall, ok := outgoingCalls[identifier.Declaration.node]; ok {
|
||||
if outgoingCall, ok := outgoingCalls[key{identifier.Declaration.node, identifier.Name}]; ok {
|
||||
outgoingCall.FromRanges = append(outgoingCall.FromRanges, callRange)
|
||||
continue
|
||||
}
|
||||
|
|
@ -277,7 +283,7 @@ func toProtocolOutgoingCalls(ctx context.Context, snapshot Snapshot, fh FileHand
|
|||
return nil, err
|
||||
}
|
||||
|
||||
outgoingCalls[identifier.Declaration.node] = &protocol.CallHierarchyOutgoingCall{
|
||||
outgoingCalls[key{identifier.Declaration.node, identifier.Name}] = &protocol.CallHierarchyOutgoingCall{
|
||||
To: protocol.CallHierarchyItem{
|
||||
Name: identifier.Name,
|
||||
Kind: protocol.Function,
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ var x = func() { //@mark(hierarchyLiteral, "func"),mark(hierarchyLiteralOut, "x"
|
|||
}
|
||||
|
||||
// D is exported to test incoming/outgoing calls across packages
|
||||
func D() { //@mark(hierarchyD, "D"),incomingcalls(hierarchyD, hierarchyA, hierarchyB, hierarchyC, hierarchyLiteral, incomingA),outgoingcalls(hierarchyD, hierarchyE, hierarchyF, hierarchyG, hierarchyLiteralOut, outgoingB, hierarchyFoo)
|
||||
func D() { //@mark(hierarchyD, "D"),incomingcalls(hierarchyD, hierarchyA, hierarchyB, hierarchyC, hierarchyLiteral, incomingA),outgoingcalls(hierarchyD, hierarchyE, hierarchyF, hierarchyG, hierarchyLiteralOut, outgoingB, hierarchyFoo, hierarchyH, hierarchyI, hierarchyJ, hierarchyK)
|
||||
e()
|
||||
x()
|
||||
F()
|
||||
|
|
@ -34,6 +34,14 @@ func D() { //@mark(hierarchyD, "D"),incomingcalls(hierarchyD, hierarchyA, hierar
|
|||
outgoing.B()
|
||||
foo := func() {} //@mark(hierarchyFoo, "foo"),incomingcalls(hierarchyFoo, hierarchyD),outgoingcalls(hierarchyFoo)
|
||||
foo()
|
||||
|
||||
var i Interface = impl{}
|
||||
i.H()
|
||||
i.I()
|
||||
|
||||
s := Struct{}
|
||||
s.J()
|
||||
s.K()
|
||||
}
|
||||
|
||||
func e() {} //@mark(hierarchyE, "e")
|
||||
|
|
@ -42,3 +50,18 @@ func e() {} //@mark(hierarchyE, "e")
|
|||
func F() {} //@mark(hierarchyF, "F")
|
||||
|
||||
func g() {} //@mark(hierarchyG, "g")
|
||||
|
||||
type Interface interface {
|
||||
H() //@mark(hierarchyH, "H")
|
||||
I() //@mark(hierarchyI, "I")
|
||||
}
|
||||
|
||||
type impl struct{}
|
||||
|
||||
func (i impl) H() {}
|
||||
func (i impl) I() {}
|
||||
|
||||
type Struct struct {
|
||||
J func() //@mark(hierarchyJ, "J")
|
||||
K func() //@mark(hierarchyK, "K")
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue