mirror of
https://github.com/golang/go
synced 2024-11-18 16:44:43 -07: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:
parent
8d77031968
commit
c4f5635f10
@ -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
|
||||
}
|
||||
|
||||
|
@ -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(),
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
}
|
||||
|
||||
|
@ -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`)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
-- summary --
|
||||
CodeLensCount = 1
|
||||
CodeLensCount = 2
|
||||
CompletionsCount = 0
|
||||
CompletionSnippetCount = 0
|
||||
UnimportedCompletionsCount = 0
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user