diff options
author | Jerko Steiner <jerko.steiner@gmail.com> | 2022-02-08 12:07:39 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-02-08 20:07:39 +0900 |
commit | 4a4516e3bf792300f377c435c2206526a8963103 (patch) | |
tree | 7e0b2951cc32f55fe72dfc2cea440da7b0343eee | |
parent | 8b1ea33cc0cb18bec3bf19d1131b322b313cea4e (diff) | |
download | ale-4a4516e3bf792300f377c435c2206526a8963103.zip |
Dispatch textDocument/didChange after rename (2) (#4049)
* Dispatch textDocument/didChange after rename
Previously whenever we renamed a symbol that was referenced from other
files we'd just edit those files in the background, and the LSP wouldn't
know about these changes. If we tried to rename the same symbol again,
the renaming would fail. In some scenarios, the operation would just be
wrong. Here is an attempt to fix this issue.
I also noticed another bug when using Go with `gopls` LSP and the `gofmt`
fixer. Whenever the file was saved, the `gofmt` would run and reformat
the file. But it seems there was some kind of a race condition so I
disabled saving for now, and all of the modified files will be unsaved,
so the user should call `:wa` to save them. I personally like this even
better because I can inspect exactly what changes happened, and I
instantly see them in the other opened buffers, which was previously not
the case.
Fixes #3343, #3642, #3781.
* Address PR comments
* Remove mode tests in corner case tests
* Address PR comments
* Save after ALERename and ALEOrganizeImports
Also provide options to disable automatic saving, as well as instructions to
enable `set hidden` before doing that.
* Fix broken test
* Save only when !&hidden
* Update doc
* Update doc
* Add silent
-rw-r--r-- | autoload/ale/code_action.vim | 80 | ||||
-rw-r--r-- | autoload/ale/organize_imports.vim | 7 | ||||
-rw-r--r-- | autoload/ale/rename.vim | 6 | ||||
-rw-r--r-- | doc/ale.txt | 6 | ||||
-rw-r--r-- | test/test_code_action.vader | 235 | ||||
-rw-r--r-- | test/test_code_action_corner_cases.vader | 168 | ||||
-rw-r--r-- | test/test_code_action_python.vader | 4 | ||||
-rw-r--r-- | test/test_organize_imports.vader | 2 | ||||
-rw-r--r-- | test/test_rename.vader | 2 |
9 files changed, 329 insertions, 181 deletions
diff --git a/autoload/ale/code_action.vim b/autoload/ale/code_action.vim index 917190be..65db6246 100644 --- a/autoload/ale/code_action.vim +++ b/autoload/ale/code_action.vim @@ -16,13 +16,12 @@ endfunction function! ale#code_action#HandleCodeAction(code_action, options) abort let l:current_buffer = bufnr('') let l:changes = a:code_action.changes - let l:should_save = get(a:options, 'should_save') for l:file_code_edit in l:changes call ale#code_action#ApplyChanges( \ l:file_code_edit.fileName, \ l:file_code_edit.textChanges, - \ l:should_save, + \ a:options, \) endfor endfunction @@ -63,29 +62,29 @@ function! s:ChangeCmp(left, right) abort return 0 endfunction -function! ale#code_action#ApplyChanges(filename, changes, should_save) abort - let l:current_buffer = bufnr('') +function! ale#code_action#ApplyChanges(filename, changes, options) abort + let l:should_save = get(a:options, 'should_save') + let l:conn_id = get(a:options, 'conn_id') + + let l:orig_buffer = bufnr('') + " The buffer is used to determine the fileformat, if available. let l:buffer = bufnr(a:filename) - let l:is_current_buffer = l:buffer > 0 && l:buffer == l:current_buffer - if l:buffer > 0 - let l:lines = getbufline(l:buffer, 1, '$') - - " Add empty line if there's trailing newline, like readfile() does. - if getbufvar(l:buffer, '&eol') - let l:lines += [''] - endif - else - let l:lines = readfile(a:filename, 'b') + if l:buffer != l:orig_buffer + call ale#util#Execute('silent edit ' . a:filename) + let l:buffer = bufnr('') endif - if l:is_current_buffer - let l:pos = getpos('.')[1:2] - else - let l:pos = [1, 1] + let l:lines = getbufline(l:buffer, 1, '$') + + " Add empty line if there's trailing newline, like readfile() does. + if getbufvar(l:buffer, '&eol') + let l:lines += [''] endif + let l:pos = getpos('.')[1:2] + " Changes have to be sorted so we apply them from bottom-to-top for l:code_edit in reverse(sort(copy(a:changes), function('s:ChangeCmp'))) let l:line = l:code_edit.start.line @@ -155,46 +154,25 @@ function! ale#code_action#ApplyChanges(filename, changes, should_save) abort endif endfor - if l:buffer > 0 - " Make sure ale#util#{Writefile,SetBufferContents} add trailing - " newline if and only if it should be added. - if l:lines[-1] is# '' && getbufvar(l:buffer, '&eol') - call remove(l:lines, -1) - else - call setbufvar(l:buffer, '&eol', 0) - endif - elseif exists('+fixeol') && &fixeol && l:lines[-1] is# '' - " Not in buffer, ale#util#Writefile can't check &eol and always adds - " newline if &fixeol: remove to prevent double trailing newline. + " Make sure to add a trailing newline if and only if it should be added. + if l:lines[-1] is# '' && getbufvar(l:buffer, '&eol') call remove(l:lines, -1) - endif - - if a:should_save || l:buffer < 0 - call ale#util#Writefile(l:buffer, l:lines, a:filename) else - call ale#util#SetBufferContents(l:buffer, l:lines) + call setbufvar(l:buffer, '&eol', 0) endif - if l:is_current_buffer - if a:should_save - call ale#util#Execute(':e!') - endif + call ale#util#SetBufferContents(l:buffer, l:lines) - call setpos('.', [0, l:pos[0], l:pos[1], 0]) + call ale#lsp#NotifyForChanges(l:conn_id, l:buffer) + + if l:should_save + call ale#util#Execute('silent w!') endif - if a:should_save && l:buffer > 0 && !l:is_current_buffer - " Set up a one-time use event that will delete itself to reload the - " buffer next time it's entered to view the changes made to it. - execute 'augroup ALECodeActionReloadGroup' . l:buffer - autocmd! - - execute printf( - \ 'autocmd BufEnter <buffer=%d>' - \ . ' call ale#code_action#ReloadBuffer()', - \ l:buffer - \) - augroup END + call setpos('.', [0, l:pos[0], l:pos[1], 0]) + + if l:orig_buffer != l:buffer && bufexists(l:orig_buffer) + call ale#util#Execute('silent buf ' . string(l:orig_buffer)) endif endfunction diff --git a/autoload/ale/organize_imports.vim b/autoload/ale/organize_imports.vim index e2b1c0d2..a6e77863 100644 --- a/autoload/ale/organize_imports.vim +++ b/autoload/ale/organize_imports.vim @@ -1,6 +1,6 @@ " Author: Jerko Steiner <jerko.steiner@gmail.com> " Description: Organize imports support for tsserver -" + function! ale#organize_imports#HandleTSServerResponse(conn_id, response) abort if get(a:response, 'command', '') isnot# 'organizeImports' return @@ -17,7 +17,10 @@ function! ale#organize_imports#HandleTSServerResponse(conn_id, response) abort \ 'description': 'Organize Imports', \ 'changes': l:file_code_edits, \ }, - \ {} + \ { + \ 'conn_id': a:conn_id, + \ 'should_save': !&hidden, + \ }, \) endfunction diff --git a/autoload/ale/rename.vim b/autoload/ale/rename.vim index 9030618e..a722cc94 100644 --- a/autoload/ale/rename.vim +++ b/autoload/ale/rename.vim @@ -84,7 +84,8 @@ function! ale#rename#HandleTSServerResponse(conn_id, response) abort \ 'changes': l:changes, \ }, \ { - \ 'should_save': 1, + \ 'conn_id': a:conn_id, + \ 'should_save': !&hidden, \ }, \) endfunction @@ -116,7 +117,8 @@ function! ale#rename#HandleLSPResponse(conn_id, response) abort \ 'changes': l:changes, \ }, \ { - \ 'should_save': 1, + \ 'conn_id': a:conn_id, + \ 'should_save': !&hidden, \ }, \) endif diff --git a/doc/ale.txt b/doc/ale.txt index 6dbfb6d0..348cffaf 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -1820,8 +1820,8 @@ g:ale_open_list *g:ale_open_list* autocmd! autocmd QuitPre * if empty(&buftype) | lclose | endif augroup END -< +< g:ale_pattern_options *g:ale_pattern_options* Type: |Dictionary| @@ -3435,6 +3435,10 @@ ALERename *ALERename* The symbol where the cursor is resting will be the symbol renamed, and a prompt will open to request a new name. + The rename operation will save all modified buffers when `set nohidden` is + set, because that disables leaving unsaved buffers in the background. See + `:help hidden` for more details. + ALEFileRename *ALEFileRename* Rename a file and fix imports using `tsserver`. diff --git a/test/test_code_action.vader b/test/test_code_action.vader index c613222c..80e2b1d8 100644 --- a/test/test_code_action.vader +++ b/test/test_code_action.vader @@ -1,4 +1,15 @@ Before: + let g:notified_changes = [] + + runtime autoload/ale/lsp.vim + + function! ale#lsp#NotifyForChanges(conn_id, buffer) abort + call add(g:notified_changes, { + \ 'conn_id': a:conn_id, + \ 'buffer': a:buffer + \}) + endfunction + Save g:ale_enabled let g:ale_enabled = 0 @@ -36,10 +47,10 @@ Before: After: " Close the extra buffers if we opened it. - if bufnr(g:file1) != -1 + if bufnr(g:file1) != -1 && buflisted(bufnr(g:file1)) execute ':bp! | :bd! ' . bufnr(g:file1) endif - if bufnr(g:file2) != -1 + if bufnr(g:file2) != -1 && buflisted(bufnr(g:file2)) execute ':bp! | :bd! ' . bufnr(g:file2) endif @@ -50,12 +61,16 @@ After: call delete(g:file2) endif + unlet! g:notified_changes + " unlet! g:expected_notified_changes unlet! g:file1 unlet! g:file2 unlet! g:test unlet! g:changes delfunction WriteFileAndEdit + runtime autoload/ale/lsp.vim + Restore @@ -118,7 +133,7 @@ Execute(It should modify and save multiple files): \ }] \ }], \ }, - \ {'should_save': 1}, + \ {'should_save': 1, 'conn_id': 'test_conn'}, \) AssertEqual [ @@ -140,6 +155,13 @@ Execute(It should modify and save multiple files): \ '', \], readfile(g:file2, 'b') + AssertEqual [{ + \ 'conn_id': 'test_conn', + \ 'buffer': bufnr(g:file1), + \}, { + \ 'conn_id': 'test_conn', + \ 'buffer': bufnr(g:file2), + \}], g:notified_changes Execute(Beginning of file can be modified): let g:test.text = [ @@ -166,7 +188,7 @@ Execute(Beginning of file can be modified): \ }], \ }] \ }, - \ {'should_save': 1}, + \ {'should_save': 1, 'conn_id': 'test_conn'}, \) AssertEqual [ @@ -174,6 +196,11 @@ Execute(Beginning of file can be modified): \ 'type B: number', \] + g:test.text + [''], readfile(g:file1, 'b') + AssertEqual [{ + \ 'conn_id': 'test_conn', + \ 'buffer': bufnr(g:file1), + \}], g:notified_changes + Execute(End of file can be modified): let g:test.text = [ @@ -200,7 +227,7 @@ Execute(End of file can be modified): \ }], \ }] \ }, - \ {'should_save': 1}, + \ {'should_save': 1, 'conn_id': 'test_conn'}, \) AssertEqual g:test.text + [ @@ -209,6 +236,11 @@ Execute(End of file can be modified): \ '', \], readfile(g:file1, 'b') + AssertEqual [{ + \ 'conn_id': 'test_conn', + \ 'buffer': bufnr(g:file1), + \}], g:notified_changes + Execute(Current buffer contents will be reloaded): let g:test.text = [ @@ -238,7 +270,7 @@ Execute(Current buffer contents will be reloaded): \ }], \ }] \ }, - \ {'should_save': 1}, + \ {'should_save': 1, 'conn_id': 'test_conn'}, \) AssertEqual [ @@ -251,6 +283,55 @@ Execute(Current buffer contents will be reloaded): \ 'type B: number', \] + g:test.text, getbufline(g:test.buffer, 1, '$') + AssertEqual [{ + \ 'conn_id': 'test_conn', + \ 'buffer': bufnr(g:file1), + \}], g:notified_changes + + +Execute(Unlisted buffer contents will be modified correctly): + let g:test.text = [ + \ 'class Name {', + \ ' value: string', + \ '}', + \] + call writefile(g:test.text, g:file1, 'S') + + execute 'edit ' . g:file1 + let g:test.buffer = bufnr(g:file1) + + execute 'bd' + AssertEqual bufnr(g:file1), g:test.buffer + + call ale#code_action#HandleCodeAction( + \ { + \ 'changes': [{ + \ 'fileName': g:file1, + \ 'textChanges': [{ + \ 'start': { + \ 'line': 1, + \ 'offset': 1, + \ }, + \ 'end': { + \ 'line': 1, + \ 'offset': 1, + \ }, + \ 'newText': "type A: string\ntype B: number\n", + \ }], + \ }] + \ }, + \ {'should_save': 1, 'conn_id': 'test_conn'}, + \) + + AssertEqual [ + \ 'type A: string', + \ 'type B: number', + \] + g:test.text + [''], readfile(g:file1, 'b') + + AssertEqual [{ + \ 'conn_id': 'test_conn', + \ 'buffer': bufnr(g:file1), + \}], g:notified_changes # Tests for cursor repositioning. In comments `=` designates change range, and # `C` cursor position @@ -261,13 +342,32 @@ Execute(Cursor will not move when it is before text change): let g:test.changes = g:test.create_change(2, 3, 2, 8, 'value2') call setpos('.', [0, 1, 1, 0]) - call ale#code_action#HandleCodeAction(g:test.changes, {'should_save': 1}) + call ale#code_action#HandleCodeAction(g:test.changes, { + \ 'should_save': 1, + \ 'conn_id': 'test_conn', + \}) AssertEqual [1, 1], getpos('.')[1:2] + AssertEqual [{ + \ 'conn_id': 'test_conn', + \ 'buffer': bufnr(''), + \}], g:notified_changes + call setpos('.', [0, 2, 2, 0]) - call ale#code_action#HandleCodeAction(g:test.changes, {'should_save': 1}) + call ale#code_action#HandleCodeAction(g:test.changes, { + \ 'should_save': 1, + \ 'conn_id': 'test_conn', + \}) AssertEqual [2, 2], getpos('.')[1:2] + AssertEqual [{ + \ 'conn_id': 'test_conn', + \ 'buffer': bufnr(''), + \}, { + \ 'conn_id': 'test_conn', + \ 'buffer': bufnr(''), + \}], g:notified_changes + # ====C==== Execute(Cursor column will move to the change end when cursor between start/end): let g:test.changes = g:test.create_change(2, 3, 2, 8, 'value2') @@ -276,11 +376,34 @@ Execute(Cursor column will move to the change end when cursor between start/end) call WriteFileAndEdit() call setpos('.', [0, 2, r, 0]) AssertEqual ' value: string', getline('.') - call ale#code_action#HandleCodeAction(g:test.changes, {'should_save': 1}) + call ale#code_action#HandleCodeAction(g:test.changes, { + \ 'should_save': 1, + \ 'conn_id': 'test_conn', + \}) AssertEqual ' value2: string', getline('.') AssertEqual [2, 9], getpos('.')[1:2] endfor + AssertEqual [{ + \ 'conn_id': 'test_conn', + \ 'buffer': bufnr(''), + \}, { + \ 'conn_id': 'test_conn', + \ 'buffer': bufnr(''), + \}, { + \ 'conn_id': 'test_conn', + \ 'buffer': bufnr(''), + \}, { + \ 'conn_id': 'test_conn', + \ 'buffer': bufnr(''), + \}, { + \ 'conn_id': 'test_conn', + \ 'buffer': bufnr(''), + \}, { + \ 'conn_id': 'test_conn', + \ 'buffer': bufnr(''), + \}], g:notified_changes + # ====C Execute(Cursor column will move back when new text is shorter): @@ -289,11 +412,18 @@ Execute(Cursor column will move back when new text is shorter): AssertEqual ' value: string', getline('.') call ale#code_action#HandleCodeAction( \ g:test.create_change(2, 3, 2, 8, 'val'), - \ {'should_save': 1}, - \) + \ { + \ 'should_save': 1, + \ 'conn_id': 'test_conn', + \ }) AssertEqual ' val: string', getline('.') AssertEqual [2, 6], getpos('.')[1:2] + AssertEqual [{ + \ 'conn_id': 'test_conn', + \ 'buffer': bufnr(''), + \}], g:notified_changes + # ==== C Execute(Cursor column will move forward when new text is longer): @@ -302,10 +432,19 @@ Execute(Cursor column will move forward when new text is longer): call setpos('.', [0, 2, 8, 0]) AssertEqual ' value: string', getline('.') call ale#code_action#HandleCodeAction( - \ g:test.create_change(2, 3, 2, 8, 'longValue'), {'should_save': 1}) + \ g:test.create_change(2, 3, 2, 8, 'longValue'), + \ { + \ 'should_save': 1, + \ 'conn_id': 'test_conn', + \ }) AssertEqual ' longValue: string', getline('.') AssertEqual [2, 12], getpos('.')[1:2] + AssertEqual [{ + \ 'conn_id': 'test_conn', + \ 'buffer': bufnr(''), + \}], g:notified_changes + # ========= # = # C @@ -314,10 +453,19 @@ Execute(Cursor line will move when updates are happening on lines above): call setpos('.', [0, 3, 1, 0]) AssertEqual '}', getline('.') call ale#code_action#HandleCodeAction( - \ g:test.create_change(1, 1, 2, 1, "test\ntest\n"), {'should_save': 1}) + \ g:test.create_change(1, 1, 2, 1, "test\ntest\n"), + \ { + \ 'should_save': 1, + \ 'conn_id': 'test_conn', + \ }) AssertEqual '}', getline('.') AssertEqual [4, 1], getpos('.')[1:2] + AssertEqual [{ + \ 'conn_id': 'test_conn', + \ 'buffer': bufnr(''), + \}], g:notified_changes + # ========= # =C @@ -326,10 +474,19 @@ Execute(Cursor line and column will move when change on lines above and just bef call setpos('.', [0, 2, 2, 0]) AssertEqual ' value: string', getline('.') call ale#code_action#HandleCodeAction( - \ g:test.create_change(1, 1, 2, 1, "test\ntest\n123"), {'should_save': 1}) + \ g:test.create_change(1, 1, 2, 1, "test\ntest\n123"), + \ { + \ 'should_save': 1, + \ 'conn_id': 'test_conn', + \ }) AssertEqual '123 value: string', getline('.') AssertEqual [3, 5], getpos('.')[1:2] + AssertEqual [{ + \ 'conn_id': 'test_conn', + \ 'buffer': bufnr(''), + \}], g:notified_changes + # ========= # ======C== # = @@ -338,10 +495,19 @@ Execute(Cursor line and column will move at the end of changes): call setpos('.', [0, 2, 10, 0]) AssertEqual ' value: string', getline('.') call ale#code_action#HandleCodeAction( - \ g:test.create_change(1, 1, 3, 1, "test\n"), {'should_save': 1}) + \ g:test.create_change(1, 1, 3, 1, "test\n"), + \ { + \ 'should_save': 1, + \ 'conn_id': 'test_conn', + \ }) AssertEqual '}', getline('.') AssertEqual [2, 1], getpos('.')[1:2] + AssertEqual [{ + \ 'conn_id': 'test_conn', + \ 'buffer': bufnr(''), + \}], g:notified_changes + # C == # === Execute(Cursor will not move when changes happening on lines >= cursor, but after cursor): @@ -349,23 +515,42 @@ Execute(Cursor will not move when changes happening on lines >= cursor, but afte call setpos('.', [0, 2, 3, 0]) AssertEqual ' value: string', getline('.') call ale#code_action#HandleCodeAction( - \ g:test.create_change(2, 10, 3, 1, "number\n"), {'should_save': 1}) + \ g:test.create_change(2, 10, 3, 1, "number\n"), + \ { + \ 'should_save': 1, + \ 'conn_id': 'test_conn', + \ }) AssertEqual ' value: number', getline('.') AssertEqual [2, 3], getpos('.')[1:2] + AssertEqual [{ + \ 'conn_id': 'test_conn', + \ 'buffer': bufnr(''), + \}], g:notified_changes + Execute(Cursor will not move when change covers entire file): call WriteFileAndEdit() call setpos('.', [0, 2, 3, 0]) call ale#code_action#HandleCodeAction( \ g:test.create_change(1, 1, len(g:test.text) + 1, 1, \ join(g:test.text + ['x'], "\n")), - \ {'should_save': 1}) + \ { + \ 'should_save': 1, + \ 'conn_id': 'test_conn', + \ }) AssertEqual [2, 3], getpos('.')[1:2] + AssertEqual [{ + \ 'conn_id': 'test_conn', + \ 'buffer': bufnr(''), + \}], g:notified_changes + Execute(It should just modify file when should_save is set to v:false): call WriteFileAndEdit() let g:test.change = g:test.create_change(1, 1, 1, 1, "import { writeFile } from 'fs';\n") - call ale#code_action#HandleCodeAction(g:test.change, {}) + call ale#code_action#HandleCodeAction(g:test.change, { + \ 'conn_id': 'test_conn', + \}) AssertEqual 1, getbufvar(bufnr(''), '&modified') AssertEqual [ \ 'import { writeFile } from ''fs'';', @@ -374,6 +559,11 @@ Execute(It should just modify file when should_save is set to v:false): \ '}', \], getline(1, '$') + AssertEqual [{ + \ 'conn_id': 'test_conn', + \ 'buffer': bufnr(''), + \}], g:notified_changes + Given typescript(An example TypeScript file): type Foo = {} @@ -393,7 +583,14 @@ Execute(): \ {'end': {'offset': 14, 'line': 9}, 'newText': 'foo', 'start': {'offset': 3, 'line': 9}}, \] - call ale#code_action#ApplyChanges(expand('%:p'), g:changes, 0) + call ale#code_action#ApplyChanges(expand('%:p'), g:changes, { + \ 'conn_id': 'test_conn', + \}) + + AssertEqual [{ + \ 'conn_id': 'test_conn', + \ 'buffer': bufnr(''), + \}], g:notified_changes Expect(The changes should be applied correctly): type Foo = {} diff --git a/test/test_code_action_corner_cases.vader b/test/test_code_action_corner_cases.vader index c44cf0ea..7cdbba8a 100644 --- a/test/test_code_action_corner_cases.vader +++ b/test/test_code_action_corner_cases.vader @@ -34,20 +34,16 @@ Before: Save &fileformats set fileformats=unix - " two files, one accessed through a buffer, the other using write/readfile only - let g:files = [tempname(), tempname()] - - function! TestChanges(contents, changes, mode) abort - let l:file = g:files[a:mode is 'file' ? 0 : 1] - call writefile(split(a:contents, '\n', 1), l:file, 'bS') - if a:mode isnot 'file' - execute 'edit ' . l:file - endif - call ale#code_action#ApplyChanges(l:file, a:changes, a:mode isnot 'buffer') - if a:mode is 'buffer' - execute 'write ' . l:file - endif - return join(readfile(l:file, 'b'), "\n") + let g:file = tempname() + + function! TestChanges(contents, changes) abort + call writefile(split(a:contents, '\n', 1), g:file, 'bS') + + call ale#code_action#ApplyChanges(g:file, a:changes, { + \ 'should_save': 1, + \}) + + return join(readfile(g:file, 'b'), "\n") endfunction! function! MkPos(line, offset) abort @@ -63,17 +59,15 @@ Before: endfunction! After: - for g:file in g:files - if bufnr(g:file) != -1 - execute ':bp! | :bd! ' . bufnr(g:file) - endif - if filereadable(g:file) - call delete(g:file) - endif - endfor - unlet! g:files g:file - - unlet! g:mode + if bufnr(g:file) != -1 + execute ':bp! | :bd! ' . bufnr(g:file) + endif + + if filereadable(g:file) + call delete(g:file) + endif + + unlet! g:file delfunction TestChanges delfunction MkPos @@ -83,97 +77,67 @@ After: Restore Execute(Preserve (no)eol at eof): - for g:mode in ['save', 'file', 'buffer'] - Log g:mode - AssertEqual "noeol", TestChanges("noeol", [], g:mode) - AssertEqual "eol\n", TestChanges("eol\n", [], g:mode) - AssertEqual "eols\n\n", TestChanges("eols\n\n", [], g:mode) - endfor - - " there doesn't seem to be a way to tell if a buffer is empty or contains one - " empty line :-( - AssertEqual "", TestChanges("", [], 'file') + AssertEqual "noeol", TestChanges("noeol", []) + AssertEqual "eol\n", TestChanges("eol\n", []) + AssertEqual "eols\n\n", TestChanges("eols\n\n", []) Execute(Respect fixeol): set fixeol - for g:mode in ['save', 'file', 'buffer'] - Log g:mode - silent echo "vscode skip" | AssertEqual "noeol\n", TestChanges("noeol", [], g:mode) - silent echo "vscode skip" | AssertEqual "eol\n", TestChanges("eol\n", [], g:mode) - endfor + + silent echo "vscode skip" | AssertEqual "noeol\n", TestChanges("noeol", []) + silent echo "vscode skip" | AssertEqual "eol\n", TestChanges("eol\n", []) Execute(Add/del eol at eof): - for g:mode in ['save', 'file', 'buffer'] - Log g:mode - AssertEqual "addeol\n", TestChanges("addeol", [MkInsert(MkPos(1, 7), "\n")], g:mode) - AssertEqual "deleol", TestChanges("deleol\n", [MkDelete(MkPos(1, 7), MkPos(1, 8))], g:mode) - endfor + AssertEqual "addeol\n", TestChanges("addeol", [MkInsert(MkPos(1, 7), "\n")]) + AssertEqual "deleol", TestChanges("deleol\n", [MkDelete(MkPos(1, 7), MkPos(1, 8))]) Execute(One character insertions to first line): - for g:mode in ['save', 'file', 'buffer'] - Log g:mode - AssertEqual "xabc\ndef1\nghi\n", TestChanges("abc\ndef1\nghi\n", [MkInsert(MkPos(1, 0), "x")], g:mode) - AssertEqual "xabc\ndef2\nghi\n", TestChanges("abc\ndef2\nghi\n", [MkInsert(MkPos(1, 1), "x")], g:mode) - AssertEqual "axbc\ndef3\nghi\n", TestChanges("abc\ndef3\nghi\n", [MkInsert(MkPos(1, 2), "x")], g:mode) - AssertEqual "abcx\ndef4\nghi\n", TestChanges("abc\ndef4\nghi\n", [MkInsert(MkPos(1, 4), "x")], g:mode) - AssertEqual "abc\nxdef5\nghi\n", TestChanges("abc\ndef5\nghi\n", [MkInsert(MkPos(1, 5), "x")], g:mode) - AssertEqual "abc\nxdef6\nghi\n", TestChanges("abc\ndef6\nghi\n", [MkInsert(MkPos(1, 6), "x")], g:mode) - endfor + AssertEqual "xabc\ndef1\nghi\n", TestChanges("abc\ndef1\nghi\n", [MkInsert(MkPos(1, 0), "x")]) + AssertEqual "xabc\ndef2\nghi\n", TestChanges("abc\ndef2\nghi\n", [MkInsert(MkPos(1, 1), "x")]) + AssertEqual "axbc\ndef3\nghi\n", TestChanges("abc\ndef3\nghi\n", [MkInsert(MkPos(1, 2), "x")]) + AssertEqual "abcx\ndef4\nghi\n", TestChanges("abc\ndef4\nghi\n", [MkInsert(MkPos(1, 4), "x")]) + AssertEqual "abc\nxdef5\nghi\n", TestChanges("abc\ndef5\nghi\n", [MkInsert(MkPos(1, 5), "x")]) + AssertEqual "abc\nxdef6\nghi\n", TestChanges("abc\ndef6\nghi\n", [MkInsert(MkPos(1, 6), "x")]) Execute(One character + newline insertions to first line): - for g:mode in ['save', 'file', 'buffer'] - Log g:mode - AssertEqual "x\nabc\ndef1\nghi\n", TestChanges("abc\ndef1\nghi\n", [MkInsert(MkPos(1, 0), "x\n")], g:mode) - AssertEqual "x\nabc\ndef2\nghi\n", TestChanges("abc\ndef2\nghi\n", [MkInsert(MkPos(1, 1), "x\n")], g:mode) - AssertEqual "ax\nbc\ndef3\nghi\n", TestChanges("abc\ndef3\nghi\n", [MkInsert(MkPos(1, 2), "x\n")], g:mode) - AssertEqual "abcx\n\ndef4\nghi\n", TestChanges("abc\ndef4\nghi\n", [MkInsert(MkPos(1, 4), "x\n")], g:mode) - AssertEqual "abc\nx\ndef5\nghi\n", TestChanges("abc\ndef5\nghi\n", [MkInsert(MkPos(1, 5), "x\n")], g:mode) - AssertEqual "abc\nx\ndef6\nghi\n", TestChanges("abc\ndef6\nghi\n", [MkInsert(MkPos(1, 6), "x\n")], g:mode) - endfor + AssertEqual "x\nabc\ndef1\nghi\n", TestChanges("abc\ndef1\nghi\n", [MkInsert(MkPos(1, 0), "x\n")]) + AssertEqual "x\nabc\ndef2\nghi\n", TestChanges("abc\ndef2\nghi\n", [MkInsert(MkPos(1, 1), "x\n")]) + AssertEqual "ax\nbc\ndef3\nghi\n", TestChanges("abc\ndef3\nghi\n", [MkInsert(MkPos(1, 2), "x\n")]) + AssertEqual "abcx\n\ndef4\nghi\n", TestChanges("abc\ndef4\nghi\n", [MkInsert(MkPos(1, 4), "x\n")]) + AssertEqual "abc\nx\ndef5\nghi\n", TestChanges("abc\ndef5\nghi\n", [MkInsert(MkPos(1, 5), "x\n")]) + AssertEqual "abc\nx\ndef6\nghi\n", TestChanges("abc\ndef6\nghi\n", [MkInsert(MkPos(1, 6), "x\n")]) Execute(One character insertions near end): - for g:mode in ['save', 'file', 'buffer'] - Log g:mode - AssertEqual "abc\ndef1\nghxi\n", TestChanges("abc\ndef1\nghi\n", [MkInsert(MkPos(3, 3), "x")], g:mode) - AssertEqual "abc\ndef2\nghix\n", TestChanges("abc\ndef2\nghi\n", [MkInsert(MkPos(3, 4), "x")], g:mode) - AssertEqual "abc\ndef3\nghi\nx", TestChanges("abc\ndef3\nghi\n", [MkInsert(MkPos(3, 5), "x")], g:mode) - AssertEqual "abc\ndef4\nghi\nx", TestChanges("abc\ndef4\nghi\n", [MkInsert(MkPos(3, 6), "x")], g:mode) - AssertEqual "abc\ndef5\nghi\nx", TestChanges("abc\ndef5\nghi\n", [MkInsert(MkPos(4, 1), "x")], g:mode) - AssertEqual "abc\ndef6\nghi\nx", TestChanges("abc\ndef6\nghi\n", [MkInsert(MkPos(4, 2), "x")], g:mode) - AssertEqual "abc\ndef7\nghi\nx", TestChanges("abc\ndef7\nghi\n", [MkInsert(MkPos(5, 1), "x")], g:mode) - AssertEqual "abc\ndef8\nghi\nx", TestChanges("abc\ndef8\nghi\n", [MkInsert(MkPos(5, 2), "x")], g:mode) - endfor + AssertEqual "abc\ndef1\nghxi\n", TestChanges("abc\ndef1\nghi\n", [MkInsert(MkPos(3, 3), "x")]) + AssertEqual "abc\ndef2\nghix\n", TestChanges("abc\ndef2\nghi\n", [MkInsert(MkPos(3, 4), "x")]) + AssertEqual "abc\ndef3\nghi\nx", TestChanges("abc\ndef3\nghi\n", [MkInsert(MkPos(3, 5), "x")]) + AssertEqual "abc\ndef4\nghi\nx", TestChanges("abc\ndef4\nghi\n", [MkInsert(MkPos(3, 6), "x")]) + AssertEqual "abc\ndef5\nghi\nx", TestChanges("abc\ndef5\nghi\n", [MkInsert(MkPos(4, 1), "x")]) + AssertEqual "abc\ndef6\nghi\nx", TestChanges("abc\ndef6\nghi\n", [MkInsert(MkPos(4, 2), "x")]) + AssertEqual "abc\ndef7\nghi\nx", TestChanges("abc\ndef7\nghi\n", [MkInsert(MkPos(5, 1), "x")]) + AssertEqual "abc\ndef8\nghi\nx", TestChanges("abc\ndef8\nghi\n", [MkInsert(MkPos(5, 2), "x")]) Execute(One character + newline insertions near end): - for g:mode in ['save', 'file', 'buffer'] - Log g:mode - AssertEqual "abc\ndef1\nghx\ni\n", TestChanges("abc\ndef1\nghi\n", [MkInsert(MkPos(3, 3), "x\n")], g:mode) - AssertEqual "abc\ndef2\nghix\n\n", TestChanges("abc\ndef2\nghi\n", [MkInsert(MkPos(3, 4), "x\n")], g:mode) - AssertEqual "abc\ndef3\nghi\nx\n", TestChanges("abc\ndef3\nghi\n", [MkInsert(MkPos(3, 5), "x\n")], g:mode) - AssertEqual "abc\ndef4\nghi\nx\n", TestChanges("abc\ndef4\nghi\n", [MkInsert(MkPos(3, 6), "x\n")], g:mode) - AssertEqual "abc\ndef5\nghi\nx\n", TestChanges("abc\ndef5\nghi\n", [MkInsert(MkPos(4, 1), "x\n")], g:mode) - AssertEqual "abc\ndef6\nghi\nx\n", TestChanges("abc\ndef6\nghi\n", [MkInsert(MkPos(4, 2), "x\n")], g:mode) - endfor + AssertEqual "abc\ndef1\nghx\ni\n", TestChanges("abc\ndef1\nghi\n", [MkInsert(MkPos(3, 3), "x\n")]) + AssertEqual "abc\ndef2\nghix\n\n", TestChanges("abc\ndef2\nghi\n", [MkInsert(MkPos(3, 4), "x\n")]) + AssertEqual "abc\ndef3\nghi\nx\n", TestChanges("abc\ndef3\nghi\n", [MkInsert(MkPos(3, 5), "x\n")]) + AssertEqual "abc\ndef4\nghi\nx\n", TestChanges("abc\ndef4\nghi\n", [MkInsert(MkPos(3, 6), "x\n")]) + AssertEqual "abc\ndef5\nghi\nx\n", TestChanges("abc\ndef5\nghi\n", [MkInsert(MkPos(4, 1), "x\n")]) + AssertEqual "abc\ndef6\nghi\nx\n", TestChanges("abc\ndef6\nghi\n", [MkInsert(MkPos(4, 2), "x\n")]) Execute(Newline insertions near end): - for g:mode in ['save', 'file', 'buffer'] - Log g:mode - AssertEqual "abc\ndef1\ngh\ni\n", TestChanges("abc\ndef1\nghi\n", [MkInsert(MkPos(3, 3), "\n")], g:mode) - AssertEqual "abc\ndef2\nghi\n\n", TestChanges("abc\ndef2\nghi\n", [MkInsert(MkPos(3, 4), "\n")], g:mode) - AssertEqual "abc\ndef3\nghi\n\n", TestChanges("abc\ndef3\nghi\n", [MkInsert(MkPos(3, 5), "\n")], g:mode) - AssertEqual "abc\ndef4\nghi\n\n", TestChanges("abc\ndef4\nghi\n", [MkInsert(MkPos(3, 6), "\n")], g:mode) - AssertEqual "abc\ndef5\nghi\n\n", TestChanges("abc\ndef5\nghi\n", [MkInsert(MkPos(4, 1), "\n")], g:mode) - endfor + AssertEqual "abc\ndef1\ngh\ni\n", TestChanges("abc\ndef1\nghi\n", [MkInsert(MkPos(3, 3), "\n")]) + AssertEqual "abc\ndef2\nghi\n\n", TestChanges("abc\ndef2\nghi\n", [MkInsert(MkPos(3, 4), "\n")]) + AssertEqual "abc\ndef3\nghi\n\n", TestChanges("abc\ndef3\nghi\n", [MkInsert(MkPos(3, 5), "\n")]) + AssertEqual "abc\ndef4\nghi\n\n", TestChanges("abc\ndef4\nghi\n", [MkInsert(MkPos(3, 6), "\n")]) + AssertEqual "abc\ndef5\nghi\n\n", TestChanges("abc\ndef5\nghi\n", [MkInsert(MkPos(4, 1), "\n")]) Execute(Single char deletions): - for g:mode in ['save', 'file', 'buffer'] - Log g:mode - AssertEqual "bc\ndef1\nghi\n", TestChanges("abc\ndef1\nghi\n", [MkDelete(MkPos(1, 1), MkPos(1, 2))], g:mode) - AssertEqual "ab\ndef2\nghi\n", TestChanges("abc\ndef2\nghi\n", [MkDelete(MkPos(1, 3), MkPos(1, 4))], g:mode) - AssertEqual "abcdef3\nghi\n", TestChanges("abc\ndef3\nghi\n", [MkDelete(MkPos(1, 4), MkPos(1, 5))], g:mode) - AssertEqual "abcdef4\nghi\n", TestChanges("abc\ndef4\nghi\n", [MkDelete(MkPos(1, 4), MkPos(1, 6))], g:mode) - AssertEqual "abc\ndef5\ngh\n", TestChanges("abc\ndef5\nghi\n", [MkDelete(MkPos(3, 3), MkPos(3, 4))], g:mode) - AssertEqual "abc\ndef6\nghi", TestChanges("abc\ndef6\nghi\n", [MkDelete(MkPos(3, 4), MkPos(3, 5))], g:mode) - AssertEqual "abc\ndef7\nghi", TestChanges("abc\ndef7\nghi\n", [MkDelete(MkPos(3, 4), MkPos(3, 6))], g:mode) - AssertEqual "abc\ndef8\nghi\n", TestChanges("abc\ndef8\nghi\n", [MkDelete(MkPos(4, 1), MkPos(4, 2))], g:mode) - endfor + AssertEqual "bc\ndef1\nghi\n", TestChanges("abc\ndef1\nghi\n", [MkDelete(MkPos(1, 1), MkPos(1, 2))]) + AssertEqual "ab\ndef2\nghi\n", TestChanges("abc\ndef2\nghi\n", [MkDelete(MkPos(1, 3), MkPos(1, 4))]) + AssertEqual "abcdef3\nghi\n", TestChanges("abc\ndef3\nghi\n", [MkDelete(MkPos(1, 4), MkPos(1, 5))]) + AssertEqual "abcdef4\nghi\n", TestChanges("abc\ndef4\nghi\n", [MkDelete(MkPos(1, 4), MkPos(1, 6))]) + AssertEqual "abc\ndef5\ngh\n", TestChanges("abc\ndef5\nghi\n", [MkDelete(MkPos(3, 3), MkPos(3, 4))]) + AssertEqual "abc\ndef6\nghi", TestChanges("abc\ndef6\nghi\n", [MkDelete(MkPos(3, 4), MkPos(3, 5))]) + AssertEqual "abc\ndef7\nghi", TestChanges("abc\ndef7\nghi\n", [MkDelete(MkPos(3, 4), MkPos(3, 6))]) + AssertEqual "abc\ndef8\nghi\n", TestChanges("abc\ndef8\nghi\n", [MkDelete(MkPos(4, 1), MkPos(4, 2))]) diff --git a/test/test_code_action_python.vader b/test/test_code_action_python.vader index 2aac1ec7..3c784816 100644 --- a/test/test_code_action_python.vader +++ b/test/test_code_action_python.vader @@ -10,7 +10,7 @@ Execute(): \ {'end': {'offset': 15, 'line': 3}, 'newText': " return c\n\n\ndef main():\n c = func_qtffgsvi()\n", 'start': {'offset': 15, 'line': 3}} \] - call ale#code_action#ApplyChanges(expand('%:p'), g:changes, 0) + call ale#code_action#ApplyChanges(expand('%:p'), g:changes, {}) Expect(The changes should be applied correctly): def func_qtffgsvi(): @@ -40,7 +40,7 @@ Execute(): \ {'end': {'offset': 42, 'line': 8}, 'newText': "ivlpdpao(f)\n", 'start': {'offset': 33, 'line': 6}} \] - call ale#code_action#ApplyChanges(expand('%:p'), g:changes, 0) + call ale#code_action#ApplyChanges(expand('%:p'), g:changes, {}) Expect(The changes should be applied correctly): import sys diff --git a/test/test_organize_imports.vader b/test/test_organize_imports.vader index 63973a54..87cd295a 100644 --- a/test/test_organize_imports.vader +++ b/test/test_organize_imports.vader @@ -59,7 +59,7 @@ Before: function! ale#code_action#HandleCodeAction(code_action, options) abort let g:handle_code_action_called = 1 - Assert !get(a:options, 'should_save') + AssertEqual !&hidden, get(a:options, 'should_save') call add(g:code_actions, a:code_action) endfunction diff --git a/test/test_rename.vader b/test/test_rename.vader index 42bcfd95..4298715f 100644 --- a/test/test_rename.vader +++ b/test/test_rename.vader @@ -59,7 +59,7 @@ Before: function! ale#code_action#HandleCodeAction(code_action, options) abort let g:handle_code_action_called = 1 - Assert get(a:options, 'should_save') + AssertEqual !&hidden, get(a:options, 'should_save', 0) call add(g:code_actions, a:code_action) endfunction |