/ test / test_code_action_corner_cases.vader
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))])