mirror of
https://github.com/dense-analysis/ale.git
synced 2026-02-17 23:44:17 +08:00
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
This commit is contained in:
@@ -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()]
|
||||
let g:file = 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")
|
||||
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
|
||||
if bufnr(g:file) != -1
|
||||
execute ':bp! | :bd! ' . bufnr(g:file)
|
||||
endif
|
||||
|
||||
unlet! g:mode
|
||||
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))])
|
||||
|
||||
Reference in New Issue
Block a user