Close #3333 - Add an ALECompletePost event

Add an `ALECompletePost` event along with everything needed to make it
useful for its primary purpose: fixing code after inserting completions.

* `ALEFix` can now be called with a bang (`!`) to suppress errors.
* A new `ALELintStop` command lets you stop linting, and start it later.
This commit is contained in:
w0rp
2020-09-08 21:40:10 +01:00
parent b4b75126f9
commit 7d90ff56d9
12 changed files with 273 additions and 92 deletions

View File

@@ -503,17 +503,19 @@ function! ale#completion#ParseTSServerCompletionEntryDetails(response) abort
\ || g:ale_completion_autoimport,
\ 'info': join(l:documentationParts, ''),
\}
" This flag is used to tell if this completion came from ALE or not.
let l:user_data = {'_ale_completion_item': 1}
if has_key(l:suggestion, 'codeActions')
let l:result.user_data = json_encode({
\ 'codeActions': l:suggestion.codeActions,
\ })
let l:user_data.code_actions = l:suggestion.codeActions
endif
let l:result.user_data = json_encode(l:user_data)
" Include this item if we'll accept any items,
" or if we only want items with additional edits, and this has them.
if !get(l:info, 'additional_edits_only', 0)
\|| has_key(l:result, 'user_data')
\|| has_key(l:user_data, 'code_actions')
call add(l:results, l:result)
endif
endfor
@@ -534,6 +536,7 @@ function! ale#completion#ParseTSServerCompletionEntryDetails(response) abort
\ 'icase': 1,
\ 'menu': '',
\ 'info': '',
\ 'user_data': json_encode({'_ale_completion_item': 1}),
\})
endfor
endif
@@ -610,6 +613,8 @@ function! ale#completion#ParseLSPCompletions(response) abort
\ 'menu': get(l:item, 'detail', ''),
\ 'info': (type(l:doc) is v:t_string ? l:doc : ''),
\}
" This flag is used to tell if this completion came from ALE or not.
let l:user_data = {'_ale_completion_item': 1}
if has_key(l:item, 'additionalTextEdits')
let l:text_changes = []
@@ -629,24 +634,24 @@ function! ale#completion#ParseLSPCompletions(response) abort
endfor
if !empty(l:text_changes)
let l:result.user_data = json_encode({
\ 'codeActions': [{
\ 'description': 'completion',
\ 'changes': [
\ {
\ 'fileName': expand('#' . l:buffer . ':p'),
\ 'textChanges': l:text_changes,
\ }
\ ],
\ }],
\})
let l:user_data.code_actions = [{
\ 'description': 'completion',
\ 'changes': [
\ {
\ 'fileName': expand('#' . l:buffer . ':p'),
\ 'textChanges': l:text_changes,
\ },
\ ],
\}]
endif
endif
let l:result.user_data = json_encode(l:user_data)
" Include this item if we'll accept any items,
" or if we only want items with additional edits, and this has them.
if !get(l:info, 'additional_edits_only', 0)
\|| has_key(l:result, 'user_data')
\|| has_key(l:user_data, 'code_actions')
call add(l:results, l:result)
endif
endfor
@@ -983,30 +988,29 @@ function! ale#completion#Queue() abort
endfunction
function! ale#completion#HandleUserData(completed_item) abort
let l:source = get(get(b:, 'ale_completion_info', {}), 'source', '')
if l:source isnot# 'ale-automatic'
\&& l:source isnot# 'ale-manual'
\&& l:source isnot# 'ale-callback'
\&& l:source isnot# 'ale-import'
return
endif
let l:user_data_json = get(a:completed_item, 'user_data', '')
if empty(l:user_data_json)
return
endif
let l:user_data = json_decode(l:user_data_json)
let l:user_data = !empty(l:user_data_json)
\ ? json_decode(l:user_data_json)
\ : v:null
if type(l:user_data) isnot v:t_dict
\|| get(l:user_data, '_ale_completion_item', 0) isnot 1
return
endif
for l:code_action in get(l:user_data, 'codeActions', [])
call ale#code_action#HandleCodeAction(l:code_action, v:false)
endfor
let l:source = get(get(b:, 'ale_completion_info', {}), 'source', '')
if l:source is# 'ale-automatic'
\|| l:source is# 'ale-manual'
\|| l:source is# 'ale-callback'
\|| l:source is# 'ale-import'
\|| l:source is# 'ale-omnifunc'
for l:code_action in get(l:user_data, 'code_actions', [])
call ale#code_action#HandleCodeAction(l:code_action, v:false)
endfor
endif
silent doautocmd <nomodeline> User ALECompletePost
endfunction
function! ale#completion#Done() abort

View File

@@ -458,6 +458,10 @@ function! s:StopCurrentJobs(buffer, clear_lint_file_jobs) abort
endif
endfunction
function! ale#engine#Stop(buffer) abort
call s:StopCurrentJobs(a:buffer, 1)
endfunction
function! s:RemoveProblemsForDisabledLinters(buffer, linters) abort
" Figure out which linters are still enabled, and remove
" problems for linters which are no longer enabled.

View File

@@ -75,7 +75,10 @@ function! ale#fix#ApplyFixes(buffer, output) abort
if l:data.lines_before != l:lines
call remove(g:ale_fix_buffer_data, a:buffer)
execute 'echoerr ''The file was changed before fixing finished'''
if !l:data.ignore_file_changed_errors
execute 'echoerr ''The file was changed before fixing finished'''
endif
return
endif
@@ -329,6 +332,7 @@ function! ale#fix#InitBufferData(buffer, fixing_flag) abort
\ 'lines_before': getbufline(a:buffer, 1, '$'),
\ 'done': 0,
\ 'should_save': a:fixing_flag is# 'save_file',
\ 'ignore_file_changed_errors': a:fixing_flag is# '!',
\ 'temporary_directory_list': [],
\}
endfunction
@@ -337,19 +341,23 @@ endfunction
"
" Returns 0 if no fixes can be applied, and 1 if fixing can be done.
function! ale#fix#Fix(buffer, fixing_flag, ...) abort
if a:fixing_flag isnot# '' && a:fixing_flag isnot# 'save_file'
throw "fixing_flag must be either '' or 'save_file'"
if a:fixing_flag isnot# ''
\&& a:fixing_flag isnot# '!'
\&& a:fixing_flag isnot# 'save_file'
throw "fixing_flag must be '', '!', or 'save_file'"
endif
try
let l:callback_list = s:GetCallbacks(a:buffer, a:fixing_flag, a:000)
catch /E700\|BADNAME/
let l:function_name = join(split(split(v:exception, ':')[3]))
let l:echo_message = printf(
\ 'There is no fixer named `%s`. Check :ALEFixSuggest',
\ l:function_name,
\)
execute 'echom l:echo_message'
if a:fixing_flag isnot# '!'
let l:function_name = join(split(split(v:exception, ':')[3]))
let l:echo_message = printf(
\ 'There is no fixer named `%s`. Check :ALEFixSuggest',
\ l:function_name,
\)
execute 'echom l:echo_message'
endif
return 0
endtry