Skip to content

Commit c2ddf3d

Browse files
committed
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>
1 parent 0e44f7a commit c2ddf3d

File tree

6 files changed

+93
-0
lines changed

6 files changed

+93
-0
lines changed

gopls/doc/commands.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,22 @@ Args:
8484
}
8585
```
8686

87+
### **Run go mod edit -go=version**
88+
Identifier: `gopls.edit_go_directive`
89+
90+
Runs `go mod edit -go=version` for a module.
91+
92+
Args:
93+
94+
```
95+
{
96+
// Any document URI within the relevant module.
97+
"URI": string,
98+
// The version to pass to `go mod edit -go`.
99+
"Version": string,
100+
}
101+
```
102+
87103
### **Toggle gc_details**
88104
Identifier: `gopls.gc_details`
89105

internal/lsp/cache/errors.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ func parseErrorDiagnostics(snapshot *snapshot, pkg *pkg, errList scanner.ErrorLi
101101
}
102102

103103
var importErrorRe = regexp.MustCompile(`could not import ([^\s]+)`)
104+
var unsupportedFeatureRe = regexp.MustCompile(`.*require go(\d+\.\d+) or later`)
104105

105106
func typeErrorDiagnostics(snapshot *snapshot, pkg *pkg, e extendedError) ([]*source.Diagnostic, error) {
106107
code, spn, err := typeErrorData(snapshot.FileSet(), pkg, e.primary)
@@ -145,6 +146,14 @@ func typeErrorDiagnostics(snapshot *snapshot, pkg *pkg, e extendedError) ([]*sou
145146
return nil, err
146147
}
147148
}
149+
if code == typesinternal.UnsupportedFeature {
150+
if match := unsupportedFeatureRe.FindStringSubmatch(e.primary.Msg); match != nil {
151+
diag.SuggestedFixes, err = editGoDirectiveQuickFix(snapshot, spn.URI(), match[1])
152+
if err != nil {
153+
return nil, err
154+
}
155+
}
156+
}
148157
return []*source.Diagnostic{diag}, nil
149158
}
150159

@@ -165,6 +174,22 @@ func goGetQuickFixes(snapshot *snapshot, uri span.URI, pkg string) ([]source.Sug
165174
return []source.SuggestedFix{source.SuggestedFixFromCommand(cmd, protocol.QuickFix)}, nil
166175
}
167176

177+
func editGoDirectiveQuickFix(snapshot *snapshot, uri span.URI, version string) ([]source.SuggestedFix, error) {
178+
// Go mod edit only supports module mode.
179+
if snapshot.workspaceMode()&moduleMode == 0 {
180+
return nil, nil
181+
}
182+
title := fmt.Sprintf("go mod edit -go=%s", version)
183+
cmd, err := command.NewEditGoDirectiveCommand(title, command.EditGoDirectiveArgs{
184+
URI: protocol.URIFromSpanURI(uri),
185+
Version: version,
186+
})
187+
if err != nil {
188+
return nil, err
189+
}
190+
return []source.SuggestedFix{source.SuggestedFixFromCommand(cmd, protocol.QuickFix)}, nil
191+
}
192+
168193
func analysisDiagnosticDiagnostics(snapshot *snapshot, pkg *pkg, a *analysis.Analyzer, e *analysis.Diagnostic) ([]*source.Diagnostic, error) {
169194
var srcAnalyzer *source.Analyzer
170195
// Find the analyzer that generated this diagnostic.

internal/lsp/command.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,20 @@ func (c *commandHandler) Vendor(ctx context.Context, args command.URIArg) error
261261
})
262262
}
263263

264+
func (c *commandHandler) EditGoDirective(ctx context.Context, args command.EditGoDirectiveArgs) error {
265+
return c.run(ctx, commandConfig{
266+
requireSave: true, // if go.mod isn't saved it could cause a problem
267+
forURI: args.URI,
268+
}, func(ctx context.Context, deps commandDeps) error {
269+
_, err := deps.snapshot.RunGoCommandDirect(ctx, source.Normal, &gocommand.Invocation{
270+
Verb: "mod",
271+
Args: []string{"edit", "-go", args.Version},
272+
WorkingDir: filepath.Dir(args.URI.SpanURI().Filename()),
273+
})
274+
return err
275+
})
276+
}
277+
264278
func (c *commandHandler) RemoveDependency(ctx context.Context, args command.RemoveDependencyArgs) error {
265279
return c.run(ctx, commandConfig{
266280
progress: "Removing dependency",

internal/lsp/command/command_gen.go

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/lsp/command/interface.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ type Interface interface {
6868
// Runs `go mod vendor` for a module.
6969
Vendor(context.Context, URIArg) error
7070

71+
// EditGoDirective: Run go mod edit -go=version
72+
//
73+
// Runs `go mod edit -go=version` for a module.
74+
EditGoDirective(context.Context, EditGoDirectiveArgs) error
75+
7176
// UpdateGoSum: Update go.sum
7277
//
7378
// Updates the go.sum file for a module.
@@ -204,6 +209,13 @@ type RemoveDependencyArgs struct {
204209
OnlyDiagnostic bool
205210
}
206211

212+
type EditGoDirectiveArgs struct {
213+
// Any document URI within the relevant module.
214+
URI protocol.DocumentURI
215+
// The version to pass to `go mod edit -go`.
216+
Version string
217+
}
218+
207219
type GoGetPackageArgs struct {
208220
// Any document URI within the relevant module.
209221
URI protocol.DocumentURI

internal/lsp/source/api_json.go

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)