internal/lsp: add a reg test to test "go mod init"

This change adds a RunGoCommand function to the workspace, which will
allow us to test how gopls responds when a certain go command is
executed. Add a test that checks behavior after "go mod init" runs.

Change-Id: I679249c1654b136d44187397b4196b8a10b5615e
Reviewed-on: https://go-review.googlesource.com/c/tools/+/226478
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
diff --git a/internal/lsp/diagnostics.go b/internal/lsp/diagnostics.go
index b98d901..1519f32 100644
--- a/internal/lsp/diagnostics.go
+++ b/internal/lsp/diagnostics.go
@@ -82,7 +82,7 @@
 	// Diagnose all of the packages in the workspace.
 	wsPackages, err := snapshot.WorkspacePackages(ctx)
 	if err != nil {
-		event.Error(ctx, "failed to load workspace packages, skipping diagnostics", err, tag.Snapshot.Of(snapshot.ID()), tag.Directory.Of(snapshot.View().Folder))
+		event.Error(ctx, "failed to load workspace packages, skipping diagnostics", err, tag.Snapshot.Of(snapshot.ID()), tag.Directory.Of(snapshot.View().Folder()))
 		return nil
 	}
 	for _, ph := range wsPackages {
diff --git a/internal/lsp/fake/workspace.go b/internal/lsp/fake/workspace.go
index f1b39d1..446216a 100644
--- a/internal/lsp/fake/workspace.go
+++ b/internal/lsp/fake/workspace.go
@@ -13,6 +13,7 @@
 	"strings"
 	"sync"
 
+	"golang.org/x/tools/internal/gocommand"
 	"golang.org/x/tools/internal/lsp/protocol"
 	"golang.org/x/tools/internal/span"
 	"golang.org/x/tools/txtar"
@@ -149,6 +150,32 @@
 	return nil
 }
 
+// RunGoCommand executes a go command in the workspace.
+func (w *Workspace) RunGoCommand(ctx context.Context, verb string, args ...string) error {
+	inv := gocommand.Invocation{
+		Verb:       verb,
+		Args:       args,
+		WorkingDir: w.workdir,
+	}
+	_, stderr, _, err := inv.RunRaw(ctx)
+	if err != nil {
+		return err
+	}
+	// Hardcoded "file watcher": If the command executed was "go mod init",
+	// send a file creation event for a go.mod in the working directory.
+	if strings.HasPrefix(stderr.String(), "go: creating new go.mod") {
+		modpath := filepath.Join(w.workdir, "go.mod")
+		w.sendEvents(ctx, []FileEvent{{
+			Path: modpath,
+			ProtocolEvent: protocol.FileEvent{
+				URI:  toURI(modpath),
+				Type: protocol.Created,
+			},
+		}})
+	}
+	return nil
+}
+
 func (w *Workspace) sendEvents(ctx context.Context, evts []FileEvent) {
 	w.watcherMu.Lock()
 	watchers := make([]func(context.Context, []FileEvent), len(w.watchers))
diff --git a/internal/lsp/regtest/diagnostics_test.go b/internal/lsp/regtest/diagnostics_test.go
index 7123db3..52f1a3d 100644
--- a/internal/lsp/regtest/diagnostics_test.go
+++ b/internal/lsp/regtest/diagnostics_test.go
@@ -152,34 +152,46 @@
 func main() {
 	bob.Hello()
 }
+-- bob/bob.go --
+package bob
+
+func Hello() {
+	var x int
+}
 `
 
 // TestNoMod confirms that gopls continues to work when a user adds a go.mod
 // file to their workspace.
 func TestNoMod(t *testing.T) {
-	runner.Run(t, noMod, func(env *Env) {
-		env.Await(
-			env.DiagnosticAtRegexp("main.go", `"mod.com/bob"`),
-		)
-		env.CreateBuffer("bob/bob.go", `package bob
+	t.Run("manual", func(t *testing.T) {
+		runner.Run(t, noMod, func(env *Env) {
+			env.Await(
+				env.DiagnosticAtRegexp("main.go", `"mod.com/bob"`),
+			)
+			env.CreateBuffer("go.mod", `module mod.com
 
-func Hello() {
-	var x int
-}
+	go 1.12
 `)
-		env.Await(
-			env.DiagnosticAtRegexp("bob/bob.go", "x"),
-		)
-		// Save this file because otherwise, the go command will not be able to
-		// resolve mod.com/bob as a package.
-		env.SaveBuffer("bob/bob.go")
-		env.CreateBuffer("go.mod", `module mod.com
-
-go 1.12
-`)
-		env.SaveBuffer("go.mod")
-		env.Await(
-			EmptyDiagnostics("main.go"),
-		)
+			env.SaveBuffer("go.mod")
+			env.Await(
+				EmptyDiagnostics("main.go"),
+				env.DiagnosticAtRegexp("bob/bob.go", "x"),
+			)
+		})
 	})
+	t.Run("initialized", func(t *testing.T) {
+		runner.Run(t, noMod, func(env *Env) {
+			env.Await(
+				env.DiagnosticAtRegexp("main.go", `"mod.com/bob"`),
+			)
+			if err := env.W.RunGoCommand(env.Ctx, "mod", "init", "mod.com"); err != nil {
+				t.Fatal(err)
+			}
+			env.Await(
+				EmptyDiagnostics("main.go"),
+				env.DiagnosticAtRegexp("bob/bob.go", "x"),
+			)
+		})
+	})
+
 }