mirror of
https://github.com/golang/go
synced 2024-11-05 22:56:11 -07:00
47c907e258
Refactor internal/lsp/cache to use a new temporary go.mod file for each go command invocation. This cleans up the abstraction in the source package, as we no longer are aware of temporary go.mod files. This will also fix the raciness of reusing the same temporary go.mod file for each invocation. Updates golang/go#37318. Fixes golang/go#39504. Change-Id: I90bc17a678b5df222ab598c8f7dbf6c6fdd393f6 Reviewed-on: https://go-review.googlesource.com/c/tools/+/237517 Run-TryBot: Rebecca Stambler <rstambler@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Heschi Kreinick <heschi@google.com>
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
|
|
}
|
|
ctx, done := event.Start(ctx, "mod.CodeLens", tag.URI.Of(uri))
|
|
defer done()
|
|
|
|
// Don't show go.mod code lenses in module mode.
|
|
if snapshot.View().ModFile() == "" {
|
|
return nil, nil
|
|
}
|
|
fh, err := snapshot.GetFile(ctx, uri)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
mh, err := snapshot.ModHandle(ctx, fh)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
f, m, upgrades, err := mh.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
|
|
}
|