Skip to content

Commit 6fc5d0b

Browse files
committed
internal/lsp: print view-specific environment
For debugging purposes, we print the output of `go env` on start. Now, we print a view-specific `go env`, which will helps us when debugging multi-project workspaces. Additional information included: the folder of the view, if the view has a valid build configuration, and the build flags for the view. Updates golang/go#37978 Change-Id: Iadffd46f8ac5410971558a304b8bbcb2f9bdbcc3 Reviewed-on: https://go-review.googlesource.com/c/tools/+/225137 Run-TryBot: Rebecca Stambler <[email protected]> Reviewed-by: Heschi Kreinick <[email protected]>
1 parent a5e5fed commit 6fc5d0b

File tree

7 files changed

+55
-20
lines changed

7 files changed

+55
-20
lines changed

internal/lsp/cache/load.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ func (s *snapshot) load(ctx context.Context, scopes ...interface{}) error {
9393
return ctx.Err()
9494
}
9595

96-
event.Print(ctx, "go/packages.Load", tag.Snapshot.Of(s.ID()), tag.Query.Of(query), tag.PackageCount.Of(len(pkgs)))
96+
event.Print(ctx, "go/packages.Load", tag.Snapshot.Of(s.ID()), tag.Directory.Of(cfg.Dir), tag.Query.Of(query), tag.PackageCount.Of(len(pkgs)))
9797
if len(pkgs) == 0 {
9898
return err
9999
}

internal/lsp/cache/view.go

+18
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,24 @@ func (v *view) buildBuiltinPackage(ctx context.Context, goFiles []string) error
262262
return nil
263263
}
264264

265+
func (v *view) WriteEnv(ctx context.Context, w io.Writer) error {
266+
env, buildFlags := v.env()
267+
// TODO(rstambler): We could probably avoid running this by saving the
268+
// output on original create, but I'm not sure if it's worth it.
269+
inv := gocommand.Invocation{
270+
Verb: "env",
271+
Env: env,
272+
WorkingDir: v.Folder().Filename(),
273+
}
274+
stdout, err := inv.Run(ctx)
275+
if err != nil {
276+
return err
277+
}
278+
fmt.Fprintf(w, "go env for %v\n(valid build configuration = %v)\n(build flags: %v)\n", v.folder.Filename(), v.hasValidBuildConfiguration, buildFlags)
279+
fmt.Fprint(w, stdout)
280+
return nil
281+
}
282+
265283
func (v *view) RunProcessEnvFunc(ctx context.Context, fn func(*imports.Options) error) error {
266284
v.importsMu.Lock()
267285
defer v.importsMu.Unlock()

internal/lsp/cmd/info.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func (v *version) DetailedHelp(f *flag.FlagSet) {
3232

3333
// Run prints version information to stdout.
3434
func (v *version) Run(ctx context.Context, args ...string) error {
35-
debug.PrintVersionInfo(os.Stdout, v.app.Verbose, debug.PlainText)
35+
debug.PrintVersionInfo(ctx, os.Stdout, v.app.Verbose, debug.PlainText)
3636
return nil
3737
}
3838

@@ -69,7 +69,7 @@ A failing unit test is the best.
6969
func (b *bug) Run(ctx context.Context, args ...string) error {
7070
buf := &bytes.Buffer{}
7171
fmt.Fprint(buf, goplsBugHeader)
72-
debug.PrintVersionInfo(buf, true, debug.Markdown)
72+
debug.PrintVersionInfo(ctx, buf, true, debug.Markdown)
7373
body := buf.String()
7474
title := strings.Join(args, " ")
7575
if !strings.HasPrefix(title, goplsBugPrefix) {

internal/lsp/debug/info.go

+17-14
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@
66
package debug
77

88
import (
9+
"context"
910
"fmt"
1011
"io"
11-
"os/exec"
1212
"strings"
13+
14+
"golang.org/x/tools/internal/gocommand"
1315
)
1416

1517
type PrintMode int
@@ -24,21 +26,21 @@ const (
2426
var Version = "master"
2527

2628
// PrintServerInfo writes HTML debug info to w for the Instance.
27-
func (i *Instance) PrintServerInfo(w io.Writer) {
29+
func (i *Instance) PrintServerInfo(ctx context.Context, w io.Writer) {
2830
section(w, HTML, "Server Instance", func() {
2931
fmt.Fprintf(w, "Start time: %v\n", i.StartTime)
3032
fmt.Fprintf(w, "LogFile: %s\n", i.Logfile)
3133
fmt.Fprintf(w, "Working directory: %s\n", i.Workdir)
3234
fmt.Fprintf(w, "Address: %s\n", i.ServerAddress)
3335
fmt.Fprintf(w, "Debug address: %s\n", i.DebugAddress)
3436
})
35-
PrintVersionInfo(w, true, HTML)
37+
PrintVersionInfo(ctx, w, true, HTML)
3638
}
3739

38-
// PrintVersionInfo writes version and environment information to w, using the
39-
// output format specified by mode. verbose controls whether additional
40-
// information is written, including section headers.
41-
func PrintVersionInfo(w io.Writer, verbose bool, mode PrintMode) {
40+
// PrintVersionInfo writes version information to w, using the output format
41+
// specified by mode. verbose controls whether additional information is
42+
// written, including section headers.
43+
func PrintVersionInfo(ctx context.Context, w io.Writer, verbose bool, mode PrintMode) {
4244
if !verbose {
4345
printBuildInfo(w, false, mode)
4446
return
@@ -48,13 +50,14 @@ func PrintVersionInfo(w io.Writer, verbose bool, mode PrintMode) {
4850
})
4951
fmt.Fprint(w, "\n")
5052
section(w, mode, "Go info", func() {
51-
cmd := exec.Command("go", "version")
52-
cmd.Stdout = w
53-
cmd.Run()
54-
fmt.Fprint(w, "\n")
55-
cmd = exec.Command("go", "env")
56-
cmd.Stdout = w
57-
cmd.Run()
53+
i := &gocommand.Invocation{
54+
Verb: "version",
55+
}
56+
version, err := i.Run(ctx)
57+
if err != nil {
58+
panic(err)
59+
}
60+
fmt.Fprintln(w, version.String())
5861
})
5962
}
6063

internal/lsp/debug/serve.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ func (i *Instance) getFile(r *http.Request) interface{} {
376376

377377
func (i *Instance) getInfo(r *http.Request) interface{} {
378378
buf := &bytes.Buffer{}
379-
i.PrintServerInfo(buf)
379+
i.PrintServerInfo(r.Context(), buf)
380380
return template.HTML(buf.String())
381381
}
382382

internal/lsp/general.go

+12-2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313

1414
"golang.org/x/tools/internal/jsonrpc2"
1515
"golang.org/x/tools/internal/lsp/debug"
16+
"golang.org/x/tools/internal/lsp/debug/tag"
1617
"golang.org/x/tools/internal/lsp/protocol"
1718
"golang.org/x/tools/internal/lsp/source"
1819
"golang.org/x/tools/internal/span"
@@ -156,7 +157,7 @@ func (s *Server) initialized(ctx context.Context, params *protocol.InitializedPa
156157
}
157158

158159
buf := &bytes.Buffer{}
159-
debug.PrintVersionInfo(buf, true, debug.PlainText)
160+
debug.PrintVersionInfo(ctx, buf, true, debug.PlainText)
160161
event.Print(ctx, buf.String())
161162

162163
s.addFolders(ctx, s.pendingFolders)
@@ -171,11 +172,20 @@ func (s *Server) addFolders(ctx context.Context, folders []protocol.WorkspaceFol
171172

172173
for _, folder := range folders {
173174
uri := span.URIFromURI(folder.URI)
174-
_, snapshot, err := s.addView(ctx, folder.Name, uri)
175+
view, snapshot, err := s.addView(ctx, folder.Name, uri)
175176
if err != nil {
176177
viewErrors[uri] = err
177178
continue
178179
}
180+
// Print each view's environment.
181+
buf := &bytes.Buffer{}
182+
if err := view.WriteEnv(ctx, buf); err != nil {
183+
event.Error(ctx, "failed to write environment", err, tag.Directory.Of(view.Folder()))
184+
continue
185+
}
186+
event.Print(ctx, buf.String())
187+
188+
// Diagnose the newly created view.
179189
go s.diagnoseDetached(snapshot)
180190
}
181191
if len(viewErrors) > 0 {

internal/lsp/source/view.go

+4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"go/ast"
1111
"go/token"
1212
"go/types"
13+
"io"
1314

1415
"golang.org/x/mod/modfile"
1516
"golang.org/x/tools/go/analysis"
@@ -125,6 +126,9 @@ type View interface {
125126
// Ignore returns true if this file should be ignored by this view.
126127
Ignore(span.URI) bool
127128

129+
// WriteEnv writes the view-specific environment to the io.Writer.
130+
WriteEnv(ctx context.Context, w io.Writer) error
131+
128132
// RunProcessEnvFunc runs fn with the process env for this snapshot's view.
129133
// Note: the process env contains cached module and filesystem state.
130134
RunProcessEnvFunc(ctx context.Context, fn func(*imports.Options) error) error

0 commit comments

Comments
 (0)