gopls/internal/regtest: use gopls hooks and add a test for staticcheck

To match the actual gopls binary, use hooks.Options when creating the
regtest server.

Add a test for staticcheck diagnostics to leverage this.

For golang/go#39384

Change-Id: I52837c2b12bb586a2530343bdfae5172b08df49c
Reviewed-on: https://go-review.googlesource.com/c/tools/+/252683
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
diff --git a/gopls/internal/regtest/diagnostics_test.go b/gopls/internal/regtest/diagnostics_test.go
index 5540967..a7973fe 100644
--- a/gopls/internal/regtest/diagnostics_test.go
+++ b/gopls/internal/regtest/diagnostics_test.go
@@ -1246,3 +1246,31 @@
 		)
 	})
 }
+
+func TestStaticcheckDiagnostic(t *testing.T) {
+	const files = `
+-- go.mod --
+module mod.com
+-- main.go --
+package main
+
+import "fmt"
+
+type t struct {
+	msg string
+}
+
+func main() {
+	x := []t{t{"msg"}}
+	fmt.Println(x)
+}
+`
+
+	withOptions(
+		WithEditorConfig(fake.EditorConfig{EnableStaticcheck: true}),
+	).run(t, files, func(t *testing.T, env *Env) {
+		env.OpenFile("main.go")
+		// Staticcheck should generate a diagnostic to simplify this literal.
+		env.Await(env.DiagnosticAtRegexp("main.go", `t{"msg"}`))
+	})
+}
diff --git a/gopls/internal/regtest/runner.go b/gopls/internal/regtest/runner.go
index 15bac64..ad38463 100644
--- a/gopls/internal/regtest/runner.go
+++ b/gopls/internal/regtest/runner.go
@@ -20,6 +20,7 @@
 	"testing"
 	"time"
 
+	"golang.org/x/tools/gopls/internal/hooks"
 	"golang.org/x/tools/internal/jsonrpc2"
 	"golang.org/x/tools/internal/jsonrpc2/servertest"
 	"golang.org/x/tools/internal/lsp/cache"
@@ -315,7 +316,7 @@
 }
 
 func singletonServer(ctx context.Context, t *testing.T) jsonrpc2.StreamServer {
-	return lsprpc.NewStreamServer(cache.New(ctx, nil), false)
+	return lsprpc.NewStreamServer(cache.New(ctx, hooks.Options), false)
 }
 
 func (r *Runner) forwardedServer(ctx context.Context, t *testing.T) jsonrpc2.StreamServer {
@@ -331,7 +332,7 @@
 	if r.ts == nil {
 		ctx := context.Background()
 		ctx = debug.WithInstance(ctx, "", "off")
-		ss := lsprpc.NewStreamServer(cache.New(ctx, nil), false)
+		ss := lsprpc.NewStreamServer(cache.New(ctx, hooks.Options), false)
 		r.ts = servertest.NewTCPServer(ctx, ss, nil)
 	}
 	return r.ts
diff --git a/internal/lsp/fake/editor.go b/internal/lsp/fake/editor.go
index 567a0e9..be07339 100644
--- a/internal/lsp/fake/editor.go
+++ b/internal/lsp/fake/editor.go
@@ -81,6 +81,9 @@
 	// EditorRootPath specifies the root path of the workspace folder used when
 	// initializing gopls in the sandbox. If empty, the Workdir is used.
 	EditorRootPath string
+
+	// EnableStaticcheck enables staticcheck analyzers.
+	EnableStaticcheck bool
 }
 
 // NewEditor Creates a new Editor.
@@ -180,14 +183,15 @@
 	if e.Config.CodeLens != nil {
 		config["codelens"] = e.Config.CodeLens
 	}
-
 	if e.Config.SymbolMatcher != nil {
 		config["symbolMatcher"] = *e.Config.SymbolMatcher
 	}
-
 	if e.Config.SymbolStyle != nil {
 		config["symbolStyle"] = *e.Config.SymbolStyle
 	}
+	if e.Config.EnableStaticcheck {
+		config["staticcheck"] = true
+	}
 
 	return config
 }