mirror of
https://github.com/golang/go
synced 2024-11-05 18:36:10 -07:00
cb8d9cd245
Some code lenses may be undesirable for certain users or editors -- for example a code lens that runs tests, when VSCode already supports this functionality outside of the LSP. To handle such situations, support configuring code lenses via a new 'codelens' gopls option. Add support for code lens in regtests, and use this to test the new configuration. To achieve this, thread through a new 'EditorConfig' type that configures the fake editor's LSP session. It made sense to move the test Env overlay onto this config object as well. While looking at them, document some types in source.Options. Change-Id: I961077422a273829c5cbd83c3b87fae29f77eeda Reviewed-on: https://go-review.googlesource.com/c/tools/+/232680 Run-TryBot: Robert Findley <rfindley@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Rebecca Stambler <rstambler@golang.org>
99 lines
2.7 KiB
Go
99 lines
2.7 KiB
Go
package mod
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"golang.org/x/mod/modfile"
|
|
"golang.org/x/tools/internal/event"
|
|
"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"
|
|
)
|
|
|
|
// CodeLens computes code lens for a go.mod file.
|
|
func CodeLens(ctx context.Context, snapshot source.Snapshot, uri span.URI) ([]protocol.CodeLens, error) {
|
|
if !snapshot.View().Options().EnabledCodeLens[source.CommandUpgradeDependency] {
|
|
return nil, nil
|
|
}
|
|
realURI, _ := snapshot.View().ModFiles()
|
|
if realURI == "" {
|
|
return nil, nil
|
|
}
|
|
// Only get code lens on the go.mod for the view.
|
|
if uri != realURI {
|
|
return nil, nil
|
|
}
|
|
ctx, done := event.Start(ctx, "mod.CodeLens", tag.URI.Of(realURI))
|
|
defer done()
|
|
|
|
fh, err := snapshot.GetFile(realURI)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
f, m, upgrades, err := snapshot.ModHandle(ctx, fh).Upgrades(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var codelens []protocol.CodeLens
|
|
var allUpgrades []string
|
|
for _, req := range f.Require {
|
|
dep := req.Mod.Path
|
|
latest, ok := upgrades[dep]
|
|
if !ok {
|
|
continue
|
|
}
|
|
// Get the range of the require directive.
|
|
rng, err := positionsToRange(uri, m, req.Syntax.Start, req.Syntax.End)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
codelens = append(codelens, protocol.CodeLens{
|
|
Range: rng,
|
|
Command: protocol.Command{
|
|
Title: fmt.Sprintf("Upgrade dependency to %s", latest),
|
|
Command: source.CommandUpgradeDependency,
|
|
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: source.CommandUpgradeDependency,
|
|
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
|
|
}
|