Skip to content

Commit 7c7d7db

Browse files
committed
gopls/internal/golang: allow "query" CodeActions on generated files
Previously, all CodeAction were assumed to be fixes or refactorings, but GoTest and GoDoc are pure queries, and should be permitted even in generated files. Unfortunately there's no systematic way to distinguish, so for now we use an ad-hoc allow-list. + Test Also: - unexport golang.TestsAndBenchmarks - clarify "want kind" logic in server.CodeAction Change-Id: I78b991c68252505c962d22275a9e47bb1433ee40 Reviewed-on: https://go-review.googlesource.com/c/tools/+/577257 LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Robert Findley <[email protected]>
1 parent cb134f5 commit 7c7d7db

File tree

4 files changed

+98
-23
lines changed

4 files changed

+98
-23
lines changed

gopls/internal/golang/code_lens.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ func runTestCodeLens(ctx context.Context, snapshot *cache.Snapshot, fh file.Hand
4343
if err != nil {
4444
return nil, err
4545
}
46-
fns, err := TestsAndBenchmarks(pkg, pgf)
46+
fns, err := testsAndBenchmarks(pkg, pgf)
4747
if err != nil {
4848
return nil, err
4949
}
@@ -99,7 +99,7 @@ type TestFns struct {
9999
Benchmarks []TestFn
100100
}
101101

102-
func TestsAndBenchmarks(pkg *cache.Package, pgf *parsego.File) (TestFns, error) {
102+
func testsAndBenchmarks(pkg *cache.Package, pgf *parsego.File) (TestFns, error) {
103103
var out TestFns
104104

105105
if !strings.HasSuffix(pgf.URI.Path(), "_test.go") {

gopls/internal/golang/codeaction.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ func CodeActions(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle,
3333
// Only compute quick fixes if there are any diagnostics to fix.
3434
wantQuickFixes := want[protocol.QuickFix] && len(diagnostics) > 0
3535

36+
// Note: don't forget to update the allow-list in Server.CodeAction
37+
// when adding new query operations like GoTest and GoDoc that
38+
// are permitted even in generated source files
39+
3640
// Code actions requiring syntax information alone.
3741
if wantQuickFixes || want[protocol.SourceOrganizeImports] || want[protocol.RefactorExtract] {
3842
pgf, err := snapshot.ParseGo(ctx, fh, parsego.Full)
@@ -478,7 +482,7 @@ func getInlineCodeActions(pkg *cache.Package, pgf *parsego.File, rng protocol.Ra
478482

479483
// getGoTestCodeActions returns any "run this test/benchmark" code actions for the selection.
480484
func getGoTestCodeActions(pkg *cache.Package, pgf *parsego.File, rng protocol.Range) ([]protocol.CodeAction, error) {
481-
fns, err := TestsAndBenchmarks(pkg, pgf)
485+
fns, err := testsAndBenchmarks(pkg, pgf)
482486
if err != nil {
483487
return nil, err
484488
}

gopls/internal/server/code_action.go

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"golang.org/x/tools/gopls/internal/mod"
1717
"golang.org/x/tools/gopls/internal/protocol"
1818
"golang.org/x/tools/gopls/internal/protocol/command"
19+
"golang.org/x/tools/gopls/internal/util/slices"
1920
"golang.org/x/tools/internal/event"
2021
)
2122

@@ -42,27 +43,24 @@ func (s *server) CodeAction(ctx context.Context, params *protocol.CodeActionPara
4243

4344
// The Only field of the context specifies which code actions the client wants.
4445
// If Only is empty, assume that the client wants all of the non-explicit code actions.
45-
var want map[protocol.CodeActionKind]bool
46-
{
47-
// Explicit Code Actions are opt-in and shouldn't be returned to the client unless
48-
// requested using Only.
46+
want := supportedCodeActions
47+
if len(params.Context.Only) > 0 {
48+
want = make(map[protocol.CodeActionKind]bool)
49+
50+
// Explicit Code Actions are opt-in and shouldn't be
51+
// returned to the client unless requested using Only.
4952
// TODO: Add other CodeLenses such as GoGenerate, RegenerateCgo, etc..
5053
explicit := map[protocol.CodeActionKind]bool{
5154
protocol.GoTest: true,
5255
}
5356

54-
if len(params.Context.Only) == 0 {
55-
want = supportedCodeActions
56-
} else {
57-
want = make(map[protocol.CodeActionKind]bool)
58-
for _, only := range params.Context.Only {
59-
for k, v := range supportedCodeActions {
60-
if only == k || strings.HasPrefix(string(k), string(only)+".") {
61-
want[k] = want[k] || v
62-
}
57+
for _, only := range params.Context.Only {
58+
for k, v := range supportedCodeActions {
59+
if only == k || strings.HasPrefix(string(k), string(only)+".") {
60+
want[k] = want[k] || v
6361
}
64-
want[only] = want[only] || explicit[only]
6562
}
63+
want[only] = want[only] || explicit[only]
6664
}
6765
}
6866
if len(want) == 0 {
@@ -103,12 +101,6 @@ func (s *server) CodeAction(ctx context.Context, params *protocol.CodeActionPara
103101
return actions, nil
104102

105103
case file.Go:
106-
// Don't suggest fixes for generated files, since they are generally
107-
// not useful and some editors may apply them automatically on save.
108-
if golang.IsGenerated(ctx, snapshot, uri) {
109-
return nil, nil
110-
}
111-
112104
actions, err := s.codeActionsMatchingDiagnostics(ctx, uri, snapshot, params.Context.Diagnostics, want)
113105
if err != nil {
114106
return nil, err
@@ -120,6 +112,20 @@ func (s *server) CodeAction(ctx context.Context, params *protocol.CodeActionPara
120112
}
121113
actions = append(actions, moreActions...)
122114

115+
// Don't suggest fixes for generated files, since they are generally
116+
// not useful and some editors may apply them automatically on save.
117+
// (Unfortunately there's no reliable way to distinguish fixes from
118+
// queries, so we must list all kinds of queries here.)
119+
if golang.IsGenerated(ctx, snapshot, uri) {
120+
actions = slices.DeleteFunc(actions, func(a protocol.CodeAction) bool {
121+
switch a.Kind {
122+
case protocol.GoTest, protocol.GoDoc:
123+
return false // read-only query
124+
}
125+
return true // potential write operation
126+
})
127+
}
128+
123129
return actions, nil
124130

125131
default:

gopls/internal/test/integration/misc/codeactions_test.go

Lines changed: 65 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)