[gopls-release-branch.0.5] internal/lsp: print the go version only once the view is created

Printing the Go version without the session's go command runner means
that we may not find the right Go version. Also, panicking when we
cannot find a go command is not useful to the user--show the error as a
view initialization error instead.

Fixes golang/go#41701

Change-Id: I0e0753da9795b1c78331db1faecd27c2bfcee9b4
Reviewed-on: https://go-review.googlesource.com/c/tools/+/258312
Trust: Rebecca Stambler <rstambler@golang.org>
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
(cherry picked from commit 66e72d03b26e448b1d379376a19a702497da54aa)
Reviewed-on: https://go-review.googlesource.com/c/tools/+/258517
diff --git a/internal/lsp/cache/view.go b/internal/lsp/cache/view.go
index 3768001..ae60250 100644
--- a/internal/lsp/cache/view.go
+++ b/internal/lsp/cache/view.go
@@ -359,8 +359,26 @@
 		}
 
 	}
-	fmt.Fprintf(w, "go env for %v\n(root %s)\n(valid build configuration = %v)\n(build flags: %v)\n",
-		v.folder.Filename(), v.rootURI.Filename(), v.hasValidBuildConfiguration, buildFlags)
+	goVersion, err := v.session.gocmdRunner.Run(ctx, gocommand.Invocation{
+		Verb:       "version",
+		BuildFlags: buildFlags,
+		Env:        env,
+		WorkingDir: v.rootURI.Filename(),
+	})
+	if err != nil {
+		return err
+	}
+	fmt.Fprintf(w, `go env for %v
+(root %s)
+(go version %s)
+(valid build configuration = %v)
+(build flags: %v)
+`,
+		v.folder.Filename(),
+		v.rootURI.Filename(),
+		goVersion.String(),
+		v.hasValidBuildConfiguration,
+		buildFlags)
 	for k, v := range fullEnv {
 		fmt.Fprintf(w, "%s=%s\n", k, v)
 	}
diff --git a/internal/lsp/debug/info.go b/internal/lsp/debug/info.go
index b3cc357..e7034af 100644
--- a/internal/lsp/debug/info.go
+++ b/internal/lsp/debug/info.go
@@ -10,8 +10,6 @@
 	"fmt"
 	"io"
 	"strings"
-
-	"golang.org/x/tools/internal/gocommand"
 )
 
 type PrintMode int
@@ -48,17 +46,6 @@
 	section(w, mode, "Build info", func() {
 		printBuildInfo(w, true, mode)
 	})
-	fmt.Fprint(w, "\n")
-	section(w, mode, "Go info", func() {
-		gocmdRunner := &gocommand.Runner{}
-		version, err := gocmdRunner.Run(ctx, gocommand.Invocation{
-			Verb: "version",
-		})
-		if err != nil {
-			panic(err)
-		}
-		fmt.Fprintln(w, version.String())
-	})
 }
 
 func section(w io.Writer, mode PrintMode, title string, body func()) {
diff --git a/internal/lsp/general.go b/internal/lsp/general.go
index 78b8e0a..ce03ec2 100644
--- a/internal/lsp/general.go
+++ b/internal/lsp/general.go
@@ -18,7 +18,6 @@
 	"golang.org/x/tools/internal/event"
 	"golang.org/x/tools/internal/jsonrpc2"
 	"golang.org/x/tools/internal/lsp/debug"
-	"golang.org/x/tools/internal/lsp/debug/tag"
 	"golang.org/x/tools/internal/lsp/protocol"
 	"golang.org/x/tools/internal/lsp/source"
 	"golang.org/x/tools/internal/span"
@@ -147,12 +146,6 @@
 	options := s.session.Options()
 	defer func() { s.session.SetOptions(options) }()
 
-	// TODO: this event logging may be unnecessary.
-	// The version info is included in the initialize response.
-	buf := &bytes.Buffer{}
-	debug.PrintVersionInfo(ctx, buf, true, debug.PlainText)
-	event.Log(ctx, buf.String())
-
 	if err := s.addFolders(ctx, s.pendingFolders); err != nil {
 		return err
 	}
@@ -199,7 +192,7 @@
 			continue
 		}
 		work := s.progress.start(ctx, "Setting up workspace", "Loading packages...", nil, nil)
-		view, snapshot, release, err := s.addView(ctx, folder.Name, uri)
+		snapshot, release, err := s.addView(ctx, folder.Name, uri)
 		if err != nil {
 			viewErrors[uri] = err
 			work.end(fmt.Sprintf("Error loading packages: %s", err))
@@ -219,8 +212,8 @@
 
 		// Print each view's environment.
 		buf := &bytes.Buffer{}
-		if err := view.WriteEnv(ctx, buf); err != nil {
-			event.Error(ctx, "failed to write environment", err, tag.Directory.Of(view.Folder().Filename()))
+		if err := snapshot.View().WriteEnv(ctx, buf); err != nil {
+			viewErrors[uri] = err
 			continue
 		}
 		event.Log(ctx, buf.String())
diff --git a/internal/lsp/workspace.go b/internal/lsp/workspace.go
index 6d77d92..72123a2 100644
--- a/internal/lsp/workspace.go
+++ b/internal/lsp/workspace.go
@@ -26,18 +26,19 @@
 	return s.addFolders(ctx, event.Added)
 }
 
-func (s *Server) addView(ctx context.Context, name string, uri span.URI) (source.View, source.Snapshot, func(), error) {
+func (s *Server) addView(ctx context.Context, name string, uri span.URI) (source.Snapshot, func(), error) {
 	s.stateMu.Lock()
 	state := s.state
 	s.stateMu.Unlock()
 	if state < serverInitialized {
-		return nil, nil, func() {}, errors.Errorf("addView called before server initialized")
+		return nil, func() {}, errors.Errorf("addView called before server initialized")
 	}
 	options := s.session.Options().Clone()
 	if err := s.fetchConfig(ctx, name, uri, options); err != nil {
-		return nil, nil, func() {}, err
+		return nil, func() {}, err
 	}
-	return s.session.NewView(ctx, name, uri, options)
+	_, snapshot, release, err := s.session.NewView(ctx, name, uri, options)
+	return snapshot, release, err
 }
 
 func (s *Server) didChangeConfiguration(ctx context.Context, changed interface{}) error {