1
0
mirror of https://github.com/golang/go synced 2024-09-30 20:38:32 -06:00

internal/lsp: add an upgrade all dependencies codelens

This change adds an upgrade all dependencies codelens on the go.mod file if there are available upgrades.

Updates golang/go#36501

Change-Id: I86c1ae7e7a6dc01b7f5cd7eb18e5a11d96a3acc1
Reviewed-on: https://go-review.googlesource.com/c/tools/+/221108
Run-TryBot: Rohan Challa <rohan@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
This commit is contained in:
Rohan Challa 2020-02-26 14:11:30 -05:00
parent 8d77031968
commit c4f5635f10
10 changed files with 62 additions and 37 deletions

View File

@ -71,7 +71,7 @@ func NewRunner(exporter packagestest.Exporter, data *tests.Data, ctx context.Con
return r
}
func (r *runner) CodeLens(t *testing.T, spn span.Span, want []protocol.CodeLens) {
func (r *runner) CodeLens(t *testing.T, uri span.URI, want []protocol.CodeLens) {
//TODO: add command line completions tests when it works
}

View File

@ -2,6 +2,7 @@ package lsp
import (
"context"
"strings"
"golang.org/x/tools/internal/gocommand"
"golang.org/x/tools/internal/lsp/protocol"
@ -35,15 +36,15 @@ func (s *Server) executeCommand(ctx context.Context, params *protocol.ExecuteCom
return nil, errors.Errorf("expected one file URI and one dependency for call to `go get`, got %v", params.Arguments)
}
uri := protocol.DocumentURI(params.Arguments[0].(string))
deps := params.Arguments[1].(string)
snapshot, _, ok, err := s.beginFileRequest(uri, source.UnknownKind)
if !ok {
return nil, err
}
dep := params.Arguments[1].(string)
// Run "go get" on the dependency to upgrade it to the latest version.
inv := gocommand.Invocation{
Verb: "get",
Args: []string{dep},
Args: strings.Split(deps, " "),
Env: snapshot.Config(ctx).Env,
WorkingDir: snapshot.View().Folder().Filename(),
}

View File

@ -96,19 +96,19 @@ func testLSP(t *testing.T, exporter packagestest.Exporter) {
}
}
func (r *runner) CodeLens(t *testing.T, spn span.Span, want []protocol.CodeLens) {
if source.DetectLanguage("", spn.URI().Filename()) != source.Mod {
func (r *runner) CodeLens(t *testing.T, uri span.URI, want []protocol.CodeLens) {
if source.DetectLanguage("", uri.Filename()) != source.Mod {
return
}
v, err := r.server.session.ViewOf(spn.URI())
v, err := r.server.session.ViewOf(uri)
if err != nil {
t.Fatal(err)
}
got, err := mod.CodeLens(r.ctx, v.Snapshot(), spn.URI())
got, err := mod.CodeLens(r.ctx, v.Snapshot(), uri)
if err != nil {
t.Fatal(err)
}
if diff := tests.DiffCodeLens(spn.URI(), want, got); diff != "" {
if diff := tests.DiffCodeLens(uri, want, got); diff != "" {
t.Error(diff)
}
}

View File

@ -3,7 +3,9 @@ package mod
import (
"context"
"fmt"
"strings"
"golang.org/x/mod/modfile"
"golang.org/x/tools/internal/lsp/protocol"
"golang.org/x/tools/internal/lsp/source"
"golang.org/x/tools/internal/lsp/telemetry"
@ -32,6 +34,7 @@ func CodeLens(ctx context.Context, snapshot source.Snapshot, uri span.URI) ([]pr
return nil, err
}
var codelens []protocol.CodeLens
var allUpgrades []string
for _, req := range f.Require {
dep := req.Mod.Path
latest, ok := upgrades[dep]
@ -39,18 +42,7 @@ func CodeLens(ctx context.Context, snapshot source.Snapshot, uri span.URI) ([]pr
continue
}
// Get the range of the require directive.
s, e := req.Syntax.Start, req.Syntax.End
line, col, err := m.Converter.ToPosition(s.Byte)
if err != nil {
return nil, err
}
start := span.NewPoint(line, col, s.Byte)
line, col, err = m.Converter.ToPosition(e.Byte)
if err != nil {
return nil, err
}
end := span.NewPoint(line, col, e.Byte)
rng, err := m.Range(span.New(uri, start, end))
rng, err := positionsToRange(uri, m, req.Syntax.Start, req.Syntax.End)
if err != nil {
return nil, err
}
@ -62,6 +54,41 @@ func CodeLens(ctx context.Context, snapshot source.Snapshot, uri span.URI) ([]pr
Arguments: []interface{}{uri, dep},
},
})
allUpgrades = append(allUpgrades, dep)
}
// If there is at least 1 upgrade, add an "Upgrade all dependencies" to the module statement.
if module := f.Module; len(allUpgrades) > 0 && module != nil && module.Syntax != nil {
// Get the range of the module directive.
rng, err := positionsToRange(uri, m, module.Syntax.Start, module.Syntax.End)
if err != nil {
return nil, err
}
codelens = append(codelens, protocol.CodeLens{
Range: rng,
Command: protocol.Command{
Title: "Upgrade all dependencies",
Command: "upgrade.dependency",
Arguments: []interface{}{uri, strings.Join(append([]string{"-u"}, allUpgrades...), " ")},
},
})
}
return codelens, err
}
func positionsToRange(uri span.URI, m *protocol.ColumnMapper, s, e modfile.Position) (protocol.Range, error) {
line, col, err := m.Converter.ToPosition(s.Byte)
if err != nil {
return protocol.Range{}, err
}
start := span.NewPoint(line, col, s.Byte)
line, col, err = m.Converter.ToPosition(e.Byte)
if err != nil {
return protocol.Range{}, err
}
end := span.NewPoint(line, col, e.Byte)
rng, err := m.Range(span.New(uri, start, end))
if err != nil {
return protocol.Range{}, err
}
return rng, err
}

View File

@ -83,9 +83,6 @@ func (s *Server) codeLens(ctx context.Context, params *protocol.CodeLensParams)
if !ok {
return nil, err
}
if !snapshot.IsSaved(fh.Identity().URI) {
return nil, nil
}
return mod.CodeLens(ctx, snapshot, fh.Identity().URI)
}

View File

@ -894,7 +894,7 @@ func (r *runner) Link(t *testing.T, uri span.URI, wantLinks []tests.Link) {
// This is a pure LSP feature, no source level functionality to be tested.
}
func (r *runner) CodeLens(t *testing.T, spn span.Span, want []protocol.CodeLens) {
func (r *runner) CodeLens(t *testing.T, uri span.URI, want []protocol.CodeLens) {
// This is a pure LSP feature, no source level functionality to be tested.
}

View File

@ -1,4 +1,4 @@
module upgradedep
module upgradedep //@codelens("module upgradedep", "Upgrade all dependencies", "upgrade.dependency")
// TODO(microsoft/vscode-go#12): Another issue. //@link(`microsoft/vscode-go#12`, `https://github.com/microsoft/vscode-go/issues/12`)

View File

@ -1,5 +1,5 @@
-- summary --
CodeLensCount = 1
CodeLensCount = 2
CompletionsCount = 0
CompletionSnippetCount = 0
UnimportedCompletionsCount = 0

View File

@ -43,7 +43,7 @@ const (
var UpdateGolden = flag.Bool("golden", false, "Update golden files")
type CodeLens map[span.Span][]protocol.CodeLens
type CodeLens map[span.URI][]protocol.CodeLens
type Diagnostics map[span.URI][]source.Diagnostic
type CompletionItems map[token.Pos]*source.CompletionItem
type Completions map[span.Span][]Completion
@ -115,7 +115,7 @@ type Data struct {
}
type Tests interface {
CodeLens(*testing.T, span.Span, []protocol.CodeLens)
CodeLens(*testing.T, span.URI, []protocol.CodeLens)
Diagnostics(*testing.T, span.URI, []source.Diagnostic)
Completion(*testing.T, span.Span, Completion, CompletionItems)
CompletionSnippet(*testing.T, span.Span, CompletionSnippet, bool, CompletionItems)
@ -530,14 +530,14 @@ func Run(t *testing.T, tests Tests, data *Data) {
t.Run("CodeLens", func(t *testing.T) {
t.Helper()
for spn, want := range data.CodeLens {
for uri, want := range data.CodeLens {
// Check if we should skip this URI if the -modfile flag is not available.
if shouldSkip(data, spn.URI()) {
if shouldSkip(data, uri) {
continue
}
t.Run(SpanName(spn), func(t *testing.T) {
t.Run(uriName(uri), func(t *testing.T) {
t.Helper()
tests.CodeLens(t, spn, want)
tests.CodeLens(t, uri, want)
})
}
})
@ -767,7 +767,7 @@ func checkData(t *testing.T, data *Data) {
return count
}
countCodeLens := func(c map[span.Span][]protocol.CodeLens) (count int) {
countCodeLens := func(c map[span.URI][]protocol.CodeLens) (count int) {
for _, want := range c {
count += len(want)
}
@ -883,8 +883,8 @@ func (data *Data) Golden(tag string, target string, update func() ([]byte, error
}
func (data *Data) collectCodeLens(spn span.Span, title, cmd string) {
if _, ok := data.CodeLens[spn]; !ok {
data.CodeLens[spn] = []protocol.CodeLens{}
if _, ok := data.CodeLens[spn.URI()]; !ok {
data.CodeLens[spn.URI()] = []protocol.CodeLens{}
}
m, err := data.Mapper(spn.URI())
if err != nil {
@ -894,7 +894,7 @@ func (data *Data) collectCodeLens(spn span.Span, title, cmd string) {
if err != nil {
return
}
data.CodeLens[spn] = append(data.CodeLens[spn], protocol.CodeLens{
data.CodeLens[spn.URI()] = append(data.CodeLens[spn.URI()], protocol.CodeLens{
Range: rng,
Command: protocol.Command{
Title: title,

View File

@ -197,7 +197,7 @@ func DiffDiagnostics(uri span.URI, want, got []source.Diagnostic) string {
return ""
}
func summarizeDiagnostics(i int, uri span.URI, want []source.Diagnostic, got []source.Diagnostic, reason string, args ...interface{}) string {
func summarizeDiagnostics(i int, uri span.URI, want, got []source.Diagnostic, reason string, args ...interface{}) string {
msg := &bytes.Buffer{}
fmt.Fprint(msg, "diagnostics failed")
if i >= 0 {