diff --git a/internal/lsp/regtest/diagnostics_test.go b/internal/lsp/regtest/diagnostics_test.go index ef6cb71b83..6525c2d324 100644 --- a/internal/lsp/regtest/diagnostics_test.go +++ b/internal/lsp/regtest/diagnostics_test.go @@ -803,3 +803,24 @@ func TestHello(t *testing.T) { ) }) } + +func TestIgnoredFiles(t *testing.T) { + const ws = ` +-- go.mod -- +module mod.com + +go 1.15 +-- _foo/x.go -- +package x + +var _ = foo.Bar +` + runner.Run(t, ws, func(t *testing.T, env *Env) { + env.OpenFile("_foo/x.go") + env.Await( + OnceMet( + CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidOpen), 1), + NoDiagnostics("_foo/x.go"), + )) + }) +} diff --git a/internal/lsp/source/diagnostics.go b/internal/lsp/source/diagnostics.go index e558e737bb..c29f2e07d3 100644 --- a/internal/lsp/source/diagnostics.go +++ b/internal/lsp/source/diagnostics.go @@ -8,6 +8,7 @@ import ( "context" "fmt" "go/ast" + "path/filepath" "strconv" "strings" @@ -42,6 +43,14 @@ type RelatedInformation struct { } func Diagnostics(ctx context.Context, snapshot Snapshot, ph PackageHandle, missingModules map[string]*modfile.Require, withAnalysis bool) (map[FileIdentity][]*Diagnostic, bool, error) { + onlyIgnoredFiles := true + for _, pgh := range ph.CompiledGoFiles() { + onlyIgnoredFiles = onlyIgnoredFiles && ignoreFile(pgh.File().URI().Filename()) + } + if onlyIgnoredFiles { + return nil, false, nil + } + // If we are missing dependencies, it may because the user's workspace is // not correctly configured. Report errors, if possible. var warn bool @@ -134,6 +143,24 @@ func Diagnostics(ctx context.Context, snapshot Snapshot, ph PackageHandle, missi return reports, warn, nil } +// ignoreFile is an approximation of go list's exclusion rules. go help list: +// Directory and file names that begin with "." or "_" are ignored +// by the go tool, as are directories named "testdata". +// Those rules only apply if the directory in question is beneath GOPATH +// or the module root, but we don't really have that information, so we just +// hope that nobody's messing with us. +func ignoreFile(path string) bool { + for _, component := range strings.Split(path, string(filepath.Separator)) { + if len(component) == 0 { + continue + } + if component[0] == '.' || component[0] == '_' || component == "testdata" { + return true + } + } + return false +} + func FileDiagnostics(ctx context.Context, snapshot Snapshot, uri span.URI) (FileIdentity, []*Diagnostic, error) { fh, err := snapshot.GetFile(ctx, uri) if err != nil {