Skip to content

Commit

Permalink
internal/lsp: add quick fix for unsupported feature
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
suzmue committed Feb 28, 2022
1 parent 0e44f7a commit c2ddf3d
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 0 deletions.
16 changes: 16 additions & 0 deletions gopls/doc/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`

Expand Down
25 changes: 25 additions & 0 deletions internal/lsp/cache/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
}

Expand All @@ -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.
Expand Down
14 changes: 14 additions & 0 deletions internal/lsp/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
20 changes: 20 additions & 0 deletions internal/lsp/command/command_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions internal/lsp/command/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions internal/lsp/source/api_json.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit c2ddf3d

Please sign in to comment.