mirror of
https://github.com/golang/go.git
synced 2025-05-05 15:43:04 +00:00
internal/lsp: add version and bug commands
Also log gopls version information on startup in server mode. Change-Id: If7bf85d19f993430709b1fae83083e6fdfe1b2ca Reviewed-on: https://go-review.googlesource.com/c/tools/+/175199 Run-TryBot: Ian Cottrell <iancottrell@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Rebecca Stambler <rstambler@golang.org>
This commit is contained in:
parent
90441677ad
commit
44dd571771
1
internal/lsp/browser/README.md
Normal file
1
internal/lsp/browser/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
This package is a copy of cmd/internal/browser from the go distribution
|
67
internal/lsp/browser/browser.go
Normal file
67
internal/lsp/browser/browser.go
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
// Copyright 2016 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 browser provides utilities for interacting with users' browsers.
|
||||||
|
package browser
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"runtime"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Commands returns a list of possible commands to use to open a url.
|
||||||
|
func Commands() [][]string {
|
||||||
|
var cmds [][]string
|
||||||
|
if exe := os.Getenv("BROWSER"); exe != "" {
|
||||||
|
cmds = append(cmds, []string{exe})
|
||||||
|
}
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "darwin":
|
||||||
|
cmds = append(cmds, []string{"/usr/bin/open"})
|
||||||
|
case "windows":
|
||||||
|
cmds = append(cmds, []string{"cmd", "/c", "start"})
|
||||||
|
default:
|
||||||
|
if os.Getenv("DISPLAY") != "" {
|
||||||
|
// xdg-open is only for use in a desktop environment.
|
||||||
|
cmds = append(cmds, []string{"xdg-open"})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cmds = append(cmds,
|
||||||
|
[]string{"chrome"},
|
||||||
|
[]string{"google-chrome"},
|
||||||
|
[]string{"chromium"},
|
||||||
|
[]string{"firefox"},
|
||||||
|
)
|
||||||
|
return cmds
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open tries to open url in a browser and reports whether it succeeded.
|
||||||
|
func Open(url string) bool {
|
||||||
|
for _, args := range Commands() {
|
||||||
|
cmd := exec.Command(args[0], append(args[1:], url)...)
|
||||||
|
if cmd.Start() == nil && appearsSuccessful(cmd, 3*time.Second) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// appearsSuccessful reports whether the command appears to have run successfully.
|
||||||
|
// If the command runs longer than the timeout, it's deemed successful.
|
||||||
|
// If the command runs within the timeout, it's deemed successful if it exited cleanly.
|
||||||
|
func appearsSuccessful(cmd *exec.Cmd, timeout time.Duration) bool {
|
||||||
|
errc := make(chan error, 1)
|
||||||
|
go func() {
|
||||||
|
errc <- cmd.Wait()
|
||||||
|
}()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-time.After(timeout):
|
||||||
|
return true
|
||||||
|
case err := <-errc:
|
||||||
|
return err == nil
|
||||||
|
}
|
||||||
|
}
|
@ -118,9 +118,11 @@ func (app *Application) Run(ctx context.Context, args ...string) error {
|
|||||||
func (app *Application) commands() []tool.Application {
|
func (app *Application) commands() []tool.Application {
|
||||||
return []tool.Application{
|
return []tool.Application{
|
||||||
&app.Serve,
|
&app.Serve,
|
||||||
|
&bug{},
|
||||||
&check{app: app},
|
&check{app: app},
|
||||||
&format{app: app},
|
&format{app: app},
|
||||||
&query{app: app},
|
&query{app: app},
|
||||||
|
&version{app: app},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
84
internal/lsp/cmd/info.go
Normal file
84
internal/lsp/cmd/info.go
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
// 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 cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"golang.org/x/tools/internal/lsp"
|
||||||
|
"golang.org/x/tools/internal/lsp/browser"
|
||||||
|
)
|
||||||
|
|
||||||
|
// version implements the version command.
|
||||||
|
type version struct {
|
||||||
|
app *Application
|
||||||
|
}
|
||||||
|
|
||||||
|
// bug implements the bug command.
|
||||||
|
type bug struct{}
|
||||||
|
|
||||||
|
func (v *version) Name() string { return "version" }
|
||||||
|
func (v *version) Usage() string { return "" }
|
||||||
|
func (v *version) ShortHelp() string { return "print the gopls version information" }
|
||||||
|
func (v *version) DetailedHelp(f *flag.FlagSet) {
|
||||||
|
fmt.Fprint(f.Output(), ``)
|
||||||
|
f.PrintDefaults()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *bug) Name() string { return "bug" }
|
||||||
|
func (b *bug) Usage() string { return "" }
|
||||||
|
func (b *bug) ShortHelp() string { return "report a bug in gopls" }
|
||||||
|
func (b *bug) DetailedHelp(f *flag.FlagSet) {
|
||||||
|
fmt.Fprint(f.Output(), ``)
|
||||||
|
f.PrintDefaults()
|
||||||
|
}
|
||||||
|
|
||||||
|
const goplsBugPrefix = "gopls: "
|
||||||
|
const goplsBugHeader = `Please answer these questions before submitting your issue. Thanks!
|
||||||
|
|
||||||
|
#### What did you do?
|
||||||
|
If possible, provide a recipe for reproducing the error.
|
||||||
|
A complete runnable program is good.
|
||||||
|
A link on play.golang.org is better.
|
||||||
|
A failing unit test is the best.
|
||||||
|
|
||||||
|
#### What did you expect to see?
|
||||||
|
|
||||||
|
|
||||||
|
#### What did you see instead?
|
||||||
|
|
||||||
|
|
||||||
|
`
|
||||||
|
|
||||||
|
// Run collects some basic information and then prepares an issue ready to
|
||||||
|
// be reported.
|
||||||
|
func (b *bug) Run(ctx context.Context, args ...string) error {
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
fmt.Fprint(buf, goplsBugHeader)
|
||||||
|
lsp.PrintVersionInfo(buf, true, true)
|
||||||
|
body := buf.String()
|
||||||
|
title := strings.Join(args, " ")
|
||||||
|
if !strings.HasPrefix(title, goplsBugPrefix) {
|
||||||
|
title = goplsBugPrefix + title
|
||||||
|
}
|
||||||
|
if !browser.Open("https://github.com/golang/go/issues/new?title=" + url.QueryEscape(title) + "&body=" + url.QueryEscape(body)) {
|
||||||
|
fmt.Print("Please file a new issue at golang.org/issue/new using this template:\n\n")
|
||||||
|
fmt.Print(body)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
@ -5,6 +5,7 @@
|
|||||||
package lsp
|
package lsp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
@ -139,6 +140,9 @@ func (s *Server) initialized(ctx context.Context, params *protocol.InitializedPa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
PrintVersionInfo(buf, true, false)
|
||||||
|
s.log.Infof(ctx, "%s", buf)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
16
internal/lsp/info.1.11.go
Normal file
16
internal/lsp/info.1.11.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
// +build !go1.12
|
||||||
|
|
||||||
|
package lsp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
func printBuildInfo(w io.Writer, verbose bool) {
|
||||||
|
fmt.Fprintf(w, "no module information, gopls not build with go 1.11 or earlier\n")
|
||||||
|
}
|
38
internal/lsp/info.go
Normal file
38
internal/lsp/info.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
// +build go1.12
|
||||||
|
|
||||||
|
package lsp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"runtime/debug"
|
||||||
|
)
|
||||||
|
|
||||||
|
func printBuildInfo(w io.Writer, verbose bool) {
|
||||||
|
if info, ok := debug.ReadBuildInfo(); ok {
|
||||||
|
fmt.Fprintf(w, "%v\n", info.Path)
|
||||||
|
printModuleInfo(w, &info.Main)
|
||||||
|
if verbose {
|
||||||
|
for _, dep := range info.Deps {
|
||||||
|
printModuleInfo(w, dep)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(w, "no module information, gopls not built in module mode\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func printModuleInfo(w io.Writer, m *debug.Module) {
|
||||||
|
fmt.Fprintf(w, " %s@%s", m.Path, m.Version)
|
||||||
|
if m.Sum != "" {
|
||||||
|
fmt.Fprintf(w, " %s", m.Sum)
|
||||||
|
}
|
||||||
|
if m.Replace != nil {
|
||||||
|
fmt.Fprintf(w, " => %v", m.Replace.Path)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, "\n")
|
||||||
|
}
|
@ -34,7 +34,6 @@ func (s *Server) didChange(ctx context.Context, params *protocol.DidChangeTextDo
|
|||||||
}
|
}
|
||||||
text = change.Text
|
text = change.Text
|
||||||
}
|
}
|
||||||
s.log.Debugf(ctx, "didChange: %s", params.TextDocument.URI)
|
|
||||||
return s.cacheAndDiagnose(ctx, span.NewURI(params.TextDocument.URI), text)
|
return s.cacheAndDiagnose(ctx, span.NewURI(params.TextDocument.URI), text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,12 +7,45 @@ package lsp
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os/exec"
|
||||||
|
|
||||||
"golang.org/x/tools/internal/lsp/protocol"
|
"golang.org/x/tools/internal/lsp/protocol"
|
||||||
"golang.org/x/tools/internal/lsp/source"
|
"golang.org/x/tools/internal/lsp/source"
|
||||||
"golang.org/x/tools/internal/span"
|
"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 newColumnMap(ctx context.Context, v source.View, uri span.URI) (source.File, *protocol.ColumnMapper, error) {
|
func newColumnMap(ctx context.Context, v source.View, uri span.URI) (source.File, *protocol.ColumnMapper, error) {
|
||||||
f, err := v.GetFile(ctx, uri)
|
f, err := v.GetFile(ctx, uri)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user