internal/lsp: handle nil pointer with import shortcut = link
It makes more sense to handle the import shortcut behavior at a higher
level anyway, so pull it out of findIdentifier and add a test for the
configuration.
Fixes golang/go#44189
Change-Id: I96f08c7def154f6761efa727d693fdfb2fb722ab
Reviewed-on: https://go-review.googlesource.com/c/tools/+/290789
Trust: Rebecca Stambler <rstambler@golang.org>
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
(cherry picked from commit fca8992500401369a4ef891b85f7570d77d080e0)
Reviewed-on: https://go-review.googlesource.com/c/tools/+/292729
Reviewed-by: Robert Findley <rfindley@google.com>
diff --git a/gopls/go.mod b/gopls/go.mod
index 50dc2a4..93a91a0 100644
--- a/gopls/go.mod
+++ b/gopls/go.mod
@@ -14,3 +14,5 @@
mvdan.cc/gofumpt v0.1.0
mvdan.cc/xurls/v2 v2.2.0
)
+
+replace golang.org/x/tools => ../
diff --git a/gopls/internal/regtest/misc/definition_test.go b/gopls/internal/regtest/misc/definition_test.go
index a5e220c..48b7617 100644
--- a/gopls/internal/regtest/misc/definition_test.go
+++ b/gopls/internal/regtest/misc/definition_test.go
@@ -11,6 +11,7 @@
. "golang.org/x/tools/gopls/internal/regtest"
+ "golang.org/x/tools/internal/lsp/fake"
"golang.org/x/tools/internal/lsp/tests"
)
@@ -134,3 +135,47 @@
}
})
}
+
+func TestImportShortcut(t *testing.T) {
+ const mod = `
+-- go.mod --
+module mod.com
+
+go 1.12
+-- main.go --
+package main
+
+import "fmt"
+
+func main() {}
+`
+ for _, tt := range []struct {
+ wantLinks int
+ wantDef bool
+ importShortcut string
+ }{
+ {1, false, "Link"},
+ {0, true, "Definition"},
+ {1, true, "Both"},
+ } {
+ t.Run(tt.importShortcut, func(t *testing.T) {
+ WithOptions(
+ EditorConfig{
+ ImportShortcut: tt.importShortcut,
+ },
+ ).Run(t, mod, func(t *testing.T, env *Env) {
+ env.OpenFile("main.go")
+ file, pos := env.GoToDefinition("main.go", env.RegexpSearch("main.go", `"fmt"`))
+ if !tt.wantDef && (file != "" || pos != (fake.Pos{})) {
+ t.Fatalf("expected no definition, got one: %s:%v", file, pos)
+ } else if tt.wantDef && file == "" && pos == (fake.Pos{}) {
+ t.Fatalf("expected definition, got none")
+ }
+ links := env.DocumentLink("main.go")
+ if len(links) != tt.wantLinks {
+ t.Fatalf("expected %v links, got %v", tt.wantLinks, len(links))
+ }
+ })
+ })
+ }
+}
diff --git a/internal/lsp/definition.go b/internal/lsp/definition.go
index acd5ac2..46643e1 100644
--- a/internal/lsp/definition.go
+++ b/internal/lsp/definition.go
@@ -21,7 +21,9 @@
if err != nil {
return nil, err
}
-
+ if !snapshot.View().Options().ImportShortcut.ShowDefinition() {
+ return nil, nil
+ }
var locations []protocol.Location
for _, ref := range ident.Declaration.MappedRange {
decRange, err := ref.Range()
diff --git a/internal/lsp/fake/editor.go b/internal/lsp/fake/editor.go
index 0764e6e..96410d9 100644
--- a/internal/lsp/fake/editor.go
+++ b/internal/lsp/fake/editor.go
@@ -109,6 +109,8 @@
DirectoryFilters []string
VerboseOutput bool
+
+ ImportShortcut string
}
// NewEditor Creates a new Editor.
@@ -238,6 +240,10 @@
config["verboseOutput"] = true
}
+ if e.Config.ImportShortcut != "" {
+ config["importShortcut"] = e.Config.ImportShortcut
+ }
+
// TODO(rFindley): change to the new settings name once it is no longer
// designated experimental.
config["experimentalDiagnosticsDelay"] = "10ms"
diff --git a/internal/lsp/source/identifier.go b/internal/lsp/source/identifier.go
index 362604e..e648893 100644
--- a/internal/lsp/source/identifier.go
+++ b/internal/lsp/source/identifier.go
@@ -98,10 +98,7 @@
// Handle import specs separately, as there is no formal position for a
// package declaration.
if result, err := importSpec(snapshot, pkg, file, pos); result != nil || err != nil {
- if snapshot.View().Options().ImportShortcut.ShowDefinition() {
- return result, err
- }
- return nil, nil
+ return result, err
}
path := pathEnclosingObjNode(file, pos)
if path == nil {