From b1c90890d22a5a9bc99e32cfc8b18d82da044b52 Mon Sep 17 00:00:00 2001 From: Pontus Leitzler Date: Fri, 25 Dec 2020 11:51:51 +0100 Subject: [PATCH] internal/lsp/source: do not panic in "var func" outgoing callhierarchy When trying to get outgoing call hierarchy from an var func like: func main() { foo := func() {} foo() } gopls crashed with a panic. This change makes it return an empty call hierarchy instead. It also adds support for testing outgoing calls where the expected result is 0 items, to be able to test this change. Fixes golang/go#43376 Change-Id: Icd91bf54cb4fbd5203f5865f0ff9d81365c27d5d Reviewed-on: https://go-review.googlesource.com/c/tools/+/279469 Trust: Pontus Leitzler gopls-CI: kokoro Run-TryBot: Pontus Leitzler Reviewed-by: Rebecca Stambler --- internal/lsp/source/call_hierarchy.go | 4 +++- .../testdata/callhierarchy/callhierarchy.go | 4 +++- internal/lsp/testdata/summary.txt.golden | 2 +- internal/lsp/tests/tests.go | 21 +++++++------------ 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/internal/lsp/source/call_hierarchy.go b/internal/lsp/source/call_hierarchy.go index 7a521edf20..c7dfea5f68 100644 --- a/internal/lsp/source/call_hierarchy.go +++ b/internal/lsp/source/call_hierarchy.go @@ -193,7 +193,9 @@ func OutgoingCalls(ctx context.Context, snapshot Snapshot, fh FileHandle, pos pr if _, ok := identifier.Declaration.obj.Type().Underlying().(*types.Signature); !ok { return nil, nil } - + if identifier.Declaration.node == nil { + return nil, nil + } if len(identifier.Declaration.MappedRange) == 0 { return nil, nil } diff --git a/internal/lsp/testdata/callhierarchy/callhierarchy.go b/internal/lsp/testdata/callhierarchy/callhierarchy.go index 95cb471e9d..4f45a28b82 100644 --- a/internal/lsp/testdata/callhierarchy/callhierarchy.go +++ b/internal/lsp/testdata/callhierarchy/callhierarchy.go @@ -26,12 +26,14 @@ 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) +func D() { //@mark(hierarchyD, "D"),incomingcalls(hierarchyD, hierarchyA, hierarchyB, hierarchyC, hierarchyLiteral, incomingA),outgoingcalls(hierarchyD, hierarchyE, hierarchyF, hierarchyG, hierarchyLiteralOut, outgoingB, hierarchyFoo) e() x() F() g() outgoing.B() + foo := func() {} //@mark(hierarchyFoo, "foo"),incomingcalls(hierarchyFoo, hierarchyD),outgoingcalls(hierarchyFoo) + foo() } func e() {} //@mark(hierarchyE, "e") diff --git a/internal/lsp/testdata/summary.txt.golden b/internal/lsp/testdata/summary.txt.golden index a2bb47340b..4c35b25e4e 100644 --- a/internal/lsp/testdata/summary.txt.golden +++ b/internal/lsp/testdata/summary.txt.golden @@ -1,5 +1,5 @@ -- summary -- -CallHierarchyCount = 1 +CallHierarchyCount = 2 CodeLensCount = 5 CompletionsCount = 258 CompletionSnippetCount = 88 diff --git a/internal/lsp/tests/tests.go b/internal/lsp/tests/tests.go index 3ee0e65076..bc44f36d2e 100644 --- a/internal/lsp/tests/tests.go +++ b/internal/lsp/tests/tests.go @@ -1131,6 +1131,9 @@ func (data *Data) collectIncomingCalls(src span.Span, calls []span.Span) { } func (data *Data) collectOutgoingCalls(src span.Span, calls []span.Span) { + if data.CallHierarchy[src] == nil { + data.CallHierarchy[src] = &CallHierarchyResult{} + } for _, call := range calls { m, err := data.Mapper(call.URI()) if err != nil { @@ -1141,19 +1144,11 @@ func (data *Data) collectOutgoingCalls(src span.Span, calls []span.Span) { data.t.Fatal(err) } // we're only comparing protocol.range - if data.CallHierarchy[src] != nil { - data.CallHierarchy[src].OutgoingCalls = append(data.CallHierarchy[src].OutgoingCalls, - protocol.CallHierarchyItem{ - URI: protocol.DocumentURI(call.URI()), - Range: rng, - }) - } else { - data.CallHierarchy[src] = &CallHierarchyResult{ - OutgoingCalls: []protocol.CallHierarchyItem{ - {URI: protocol.DocumentURI(call.URI()), Range: rng}, - }, - } - } + data.CallHierarchy[src].OutgoingCalls = append(data.CallHierarchy[src].OutgoingCalls, + protocol.CallHierarchyItem{ + URI: protocol.DocumentURI(call.URI()), + Range: rng, + }) } }