Skip to content

Commit d9b9452

Browse files
committed
gopls/internal/lsp/cache: move quick-fix bundling logic to the cache pkg
Change-Id: I49ee8d6a84c12be8e4e993c5f9a1fcd597c27e40 Reviewed-on: https://go-review.googlesource.com/c/tools/+/543718 Reviewed-by: Alan Donovan <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent 1733061 commit d9b9452

File tree

4 files changed

+86
-83
lines changed

4 files changed

+86
-83
lines changed

gopls/internal/lsp/cache/diagnostics.go

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@
44

55
package cache
66

7-
import "golang.org/x/tools/gopls/internal/lsp/protocol"
7+
import (
8+
"encoding/json"
9+
10+
"golang.org/x/tools/gopls/internal/bug"
11+
"golang.org/x/tools/gopls/internal/lsp/protocol"
12+
)
813

914
// SuggestedFixFromCommand returns a suggested fix to run the given command.
1015
func SuggestedFixFromCommand(cmd protocol.Command, kind protocol.CodeActionKind) SuggestedFix {
@@ -14,3 +19,81 @@ func SuggestedFixFromCommand(cmd protocol.Command, kind protocol.CodeActionKind)
1419
ActionKind: kind,
1520
}
1621
}
22+
23+
// quickFixesJSON is a JSON-serializable list of quick fixes
24+
// to be saved in the protocol.Diagnostic.Data field.
25+
type quickFixesJSON struct {
26+
// TODO(rfindley): pack some sort of identifier here for later
27+
// lookup/validation?
28+
Fixes []protocol.CodeAction
29+
}
30+
31+
// BundleQuickFixes attempts to bundle sd.SuggestedFixes into the
32+
// sd.BundledFixes field, so that it can be round-tripped through the client.
33+
// It returns false if the quick-fixes cannot be bundled.
34+
func BundleQuickFixes(sd *Diagnostic) bool {
35+
if len(sd.SuggestedFixes) == 0 {
36+
return true
37+
}
38+
var actions []protocol.CodeAction
39+
for _, fix := range sd.SuggestedFixes {
40+
if fix.Edits != nil {
41+
// For now, we only support bundled code actions that execute commands.
42+
//
43+
// In order to cleanly support bundled edits, we'd have to guarantee that
44+
// the edits were generated on the current snapshot. But this naively
45+
// implies that every fix would have to include a snapshot ID, which
46+
// would require us to republish all diagnostics on each new snapshot.
47+
//
48+
// TODO(rfindley): in order to avoid this additional chatter, we'd need
49+
// to build some sort of registry or other mechanism on the snapshot to
50+
// check whether a diagnostic is still valid.
51+
return false
52+
}
53+
action := protocol.CodeAction{
54+
Title: fix.Title,
55+
Kind: fix.ActionKind,
56+
Command: fix.Command,
57+
}
58+
actions = append(actions, action)
59+
}
60+
fixes := quickFixesJSON{
61+
Fixes: actions,
62+
}
63+
data, err := json.Marshal(fixes)
64+
if err != nil {
65+
bug.Reportf("marshalling quick fixes: %v", err)
66+
return false
67+
}
68+
msg := json.RawMessage(data)
69+
sd.BundledFixes = &msg
70+
return true
71+
}
72+
73+
// BundledQuickFixes extracts any bundled codeActions from the
74+
// diag.Data field.
75+
func BundledQuickFixes(diag protocol.Diagnostic) []protocol.CodeAction {
76+
if diag.Data == nil {
77+
return nil
78+
}
79+
var fix quickFixesJSON
80+
if err := json.Unmarshal(*diag.Data, &fix); err != nil {
81+
bug.Reportf("unmarshalling quick fix: %v", err)
82+
return nil
83+
}
84+
85+
var actions []protocol.CodeAction
86+
for _, action := range fix.Fixes {
87+
// See BundleQuickFixes: for now we only support bundling commands.
88+
if action.Edit != nil {
89+
bug.Reportf("bundled fix %q includes workspace edits", action.Title)
90+
continue
91+
}
92+
// associate the action with the incoming diagnostic
93+
// (Note that this does not mutate the fix.Fixes slice).
94+
action.Diagnostics = []protocol.Diagnostic{diag}
95+
actions = append(actions, action)
96+
}
97+
98+
return actions
99+
}

gopls/internal/lsp/cache/pkg.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@ var (
7474
IsValidImport = source.IsValidImport
7575
RemoveIntermediateTestVariants = source.RemoveIntermediateTestVariants
7676
IsCommandLineArguments = source.IsCommandLineArguments
77-
BundleQuickFixes = source.BundleQuickFixes
7877
NewFilterer = source.NewFilterer
7978
)
8079

gopls/internal/lsp/code_action.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"golang.org/x/tools/gopls/internal/lsp/analysis/fillstruct"
1818
"golang.org/x/tools/gopls/internal/lsp/analysis/infertypeargs"
1919
"golang.org/x/tools/gopls/internal/lsp/analysis/stubmethods"
20+
"golang.org/x/tools/gopls/internal/lsp/cache"
2021
"golang.org/x/tools/gopls/internal/lsp/command"
2122
"golang.org/x/tools/gopls/internal/lsp/mod"
2223
"golang.org/x/tools/gopls/internal/lsp/protocol"
@@ -629,7 +630,7 @@ func (s *server) codeActionsMatchingDiagnostics(ctx context.Context, uri protoco
629630
var actions []protocol.CodeAction
630631
var unbundled []protocol.Diagnostic // diagnostics without bundled code actions in their Data field
631632
for _, pd := range pds {
632-
bundled := source.BundledQuickFixes(pd)
633+
bundled := cache.BundledQuickFixes(pd)
633634
if len(bundled) > 0 {
634635
for _, fix := range bundled {
635636
if want[fix.Kind] {

gopls/internal/lsp/source/diagnostics.go

Lines changed: 0 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@ package source
66

77
import (
88
"context"
9-
"encoding/json"
109

11-
"golang.org/x/tools/gopls/internal/bug"
1210
"golang.org/x/tools/gopls/internal/lsp/progress"
1311
"golang.org/x/tools/gopls/internal/lsp/protocol"
1412
"golang.org/x/tools/gopls/internal/settings"
@@ -107,81 +105,3 @@ func CombineDiagnostics(tdiags []*Diagnostic, adiags []*Diagnostic, outT, outA *
107105

108106
*outT = append(*outT, tdiags...)
109107
}
110-
111-
// quickFixesJSON is a JSON-serializable list of quick fixes
112-
// to be saved in the protocol.Diagnostic.Data field.
113-
type quickFixesJSON struct {
114-
// TODO(rfindley): pack some sort of identifier here for later
115-
// lookup/validation?
116-
Fixes []protocol.CodeAction
117-
}
118-
119-
// BundleQuickFixes attempts to bundle sd.SuggestedFixes into the
120-
// sd.BundledFixes field, so that it can be round-tripped through the client.
121-
// It returns false if the quick-fixes cannot be bundled.
122-
func BundleQuickFixes(sd *Diagnostic) bool {
123-
if len(sd.SuggestedFixes) == 0 {
124-
return true
125-
}
126-
var actions []protocol.CodeAction
127-
for _, fix := range sd.SuggestedFixes {
128-
if fix.Edits != nil {
129-
// For now, we only support bundled code actions that execute commands.
130-
//
131-
// In order to cleanly support bundled edits, we'd have to guarantee that
132-
// the edits were generated on the current snapshot. But this naively
133-
// implies that every fix would have to include a snapshot ID, which
134-
// would require us to republish all diagnostics on each new snapshot.
135-
//
136-
// TODO(rfindley): in order to avoid this additional chatter, we'd need
137-
// to build some sort of registry or other mechanism on the snapshot to
138-
// check whether a diagnostic is still valid.
139-
return false
140-
}
141-
action := protocol.CodeAction{
142-
Title: fix.Title,
143-
Kind: fix.ActionKind,
144-
Command: fix.Command,
145-
}
146-
actions = append(actions, action)
147-
}
148-
fixes := quickFixesJSON{
149-
Fixes: actions,
150-
}
151-
data, err := json.Marshal(fixes)
152-
if err != nil {
153-
bug.Reportf("marshalling quick fixes: %v", err)
154-
return false
155-
}
156-
msg := json.RawMessage(data)
157-
sd.BundledFixes = &msg
158-
return true
159-
}
160-
161-
// BundledQuickFixes extracts any bundled codeActions from the
162-
// diag.Data field.
163-
func BundledQuickFixes(diag protocol.Diagnostic) []protocol.CodeAction {
164-
if diag.Data == nil {
165-
return nil
166-
}
167-
var fix quickFixesJSON
168-
if err := json.Unmarshal(*diag.Data, &fix); err != nil {
169-
bug.Reportf("unmarshalling quick fix: %v", err)
170-
return nil
171-
}
172-
173-
var actions []protocol.CodeAction
174-
for _, action := range fix.Fixes {
175-
// See BundleQuickFixes: for now we only support bundling commands.
176-
if action.Edit != nil {
177-
bug.Reportf("bundled fix %q includes workspace edits", action.Title)
178-
continue
179-
}
180-
// associate the action with the incoming diagnostic
181-
// (Note that this does not mutate the fix.Fixes slice).
182-
action.Diagnostics = []protocol.Diagnostic{diag}
183-
actions = append(actions, action)
184-
}
185-
186-
return actions
187-
}

0 commit comments

Comments
 (0)