]> git.madduck.net Git - etc/vim.git/blob - .vim/bundle/ale/test/test_codefix.vader

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

Do not set EDITOR/VISUAL for shell
[etc/vim.git] / .vim / bundle / ale / test / test_codefix.vader
1 Before:
2   call ale#test#SetDirectory('/testplugin/test')
3   call ale#test#SetFilename('dummy.txt')
4   Save g:ale_buffer_info
5
6   let g:ale_buffer_info = {}
7
8   let g:old_filename = expand('%:p')
9   let g:Callback = ''
10   let g:expr_list = []
11   let g:message_list = []
12   let g:handle_code_action_called = 0
13   let g:code_actions = []
14   let g:options = {}
15   let g:capability_checked = ''
16   let g:conn_id = v:null
17   let g:InitCallback = v:null
18
19   runtime autoload/ale/lsp_linter.vim
20   runtime autoload/ale/lsp.vim
21   runtime autoload/ale/util.vim
22   runtime autoload/ale/codefix.vim
23   runtime autoload/ale/code_action.vim
24
25   function! ale#lsp_linter#StartLSP(buffer, linter, Callback) abort
26     let g:conn_id = ale#lsp#Register('executable', '/foo/bar', '', {})
27     call ale#lsp#MarkDocumentAsOpen(g:conn_id, a:buffer)
28
29     if a:linter.lsp is# 'tsserver'
30         call ale#lsp#MarkConnectionAsTsserver(g:conn_id)
31     endif
32
33     let l:details = {
34     \ 'command': 'foobar',
35     \ 'buffer': a:buffer,
36     \ 'connection_id': g:conn_id,
37     \ 'project_root': '/foo/bar',
38     \}
39
40     let g:InitCallback = {-> ale#lsp_linter#OnInit(a:linter, l:details, a:Callback)}
41   endfunction
42
43   function! ale#lsp#HasCapability(conn_id, capability) abort
44     let g:capability_checked = a:capability
45
46     return 1
47   endfunction
48
49   function! ale#lsp#RegisterCallback(conn_id, callback) abort
50     let g:Callback = a:callback
51   endfunction
52
53   function! ale#lsp#Send(conn_id, message) abort
54     call add(g:message_list, a:message)
55
56     return 42
57   endfunction
58
59   function! ale#util#Execute(expr) abort
60     call add(g:expr_list, a:expr)
61   endfunction
62
63   function! ale#code_action#HandleCodeAction(code_action, options) abort
64     let g:handle_code_action_called = 1
65     Assert !get(a:options, 'should_save')
66     call add(g:code_actions, a:code_action)
67   endfunction
68
69   function! ale#util#Input(message, value) abort
70     return '2'
71   endfunction
72
73 After:
74   Restore
75
76   if g:conn_id isnot v:null
77     call ale#lsp#RemoveConnectionWithID(g:conn_id)
78   endif
79
80   call ale#test#RestoreDirectory()
81   call ale#linter#Reset()
82
83   unlet! g:capability_checked
84   unlet! g:InitCallback
85   unlet! g:old_filename
86   unlet! g:conn_id
87   unlet! g:Callback
88   unlet! g:message_list
89   unlet! g:expr_list
90   unlet! b:ale_linters
91   unlet! g:options
92   unlet! g:code_actions
93   unlet! g:handle_code_action_called
94
95   runtime autoload/ale/lsp_linter.vim
96   runtime autoload/ale/lsp.vim
97   runtime autoload/ale/util.vim
98   runtime autoload/ale/codefix.vim
99   runtime autoload/ale/code_action.vim
100
101 Execute(Failed codefix responses should be handled correctly):
102   call ale#codefix#HandleTSServerResponse(
103   \ 1,
104   \ {'command': 'getCodeFixes', 'request_seq': 3}
105   \)
106   AssertEqual g:handle_code_action_called, 0
107
108 Given typescript(Some typescript file):
109   foo
110   somelongerline ()
111   bazxyzxyzxyz
112
113 Execute(getCodeFixes from tsserver should be handled):
114   call ale#codefix#SetMap({3: {}})
115   call ale#codefix#HandleTSServerResponse(1, {
116     \ 'command': 'getCodeFixes',
117     \ 'request_seq': 3,
118     \ 'success': v:true,
119     \ 'type': 'response',
120     \ 'body': [
121     \   {
122     \     'description': 'Import default "x" from module "./z"',
123     \     'fixName': 'import',
124     \     'changes': [
125     \       {
126     \         'fileName': "/foo/bar/file1.ts",
127     \         'textChanges': [
128     \           {
129     \             'end': {
130     \               'line': 2,
131     \               'offset': 1,
132     \             },
133     \             'newText': 'import x from "./z";^@',
134     \             'start': {
135     \               'line': 2,
136     \               'offset': 1,
137     \             }
138     \           }
139     \         ]
140     \       }
141     \     ]
142     \   }
143     \ ]
144     \})
145
146   AssertEqual g:handle_code_action_called, 1
147   AssertEqual
148   \ [
149   \   {
150   \     'description': 'codefix',
151   \     'changes': [
152   \       {
153   \         'fileName': "/foo/bar/file1.ts",
154   \         'textChanges': [
155   \           {
156   \             'end': {
157   \               'line': 2,
158   \               'offset': 1
159   \             },
160   \             'newText': 'import x from "./z";^@',
161   \             'start': {
162   \               'line': 2,
163   \               'offset': 1
164   \             }
165   \           }
166   \         ]
167   \       }
168   \     ]
169   \   }
170   \ ],
171   \ g:code_actions
172
173 Execute(getCodeFixes from tsserver should be handled with user input if there are more than one action):
174   call ale#codefix#SetMap({3: {}})
175   call ale#codefix#HandleTSServerResponse(1, {
176     \ 'command': 'getCodeFixes',
177     \ 'request_seq': 3,
178     \ 'success': v:true,
179     \ 'type': 'response',
180     \ 'body': [
181     \   {
182     \     'description': 'Import default "x" from module "./z"',
183     \     'fixName': 'import',
184     \     'changes': [
185     \       {
186     \         'fileName': "/foo/bar/file1.ts",
187     \         'textChanges': [
188     \           {
189     \             'end': {
190     \               'line': 2,
191     \               'offset': 1,
192     \             },
193     \             'newText': 'import x from "./z";^@',
194     \             'start': {
195     \               'line': 2,
196     \               'offset': 1,
197     \             }
198     \           }
199     \         ]
200     \       }
201     \     ]
202     \   },
203     \   {
204     \     'description': 'Import default "x" from module "./y"',
205     \     'fixName': 'import',
206     \     'changes': [
207     \       {
208     \         'fileName': "/foo/bar/file1.ts",
209     \         'textChanges': [
210     \           {
211     \             'end': {
212     \               'line': 2,
213     \               'offset': 1,
214     \             },
215     \             'newText': 'import x from "./y";^@',
216     \             'start': {
217     \               'line': 2,
218     \               'offset': 1,
219     \             }
220     \           }
221     \         ]
222     \       }
223     \     ]
224     \   }
225     \ ]
226     \})
227
228   AssertEqual g:handle_code_action_called, 1
229   AssertEqual
230   \ [
231   \   {
232   \     'description': 'codefix',
233   \     'changes': [
234   \       {
235   \         'fileName': "/foo/bar/file1.ts",
236   \         'textChanges': [
237   \           {
238   \             'end': {
239   \               'line': 2,
240   \               'offset': 1
241   \             },
242   \             'newText': 'import x from "./y";^@',
243   \             'start': {
244   \               'line': 2,
245   \               'offset': 1
246   \             }
247   \           }
248   \         ]
249   \       }
250   \     ]
251   \   }
252   \ ],
253   \ g:code_actions
254
255 Execute(Prints a tsserver error message when getCodeFixes unsuccessful):
256   call ale#codefix#SetMap({3: {}})
257   call ale#codefix#HandleTSServerResponse(1, {
258   \ 'command': 'getCodeFixes',
259   \ 'request_seq': 3,
260   \ 'success': v:false,
261   \ 'message': 'something is wrong',
262   \})
263
264   AssertEqual g:handle_code_action_called, 0
265   AssertEqual ['echom ''Error while getting code fixes. Reason: something is wrong'''], g:expr_list
266
267 Execute(Does nothing when where are no code fixes):
268   call ale#codefix#SetMap({3: {}})
269   call ale#codefix#HandleTSServerResponse(1, {
270   \ 'command': 'getCodeFixes',
271   \ 'request_seq': 3,
272   \ 'success': v:true,
273   \ 'body': []
274   \})
275
276   AssertEqual g:handle_code_action_called, 0
277   AssertEqual ['echom ''No code fixes available.'''], g:expr_list
278
279 Execute(tsserver codefix requests should be sent):
280   call ale#linter#Reset()
281
282   runtime ale_linters/typescript/tsserver.vim
283   let g:ale_buffer_info = {bufnr(''): {'loclist': [{'lnum': 2, 'col': 5, 'code': 2304, 'linter_name': 'tsserver'}]}}
284   call setpos('.', [bufnr(''), 2, 16, 0])
285
286   " ALECodeAction
287   call ale#codefix#Execute(0)
288
289   " We shouldn't register the callback yet.
290   AssertEqual '''''', string(g:Callback)
291
292   AssertEqual type(function('type')), type(g:InitCallback)
293   call g:InitCallback()
294
295   AssertEqual 'code_actions', g:capability_checked
296   AssertEqual
297   \ 'function(''ale#codefix#HandleTSServerResponse'')',
298   \ string(g:Callback)
299   AssertEqual
300   \ [
301   \   ale#lsp#tsserver_message#Change(bufnr('')),
302   \   [0, 'ts@getCodeFixes', {
303   \     'startLine': 2,
304   \     'startOffset': 16,
305   \     'endLine': 2,
306   \     'endOffset': 17,
307   \     'file': expand('%:p'),
308   \     'errorCodes': [2304],
309   \   }]
310   \ ],
311   \ g:message_list
312
313 Execute(tsserver codefix requests should be sent only for error with code):
314   call ale#linter#Reset()
315
316   runtime ale_linters/typescript/tsserver.vim
317   let g:ale_buffer_info = {bufnr(''): {'loclist': [{'lnum': 2, 'col': 16, 'linter_name': 'tsserver'}, {'lnum': 2, 'col': 16, 'code': 2304, 'linter_name': 'tsserver'}]}}
318   call setpos('.', [bufnr(''), 2, 16, 0])
319
320   " ALECodeAction
321   call ale#codefix#Execute(0)
322
323   " We shouldn't register the callback yet.
324   AssertEqual '''''', string(g:Callback)
325
326   AssertEqual type(function('type')), type(g:InitCallback)
327   call g:InitCallback()
328
329   AssertEqual 'code_actions', g:capability_checked
330   AssertEqual
331   \ 'function(''ale#codefix#HandleTSServerResponse'')',
332   \ string(g:Callback)
333   AssertEqual
334   \ [
335   \   ale#lsp#tsserver_message#Change(bufnr('')),
336   \   [0, 'ts@getCodeFixes', {
337   \     'startLine': 2,
338   \     'startOffset': 16,
339   \     'endLine': 2,
340   \     'endOffset': 17,
341   \     'file': expand('%:p'),
342   \     'errorCodes': [2304],
343   \   }]
344   \ ],
345   \ g:message_list
346
347 Execute(getApplicableRefactors from tsserver should be handled):
348   call ale#codefix#SetMap({3: {
349   \ 'buffer': expand('%:p'),
350   \ 'line': 1,
351   \ 'column': 2,
352   \ 'end_line': 3,
353   \ 'end_column': 4,
354   \ 'connection_id': 0,
355   \}})
356   call ale#codefix#HandleTSServerResponse(1,
357   \ {'seq': 0, 'request_seq': 3, 'type': 'response', 'success': v:true, 'body': [{'actions': [{'description': 'Extract to constant in enclosing scope', 'name': 'constant_scope_0'}], 'description': 'Extract constant', 'name': 'Extract Symbol'}, {'actions': [{'description': 'Extract to function in module scope', 'name': 'function_scope_1'}], 'description': 'Extract function', 'name': 'Extract Symbol'}], 'command': 'getApplicableRefactors'})
358
359   AssertEqual
360   \ [
361   \   [0, 'ts@getEditsForRefactor', {
362   \     'startLine': 1,
363   \     'startOffset': 2,
364   \     'endLine': 3,
365   \     'endOffset': 5,
366   \     'file': expand('%:p'),
367   \     'refactor': 'Extract Symbol',
368   \     'action': 'function_scope_1',
369   \   }]
370   \ ],
371   \ g:message_list
372
373 Execute(getApplicableRefactors should print error on failure):
374   call ale#codefix#SetMap({3: {
375   \ 'buffer': expand('%:p'),
376   \ 'line': 1,
377   \ 'column': 2,
378   \ 'end_line': 3,
379   \ 'end_column': 4,
380   \ 'connection_id': 0,
381   \}})
382   call ale#codefix#HandleTSServerResponse(1,
383   \ {'seq': 0, 'request_seq': 3, 'type': 'response', 'success': v:false, 'message': 'oops', 'command': 'getApplicableRefactors'})
384
385   AssertEqual ['echom ''Error while getting applicable refactors. Reason: oops'''], g:expr_list
386
387 Execute(getApplicableRefactors should do nothing if there are no refactors):
388   call ale#codefix#SetMap({3: {
389   \ 'buffer': expand('%:p'),
390   \ 'line': 1,
391   \ 'column': 2,
392   \ 'end_line': 3,
393   \ 'end_column': 4,
394   \ 'connection_id': 0,
395   \}})
396   call ale#codefix#HandleTSServerResponse(1,
397   \ {'seq': 0, 'request_seq': 3, 'type': 'response', 'success': v:true, 'body': [], 'command': 'getApplicableRefactors'})
398
399   AssertEqual ['echom ''No applicable refactors available.'''], g:expr_list
400
401 Execute(getEditsForRefactor from tsserver should be handled):
402   call ale#codefix#SetMap({3: {}})
403   call ale#codefix#HandleTSServerResponse(1,
404   \{'seq': 0, 'request_seq': 3, 'type': 'response', 'success': v:true, 'body': {'edits': [{'fileName': '/foo/bar/file.ts', 'textChanges': [{'end': {'offset': 35, 'line': 9}, 'newText': 'newFunction(app);', 'start': {'offset': 3, 'line': 8}}, {'end': {'offset': 4, 'line': 19}, 'newText': '^@function newFunction(app: Router) {^@    app.use(booExpressCsrf());^@    app.use(booExpressRequireHttps);^@}^@', 'start': {'offset': 4, 'line': 19}}]}], 'renameLocation': {'offset': 3, 'line': 8}, 'renameFilename': '/foo/bar/file.ts'}, 'command': 'getEditsForRefactor' }
405   \)
406
407   AssertEqual g:handle_code_action_called, 1
408   AssertEqual
409   \ [
410   \   {
411   \     'description': 'editsForRefactor',
412   \     'changes': [{'fileName': '/foo/bar/file.ts', 'textChanges': [{'end': {'offset': 35, 'line': 9}, 'newText': 'newFunction(app);', 'start': {'offset': 3, 'line': 8}}, {'end': {'offset': 4, 'line': 19}, 'newText': '^@function newFunction(app: Router) {^@    app.use(booExpressCsrf());^@    app.use(booExpressRequireHttps);^@}^@', 'start': {'offset': 4, 'line': 19}}]}],
413   \   }
414   \ ],
415   \ g:code_actions
416
417 Execute(getEditsForRefactor should print error on failure):
418   call ale#codefix#SetMap({3: {}})
419   call ale#codefix#HandleTSServerResponse(1,
420   \{'seq': 0, 'request_seq': 3, 'type': 'response', 'success': v:false, 'message': 'oops', 'command': 'getEditsForRefactor' }
421   \)
422
423   AssertEqual ['echom ''Error while getting edits for refactor. Reason: oops'''], g:expr_list
424
425 Execute(Failed LSP responses should be handled correctly):
426   call ale#codefix#HandleLSPResponse(
427   \ 1,
428   \ {'method': 'workspace/applyEdit', 'request_seq': 3}
429   \)
430   AssertEqual g:handle_code_action_called, 0
431
432 Given python(Some python file):
433   def main():
434       a = 1
435       b = a + 2
436
437 Execute("workspace/applyEdit" from LSP should be handled):
438   call ale#codefix#SetMap({3: {}})
439   call ale#codefix#HandleLSPResponse(1,
440   \ {'id': 0, 'jsonrpc': '2.0', 'method': 'workspace/applyEdit', 'params': {'edit': {'changes': {'file:///foo/bar/file.ts': [{'range': {'end': {'character': 27, 'line': 7}, 'start': {'character': 27, 'line': 7}}, 'newText': ', Config'}, {'range': {'end': {'character': 12, 'line': 96}, 'start': {'character': 2, 'line': 94}}, 'newText': 'await newFunction(redis, imageKey, cover, config);'}, {'range': {'end': {'character': 2, 'line': 99}, 'start': {'character': 2, 'line': 99}}, 'newText': '^@async function newFunction(redis: IRedis, imageKey: string, cover: Buffer, config: Config) {^@    try {^@        await redis.set(imageKey, cover, ''ex'', parseInt(config.coverKeyTTL, 10));^@    }^@    catch { }^@}^@'}]}}}})
441
442   AssertEqual g:handle_code_action_called, 1
443   AssertEqual
444   \ [{'description': 'applyEdit', 'changes': [{'fileName': '/foo/bar/file.ts', 'textChanges': [{'end': {'offset': 28, 'line': 8}, 'newText': ', Config', 'start': {'offset': 28, 'line': 8}}, {'end': {'offset': 13, 'line': 97}, 'newText': 'await newFunction(redis, imageKey, cover, config);', 'start': {'offset': 3, 'line': 95}}, {'end': {'offset': 3, 'line': 100}, 'newText': '^@async function newFunction(redis: IRedis, imageKey: string, cover: Buffer, config: Config) {^@    try {^@        await redis.set(imageKey, cover, ''ex'', parseInt(config.coverKeyTTL, 10));^@    }^@    catch { }^@}^@', 'start': {'offset': 3, 'line': 100}}]}]}],
445   \ g:code_actions
446
447 Execute(Code Actions from LSP should be handled when returned with documentChanges):
448   call ale#codefix#SetMap({2: {}})
449   call ale#codefix#HandleLSPResponse(1,
450   \ {'id': 2, 'jsonrpc': '2.0', 'result': [{'diagnostics': v:null, 'edit': {'changes': v:null, 'documentChanges': [{'edits': [{'range': {'end': {'character': 4, 'line': 2}, 'start': {'character': 4, 'line': 1}}, 'newText': ''}, {'range': {'end': {'character': 9, 'line': 2}, 'start': {'character': 8, 'line': 2}}, 'newText': '(1)'}], 'textDocument': {'uri': 'file:///foo/bar/test.py', 'version': v:null}}]}, 'kind': 'refactor.inline', 'title': 'Inline variable', 'command': v:null}, {'diagnostics': v:null, 'edit': {'changes': v:null, 'documentChanges': [{'edits': [{'range': {'end': {'character': 0, 'line': 0}, 'start': {'character': 0, 'line': 0}}, 'newText': 'def func_bomdjnxh():^@    a = 1return a^@^@^@'}, {'range': {'end': {'character': 9, 'line': 1}, 'start': {'character': 8, 'line': 1}}, 'newText': 'func_bomdjnxh()^@'}], 'textDocument': {'uri': 'file:///foo/bar/test.py', 'version': v:null}}]}, 'kind': 'refactor.extract', 'title': 'Extract expression into function ''func_bomdjnxh''', 'command': v:null}]})
451
452   AssertEqual g:handle_code_action_called, 1
453   AssertEqual
454   \ [{'description': 'codeaction', 'changes': [{'fileName': '/foo/bar/test.py', 'textChanges': [{'end': {'offset': 1, 'line': 1}, 'newText': 'def func_bomdjnxh():^@    a = 1return a^@^@^@', 'start': {'offset': 1, 'line': 1}}, {'end': {'offset': 10, 'line': 2}, 'newText': 'func_bomdjnxh()^@', 'start': {'offset': 9, 'line': 2}}]}]}],
455   \ g:code_actions
456
457 Execute(LSP Code Actions handles CodeAction responses):
458   call ale#codefix#SetMap({3: {
459   \ 'connection_id': 0,
460   \}})
461   call ale#codefix#HandleLSPResponse(1,
462   \ {'id': 3, 'jsonrpc': '2.0', 'result': [{'kind': 'refactor', 'title': 'Extract to inner function in function ''getVideo''', 'command': {'arguments': [{'file': '/foo/bar/file.ts', 'endOffset': 0, 'action': 'function_scope_0', 'startOffset': 1, 'startLine': 65, 'refactor': 'Extract Symbol', 'endLine': 68}], 'title': 'Extract to inner function in function ''getVideo''', 'command': '_typescript.applyRefactoring'}}, {'kind': 'refactor', 'title': 'Extract to function in module scope', 'command': {'arguments': [{'file': '/foo/bar/file.ts', 'endOffset': 0, 'action': 'function_scope_1', 'startOffset': 1, 'startLine': 65, 'refactor': 'Extract Symbol', 'endLine': 68}], 'title': 'Extract to function in module scope', 'command': '_typescript.applyRefactoring'}}]})
463
464   AssertEqual
465   \ [[0, 'workspace/executeCommand', {'arguments': [{'file': '/foo/bar/file.ts', 'action': 'function_scope_1', 'endOffset': 0, 'refactor': 'Extract Symbol', 'endLine': 68, 'startLine': 65, 'startOffset': 1}], 'command': '_typescript.applyRefactoring'}]],
466   \ g:message_list
467
468 Execute(LSP Code Actions handles Command responses):
469   call ale#codefix#SetMap({2: {
470   \ 'connection_id': 2,
471   \}})
472   call ale#codefix#HandleLSPResponse(1,
473   \ {'id': 2, 'jsonrpc': '2.0', 'result': [{'title': 'fake for testing'}, {'arguments': [{'documentChanges': [{'edits': [{'range': {'end': {'character': 31, 'line': 2}, 'start': {'character': 31, 'line': 2}}, 'newText': ', createVideo'}], 'textDocument': {'uri': 'file:///foo/bar/file.ts', 'version': 1}}]}], 'title': 'Add ''createVideo'' to existing import declaration from "./video"', 'command': '_typescript.applyWorkspaceEdit'}]})
474
475   AssertEqual
476   \ [[0, 'workspace/executeCommand', {'arguments': [{'documentChanges': [{'edits': [{'range': {'end': {'character': 31, 'line': 2}, 'start': {'character': 31, 'line': 2}}, 'newText': ', createVideo'}], 'textDocument': {'uri': 'file:///foo/bar/file.ts', 'version': 1}}]}], 'command': '_typescript.applyWorkspaceEdit'}]],
477   \ g:message_list
478
479 Execute(Prints message when LSP code action returns no results):
480   call ale#codefix#SetMap({3: {}})
481   call ale#codefix#HandleLSPResponse(1,
482   \ {'id': 3, 'jsonrpc': '2.0', 'result': []})
483
484   AssertEqual g:handle_code_action_called, 0
485   AssertEqual ['echom ''No code actions received from server'''], g:expr_list
486
487 Execute(LSP code action requests should be sent):
488   call ale#linter#Reset()
489
490   runtime ale_linters/python/jedils.vim
491   let g:ale_buffer_info = {bufnr(''): {'loclist': [{'lnum': 2, 'col': 5, 'end_lnum': 2, 'end_col': 6, 'code': 2304, 'text': 'oops'}]}}
492   call setpos('.', [bufnr(''), 2, 5, 0])
493
494   " ALECodeAction
495   call ale#codefix#Execute(0)
496
497   " We shouldn't register the callback yet.
498   AssertEqual '''''', string(g:Callback)
499
500   AssertEqual type(function('type')), type(g:InitCallback)
501   call g:InitCallback()
502
503   AssertEqual 'code_actions', g:capability_checked
504   AssertEqual
505   \ 'function(''ale#codefix#HandleLSPResponse'')',
506   \ string(g:Callback)
507   AssertEqual
508   \ [
509   \   [0, 'textDocument/codeAction', {
510   \     'context': {
511   \       'diagnostics': [{'range': {'end': {'character': 6, 'line': 1}, 'start': {'character': 4, 'line': 1}}, 'code': 2304, 'message': 'oops'}]
512   \     },
513   \     'range': {'end': {'character': 5, 'line': 1}, 'start': {'character': 4, 'line': 1}},
514   \     'textDocument': {'uri': ale#path#ToFileURI(expand('%:p'))}
515   \   }]
516   \ ],
517   \ g:message_list[-1:]
518
519 Execute(LSP code action requests should be sent only for error with code):
520   call ale#linter#Reset()
521
522   runtime ale_linters/python/jedils.vim
523   let g:ale_buffer_info = {bufnr(''): {'loclist': [{'lnum': 2, 'col': 5, 'end_lnum': 2, 'end_col': 6, 'code': 2304, 'text': 'oops'}]}}
524   call setpos('.', [bufnr(''), 2, 5, 0])
525
526   " ALECodeAction
527   call ale#codefix#Execute(0)
528
529   " We shouldn't register the callback yet.
530   AssertEqual '''''', string(g:Callback)
531
532   AssertEqual type(function('type')), type(g:InitCallback)
533   call g:InitCallback()
534
535   AssertEqual 'code_actions', g:capability_checked
536   AssertEqual
537   \ 'function(''ale#codefix#HandleLSPResponse'')',
538   \ string(g:Callback)
539   AssertEqual
540   \ [
541   \   [0, 'textDocument/codeAction', {
542   \     'context': {
543   \       'diagnostics': [{'range': {'end': {'character': 6, 'line': 1}, 'start': {'character': 4, 'line': 1}}, 'code': 2304, 'message': 'oops'}]
544   \     },
545   \     'range': {'end': {'character': 5, 'line': 1}, 'start': {'character': 4, 'line': 1}},
546   \     'textDocument': {'uri': ale#path#ToFileURI(expand('%:p'))}
547   \   }]
548   \ ],
549   \ g:message_list[-1:]