3e8c8d3ccb
This commit adds support for renaming symbols in tsserver and with LSP tools, and for organising imports with tsserver. Completion results for symbols that can be imported are now suggested if enabled for tsserver completion done via ALE.
334 lines
8 KiB
Text
334 lines
8 KiB
Text
Before:
|
|
runtime autoload/ale/code_action.vim
|
|
runtime autoload/ale/util.vim
|
|
|
|
let g:file1 = tempname()
|
|
let g:file2 = tempname()
|
|
let g:test = {}
|
|
|
|
let g:test.create_change = {line, offset, end_line, end_offset, value ->
|
|
\{
|
|
\ 'changes': [{
|
|
\ 'fileName': g:file1,
|
|
\ 'textChanges': [{
|
|
\ 'start': {
|
|
\ 'line': line,
|
|
\ 'offset': offset,
|
|
\ },
|
|
\ 'end': {
|
|
\ 'line': end_line,
|
|
\ 'offset': end_offset,
|
|
\ },
|
|
\ 'newText': value,
|
|
\ }],
|
|
\ }]
|
|
\}}
|
|
|
|
function! WriteFileAndEdit() abort
|
|
let g:test.text = [
|
|
\ 'class Name {',
|
|
\ ' value: string',
|
|
\ '}',
|
|
\]
|
|
call writefile(g:test.text, g:file1, 'S')
|
|
execute 'edit ' . g:file1
|
|
endfunction!
|
|
|
|
After:
|
|
" Close the extra buffers if we opened it.
|
|
if bufnr(g:file1) != -1
|
|
execute ':bp | :bd ' . bufnr(g:file1)
|
|
endif
|
|
if bufnr(g:file2) != -1
|
|
execute ':bp | :bd ' . bufnr(g:file2)
|
|
endif
|
|
|
|
if filereadable(g:file1)
|
|
call delete(g:file1)
|
|
endif
|
|
if filereadable(g:file2)
|
|
call delete(g:file2)
|
|
endif
|
|
|
|
unlet g:file1
|
|
unlet g:file2
|
|
unlet g:test
|
|
delfunction WriteFileAndEdit
|
|
|
|
runtime autoload/ale/code_action.vim
|
|
runtime autoload/ale/util.vim
|
|
|
|
|
|
Execute(It should modify and save multiple files):
|
|
call writefile([
|
|
\ 'class Name {',
|
|
\ ' value: string',
|
|
\ '}',
|
|
\ '',
|
|
\ 'class B {',
|
|
\ ' constructor(readonly a: Name) {}',
|
|
\ '}'
|
|
\], g:file1, 'S')
|
|
call writefile([
|
|
\ 'import A from "A"',
|
|
\ 'import {',
|
|
\ ' B,',
|
|
\ ' C,',
|
|
\ '} from "module"',
|
|
\ 'import D from "D"',
|
|
\], g:file2, 'S')
|
|
|
|
call ale#code_action#HandleCodeAction({
|
|
\ 'changes': [{
|
|
\ 'fileName': g:file1,
|
|
\ 'textChanges': [{
|
|
\ 'start': {
|
|
\ 'line': 1,
|
|
\ 'offset': 7,
|
|
\ },
|
|
\ 'end': {
|
|
\ 'line': 1,
|
|
\ 'offset': 11,
|
|
\ },
|
|
\ 'newText': 'Value',
|
|
\ }, {
|
|
\ 'start': {
|
|
\ 'line': 6,
|
|
\ 'offset': 27,
|
|
\ },
|
|
\ 'end': {
|
|
\ 'line': 6,
|
|
\ 'offset': 31,
|
|
\ },
|
|
\ 'newText': 'Value',
|
|
\ }],
|
|
\ }, {
|
|
\ 'fileName': g:file2,
|
|
\ 'textChanges': [{
|
|
\ 'start': {
|
|
\ 'line': 2,
|
|
\ 'offset': 1,
|
|
\ },
|
|
\ 'end': {
|
|
\ 'line': 6,
|
|
\ 'offset': 1,
|
|
\ },
|
|
\ 'newText': "import {A, B} from 'module'\n\n",
|
|
\ }]
|
|
\ }],
|
|
\})
|
|
|
|
AssertEqual [
|
|
\ 'class Value {',
|
|
\ ' value: string',
|
|
\ '}',
|
|
\ '',
|
|
\ 'class B {',
|
|
\ ' constructor(readonly a: Value) {}',
|
|
\ '}',
|
|
\ '',
|
|
\], readfile(g:file1, 'b')
|
|
|
|
AssertEqual [
|
|
\ 'import A from "A"',
|
|
\ 'import {A, B} from ''module''',
|
|
\ '',
|
|
\ 'import D from "D"',
|
|
\ '',
|
|
\], readfile(g:file2, 'b')
|
|
|
|
|
|
Execute(Beginning of file can be modified):
|
|
let g:test.text = [
|
|
\ 'class Name {',
|
|
\ ' value: string',
|
|
\ '}',
|
|
\]
|
|
call writefile(g:test.text, g:file1, 'S')
|
|
|
|
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",
|
|
\ }],
|
|
\ }]
|
|
\})
|
|
|
|
AssertEqual [
|
|
\ 'type A: string',
|
|
\ 'type B: number',
|
|
\] + g:test.text + [''], readfile(g:file1, 'b')
|
|
|
|
|
|
Execute(End of file can be modified):
|
|
let g:test.text = [
|
|
\ 'class Name {',
|
|
\ ' value: string',
|
|
\ '}',
|
|
\]
|
|
call writefile(g:test.text, g:file1, 'S')
|
|
|
|
call ale#code_action#HandleCodeAction({
|
|
\ 'changes': [{
|
|
\ 'fileName': g:file1,
|
|
\ 'textChanges': [{
|
|
\ 'start': {
|
|
\ 'line': 4,
|
|
\ 'offset': 1,
|
|
\ },
|
|
\ 'end': {
|
|
\ 'line': 4,
|
|
\ 'offset': 1,
|
|
\ },
|
|
\ 'newText': "type A: string\ntype B: number\n",
|
|
\ }],
|
|
\ }]
|
|
\})
|
|
|
|
AssertEqual g:test.text + [
|
|
\ 'type A: string',
|
|
\ 'type B: number',
|
|
\ '',
|
|
\], readfile(g:file1, 'b')
|
|
|
|
|
|
Execute(Current buffer contents will be reloaded):
|
|
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)
|
|
|
|
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",
|
|
\ }],
|
|
\ }]
|
|
\})
|
|
|
|
AssertEqual [
|
|
\ 'type A: string',
|
|
\ 'type B: number',
|
|
\] + g:test.text + [''], readfile(g:file1, 'b')
|
|
|
|
AssertEqual [
|
|
\ 'type A: string',
|
|
\ 'type B: number',
|
|
\] + g:test.text, getbufline(g:test.buffer, 1, '$')
|
|
|
|
|
|
# Tests for cursor repositioning. In comments `=` designates change range, and
|
|
# `C` cursor position
|
|
|
|
# C ===
|
|
Execute(Cursor will not move when it is before text change):
|
|
call WriteFileAndEdit()
|
|
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)
|
|
AssertEqual [1, 1], getpos('.')[1:2]
|
|
|
|
call setpos('.', [0, 2, 2, 0])
|
|
call ale#code_action#HandleCodeAction(g:test.changes)
|
|
AssertEqual [2, 2], getpos('.')[1:2]
|
|
|
|
# ====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')
|
|
|
|
for r in range(3, 8)
|
|
call WriteFileAndEdit()
|
|
call setpos('.', [0, 2, r, 0])
|
|
AssertEqual ' value: string', getline('.')
|
|
call ale#code_action#HandleCodeAction(g:test.changes)
|
|
AssertEqual ' value2: string', getline('.')
|
|
AssertEqual [2, 9], getpos('.')[1:2]
|
|
endfor
|
|
|
|
|
|
# ====C
|
|
Execute(Cursor column will move back when new text is shorter):
|
|
call WriteFileAndEdit()
|
|
call setpos('.', [0, 2, 8, 0])
|
|
AssertEqual ' value: string', getline('.')
|
|
call ale#code_action#HandleCodeAction(g:test.create_change(2, 3, 2, 8, 'val'))
|
|
AssertEqual ' val: string', getline('.')
|
|
AssertEqual [2, 6], getpos('.')[1:2]
|
|
|
|
|
|
# ==== C
|
|
Execute(Cursor column will move forward when new text is longer):
|
|
call WriteFileAndEdit()
|
|
|
|
call setpos('.', [0, 2, 8, 0])
|
|
AssertEqual ' value: string', getline('.')
|
|
call ale#code_action#HandleCodeAction(g:test.create_change(2, 3, 2, 8, 'longValue'))
|
|
AssertEqual ' longValue: string', getline('.')
|
|
AssertEqual [2, 12], getpos('.')[1:2]
|
|
|
|
# =========
|
|
# =
|
|
# C
|
|
Execute(Cursor line will move when updates are happening on lines above):
|
|
call WriteFileAndEdit()
|
|
call setpos('.', [0, 3, 1, 0])
|
|
AssertEqual '}', getline('.')
|
|
call ale#code_action#HandleCodeAction(g:test.create_change(1, 1, 2, 1, "test\ntest\n"))
|
|
AssertEqual '}', getline('.')
|
|
AssertEqual [4, 1], getpos('.')[1:2]
|
|
|
|
|
|
# =========
|
|
# =C
|
|
Execute(Cursor line and column will move when change on lines above and just before cursor column):
|
|
call WriteFileAndEdit()
|
|
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"))
|
|
AssertEqual '123 value: string', getline('.')
|
|
AssertEqual [3, 5], getpos('.')[1:2]
|
|
|
|
# =========
|
|
# ======C==
|
|
# =
|
|
Execute(Cursor line and column will move at the end of changes):
|
|
call WriteFileAndEdit()
|
|
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"))
|
|
AssertEqual '}', getline('.')
|
|
AssertEqual [2, 1], getpos('.')[1:2]
|
|
|
|
# C ==
|
|
# ===
|
|
Execute(Cursor will not move when changes happening on lines >= cursor, but after cursor):
|
|
call WriteFileAndEdit()
|
|
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"))
|
|
AssertEqual ' value: number', getline('.')
|
|
AssertEqual [2, 3], getpos('.')[1:2]
|