Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools / gopls@v0.5.2 / internal / regtest / wrappers.go
1 // Copyright 2020 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package regtest
6
7 import (
8         "io"
9         "testing"
10
11         "golang.org/x/tools/internal/lsp/fake"
12         "golang.org/x/tools/internal/lsp/protocol"
13         "golang.org/x/tools/internal/lsp/source"
14         errors "golang.org/x/xerrors"
15 )
16
17 func (e *Env) ChangeFilesOnDisk(events []fake.FileEvent) {
18         e.T.Helper()
19         if err := e.Sandbox.Workdir.ChangeFilesOnDisk(e.Ctx, events); err != nil {
20                 e.T.Fatal(err)
21         }
22 }
23
24 // RemoveWorkspaceFile deletes a file on disk but does nothing in the
25 // editor. It calls t.Fatal on any error.
26 func (e *Env) RemoveWorkspaceFile(name string) {
27         e.T.Helper()
28         if err := e.Sandbox.Workdir.RemoveFile(e.Ctx, name); err != nil {
29                 e.T.Fatal(err)
30         }
31 }
32
33 // ReadWorkspaceFile reads a file from the workspace, calling t.Fatal on any
34 // error.
35 func (e *Env) ReadWorkspaceFile(name string) string {
36         e.T.Helper()
37         content, err := e.Sandbox.Workdir.ReadFile(name)
38         if err != nil {
39                 e.T.Fatal(err)
40         }
41         return content
42 }
43
44 // WriteWorkspaceFile writes a file to disk but does nothing in the editor.
45 // It calls t.Fatal on any error.
46 func (e *Env) WriteWorkspaceFile(name, content string) {
47         e.T.Helper()
48         if err := e.Sandbox.Workdir.WriteFile(e.Ctx, name, content); err != nil {
49                 e.T.Fatal(err)
50         }
51 }
52
53 // WriteWorkspaceFiles deletes a file on disk but does nothing in the
54 // editor. It calls t.Fatal on any error.
55 func (e *Env) WriteWorkspaceFiles(files map[string]string) {
56         e.T.Helper()
57         if err := e.Sandbox.Workdir.WriteFiles(e.Ctx, files); err != nil {
58                 e.T.Fatal(err)
59         }
60 }
61
62 // OpenFile opens a file in the editor, calling t.Fatal on any error.
63 func (e *Env) OpenFile(name string) {
64         e.T.Helper()
65         if err := e.Editor.OpenFile(e.Ctx, name); err != nil {
66                 e.T.Fatal(err)
67         }
68 }
69
70 // CreateBuffer creates a buffer in the editor, calling t.Fatal on any error.
71 func (e *Env) CreateBuffer(name string, content string) {
72         e.T.Helper()
73         if err := e.Editor.CreateBuffer(e.Ctx, name, content); err != nil {
74                 e.T.Fatal(err)
75         }
76 }
77
78 // CloseBuffer closes an editor buffer without saving, calling t.Fatal on any
79 // error.
80 func (e *Env) CloseBuffer(name string) {
81         e.T.Helper()
82         if err := e.Editor.CloseBuffer(e.Ctx, name); err != nil {
83                 e.T.Fatal(err)
84         }
85 }
86
87 // EditBuffer applies edits to an editor buffer, calling t.Fatal on any error.
88 func (e *Env) EditBuffer(name string, edits ...fake.Edit) {
89         e.T.Helper()
90         if err := e.Editor.EditBuffer(e.Ctx, name, edits); err != nil {
91                 e.T.Fatal(err)
92         }
93 }
94
95 // RegexpRange returns the range of the first match for re in the buffer
96 // specified by name, calling t.Fatal on any error. It first searches for the
97 // position in open buffers, then in workspace files.
98 func (e *Env) RegexpRange(name, re string) (fake.Pos, fake.Pos) {
99         e.T.Helper()
100         start, end, err := e.Editor.RegexpRange(name, re)
101         if err == fake.ErrUnknownBuffer {
102                 start, end, err = e.Sandbox.Workdir.RegexpRange(name, re)
103         }
104         if err != nil {
105                 e.T.Fatalf("RegexpRange: %v, %v", name, err)
106         }
107         return start, end
108 }
109
110 // RegexpSearch returns the starting position of the first match for re in the
111 // buffer specified by name, calling t.Fatal on any error. It first searches
112 // for the position in open buffers, then in workspace files.
113 func (e *Env) RegexpSearch(name, re string) fake.Pos {
114         e.T.Helper()
115         pos, err := e.Editor.RegexpSearch(name, re)
116         if err == fake.ErrUnknownBuffer {
117                 pos, err = e.Sandbox.Workdir.RegexpSearch(name, re)
118         }
119         if err != nil {
120                 e.T.Fatalf("RegexpSearch: %v, %v", name, err)
121         }
122         return pos
123 }
124
125 // RegexpReplace replaces the first group in the first match of regexpStr with
126 // the replace text, calling t.Fatal on any error.
127 func (e *Env) RegexpReplace(name, regexpStr, replace string) {
128         e.T.Helper()
129         if err := e.Editor.RegexpReplace(e.Ctx, name, regexpStr, replace); err != nil {
130                 e.T.Fatalf("RegexpReplace: %v", err)
131         }
132 }
133
134 // SaveBuffer saves an editor buffer, calling t.Fatal on any error.
135 func (e *Env) SaveBuffer(name string) {
136         e.T.Helper()
137         if err := e.Editor.SaveBuffer(e.Ctx, name); err != nil {
138                 e.T.Fatal(err)
139         }
140 }
141
142 // GoToDefinition goes to definition in the editor, calling t.Fatal on any
143 // error.
144 func (e *Env) GoToDefinition(name string, pos fake.Pos) (string, fake.Pos) {
145         e.T.Helper()
146         n, p, err := e.Editor.GoToDefinition(e.Ctx, name, pos)
147         if err != nil {
148                 e.T.Fatal(err)
149         }
150         return n, p
151 }
152
153 // Symbol returns symbols matching query
154 func (e *Env) Symbol(query string) []fake.SymbolInformation {
155         e.T.Helper()
156         r, err := e.Editor.Symbol(e.Ctx, query)
157         if err != nil {
158                 e.T.Fatal(err)
159         }
160         return r
161 }
162
163 // FormatBuffer formats the editor buffer, calling t.Fatal on any error.
164 func (e *Env) FormatBuffer(name string) {
165         e.T.Helper()
166         if err := e.Editor.FormatBuffer(e.Ctx, name); err != nil {
167                 e.T.Fatal(err)
168         }
169 }
170
171 // OrganizeImports processes the source.organizeImports codeAction, calling
172 // t.Fatal on any error.
173 func (e *Env) OrganizeImports(name string) {
174         e.T.Helper()
175         if err := e.Editor.OrganizeImports(e.Ctx, name); err != nil {
176                 e.T.Fatal(err)
177         }
178 }
179
180 // ApplyQuickFixes processes the quickfix codeAction, calling t.Fatal on any error.
181 func (e *Env) ApplyQuickFixes(path string, diagnostics []protocol.Diagnostic) {
182         e.T.Helper()
183         if err := e.Editor.ApplyQuickFixes(e.Ctx, path, nil, diagnostics); err != nil {
184                 e.T.Fatal(err)
185         }
186 }
187
188 // Hover in the editor, calling t.Fatal on any error.
189 func (e *Env) Hover(name string, pos fake.Pos) (*protocol.MarkupContent, fake.Pos) {
190         e.T.Helper()
191         c, p, err := e.Editor.Hover(e.Ctx, name, pos)
192         if err != nil {
193                 e.T.Fatal(err)
194         }
195         return c, p
196 }
197
198 func (e *Env) DocumentLink(name string) []protocol.DocumentLink {
199         e.T.Helper()
200         links, err := e.Editor.DocumentLink(e.Ctx, name)
201         if err != nil {
202                 e.T.Fatal(err)
203         }
204         return links
205 }
206
207 func checkIsFatal(t *testing.T, err error) {
208         t.Helper()
209         if err != nil && !errors.Is(err, io.EOF) && !errors.Is(err, io.ErrClosedPipe) {
210                 t.Fatal(err)
211         }
212 }
213
214 // CloseEditor shuts down the editor, calling t.Fatal on any error.
215 func (e *Env) CloseEditor() {
216         e.T.Helper()
217         checkIsFatal(e.T, e.Editor.Close(e.Ctx))
218 }
219
220 // RunGenerate runs go:generate on the given dir, calling t.Fatal on any error.
221 // It waits for the generate command to complete and checks for file changes
222 // before returning.
223 func (e *Env) RunGenerate(dir string) {
224         e.T.Helper()
225         if err := e.Editor.RunGenerate(e.Ctx, dir); err != nil {
226                 e.T.Fatal(err)
227         }
228         e.Await(NoOutstandingWork())
229         // Ideally the fake.Workspace would handle all synthetic file watching, but
230         // we help it out here as we need to wait for the generate command to
231         // complete before checking the filesystem.
232         e.CheckForFileChanges()
233 }
234
235 // RunGoCommand runs the given command in the sandbox's default working
236 // directory.
237 func (e *Env) RunGoCommand(verb string, args ...string) {
238         if err := e.Sandbox.RunGoCommand(e.Ctx, "", verb, args); err != nil {
239                 e.T.Fatal(err)
240         }
241 }
242
243 // CheckForFileChanges triggers a manual poll of the workspace for any file
244 // changes since creation, or since last polling. It is a workaround for the
245 // lack of true file watching support in the fake workspace.
246 func (e *Env) CheckForFileChanges() {
247         e.T.Helper()
248         if err := e.Sandbox.Workdir.CheckForFileChanges(e.Ctx); err != nil {
249                 e.T.Fatal(err)
250         }
251 }
252
253 // CodeLens calls textDocument/codeLens for the given path, calling t.Fatal on
254 // any error.
255 func (e *Env) CodeLens(path string) []protocol.CodeLens {
256         e.T.Helper()
257         lens, err := e.Editor.CodeLens(e.Ctx, path)
258         if err != nil {
259                 e.T.Fatal(err)
260         }
261         return lens
262 }
263
264 // ExecuteCodeLensCommand executes the command for the code lens matching the
265 // given command name.
266 func (e *Env) ExecuteCodeLensCommand(path string, cmd *source.Command) {
267         lenses := e.CodeLens(path)
268         var lens protocol.CodeLens
269         var found bool
270         for _, l := range lenses {
271                 if l.Command.Command == cmd.ID() {
272                         lens = l
273                         found = true
274                 }
275         }
276         if !found {
277                 e.T.Fatalf("found no command with the ID %s", cmd.ID())
278         }
279         if _, err := e.Editor.ExecuteCommand(e.Ctx, &protocol.ExecuteCommandParams{
280                 Command:   lens.Command.Command,
281                 Arguments: lens.Command.Arguments,
282         }); err != nil {
283                 e.T.Fatal(err)
284         }
285 }
286
287 // References calls textDocument/references for the given path at the given
288 // position.
289 func (e *Env) References(path string, pos fake.Pos) []protocol.Location {
290         e.T.Helper()
291         locations, err := e.Editor.References(e.Ctx, path, pos)
292         if err != nil {
293                 e.T.Fatal(err)
294         }
295         return locations
296 }
297
298 // Completion executes a completion request on the server.
299 func (e *Env) Completion(path string, pos fake.Pos) *protocol.CompletionList {
300         e.T.Helper()
301         completions, err := e.Editor.Completion(e.Ctx, path, pos)
302         if err != nil {
303                 e.T.Fatal(err)
304         }
305         return completions
306 }
307
308 // CodeAction calls testDocument/codeAction for the given path, and calls
309 // t.Fatal if there are errors.
310 func (e *Env) CodeAction(path string) []protocol.CodeAction {
311         e.T.Helper()
312         actions, err := e.Editor.CodeAction(e.Ctx, path, nil)
313         if err != nil {
314                 e.T.Fatal(err)
315         }
316         return actions
317 }
318
319 func (e *Env) changeConfiguration(t *testing.T, config *fake.EditorConfig) {
320         e.Editor.Config = *config
321         if err := e.Editor.Server.DidChangeConfiguration(e.Ctx, &protocol.DidChangeConfigurationParams{
322                 // gopls currently ignores the Settings field
323         }); err != nil {
324                 t.Fatal(err)
325         }
326 }
327
328 // ChangeEnv modifies the editor environment and reconfigures the LSP client.
329 // TODO: extend this to "ChangeConfiguration", once we refactor the way editor
330 // configuration is defined.
331 func (e *Env) ChangeEnv(overlay map[string]string) {
332         e.T.Helper()
333         // TODO: to be correct, this should probably be synchronized, but right now
334         // configuration is only ever modified synchronously in a regtest, so this
335         // correctness can wait for the previously mentioned refactoring.
336         if e.Editor.Config.Env == nil {
337                 e.Editor.Config.Env = make(map[string]string)
338         }
339         for k, v := range overlay {
340                 e.Editor.Config.Env[k] = v
341         }
342         var params protocol.DidChangeConfigurationParams
343         if err := e.Editor.Server.DidChangeConfiguration(e.Ctx, &params); err != nil {
344                 e.T.Fatal(err)
345         }
346 }