mirror of https://github.com/golang/go.git
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 <rstambler@golang.org> Reviewed-by: Heschi Kreinick <heschi@google.com>
This commit is contained in:
parent
a5e5fedfe7
commit
6fc5d0bc36
|
|
@ -93,7 +93,7 @@ func (s *snapshot) load(ctx context.Context, scopes ...interface{}) error {
|
|||
return ctx.Err()
|
||||
}
|
||||
|
||||
event.Print(ctx, "go/packages.Load", tag.Snapshot.Of(s.ID()), tag.Query.Of(query), tag.PackageCount.Of(len(pkgs)))
|
||||
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)))
|
||||
if len(pkgs) == 0 {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -262,6 +262,24 @@ func (v *view) buildBuiltinPackage(ctx context.Context, goFiles []string) error
|
|||
return nil
|
||||
}
|
||||
|
||||
func (v *view) WriteEnv(ctx context.Context, w io.Writer) error {
|
||||
env, buildFlags := v.env()
|
||||
// TODO(rstambler): We could probably avoid running this by saving the
|
||||
// output on original create, but I'm not sure if it's worth it.
|
||||
inv := gocommand.Invocation{
|
||||
Verb: "env",
|
||||
Env: env,
|
||||
WorkingDir: v.Folder().Filename(),
|
||||
}
|
||||
stdout, err := inv.Run(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(w, "go env for %v\n(valid build configuration = %v)\n(build flags: %v)\n", v.folder.Filename(), v.hasValidBuildConfiguration, buildFlags)
|
||||
fmt.Fprint(w, stdout)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *view) RunProcessEnvFunc(ctx context.Context, fn func(*imports.Options) error) error {
|
||||
v.importsMu.Lock()
|
||||
defer v.importsMu.Unlock()
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ func (v *version) DetailedHelp(f *flag.FlagSet) {
|
|||
|
||||
// Run prints version information to stdout.
|
||||
func (v *version) Run(ctx context.Context, args ...string) error {
|
||||
debug.PrintVersionInfo(os.Stdout, v.app.Verbose, debug.PlainText)
|
||||
debug.PrintVersionInfo(ctx, os.Stdout, v.app.Verbose, debug.PlainText)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -69,7 +69,7 @@ A failing unit test is the best.
|
|||
func (b *bug) Run(ctx context.Context, args ...string) error {
|
||||
buf := &bytes.Buffer{}
|
||||
fmt.Fprint(buf, goplsBugHeader)
|
||||
debug.PrintVersionInfo(buf, true, debug.Markdown)
|
||||
debug.PrintVersionInfo(ctx, buf, true, debug.Markdown)
|
||||
body := buf.String()
|
||||
title := strings.Join(args, " ")
|
||||
if !strings.HasPrefix(title, goplsBugPrefix) {
|
||||
|
|
|
|||
|
|
@ -6,10 +6,12 @@
|
|||
package debug
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/tools/internal/gocommand"
|
||||
)
|
||||
|
||||
type PrintMode int
|
||||
|
|
@ -24,7 +26,7 @@ const (
|
|||
var Version = "master"
|
||||
|
||||
// PrintServerInfo writes HTML debug info to w for the Instance.
|
||||
func (i *Instance) PrintServerInfo(w io.Writer) {
|
||||
func (i *Instance) PrintServerInfo(ctx context.Context, w io.Writer) {
|
||||
section(w, HTML, "Server Instance", func() {
|
||||
fmt.Fprintf(w, "Start time: %v\n", i.StartTime)
|
||||
fmt.Fprintf(w, "LogFile: %s\n", i.Logfile)
|
||||
|
|
@ -32,13 +34,13 @@ func (i *Instance) PrintServerInfo(w io.Writer) {
|
|||
fmt.Fprintf(w, "Address: %s\n", i.ServerAddress)
|
||||
fmt.Fprintf(w, "Debug address: %s\n", i.DebugAddress)
|
||||
})
|
||||
PrintVersionInfo(w, true, HTML)
|
||||
PrintVersionInfo(ctx, w, true, HTML)
|
||||
}
|
||||
|
||||
// PrintVersionInfo writes version and environment information to w, using the
|
||||
// output format specified by mode. verbose controls whether additional
|
||||
// information is written, including section headers.
|
||||
func PrintVersionInfo(w io.Writer, verbose bool, mode PrintMode) {
|
||||
// PrintVersionInfo writes version information to w, using the output format
|
||||
// specified by mode. verbose controls whether additional information is
|
||||
// written, including section headers.
|
||||
func PrintVersionInfo(ctx context.Context, w io.Writer, verbose bool, mode PrintMode) {
|
||||
if !verbose {
|
||||
printBuildInfo(w, false, mode)
|
||||
return
|
||||
|
|
@ -48,13 +50,14 @@ func PrintVersionInfo(w io.Writer, verbose bool, mode PrintMode) {
|
|||
})
|
||||
fmt.Fprint(w, "\n")
|
||||
section(w, mode, "Go info", func() {
|
||||
cmd := exec.Command("go", "version")
|
||||
cmd.Stdout = w
|
||||
cmd.Run()
|
||||
fmt.Fprint(w, "\n")
|
||||
cmd = exec.Command("go", "env")
|
||||
cmd.Stdout = w
|
||||
cmd.Run()
|
||||
i := &gocommand.Invocation{
|
||||
Verb: "version",
|
||||
}
|
||||
version, err := i.Run(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Fprintln(w, version.String())
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -376,7 +376,7 @@ func (i *Instance) getFile(r *http.Request) interface{} {
|
|||
|
||||
func (i *Instance) getInfo(r *http.Request) interface{} {
|
||||
buf := &bytes.Buffer{}
|
||||
i.PrintServerInfo(buf)
|
||||
i.PrintServerInfo(r.Context(), buf)
|
||||
return template.HTML(buf.String())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import (
|
|||
|
||||
"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"
|
||||
|
|
@ -156,7 +157,7 @@ func (s *Server) initialized(ctx context.Context, params *protocol.InitializedPa
|
|||
}
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
debug.PrintVersionInfo(buf, true, debug.PlainText)
|
||||
debug.PrintVersionInfo(ctx, buf, true, debug.PlainText)
|
||||
event.Print(ctx, buf.String())
|
||||
|
||||
s.addFolders(ctx, s.pendingFolders)
|
||||
|
|
@ -171,11 +172,20 @@ func (s *Server) addFolders(ctx context.Context, folders []protocol.WorkspaceFol
|
|||
|
||||
for _, folder := range folders {
|
||||
uri := span.URIFromURI(folder.URI)
|
||||
_, snapshot, err := s.addView(ctx, folder.Name, uri)
|
||||
view, snapshot, err := s.addView(ctx, folder.Name, uri)
|
||||
if err != nil {
|
||||
viewErrors[uri] = err
|
||||
continue
|
||||
}
|
||||
// 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()))
|
||||
continue
|
||||
}
|
||||
event.Print(ctx, buf.String())
|
||||
|
||||
// Diagnose the newly created view.
|
||||
go s.diagnoseDetached(snapshot)
|
||||
}
|
||||
if len(viewErrors) > 0 {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import (
|
|||
"go/ast"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"io"
|
||||
|
||||
"golang.org/x/mod/modfile"
|
||||
"golang.org/x/tools/go/analysis"
|
||||
|
|
@ -125,6 +126,9 @@ type View interface {
|
|||
// Ignore returns true if this file should be ignored by this view.
|
||||
Ignore(span.URI) bool
|
||||
|
||||
// WriteEnv writes the view-specific environment to the io.Writer.
|
||||
WriteEnv(ctx context.Context, w io.Writer) error
|
||||
|
||||
// RunProcessEnvFunc runs fn with the process env for this snapshot's view.
|
||||
// Note: the process env contains cached module and filesystem state.
|
||||
RunProcessEnvFunc(ctx context.Context, fn func(*imports.Options) error) error
|
||||
|
|
|
|||
Loading…
Reference in New Issue