internal/lsp: warn user in case of a multi-file ad-hoc package

This change surfaces a warning to the user if they might be coding in a
multi-file ad-hoc package.

Updates golang/go#36416

Change-Id: Ifaa15a0777ea97e62c1477fb33911636b13e073e
Reviewed-on: https://go-review.googlesource.com/c/tools/+/213458
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
diff --git a/internal/lsp/source/diagnostics.go b/internal/lsp/source/diagnostics.go
index fd1259c..3a530f8 100644
--- a/internal/lsp/source/diagnostics.go
+++ b/internal/lsp/source/diagnostics.go
@@ -7,6 +7,7 @@
 import (
 	"context"
 	"fmt"
+	"strings"
 
 	"golang.org/x/tools/go/analysis"
 	"golang.org/x/tools/internal/lsp/protocol"
@@ -66,6 +67,14 @@
 	if err != nil {
 		return nil, "", err
 	}
+	// If we have a package with a single file and errors about "undeclared" symbols,
+	// we may have an ad-hoc package with multiple files. Show a warning message.
+	// TODO(golang/go#36416): Remove this when golang.org/cl/202277 is merged.
+	if warningMsg == "" && len(pkg.CompiledGoFiles()) == 1 && hasUndeclaredErrors(pkg) {
+		if warningMsg, err = checkCommonErrors(ctx, snapshot.View(), fh.Identity().URI); err != nil {
+			log.Error(ctx, "error checking common errors", err, telemetry.File.Of(fh.Identity().URI))
+		}
+	}
 	// Prepare the reports we will send for the files in this package.
 	reports := make(map[FileIdentity][]Diagnostic)
 	for _, fh := range pkg.CompiledGoFiles() {
@@ -255,3 +264,17 @@
 	}
 	return true
 }
+
+// hasUndeclaredErrors returns true if a package has a type error
+// about an undeclared symbol.
+func hasUndeclaredErrors(pkg Package) bool {
+	for _, err := range pkg.GetErrors() {
+		if err.Kind != TypeError {
+			continue
+		}
+		if strings.Contains(err.Message, "undeclared name:") {
+			return true
+		}
+	}
+	return false
+}