diff --git a/autoload/ale/code_action.vim b/autoload/ale/code_action.vim index 60c3bbef..8c7263f3 100644 --- a/autoload/ale/code_action.vim +++ b/autoload/ale/code_action.vim @@ -24,6 +24,42 @@ function! ale#code_action#HandleCodeAction(code_action, should_save) abort endfor endfunction +function! s:ChangeCmp(left, right) abort + if a:left.start.line < a:right.start.line + return -1 + endif + + if a:left.start.line > a:right.start.line + return 1 + endif + + if a:left.start.offset < a:right.start.offset + return -1 + endif + + if a:left.start.offset > a:right.start.offset + return 1 + endif + + if a:left.end.line < a:right.end.line + return -1 + endif + + if a:left.end.line > a:right.end.line + return 1 + endif + + if a:left.end.offset < a:right.end.offset + return -1 + endif + + if a:left.end.offset > a:right.end.offset + return 1 + endif + + return 0 +endfunction + function! ale#code_action#ApplyChanges(filename, changes, should_save) abort let l:current_buffer = bufnr('') " The buffer is used to determine the fileformat, if available. @@ -48,7 +84,8 @@ function! ale#code_action#ApplyChanges(filename, changes, should_save) abort let l:column_offset = 0 let l:last_end_line = 0 - for l:code_edit in a:changes + " Changes have to be sorted so we apply them from top-to-bottom. + for l:code_edit in sort(copy(a:changes), function('s:ChangeCmp')) if l:code_edit.start.line isnot l:last_end_line let l:column_offset = 0 endif diff --git a/test/test_code_action.vader b/test/test_code_action.vader index b47f24ff..19de7268 100644 --- a/test/test_code_action.vader +++ b/test/test_code_action.vader @@ -1,4 +1,8 @@ Before: + Save g:ale_enabled + + let g:ale_enabled = 0 + runtime autoload/ale/code_action.vim runtime autoload/ale/util.vim @@ -35,6 +39,8 @@ Before: endfunction! After: + Restore + " Close the extra buffers if we opened it. if bufnr(g:file1) != -1 execute ':bp! | :bd! ' . bufnr(g:file1) @@ -50,9 +56,10 @@ After: call delete(g:file2) endif - unlet g:file1 - unlet g:file2 - unlet g:test + unlet! g:file1 + unlet! g:file2 + unlet! g:test + unlet! g:changes delfunction WriteFileAndEdit runtime autoload/ale/code_action.vim @@ -350,3 +357,36 @@ Execute(It should just modify file when should_save is set to v:false): \ ' value: string', \ '}', \], getline(1, '$') + +Given typescript(An example TypeScript file): + type Foo = {} + + export interface ISomething { + fooLongName: Foo | null + } + + export class SomethingElse implements ISomething { + // Bindings + fooLongName!: ISomething['fooLongName'] + } + +Execute(): + let g:changes = [ + \ {'end': {'offset': 14, 'line': 4}, 'newText': 'foo', 'start': {'offset': 3, 'line': 4}}, + \ {'end': {'offset': 40, 'line': 9}, 'newText': 'foo', 'start': {'offset': 29, 'line': 9}}, + \ {'end': {'offset': 14, 'line': 9}, 'newText': 'foo', 'start': {'offset': 3, 'line': 9}}, + \] + + call ale#code_action#ApplyChanges(expand('%:p'), g:changes, 0) + +Expect(The changes should be applied correctly): + type Foo = {} + + export interface ISomething { + foo: Foo | null + } + + export class SomethingElse implements ISomething { + // Bindings + foo!: ISomething['foo'] + }