mirror of https://github.com/dense-analysis/ale
parent
755f1a4ccf
commit
620951b6d3
|
@ -6,6 +6,8 @@
|
||||||
let g:ale_echo_msg_error_str = get(g:, 'ale_echo_msg_error_str', 'Error')
|
let g:ale_echo_msg_error_str = get(g:, 'ale_echo_msg_error_str', 'Error')
|
||||||
let g:ale_echo_msg_info_str = get(g:, 'ale_echo_msg_info_str', 'Info')
|
let g:ale_echo_msg_info_str = get(g:, 'ale_echo_msg_info_str', 'Info')
|
||||||
let g:ale_echo_msg_warning_str = get(g:, 'ale_echo_msg_warning_str', 'Warning')
|
let g:ale_echo_msg_warning_str = get(g:, 'ale_echo_msg_warning_str', 'Warning')
|
||||||
|
" Ignoring linters, for disabling some, or ignoring LSP diagnostics.
|
||||||
|
let g:ale_linters_ignore = get(g:, 'ale_linters_ignore', {})
|
||||||
|
|
||||||
let s:lint_timer = -1
|
let s:lint_timer = -1
|
||||||
let s:queued_buffer_number = -1
|
let s:queued_buffer_number = -1
|
||||||
|
@ -150,7 +152,8 @@ function! ale#Lint(...) abort
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" Use the filetype from the buffer
|
" Use the filetype from the buffer
|
||||||
let l:linters = ale#linter#Get(getbufvar(l:buffer, '&filetype'))
|
let l:filetype = getbufvar(l:buffer, '&filetype')
|
||||||
|
let l:linters = ale#linter#Get(l:filetype)
|
||||||
let l:should_lint_file = 0
|
let l:should_lint_file = 0
|
||||||
|
|
||||||
" Check if we previously requested checking the file.
|
" Check if we previously requested checking the file.
|
||||||
|
@ -160,6 +163,12 @@ function! ale#Lint(...) abort
|
||||||
let l:should_lint_file = filereadable(expand('#' . l:buffer . ':p'))
|
let l:should_lint_file = filereadable(expand('#' . l:buffer . ':p'))
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
" Apply ignore lists for linters only if needed.
|
||||||
|
let l:ignore_config = ale#Var(l:buffer, 'linters_ignore')
|
||||||
|
let l:linters = !empty(l:ignore_config)
|
||||||
|
\ ? ale#engine#ignore#Exclude(l:filetype, l:linters, l:ignore_config)
|
||||||
|
\ : l:linters
|
||||||
|
|
||||||
call ale#engine#RunLinters(l:buffer, l:linters, l:should_lint_file)
|
call ale#engine#RunLinters(l:buffer, l:linters, l:should_lint_file)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
" Author: w0rp <devw0rp@gmail.com>
|
||||||
|
" Description: Code for ignoring linters. Only loaded and if configured.
|
||||||
|
|
||||||
|
" Given a filetype and a configuration for ignoring linters, return a List of
|
||||||
|
" Strings for linter names to ignore.
|
||||||
|
function! ale#engine#ignore#GetList(filetype, config) abort
|
||||||
|
if type(a:config) is type([])
|
||||||
|
return a:config
|
||||||
|
endif
|
||||||
|
|
||||||
|
if type(a:config) is type({})
|
||||||
|
let l:names_to_remove = []
|
||||||
|
|
||||||
|
for l:part in split(a:filetype , '\.')
|
||||||
|
call extend(l:names_to_remove, get(a:config, l:part, []))
|
||||||
|
endfor
|
||||||
|
|
||||||
|
return l:names_to_remove
|
||||||
|
endif
|
||||||
|
|
||||||
|
return []
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Given a List of linter descriptions, exclude the linters to be ignored.
|
||||||
|
function! ale#engine#ignore#Exclude(filetype, all_linters, config) abort
|
||||||
|
let l:names_to_remove = ale#engine#ignore#GetList(a:filetype, a:config)
|
||||||
|
let l:filtered_linters = []
|
||||||
|
|
||||||
|
for l:linter in a:all_linters
|
||||||
|
let l:name_list = [l:linter.name] + l:linter.aliases
|
||||||
|
let l:should_include = 1
|
||||||
|
|
||||||
|
for l:name in l:name_list
|
||||||
|
if index(l:names_to_remove, l:name) >= 0
|
||||||
|
let l:should_include = 0
|
||||||
|
break
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
|
||||||
|
if l:should_include
|
||||||
|
call add(l:filtered_linters, l:linter)
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
|
||||||
|
return l:filtered_linters
|
||||||
|
endfunction
|
|
@ -8,11 +8,30 @@ if !has_key(s:, 'lsp_linter_map')
|
||||||
let s:lsp_linter_map = {}
|
let s:lsp_linter_map = {}
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
" Check if diagnostics for a particular linter should be ignored.
|
||||||
|
function! s:ShouldIgnore(buffer, linter_name) abort
|
||||||
|
let l:config = ale#Var(a:buffer, 'linters_ignore')
|
||||||
|
|
||||||
|
" Don't load code for ignoring diagnostics if there's nothing to ignore.
|
||||||
|
if empty(l:config)
|
||||||
|
return 0
|
||||||
|
endif
|
||||||
|
|
||||||
|
let l:filetype = getbufvar(a:buffer, '&filetype')
|
||||||
|
let l:ignore_list = ale#engine#ignore#GetList(l:filetype, l:config)
|
||||||
|
|
||||||
|
return index(l:ignore_list, a:linter_name) >= 0
|
||||||
|
endfunction
|
||||||
|
|
||||||
function! s:HandleLSPDiagnostics(conn_id, response) abort
|
function! s:HandleLSPDiagnostics(conn_id, response) abort
|
||||||
let l:linter_name = s:lsp_linter_map[a:conn_id]
|
let l:linter_name = s:lsp_linter_map[a:conn_id]
|
||||||
let l:filename = ale#path#FromURI(a:response.params.uri)
|
let l:filename = ale#path#FromURI(a:response.params.uri)
|
||||||
let l:buffer = bufnr(l:filename)
|
let l:buffer = bufnr(l:filename)
|
||||||
|
|
||||||
|
if s:ShouldIgnore(l:buffer, l:linter_name)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
if l:buffer <= 0
|
if l:buffer <= 0
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
@ -23,6 +42,7 @@ function! s:HandleLSPDiagnostics(conn_id, response) abort
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:HandleTSServerDiagnostics(response, error_type) abort
|
function! s:HandleTSServerDiagnostics(response, error_type) abort
|
||||||
|
let l:linter_name = 'tsserver'
|
||||||
let l:buffer = bufnr(a:response.body.file)
|
let l:buffer = bufnr(a:response.body.file)
|
||||||
let l:info = get(g:ale_buffer_info, l:buffer, {})
|
let l:info = get(g:ale_buffer_info, l:buffer, {})
|
||||||
|
|
||||||
|
@ -30,6 +50,10 @@ function! s:HandleTSServerDiagnostics(response, error_type) abort
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if s:ShouldIgnore(l:buffer, l:linter_name)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
let l:thislist = ale#lsp#response#ReadTSServerDiagnostics(a:response)
|
let l:thislist = ale#lsp#response#ReadTSServerDiagnostics(a:response)
|
||||||
|
|
||||||
" tsserver sends syntax and semantic errors in separate messages, so we
|
" tsserver sends syntax and semantic errors in separate messages, so we
|
||||||
|
@ -44,7 +68,7 @@ function! s:HandleTSServerDiagnostics(response, error_type) abort
|
||||||
let l:loclist = get(l:info, 'semantic_loclist', [])
|
let l:loclist = get(l:info, 'semantic_loclist', [])
|
||||||
\ + get(l:info, 'syntax_loclist', [])
|
\ + get(l:info, 'syntax_loclist', [])
|
||||||
|
|
||||||
call ale#engine#HandleLoclist('tsserver', l:buffer, l:loclist)
|
call ale#engine#HandleLoclist(l:linter_name, l:buffer, l:loclist)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:HandleLSPErrorMessage(linter_name, response) abort
|
function! s:HandleLSPErrorMessage(linter_name, response) abort
|
||||||
|
|
26
doc/ale.txt
26
doc/ale.txt
|
@ -1231,6 +1231,32 @@ g:ale_linters_explicit *g:ale_linters_explicit*
|
||||||
as possible, unless otherwise specified.
|
as possible, unless otherwise specified.
|
||||||
|
|
||||||
|
|
||||||
|
g:ale_linters_ignore *g:ale_linters_ignore*
|
||||||
|
*b:ale_linters_ignore*
|
||||||
|
|
||||||
|
Type: |Dictionary| or |List|
|
||||||
|
Default: `{}`
|
||||||
|
|
||||||
|
Linters to ignore. Commands for ignored linters will not be run, and
|
||||||
|
diagnostics for LSP linters will be ignored. (See |ale-lsp|)
|
||||||
|
|
||||||
|
This setting can be set to a |Dictionary| mapping filetypes to linter names,
|
||||||
|
just like |g:ale_linters|, to list linters to ignore. Ignore lists will be
|
||||||
|
applied after everything else. >
|
||||||
|
|
||||||
|
" Select flake8 and pylint, and ignore pylint, so only flake8 is run.
|
||||||
|
let g:ale_linters = {'python': ['flake8', 'pylint']}
|
||||||
|
let g:ale_linters_ignore = {'python': ['pylint']}
|
||||||
|
<
|
||||||
|
This setting can be set to simply a |List| of linter names, which is
|
||||||
|
especially more convenient when using the setting in ftplugin files for
|
||||||
|
particular buffers. >
|
||||||
|
|
||||||
|
" The same as above, in a ftplugin/python.vim.
|
||||||
|
let b:ale_linters = ['flake8', 'pylint']
|
||||||
|
let b:ale_linters_ignore = ['pylint']
|
||||||
|
<
|
||||||
|
|
||||||
g:ale_list_vertical *g:ale_list_vertical*
|
g:ale_list_vertical *g:ale_list_vertical*
|
||||||
*b:ale_list_vertical*
|
*b:ale_list_vertical*
|
||||||
Type: |Number|
|
Type: |Number|
|
||||||
|
|
|
@ -0,0 +1,250 @@
|
||||||
|
Execute(GetList should ignore some invalid values):
|
||||||
|
AssertEqual [], ale#engine#ignore#GetList('', 'foo')
|
||||||
|
AssertEqual [], ale#engine#ignore#GetList('', 0)
|
||||||
|
AssertEqual [], ale#engine#ignore#GetList('', v:null)
|
||||||
|
|
||||||
|
Execute(GetList should handle Lists):
|
||||||
|
AssertEqual ['foo', 'bar'], ale#engine#ignore#GetList('', ['foo', 'bar'])
|
||||||
|
|
||||||
|
Execute(GetList should handle Dictionaries):
|
||||||
|
AssertEqual
|
||||||
|
\ ['linter1', 'linter2'],
|
||||||
|
\ uniq(sort(ale#engine#ignore#GetList('x.y.z', {
|
||||||
|
\ 'x': ['linter1'],
|
||||||
|
\ 'abc': ['linter3'],
|
||||||
|
\ 'z': ['linter2'],
|
||||||
|
\ })))
|
||||||
|
|
||||||
|
Execute(Exclude should ignore some invalid values):
|
||||||
|
AssertEqual
|
||||||
|
\ [
|
||||||
|
\ {'name': 'linter1', 'aliases': []},
|
||||||
|
\ {'name': 'linter2', 'aliases': ['alias1']},
|
||||||
|
\ {'name': 'linter3', 'aliases': []},
|
||||||
|
\ ],
|
||||||
|
\ ale#engine#ignore#Exclude(
|
||||||
|
\ 'foo.bar',
|
||||||
|
\ [
|
||||||
|
\ {'name': 'linter1', 'aliases': []},
|
||||||
|
\ {'name': 'linter2', 'aliases': ['alias1']},
|
||||||
|
\ {'name': 'linter3', 'aliases': []},
|
||||||
|
\ ],
|
||||||
|
\ 'foo',
|
||||||
|
\ )
|
||||||
|
AssertEqual
|
||||||
|
\ [
|
||||||
|
\ {'name': 'linter1', 'aliases': []},
|
||||||
|
\ {'name': 'linter2', 'aliases': ['alias1']},
|
||||||
|
\ {'name': 'linter3', 'aliases': []},
|
||||||
|
\ ],
|
||||||
|
\ ale#engine#ignore#Exclude(
|
||||||
|
\ 'foo.bar',
|
||||||
|
\ [
|
||||||
|
\ {'name': 'linter1', 'aliases': []},
|
||||||
|
\ {'name': 'linter2', 'aliases': ['alias1']},
|
||||||
|
\ {'name': 'linter3', 'aliases': []},
|
||||||
|
\ ],
|
||||||
|
\ 0,
|
||||||
|
\ )
|
||||||
|
AssertEqual
|
||||||
|
\ [
|
||||||
|
\ {'name': 'linter1', 'aliases': []},
|
||||||
|
\ {'name': 'linter2', 'aliases': ['alias1']},
|
||||||
|
\ {'name': 'linter3', 'aliases': []},
|
||||||
|
\ ],
|
||||||
|
\ ale#engine#ignore#Exclude(
|
||||||
|
\ 'foo.bar',
|
||||||
|
\ [
|
||||||
|
\ {'name': 'linter1', 'aliases': []},
|
||||||
|
\ {'name': 'linter2', 'aliases': ['alias1']},
|
||||||
|
\ {'name': 'linter3', 'aliases': []},
|
||||||
|
\ ],
|
||||||
|
\ v:null,
|
||||||
|
\ )
|
||||||
|
|
||||||
|
Execute(Exclude should handle Lists):
|
||||||
|
AssertEqual
|
||||||
|
\ [
|
||||||
|
\ {'name': 'linter3', 'aliases': []},
|
||||||
|
\ ],
|
||||||
|
\ ale#engine#ignore#Exclude(
|
||||||
|
\ 'foo.bar',
|
||||||
|
\ [
|
||||||
|
\ {'name': 'linter1', 'aliases': []},
|
||||||
|
\ {'name': 'linter2', 'aliases': ['alias1']},
|
||||||
|
\ {'name': 'linter3', 'aliases': []},
|
||||||
|
\ ],
|
||||||
|
\ ['linter1', 'alias1'],
|
||||||
|
\ )
|
||||||
|
|
||||||
|
Execute(Exclude should handle Dictionaries):
|
||||||
|
AssertEqual
|
||||||
|
\ [
|
||||||
|
\ {'name': 'linter3', 'aliases': []},
|
||||||
|
\ ],
|
||||||
|
\ ale#engine#ignore#Exclude(
|
||||||
|
\ 'foo.bar',
|
||||||
|
\ [
|
||||||
|
\ {'name': 'linter1', 'aliases': []},
|
||||||
|
\ {'name': 'linter2', 'aliases': ['alias1']},
|
||||||
|
\ {'name': 'linter3', 'aliases': []},
|
||||||
|
\ ],
|
||||||
|
\ {'foo': ['linter1'], 'bar': ['alias1']},
|
||||||
|
\ )
|
||||||
|
|
||||||
|
Before:
|
||||||
|
Save g:ale_linters_ignore
|
||||||
|
Save g:ale_buffer_info
|
||||||
|
|
||||||
|
let g:linters = []
|
||||||
|
let g:loclist = []
|
||||||
|
let g:run_linters_called = 0
|
||||||
|
|
||||||
|
runtime autoload/ale/engine.vim
|
||||||
|
|
||||||
|
" Mock the engine function so we can set it up.
|
||||||
|
function! ale#engine#RunLinters(buffer, linters, should_lint_file) abort
|
||||||
|
let g:linters = a:linters
|
||||||
|
let g:run_linters_called = 1
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! ale#engine#HandleLoclist(linter_name, buffer, loclist) abort
|
||||||
|
let g:loclist = a:loclist
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
call ale#linter#Define('foobar', {
|
||||||
|
\ 'name': 'testlinter',
|
||||||
|
\ 'callback': 'TestCallback',
|
||||||
|
\ 'executable': has('win32') ? 'cmd' : 'true',
|
||||||
|
\ 'command': has('win32') ? 'echo' : 'true',
|
||||||
|
\})
|
||||||
|
call ale#test#SetDirectory('/testplugin/test')
|
||||||
|
|
||||||
|
After:
|
||||||
|
Restore
|
||||||
|
|
||||||
|
unlet! b:ale_linted
|
||||||
|
unlet! b:ale_linters_ignore
|
||||||
|
unlet! b:ale_quitting
|
||||||
|
unlet! b:ale_save_event_fired
|
||||||
|
unlet! g:linters
|
||||||
|
unlet! g:loclist
|
||||||
|
unlet! g:lsp_message
|
||||||
|
|
||||||
|
call ale#test#RestoreDirectory()
|
||||||
|
call ale#linter#Reset()
|
||||||
|
call ale#lsp_linter#ClearLSPData()
|
||||||
|
runtime autoload/ale/engine.vim
|
||||||
|
|
||||||
|
Given foobar(An empty file):
|
||||||
|
Execute(Global ignore lists should be applied for linters):
|
||||||
|
ALELint
|
||||||
|
Assert g:run_linters_called, "The mock callback wasn't called"
|
||||||
|
AssertEqual ['testlinter'], map(g:linters, 'v:val.name')
|
||||||
|
|
||||||
|
let g:ale_linters_ignore = ['testlinter']
|
||||||
|
ALELint
|
||||||
|
AssertEqual [], g:linters
|
||||||
|
|
||||||
|
Execute(buffer ignore lists should be applied for linters):
|
||||||
|
ALELint
|
||||||
|
Assert g:run_linters_called, "The mock callback wasn't called"
|
||||||
|
AssertEqual ['testlinter'], map(g:linters, 'v:val.name')
|
||||||
|
|
||||||
|
let b:ale_linters_ignore = ['testlinter']
|
||||||
|
ALELint
|
||||||
|
AssertEqual [], g:linters
|
||||||
|
|
||||||
|
Execute(Buffer ignore lists should be applied for tsserver):
|
||||||
|
call ale#test#SetFilename('filename.ts')
|
||||||
|
call ale#engine#InitBufferInfo(bufnr(''))
|
||||||
|
|
||||||
|
let g:lsp_message = {
|
||||||
|
\ 'seq': 0,
|
||||||
|
\ 'type': 'event',
|
||||||
|
\ 'event': 'syntaxDiag',
|
||||||
|
\ 'body': {
|
||||||
|
\ 'file': g:dir . '/filename.ts',
|
||||||
|
\ 'diagnostics':[
|
||||||
|
\ {
|
||||||
|
\ 'start': {
|
||||||
|
\ 'line':2,
|
||||||
|
\ 'offset':14,
|
||||||
|
\ },
|
||||||
|
\ 'end': {
|
||||||
|
\ 'line':2,
|
||||||
|
\ 'offset':15,
|
||||||
|
\ },
|
||||||
|
\ 'text': ''','' expected.',
|
||||||
|
\ "code":1005
|
||||||
|
\ },
|
||||||
|
\ ],
|
||||||
|
\ },
|
||||||
|
\}
|
||||||
|
|
||||||
|
call ale#lsp_linter#HandleLSPResponse(347, g:lsp_message)
|
||||||
|
|
||||||
|
AssertEqual
|
||||||
|
\ [
|
||||||
|
\ {
|
||||||
|
\ 'lnum': 2,
|
||||||
|
\ 'col': 14,
|
||||||
|
\ 'nr': 1005,
|
||||||
|
\ 'type': 'E',
|
||||||
|
\ 'end_col': 15,
|
||||||
|
\ 'end_lnum': 2,
|
||||||
|
\ 'text': ''','' expected.',
|
||||||
|
\ },
|
||||||
|
\ ],
|
||||||
|
\ g:loclist
|
||||||
|
|
||||||
|
let g:loclist = []
|
||||||
|
let b:ale_linters_ignore = ['tsserver']
|
||||||
|
call ale#lsp_linter#HandleLSPResponse(347, g:lsp_message)
|
||||||
|
|
||||||
|
AssertEqual [], g:loclist
|
||||||
|
|
||||||
|
Execute(Buffer ignore lists should be applied for LSP linters):
|
||||||
|
call ale#test#SetFilename('filename.py')
|
||||||
|
call ale#engine#InitBufferInfo(bufnr(''))
|
||||||
|
call ale#lsp_linter#SetLSPLinterMap({'347': 'lsplinter'})
|
||||||
|
|
||||||
|
let g:lsp_message = {
|
||||||
|
\ 'jsonrpc': '2.0',
|
||||||
|
\ 'method': 'textDocument/publishDiagnostics',
|
||||||
|
\ 'params': {
|
||||||
|
\ 'uri': ale#path#ToURI(expand('%:p')),
|
||||||
|
\ 'diagnostics': [
|
||||||
|
\ {
|
||||||
|
\ 'severity': 1,
|
||||||
|
\ 'message': 'x',
|
||||||
|
\ 'range': {
|
||||||
|
\ 'start': {'line': 0, 'character': 9},
|
||||||
|
\ 'end': {'line': 0, 'character': 9},
|
||||||
|
\ },
|
||||||
|
\ }
|
||||||
|
\ ],
|
||||||
|
\ },
|
||||||
|
\}
|
||||||
|
|
||||||
|
call ale#lsp_linter#HandleLSPResponse(347, g:lsp_message)
|
||||||
|
|
||||||
|
AssertEqual
|
||||||
|
\ [
|
||||||
|
\ {
|
||||||
|
\ 'lnum': 1,
|
||||||
|
\ 'col': 10,
|
||||||
|
\ 'type': 'E',
|
||||||
|
\ 'end_col': 10,
|
||||||
|
\ 'end_lnum': 1,
|
||||||
|
\ 'text': 'x',
|
||||||
|
\ }
|
||||||
|
\ ],
|
||||||
|
\ g:loclist
|
||||||
|
|
||||||
|
let b:ale_linters_ignore = ['lsplinter']
|
||||||
|
let g:loclist = []
|
||||||
|
|
||||||
|
call ale#lsp_linter#HandleLSPResponse(347, g:lsp_message)
|
||||||
|
|
||||||
|
AssertEqual [], g:loclist
|
Loading…
Reference in New Issue