Skip to content

Commit bbc30f1

Browse files
committed
gopls/protocol: Allow AnnotatedTextEdits
In the LSP specification, the Edits fields of a TextdocumentEdit are a union type TextEdit | AnnotatedTextEdit. The latter has an extra field that might be useful. This CL contains one way of allowing AnnotatedTextEdits in this context. The systematic naming of union type provides this one with a long name, Or_TextDocumentEdit_edits_Elem. Fortunately this name appears in very few places. Fitting the new type in the existing gopls code requires 1. Conversions between []newtype and []TextEdit. This code is AsTextEdits() and AsAnnotatedTextEdits() in protocol/edits.go 1a. Because gopls does not insist on go1.20, slices of the new type cannot be used as the argument to protocol.NonNilSlice(), so the second function cannot return nil, but must return a slice. 2. There are some places where previously a TextEdit was built. These now require explicitly constructing an element of the new type. This CL does not make any use of AnnotatedTextEdits, but it does make their use possible. Change-Id: Ib167f057068a5921c77572c43dc985da0e6b19bc Reviewed-on: https://go-review.googlesource.com/c/tools/+/547295 Run-TryBot: Peter Weinberger <[email protected]> Reviewed-by: Suzy Mueller <[email protected]> TryBot-Bypass: Peter Weinberger <[email protected]>
1 parent f40889d commit bbc30f1

File tree

13 files changed

+63
-20
lines changed

13 files changed

+63
-20
lines changed

gopls/internal/cmd/cmd.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,7 @@ func (cli *cmdClient) applyWorkspaceEdit(edit *protocol.WorkspaceEdit) error {
554554
for _, c := range edit.DocumentChanges {
555555
if c.TextDocumentEdit != nil {
556556
uri := c.TextDocumentEdit.TextDocument.URI
557-
edits[uri] = append(edits[uri], c.TextDocumentEdit.Edits...)
557+
edits[uri] = append(edits[uri], protocol.AsTextEdits(c.TextDocumentEdit.Edits)...)
558558
orderedURIs = append(orderedURIs, uri)
559559
}
560560
if c.RenameFile != nil {

gopls/internal/cmd/imports.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ func (t *imports) Run(ctx context.Context, args ...string) error {
7171
for _, c := range a.Edit.DocumentChanges {
7272
if c.TextDocumentEdit != nil {
7373
if c.TextDocumentEdit.TextDocument.URI == uri {
74-
edits = append(edits, c.TextDocumentEdit.Edits...)
74+
edits = append(edits, protocol.AsTextEdits(c.TextDocumentEdit.Edits)...)
7575
}
7676
}
7777
}

gopls/internal/cmd/suggested_fix.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ func (s *suggestedFix) Run(ctx context.Context, args ...string) error {
154154
for _, c := range a.Edit.DocumentChanges {
155155
if c.TextDocumentEdit != nil {
156156
if c.TextDocumentEdit.TextDocument.URI == uri {
157-
edits = append(edits, c.TextDocumentEdit.Edits...)
157+
edits = append(edits, protocol.AsTextEdits(c.TextDocumentEdit.Edits)...)
158158
}
159159
}
160160
}
@@ -168,7 +168,7 @@ func (s *suggestedFix) Run(ctx context.Context, args ...string) error {
168168
for _, c := range a.Edit.DocumentChanges {
169169
if c.TextDocumentEdit != nil {
170170
if c.TextDocumentEdit.TextDocument.URI == uri {
171-
edits = append(edits, c.TextDocumentEdit.Edits...)
171+
edits = append(edits, protocol.AsTextEdits(c.TextDocumentEdit.Edits)...)
172172
}
173173
}
174174
}
@@ -181,7 +181,7 @@ func (s *suggestedFix) Run(ctx context.Context, args ...string) error {
181181
for _, c := range a.Edit.DocumentChanges {
182182
if c.TextDocumentEdit != nil {
183183
if c.TextDocumentEdit.TextDocument.URI == uri {
184-
edits = append(edits, c.TextDocumentEdit.Edits...)
184+
edits = append(edits, protocol.AsTextEdits(c.TextDocumentEdit.Edits)...)
185185
}
186186
}
187187
}

gopls/internal/lsp/protocol/edits.go

+42-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@
44

55
package protocol
66

7-
import "golang.org/x/tools/internal/diff"
7+
import (
8+
"fmt"
9+
10+
"golang.org/x/tools/internal/diff"
11+
)
812

913
// EditsFromDiffEdits converts diff.Edits to a non-nil slice of LSP TextEdits.
1014
// See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textEditArray
@@ -60,3 +64,40 @@ func ApplyEdits(m *Mapper, edits []TextEdit) ([]byte, []diff.Edit, error) {
6064
out, err := diff.ApplyBytes(m.Content, diffEdits)
6165
return out, diffEdits, err
6266
}
67+
68+
// AsTextEdits converts a slice possibly containing AnnotatedTextEdits
69+
// to a slice of TextEdits.
70+
func AsTextEdits(edits []Or_TextDocumentEdit_edits_Elem) []TextEdit {
71+
var result []TextEdit
72+
for _, e := range edits {
73+
var te TextEdit
74+
if x, ok := e.Value.(AnnotatedTextEdit); ok {
75+
te = x.TextEdit
76+
} else if x, ok := e.Value.(TextEdit); ok {
77+
te = x
78+
} else {
79+
panic(fmt.Sprintf("unexpected type %T, expected AnnotatedTextEdit or TextEdit", e.Value))
80+
}
81+
result = append(result, te)
82+
}
83+
return result
84+
}
85+
86+
// AsAnnotatedTextEdits converts a slice of TextEdits
87+
// to a slice of Or_TextDocumentEdit_edits_Elem.
88+
// (returning a typed nil is required in server: in code_action.go and command.go))
89+
func AsAnnotatedTextEdits(edits []TextEdit) []Or_TextDocumentEdit_edits_Elem {
90+
if edits == nil {
91+
return []Or_TextDocumentEdit_edits_Elem{}
92+
}
93+
var result []Or_TextDocumentEdit_edits_Elem
94+
for _, e := range edits {
95+
result = append(result, Or_TextDocumentEdit_edits_Elem{
96+
Value: TextEdit{
97+
Range: e.Range,
98+
NewText: e.NewText,
99+
},
100+
})
101+
}
102+
return result
103+
}

gopls/internal/lsp/protocol/generate/tables.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ const (
2424
// A.B.C.D means that one of B or C would change to a pointer
2525
// so a test or initialization would be needed
2626
var goplsStar = map[prop]int{
27+
{"AnnotatedTextEdit", "annotationId"}: wantOptStar,
2728
{"ClientCapabilities", "textDocument"}: wantOpt, // A.B.C.D at fake/editor.go:255
2829
{"ClientCapabilities", "window"}: wantOpt, // test failures
2930
{"ClientCapabilities", "workspace"}: wantOpt, // test failures
@@ -85,7 +86,6 @@ var renameProp = map[prop]string{
8586
{"ServerCapabilities", "semanticTokensProvider"}: "interface{}",
8687
// slightly tricky
8788
{"ServerCapabilities", "textDocumentSync"}: "interface{}",
88-
{"TextDocumentEdit", "edits"}: "[]TextEdit",
8989
{"TextDocumentSyncOptions", "save"}: "SaveOptions",
9090
{"WorkspaceEdit", "documentChanges"}: "[]DocumentChanges",
9191
}

gopls/internal/lsp/protocol/tsprotocol.go

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

gopls/internal/lsp/source/change_quote.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ func ConvertStringLiteral(pgf *ParsedGoFile, fh file.Handle, rng protocol.Range)
8585
Version: fh.Version(),
8686
TextDocumentIdentifier: protocol.TextDocumentIdentifier{URI: fh.URI()},
8787
},
88-
Edits: pedits,
88+
Edits: protocol.AsAnnotatedTextEdits(pedits),
8989
},
9090
},
9191
},

gopls/internal/lsp/source/change_signature.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ func RemoveUnusedParameter(ctx context.Context, fh file.Handle, rng protocol.Ran
176176
Version: fh.Version(),
177177
TextDocumentIdentifier: protocol.TextDocumentIdentifier{URI: uri},
178178
},
179-
Edits: pedits,
179+
Edits: protocol.AsAnnotatedTextEdits(pedits),
180180
},
181181
})
182182
}

gopls/internal/lsp/source/fix.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,11 @@ func suggestedFixToEdits(ctx context.Context, snapshot *cache.Snapshot, fset *to
130130
if err != nil {
131131
return nil, err
132132
}
133-
te.Edits = append(te.Edits, protocol.TextEdit{
134-
Range: rng,
135-
NewText: string(edit.NewText),
133+
te.Edits = append(te.Edits, protocol.Or_TextDocumentEdit_edits_Elem{
134+
Value: protocol.TextEdit{
135+
Range: rng,
136+
NewText: string(edit.NewText),
137+
},
136138
})
137139
}
138140
var edits []protocol.TextDocumentEdit

gopls/internal/server/code_action.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -617,7 +617,7 @@ func documentChanges(fh file.Handle, edits []protocol.TextEdit) []protocol.Docum
617617
URI: fh.URI(),
618618
},
619619
},
620-
Edits: protocol.NonNilSlice(edits),
620+
Edits: protocol.AsAnnotatedTextEdits(edits),
621621
},
622622
},
623623
}

gopls/internal/server/command.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,7 @@ func (c *commandHandler) RemoveDependency(ctx context.Context, args command.Remo
451451
URI: deps.fh.URI(),
452452
},
453453
},
454-
Edits: protocol.NonNilSlice(edits),
454+
Edits: protocol.AsAnnotatedTextEdits(edits),
455455
},
456456
},
457457
},
@@ -700,7 +700,7 @@ func collectFileEdits(ctx context.Context, snapshot *cache.Snapshot, uri protoco
700700
URI: uri,
701701
},
702702
},
703-
Edits: edits,
703+
Edits: protocol.AsAnnotatedTextEdits(edits),
704704
}}, nil
705705
}
706706

gopls/internal/test/integration/fake/editor.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -910,7 +910,7 @@ func (e *Editor) ApplyCodeAction(ctx context.Context, action protocol.CodeAction
910910
// Skip edits for old versions.
911911
continue
912912
}
913-
if err := e.EditBuffer(ctx, path, change.TextDocumentEdit.Edits); err != nil {
913+
if err := e.EditBuffer(ctx, path, protocol.AsTextEdits(change.TextDocumentEdit.Edits)); err != nil {
914914
return fmt.Errorf("editing buffer %q: %w", path, err)
915915
}
916916
}
@@ -1361,7 +1361,7 @@ func (e *Editor) applyTextDocumentEdit(ctx context.Context, change protocol.Text
13611361
return err
13621362
}
13631363
}
1364-
return e.EditBuffer(ctx, path, change.Edits)
1364+
return e.EditBuffer(ctx, path, protocol.AsTextEdits(change.Edits))
13651365
}
13661366

13671367
// Config returns the current editor configuration.

gopls/internal/test/marker/marker_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1650,7 +1650,7 @@ func applyDocumentChanges(env *integration.Env, changes []protocol.DocumentChang
16501650
if err != nil {
16511651
return err
16521652
}
1653-
patched, _, err := protocol.ApplyEdits(mapper, change.TextDocumentEdit.Edits)
1653+
patched, _, err := protocol.ApplyEdits(mapper, protocol.AsTextEdits(change.TextDocumentEdit.Edits))
16541654
if err != nil {
16551655
return err
16561656
}

0 commit comments

Comments
 (0)