mirror of https://github.com/golang/go.git
internal/lsp: add quick fix for unsupported feature
Adds a command to run go mod edit -go to allow users to easily upgrade their go directive. Doing this change also revealed that changing the go directive does not invalidate the type check data and there may be stale diagnostics for a package. Updates golang/go#51086 Change-Id: I659a216059c489a88e29cd51b944c3a0274f3700 Reviewed-on: https://go-review.googlesource.com/c/tools/+/386875 Trust: Suzy Mueller <suzmue@golang.org> Run-TryBot: Suzy Mueller <suzmue@golang.org> Reviewed-by: Robert Findley <rfindley@google.com> gopls-CI: kokoro <noreply+kokoro@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
parent
0e44f7a8a7
commit
c2ddf3dda2
|
|
@ -84,6 +84,22 @@ Args:
|
|||
}
|
||||
```
|
||||
|
||||
### **Run go mod edit -go=version**
|
||||
Identifier: `gopls.edit_go_directive`
|
||||
|
||||
Runs `go mod edit -go=version` for a module.
|
||||
|
||||
Args:
|
||||
|
||||
```
|
||||
{
|
||||
// Any document URI within the relevant module.
|
||||
"URI": string,
|
||||
// The version to pass to `go mod edit -go`.
|
||||
"Version": string,
|
||||
}
|
||||
```
|
||||
|
||||
### **Toggle gc_details**
|
||||
Identifier: `gopls.gc_details`
|
||||
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@ func parseErrorDiagnostics(snapshot *snapshot, pkg *pkg, errList scanner.ErrorLi
|
|||
}
|
||||
|
||||
var importErrorRe = regexp.MustCompile(`could not import ([^\s]+)`)
|
||||
var unsupportedFeatureRe = regexp.MustCompile(`.*require go(\d+\.\d+) or later`)
|
||||
|
||||
func typeErrorDiagnostics(snapshot *snapshot, pkg *pkg, e extendedError) ([]*source.Diagnostic, error) {
|
||||
code, spn, err := typeErrorData(snapshot.FileSet(), pkg, e.primary)
|
||||
|
|
@ -145,6 +146,14 @@ func typeErrorDiagnostics(snapshot *snapshot, pkg *pkg, e extendedError) ([]*sou
|
|||
return nil, err
|
||||
}
|
||||
}
|
||||
if code == typesinternal.UnsupportedFeature {
|
||||
if match := unsupportedFeatureRe.FindStringSubmatch(e.primary.Msg); match != nil {
|
||||
diag.SuggestedFixes, err = editGoDirectiveQuickFix(snapshot, spn.URI(), match[1])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return []*source.Diagnostic{diag}, nil
|
||||
}
|
||||
|
||||
|
|
@ -165,6 +174,22 @@ func goGetQuickFixes(snapshot *snapshot, uri span.URI, pkg string) ([]source.Sug
|
|||
return []source.SuggestedFix{source.SuggestedFixFromCommand(cmd, protocol.QuickFix)}, nil
|
||||
}
|
||||
|
||||
func editGoDirectiveQuickFix(snapshot *snapshot, uri span.URI, version string) ([]source.SuggestedFix, error) {
|
||||
// Go mod edit only supports module mode.
|
||||
if snapshot.workspaceMode()&moduleMode == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
title := fmt.Sprintf("go mod edit -go=%s", version)
|
||||
cmd, err := command.NewEditGoDirectiveCommand(title, command.EditGoDirectiveArgs{
|
||||
URI: protocol.URIFromSpanURI(uri),
|
||||
Version: version,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []source.SuggestedFix{source.SuggestedFixFromCommand(cmd, protocol.QuickFix)}, nil
|
||||
}
|
||||
|
||||
func analysisDiagnosticDiagnostics(snapshot *snapshot, pkg *pkg, a *analysis.Analyzer, e *analysis.Diagnostic) ([]*source.Diagnostic, error) {
|
||||
var srcAnalyzer *source.Analyzer
|
||||
// Find the analyzer that generated this diagnostic.
|
||||
|
|
|
|||
|
|
@ -261,6 +261,20 @@ func (c *commandHandler) Vendor(ctx context.Context, args command.URIArg) error
|
|||
})
|
||||
}
|
||||
|
||||
func (c *commandHandler) EditGoDirective(ctx context.Context, args command.EditGoDirectiveArgs) error {
|
||||
return c.run(ctx, commandConfig{
|
||||
requireSave: true, // if go.mod isn't saved it could cause a problem
|
||||
forURI: args.URI,
|
||||
}, func(ctx context.Context, deps commandDeps) error {
|
||||
_, err := deps.snapshot.RunGoCommandDirect(ctx, source.Normal, &gocommand.Invocation{
|
||||
Verb: "mod",
|
||||
Args: []string{"edit", "-go", args.Version},
|
||||
WorkingDir: filepath.Dir(args.URI.SpanURI().Filename()),
|
||||
})
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
func (c *commandHandler) RemoveDependency(ctx context.Context, args command.RemoveDependencyArgs) error {
|
||||
return c.run(ctx, commandConfig{
|
||||
progress: "Removing dependency",
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ const (
|
|||
AddImport Command = "add_import"
|
||||
ApplyFix Command = "apply_fix"
|
||||
CheckUpgrades Command = "check_upgrades"
|
||||
EditGoDirective Command = "edit_go_directive"
|
||||
GCDetails Command = "gc_details"
|
||||
Generate Command = "generate"
|
||||
GenerateGoplsMod Command = "generate_gopls_mod"
|
||||
|
|
@ -46,6 +47,7 @@ var Commands = []Command{
|
|||
AddImport,
|
||||
ApplyFix,
|
||||
CheckUpgrades,
|
||||
EditGoDirective,
|
||||
GCDetails,
|
||||
Generate,
|
||||
GenerateGoplsMod,
|
||||
|
|
@ -90,6 +92,12 @@ func Dispatch(ctx context.Context, params *protocol.ExecuteCommandParams, s Inte
|
|||
return nil, err
|
||||
}
|
||||
return nil, s.CheckUpgrades(ctx, a0)
|
||||
case "gopls.edit_go_directive":
|
||||
var a0 EditGoDirectiveArgs
|
||||
if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, s.EditGoDirective(ctx, a0)
|
||||
case "gopls.gc_details":
|
||||
var a0 protocol.DocumentURI
|
||||
if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
|
||||
|
|
@ -240,6 +248,18 @@ func NewCheckUpgradesCommand(title string, a0 CheckUpgradesArgs) (protocol.Comma
|
|||
}, nil
|
||||
}
|
||||
|
||||
func NewEditGoDirectiveCommand(title string, a0 EditGoDirectiveArgs) (protocol.Command, error) {
|
||||
args, err := MarshalArgs(a0)
|
||||
if err != nil {
|
||||
return protocol.Command{}, err
|
||||
}
|
||||
return protocol.Command{
|
||||
Title: title,
|
||||
Command: "gopls.edit_go_directive",
|
||||
Arguments: args,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func NewGCDetailsCommand(title string, a0 protocol.DocumentURI) (protocol.Command, error) {
|
||||
args, err := MarshalArgs(a0)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -68,6 +68,11 @@ type Interface interface {
|
|||
// Runs `go mod vendor` for a module.
|
||||
Vendor(context.Context, URIArg) error
|
||||
|
||||
// EditGoDirective: Run go mod edit -go=version
|
||||
//
|
||||
// Runs `go mod edit -go=version` for a module.
|
||||
EditGoDirective(context.Context, EditGoDirectiveArgs) error
|
||||
|
||||
// UpdateGoSum: Update go.sum
|
||||
//
|
||||
// Updates the go.sum file for a module.
|
||||
|
|
@ -204,6 +209,13 @@ type RemoveDependencyArgs struct {
|
|||
OnlyDiagnostic bool
|
||||
}
|
||||
|
||||
type EditGoDirectiveArgs struct {
|
||||
// Any document URI within the relevant module.
|
||||
URI protocol.DocumentURI
|
||||
// The version to pass to `go mod edit -go`.
|
||||
Version string
|
||||
}
|
||||
|
||||
type GoGetPackageArgs struct {
|
||||
// Any document URI within the relevant module.
|
||||
URI protocol.DocumentURI
|
||||
|
|
|
|||
|
|
@ -603,6 +603,12 @@ var GeneratedAPIJSON = &APIJSON{
|
|||
Doc: "Checks for module upgrades.",
|
||||
ArgDoc: "{\n\t// The go.mod file URI.\n\t\"URI\": string,\n\t// The modules to check.\n\t\"Modules\": []string,\n}",
|
||||
},
|
||||
{
|
||||
Command: "gopls.edit_go_directive",
|
||||
Title: "Run go mod edit -go=version",
|
||||
Doc: "Runs `go mod edit -go=version` for a module.",
|
||||
ArgDoc: "{\n\t// Any document URI within the relevant module.\n\t\"URI\": string,\n\t// The version to pass to `go mod edit -go`.\n\t\"Version\": string,\n}",
|
||||
},
|
||||
{
|
||||
Command: "gopls.gc_details",
|
||||
Title: "Toggle gc_details",
|
||||
|
|
|
|||
Loading…
Reference in New Issue