test_code_action_corner_cases.vader
1 " Tests for various corner cases of applying code changes from LSP. 2 " 3 " These can be verified against the reference vscode implementation using the 4 " following javascript program: 5 " 6 " const { TextDocument } = require('vscode-languageserver-textdocument'); 7 " const { TextEdit, Position, Range } = require('vscode-languageserver-types'); 8 " function MkPos(line, offset) { return Position.create(line - 1, offset - 1); } 9 " function MkInsert(pos, newText) { return TextEdit.insert(pos, newText); } 10 " function MkDelete(start, end) { return TextEdit.del(Range.create(start, end)); } 11 " function TestChanges(s, es) { 12 " return TextDocument.applyEdits(TextDocument.create(null, null, null, s), es); 13 " } 14 " 15 " const fs = require("fs"); 16 " const assert = require('assert').strict; 17 " const testRegex = /(?<!vscode skip.*)AssertEqual\s+("[^"]*"),\s*TestChanges\(("[^"]*"),\s*(\[[^\]]*\])/g; 18 " const data = fs.readFileSync(0, "utf-8"); 19 " const tests = data.matchAll(testRegex); 20 " for (const test of tests) { 21 " console.log(test[0]); 22 " assert.equal(eval(test[1]), TestChanges(eval(test[2]), eval(test[3]))); 23 " } 24 " 25 " Save it to test_code_action_corner_cases.js and invoke it using: 26 " 27 " $ npm install vscode-languageserver-{textdocument,types} 28 " $ node test_code_action_corner_cases.js <test_code_action_corner_cases.vader 29 30 Before: 31 Save &fixeol 32 set nofixeol 33 34 Save &fileformats 35 set fileformats=unix 36 37 function! TestChanges(contents, changes) abort 38 let l:file = tempname() 39 40 try 41 call writefile(split(a:contents, '\n', 1), l:file, 'bs') 42 43 call ale#code_action#ApplyChanges(l:file, a:changes, { 44 \ 'should_save': 1, 45 \}) 46 47 let l:result = join(readfile(l:file, 'b'), "\n") 48 finally 49 if filereadable(l:file) 50 call delete(l:file) 51 endif 52 endtry 53 54 return l:result 55 endfunction! 56 57 function! MkPos(line, offset) abort 58 return {'line': a:line, 'offset': a:offset} 59 endfunction! 60 61 function! MkInsert(pos, newText) abort 62 return {'start': a:pos, 'end': a:pos, 'newText': a:newText} 63 endfunction! 64 65 function! MkDelete(start, end) abort 66 return {'start': a:start, 'end': a:end, 'newText': ''} 67 endfunction! 68 69 After: 70 delfunction TestChanges 71 delfunction MkPos 72 delfunction MkInsert 73 delfunction MkDelete 74 75 Restore 76 77 Execute(Preserve (no)eol at eof): 78 AssertEqual "noeol", TestChanges("noeol", []) 79 AssertEqual "eol\n", TestChanges("eol\n", []) 80 AssertEqual "eols\n\n", TestChanges("eols\n\n", []) 81 82 Execute(Respect fixeol): 83 set fixeol 84 85 silent echo "vscode skip" | AssertEqual "noeol\n", TestChanges("noeol", []) 86 silent echo "vscode skip" | AssertEqual "eol\n", TestChanges("eol\n", []) 87 88 Execute(Add/del eol at eof): 89 AssertEqual "addeol\n", TestChanges("addeol", [MkInsert(MkPos(1, 7), "\n")]) 90 AssertEqual "deleol", TestChanges("deleol\n", [MkDelete(MkPos(1, 7), MkPos(1, 8))]) 91 92 Execute(One character insertions to first line): 93 AssertEqual "xabc\ndef1\nghi\n", TestChanges("abc\ndef1\nghi\n", [MkInsert(MkPos(1, 0), "x")]) 94 AssertEqual "xabc\ndef2\nghi\n", TestChanges("abc\ndef2\nghi\n", [MkInsert(MkPos(1, 1), "x")]) 95 AssertEqual "axbc\ndef3\nghi\n", TestChanges("abc\ndef3\nghi\n", [MkInsert(MkPos(1, 2), "x")]) 96 AssertEqual "abcx\ndef4\nghi\n", TestChanges("abc\ndef4\nghi\n", [MkInsert(MkPos(1, 4), "x")]) 97 AssertEqual "abc\nxdef5\nghi\n", TestChanges("abc\ndef5\nghi\n", [MkInsert(MkPos(1, 5), "x")]) 98 AssertEqual "abc\nxdef6\nghi\n", TestChanges("abc\ndef6\nghi\n", [MkInsert(MkPos(1, 6), "x")]) 99 100 Execute(One character + newline insertions to first line): 101 AssertEqual "x\nabc\ndef1\nghi\n", TestChanges("abc\ndef1\nghi\n", [MkInsert(MkPos(1, 0), "x\n")]) 102 AssertEqual "x\nabc\ndef2\nghi\n", TestChanges("abc\ndef2\nghi\n", [MkInsert(MkPos(1, 1), "x\n")]) 103 AssertEqual "ax\nbc\ndef3\nghi\n", TestChanges("abc\ndef3\nghi\n", [MkInsert(MkPos(1, 2), "x\n")]) 104 AssertEqual "abcx\n\ndef4\nghi\n", TestChanges("abc\ndef4\nghi\n", [MkInsert(MkPos(1, 4), "x\n")]) 105 AssertEqual "abc\nx\ndef5\nghi\n", TestChanges("abc\ndef5\nghi\n", [MkInsert(MkPos(1, 5), "x\n")]) 106 AssertEqual "abc\nx\ndef6\nghi\n", TestChanges("abc\ndef6\nghi\n", [MkInsert(MkPos(1, 6), "x\n")]) 107 108 Execute(One character insertions near end): 109 AssertEqual "abc\ndef1\nghxi\n", TestChanges("abc\ndef1\nghi\n", [MkInsert(MkPos(3, 3), "x")]) 110 AssertEqual "abc\ndef2\nghix\n", TestChanges("abc\ndef2\nghi\n", [MkInsert(MkPos(3, 4), "x")]) 111 AssertEqual "abc\ndef3\nghi\nx", TestChanges("abc\ndef3\nghi\n", [MkInsert(MkPos(3, 5), "x")]) 112 AssertEqual "abc\ndef4\nghi\nx", TestChanges("abc\ndef4\nghi\n", [MkInsert(MkPos(3, 6), "x")]) 113 AssertEqual "abc\ndef5\nghi\nx", TestChanges("abc\ndef5\nghi\n", [MkInsert(MkPos(4, 1), "x")]) 114 AssertEqual "abc\ndef6\nghi\nx", TestChanges("abc\ndef6\nghi\n", [MkInsert(MkPos(4, 2), "x")]) 115 AssertEqual "abc\ndef7\nghi\nx", TestChanges("abc\ndef7\nghi\n", [MkInsert(MkPos(5, 1), "x")]) 116 AssertEqual "abc\ndef8\nghi\nx", TestChanges("abc\ndef8\nghi\n", [MkInsert(MkPos(5, 2), "x")]) 117 118 Execute(One character + newline insertions near end): 119 AssertEqual "abc\ndef1\nghx\ni\n", TestChanges("abc\ndef1\nghi\n", [MkInsert(MkPos(3, 3), "x\n")]) 120 AssertEqual "abc\ndef2\nghix\n\n", TestChanges("abc\ndef2\nghi\n", [MkInsert(MkPos(3, 4), "x\n")]) 121 AssertEqual "abc\ndef3\nghi\nx\n", TestChanges("abc\ndef3\nghi\n", [MkInsert(MkPos(3, 5), "x\n")]) 122 AssertEqual "abc\ndef4\nghi\nx\n", TestChanges("abc\ndef4\nghi\n", [MkInsert(MkPos(3, 6), "x\n")]) 123 AssertEqual "abc\ndef5\nghi\nx\n", TestChanges("abc\ndef5\nghi\n", [MkInsert(MkPos(4, 1), "x\n")]) 124 AssertEqual "abc\ndef6\nghi\nx\n", TestChanges("abc\ndef6\nghi\n", [MkInsert(MkPos(4, 2), "x\n")]) 125 126 Execute(Newline insertions near end): 127 AssertEqual "abc\ndef1\ngh\ni\n", TestChanges("abc\ndef1\nghi\n", [MkInsert(MkPos(3, 3), "\n")]) 128 AssertEqual "abc\ndef2\nghi\n\n", TestChanges("abc\ndef2\nghi\n", [MkInsert(MkPos(3, 4), "\n")]) 129 AssertEqual "abc\ndef3\nghi\n\n", TestChanges("abc\ndef3\nghi\n", [MkInsert(MkPos(3, 5), "\n")]) 130 AssertEqual "abc\ndef4\nghi\n\n", TestChanges("abc\ndef4\nghi\n", [MkInsert(MkPos(3, 6), "\n")]) 131 AssertEqual "abc\ndef5\nghi\n\n", TestChanges("abc\ndef5\nghi\n", [MkInsert(MkPos(4, 1), "\n")]) 132 133 Execute(Single char deletions): 134 AssertEqual "bc\ndef1\nghi\n", TestChanges("abc\ndef1\nghi\n", [MkDelete(MkPos(1, 1), MkPos(1, 2))]) 135 AssertEqual "ab\ndef2\nghi\n", TestChanges("abc\ndef2\nghi\n", [MkDelete(MkPos(1, 3), MkPos(1, 4))]) 136 AssertEqual "abcdef3\nghi\n", TestChanges("abc\ndef3\nghi\n", [MkDelete(MkPos(1, 4), MkPos(1, 5))]) 137 AssertEqual "abcdef4\nghi\n", TestChanges("abc\ndef4\nghi\n", [MkDelete(MkPos(1, 4), MkPos(1, 6))]) 138 AssertEqual "abc\ndef5\ngh\n", TestChanges("abc\ndef5\nghi\n", [MkDelete(MkPos(3, 3), MkPos(3, 4))]) 139 AssertEqual "abc\ndef6\nghi", TestChanges("abc\ndef6\nghi\n", [MkDelete(MkPos(3, 4), MkPos(3, 5))]) 140 AssertEqual "abc\ndef7\nghi", TestChanges("abc\ndef7\nghi\n", [MkDelete(MkPos(3, 4), MkPos(3, 6))]) 141 AssertEqual "abc\ndef8\nghi\n", TestChanges("abc\ndef8\nghi\n", [MkDelete(MkPos(4, 1), MkPos(4, 2))])