internal/lsp/cache: fix ignored file check

The return of IgnoreFile. We continue using go list's ignore rules,
but only apply them to the part of the path underneath the source root.

This should be fixed to include replace targets once we have them.

Change-Id: I054fee8c12fc860a279b0d0c1fd670f44d78a63f
Reviewed-on: https://go-review.googlesource.com/c/tools/+/239288
Run-TryBot: Heschi Kreinick <heschi@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Cottrell <iancottrell@google.com>
diff --git a/internal/lsp/cache/view.go b/internal/lsp/cache/view.go
index 4c27c0c..a831c17 100644
--- a/internal/lsp/cache/view.go
+++ b/internal/lsp/cache/view.go
@@ -641,6 +641,42 @@
 	return v.backgroundCtx
 }
 
+func (v *View) IgnoredFile(uri span.URI) bool {
+	filename := uri.Filename()
+	var prefixes []string
+	if v.modURI == "" {
+		for _, entry := range filepath.SplitList(v.gopath) {
+			prefixes = append(prefixes, filepath.Join(entry, "src"))
+		}
+	} else {
+		mainMod := filepath.Dir(v.modURI.Filename())
+		modCache := filepath.Join(filepath.SplitList(v.gopath)[0], "/pkg/mod")
+		prefixes = []string{mainMod, modCache}
+	}
+
+	for _, prefix := range prefixes {
+		if strings.HasPrefix(filename, prefix) {
+			return checkIgnored(filename[len(prefix):])
+		}
+	}
+	return false
+}
+
+// checkIgnored implements 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".
+func checkIgnored(suffix string) bool {
+	for _, component := range strings.Split(suffix, string(filepath.Separator)) {
+		if len(component) == 0 {
+			continue
+		}
+		if component[0] == '.' || component[0] == '_' || component == "testdata" {
+			return true
+		}
+	}
+	return false
+}
+
 func (v *View) Snapshot() source.Snapshot {
 	return v.getSnapshot()
 }
diff --git a/internal/lsp/source/diagnostics.go b/internal/lsp/source/diagnostics.go
index 9fe25d5..b244959 100644
--- a/internal/lsp/source/diagnostics.go
+++ b/internal/lsp/source/diagnostics.go
@@ -8,7 +8,6 @@
 	"context"
 	"fmt"
 	"go/ast"
-	"path/filepath"
 	"strconv"
 	"strings"
 
@@ -45,7 +44,7 @@
 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())
+		onlyIgnoredFiles = onlyIgnoredFiles && snapshot.View().IgnoredFile(pgh.File().URI())
 	}
 	if onlyIgnoredFiles {
 		return nil, false, nil
@@ -140,24 +139,6 @@
 	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 pickAnalyzers(snapshot Snapshot, hadTypeErrors bool) map[string]Analyzer {
 	analyzers := make(map[string]Analyzer)
 
diff --git a/internal/lsp/source/view.go b/internal/lsp/source/view.go
index bc15a6a..f66f82d 100644
--- a/internal/lsp/source/view.go
+++ b/internal/lsp/source/view.go
@@ -158,6 +158,10 @@
 	// IsGoPrivatePath reports whether target is a private import path, as identified
 	// by the GOPRIVATE environment variable.
 	IsGoPrivatePath(path string) bool
+
+	// IgnoredFile reports if a file would be ignored by a `go list` of the whole
+	// workspace.
+	IgnoredFile(uri span.URI) bool
 }
 
 type BuiltinPackage interface {