internal/lsp: improve handling of non-Go folders
CL 244117 introduced a bug when modFile == os.DevNull: v.root is left
uninitialized, resulting in a view that appears to own all files. Fixing
that exposes a problem where opening a folder with no Go files and
GO111MODULE=on shows a popup. Skip the popup when no Go files are found.
Change-Id: I7f8b2d6fd2f954af64c3a65156ff44c649f3a5b2
Reviewed-on: https://go-review.googlesource.com/c/tools/+/248620
Run-TryBot: Heschi Kreinick <heschi@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
diff --git a/internal/lsp/cache/session.go b/internal/lsp/cache/session.go
index 083ec97..a55c770 100644
--- a/internal/lsp/cache/session.go
+++ b/internal/lsp/cache/session.go
@@ -170,6 +170,7 @@
cancel: cancel,
name: name,
folder: folder,
+ root: folder,
filesByURI: make(map[span.URI]*fileBase),
filesByBase: make(map[string][]*fileBase),
}
diff --git a/internal/lsp/cache/view.go b/internal/lsp/cache/view.go
index 48b3148..5239047 100644
--- a/internal/lsp/cache/view.go
+++ b/internal/lsp/cache/view.go
@@ -734,7 +734,6 @@
v.sumURI = span.URIFromPath(sumFilename)
}
- v.root = v.folder
if options.ExpandWorkspaceToModule && v.modURI != "" {
v.root = span.URIFromPath(filepath.Dir(v.modURI.Filename()))
}
diff --git a/internal/lsp/diagnostics.go b/internal/lsp/diagnostics.go
index 5fe9e06..17fd1da 100644
--- a/internal/lsp/diagnostics.go
+++ b/internal/lsp/diagnostics.go
@@ -8,6 +8,7 @@
"context"
"crypto/sha256"
"fmt"
+ "os"
"path/filepath"
"strings"
"sync"
@@ -317,7 +318,20 @@
func (s *Server) handleFatalErrors(ctx context.Context, snapshot source.Snapshot, modErr, loadErr error) bool {
modURI := snapshot.View().ModFile()
- // We currently only have workarounds for errors associated with modules.
+ // If the folder has no Go code in it, we shouldn't spam the user with a warning.
+ var hasGo bool
+ _ = filepath.Walk(snapshot.View().Folder().Filename(), func(path string, info os.FileInfo, err error) error {
+ if !strings.HasSuffix(info.Name(), ".go") {
+ return nil
+ }
+ hasGo = true
+ return errors.New("done")
+ })
+ if !hasGo {
+ return true
+ }
+
+ // All other workarounds are for errors associated with modules.
if modURI == "" {
return false
}
diff --git a/internal/lsp/regtest/diagnostics_test.go b/internal/lsp/regtest/diagnostics_test.go
index a200fbd..57c355c 100644
--- a/internal/lsp/regtest/diagnostics_test.go
+++ b/internal/lsp/regtest/diagnostics_test.go
@@ -541,14 +541,36 @@
CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidOpen), 1),
NoDiagnostics("a.go"),
),
- EmptyShowMessage(""),
+ NoShowMessage(),
)
// introduce an error, expect no Show Message
env.RegexpReplace("a.go", "func", "fun")
- env.Await(env.DiagnosticAtRegexp("a.go", "fun"), EmptyShowMessage(""))
+ env.Await(env.DiagnosticAtRegexp("a.go", "fun"), NoShowMessage())
})
}
+func TestNonGoFolder(t *testing.T) {
+ const files = `
+-- hello.txt --
+hi mom
+`
+ for _, go111module := range []string{"on", "off", ""} {
+ t.Run(fmt.Sprintf("GO111MODULE_%v", go111module), func(t *testing.T) {
+ withOptions(WithEditorConfig(fake.EditorConfig{
+ Env: map[string]string{"GO111MODULE": go111module},
+ })).run(t, files, func(t *testing.T, env *Env) {
+ env.OpenFile("hello.txt")
+ env.Await(
+ OnceMet(
+ CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidOpen), 1),
+ NoShowMessage(),
+ ),
+ )
+ })
+ })
+ }
+}
+
// Tests golang/go#38602.
func TestNonexistentFileDiagnostics_Issue38602(t *testing.T) {
const collision = `
diff --git a/internal/lsp/regtest/env.go b/internal/lsp/regtest/env.go
index 081d92a..a341986 100644
--- a/internal/lsp/regtest/env.go
+++ b/internal/lsp/regtest/env.go
@@ -375,11 +375,11 @@
}
}
-// EmptyShowMessage asserts that the editor has not received a ShowMessage.
-func EmptyShowMessage(title string) SimpleExpectation {
+// NoShowMessage asserts that the editor has not received a ShowMessage.
+func NoShowMessage() SimpleExpectation {
check := func(s State) (Verdict, interface{}) {
if len(s.showMessage) == 0 {
- return Met, title
+ return Met, "no ShowMessage"
}
return Unmeetable, nil
}