diff --git a/internal/lsp/cmd/info.go b/internal/lsp/cmd/info.go index 2514405061c..90244643f2d 100644 --- a/internal/lsp/cmd/info.go +++ b/internal/lsp/cmd/info.go @@ -13,8 +13,8 @@ import ( "os" "strings" - "golang.org/x/tools/internal/lsp" "golang.org/x/tools/internal/lsp/browser" + "golang.org/x/tools/internal/lsp/debug" ) // version implements the version command. @@ -36,7 +36,7 @@ func (v *version) DetailedHelp(f *flag.FlagSet) { // Run collects some basic information and then prepares an issue ready to // be reported. func (v *version) Run(ctx context.Context, args ...string) error { - lsp.PrintVersionInfo(os.Stdout, v.app.Verbose, false) + debug.PrintVersionInfo(os.Stdout, v.app.Verbose, debug.PlainText) return nil } @@ -70,7 +70,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) - lsp.PrintVersionInfo(buf, true, true) + debug.PrintVersionInfo(buf, true, debug.Markdown) body := buf.String() title := strings.Join(args, " ") if !strings.HasPrefix(title, goplsBugPrefix) { diff --git a/internal/lsp/info.1.11.go b/internal/lsp/debug/info.1.11.go similarity index 78% rename from internal/lsp/info.1.11.go rename to internal/lsp/debug/info.1.11.go index ac4128f0a37..b29a15705fc 100644 --- a/internal/lsp/info.1.11.go +++ b/internal/lsp/debug/info.1.11.go @@ -4,13 +4,13 @@ // +build !go1.12 -package lsp +package debug import ( "fmt" "io" ) -func printBuildInfo(w io.Writer, verbose bool) { +func printBuildInfo(w io.Writer, verbose bool, mode PrintMode) { fmt.Fprintf(w, "no module information, gopls not built with go 1.11 or earlier\n") } diff --git a/internal/lsp/info.go b/internal/lsp/debug/info.1.12.go similarity index 74% rename from internal/lsp/info.go rename to internal/lsp/debug/info.1.12.go index 476ebb8b42b..70856f6cbbf 100644 --- a/internal/lsp/info.go +++ b/internal/lsp/debug/info.1.12.go @@ -4,7 +4,7 @@ // +build go1.12 -package lsp +package debug import ( "fmt" @@ -12,13 +12,13 @@ import ( "runtime/debug" ) -func printBuildInfo(w io.Writer, verbose bool) { +func printBuildInfo(w io.Writer, verbose bool, mode PrintMode) { if info, ok := debug.ReadBuildInfo(); ok { fmt.Fprintf(w, "%v\n", info.Path) - printModuleInfo(w, &info.Main) + printModuleInfo(w, &info.Main, mode) if verbose { for _, dep := range info.Deps { - printModuleInfo(w, dep) + printModuleInfo(w, dep, mode) } } } else { @@ -26,7 +26,7 @@ func printBuildInfo(w io.Writer, verbose bool) { } } -func printModuleInfo(w io.Writer, m *debug.Module) { +func printModuleInfo(w io.Writer, m *debug.Module, mode PrintMode) { fmt.Fprintf(w, " %s@%s", m.Path, m.Version) if m.Sum != "" { fmt.Fprintf(w, " %s", m.Sum) diff --git a/internal/lsp/debug/info.go b/internal/lsp/debug/info.go new file mode 100644 index 00000000000..4173a91c793 --- /dev/null +++ b/internal/lsp/debug/info.go @@ -0,0 +1,58 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package debug + +import ( + "fmt" + "io" + "os/exec" + "strings" +) + +type PrintMode int + +const ( + PlainText = PrintMode(iota) + Markdown + HTML +) + +// This writes the version and environment information to a writer. +func PrintVersionInfo(w io.Writer, verbose bool, mode PrintMode) { + if !verbose { + printBuildInfo(w, false, mode) + return + } + section(w, mode, "Build info", func() { + printBuildInfo(w, true, mode) + }) + 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() + }) +} + +func section(w io.Writer, mode PrintMode, title string, body func()) { + switch mode { + case PlainText: + fmt.Fprintln(w, title) + fmt.Fprintln(w, strings.Repeat("-", len(title))) + body() + case Markdown: + fmt.Fprintf(w, "#### %s\n\n```\n", title) + body() + fmt.Fprintf(w, "```\n") + case HTML: + fmt.Fprintf(w, "

%s

\n
\n", title)
+		body()
+		fmt.Fprint(w, "
\n") + } +} diff --git a/internal/lsp/debug/serve.go b/internal/lsp/debug/serve.go index bbe34e0747c..c5a1bbdf5a9 100644 --- a/internal/lsp/debug/serve.go +++ b/internal/lsp/debug/serve.go @@ -5,6 +5,7 @@ package debug import ( + "bytes" "context" "html/template" "log" @@ -16,6 +17,13 @@ import ( func init() { http.HandleFunc("/", Render(mainTmpl, nil)) http.HandleFunc("/debug/", Render(debugTmpl, nil)) + http.HandleFunc("/info", Render(infoTmpl, getInfo)) +} + +func getInfo(r *http.Request) interface{} { + buf := &bytes.Buffer{} + PrintVersionInfo(buf, true, HTML) + return template.HTML(buf.String()) } // Serve starts and runs a debug server in the background. @@ -64,9 +72,12 @@ var BaseTemplate = template.Must(template.New("").Parse(` -{{template "title"}} -
-{{block "body" .Data}} +Main +Info +Debug +
+

{{template "title" .}}

+{{block "body" .}} Unknown page {{end}} @@ -76,7 +87,13 @@ Unknown page var mainTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(` {{define "title"}}GoPls server information{{end}} {{define "body"}} -Debug +{{end}} +`)) + +var infoTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(` +{{define "title"}}GoPls version information{{end}} +{{define "body"}} +{{.}} {{end}} `)) diff --git a/internal/lsp/general.go b/internal/lsp/general.go index 6091519a68f..8ddbe595453 100644 --- a/internal/lsp/general.go +++ b/internal/lsp/general.go @@ -12,6 +12,7 @@ import ( "path" "golang.org/x/tools/internal/jsonrpc2" + "golang.org/x/tools/internal/lsp/debug" "golang.org/x/tools/internal/lsp/protocol" "golang.org/x/tools/internal/lsp/source" "golang.org/x/tools/internal/span" @@ -140,7 +141,7 @@ func (s *Server) initialized(ctx context.Context, params *protocol.InitializedPa } } buf := &bytes.Buffer{} - PrintVersionInfo(buf, true, false) + debug.PrintVersionInfo(buf, true, debug.PlainText) s.session.Logger().Infof(ctx, "%s", buf) return nil } diff --git a/internal/lsp/util.go b/internal/lsp/util.go index b931078ee97..427ff0780c6 100644 --- a/internal/lsp/util.go +++ b/internal/lsp/util.go @@ -7,45 +7,12 @@ package lsp import ( "context" "fmt" - "io" - "os/exec" "golang.org/x/tools/internal/lsp/protocol" "golang.org/x/tools/internal/lsp/source" "golang.org/x/tools/internal/span" ) -// This writes the version and environment information to a writer. -func PrintVersionInfo(w io.Writer, verbose bool, markdown bool) { - if !verbose { - printBuildInfo(w, false) - return - } - fmt.Fprint(w, "#### Build info\n\n") - if markdown { - fmt.Fprint(w, "```\n") - } - printBuildInfo(w, true) - fmt.Fprint(w, "\n") - if markdown { - fmt.Fprint(w, "```\n") - } - fmt.Fprint(w, "\n#### Go info\n\n") - if markdown { - fmt.Fprint(w, "```\n") - } - cmd := exec.Command("go", "version") - cmd.Stdout = w - cmd.Run() - fmt.Fprint(w, "\n") - cmd = exec.Command("go", "env") - cmd.Stdout = w - cmd.Run() - if markdown { - fmt.Fprint(w, "```\n") - } -} - func getSourceFile(ctx context.Context, v source.View, uri span.URI) (source.File, *protocol.ColumnMapper, error) { f, err := v.GetFile(ctx, uri) if err != nil {