Skip to content

Commit

Permalink
internal/lsp/source: return all field funcs from outgoing callhierarchy
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
leitzler authored and stamblerre committed Jan 5, 2021
1 parent a548c3f commit c658f99
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 5 deletions.
14 changes: 10 additions & 4 deletions internal/lsp/source/call_hierarchy.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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
}
Expand All @@ -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,
Expand Down
25 changes: 24 additions & 1 deletion internal/lsp/testdata/callhierarchy/callhierarchy.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,22 @@ 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()
g()
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")
Expand All @@ -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")
}

0 comments on commit c658f99

Please sign in to comment.