Improve ALE project style checking

* The project style linter now runs while you type.
* Now the scripts for checking the project require blank lines.
* Many style issues have been found and fixed.
This commit is contained in:
w0rp 2018-09-04 16:51:18 +01:00
parent 8f2e1c393f
commit d476578a40
No known key found for this signature in database
GPG key ID: 0FC1ECAA8C81CD83
69 changed files with 239 additions and 41 deletions

View file

@ -16,10 +16,12 @@ function! ale_linters#apiblueprint#drafter#HandleErrors(buffer, lines) abort
\ 'lnum': l:match[3] + 0, \ 'lnum': l:match[3] + 0,
\ 'col': l:match[4] + 0, \ 'col': l:match[4] + 0,
\} \}
if l:match[5] isnot# '' if l:match[5] isnot# ''
let l:item.end_lnum = l:match[6] + 0 let l:item.end_lnum = l:match[6] + 0
let l:item.end_col = l:match[7] + 0 let l:item.end_col = l:match[7] + 0
endif endif
call add(l:output, l:item) call add(l:output, l:item)
endfor endfor

View file

@ -6,6 +6,7 @@ call ale#Set('c_clangd_options', '')
function! ale_linters#c#clangd#GetProjectRoot(buffer) abort function! ale_linters#c#clangd#GetProjectRoot(buffer) abort
let l:project_root = ale#path#FindNearestFile(a:buffer, 'compile_commands.json') let l:project_root = ale#path#FindNearestFile(a:buffer, 'compile_commands.json')
return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : '' return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : ''
endfunction endfunction

View file

@ -9,9 +9,11 @@ function! ale_linters#clojure#joker#HandleJokerFormat(buffer, lines) abort
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:type = 'E' let l:type = 'E'
if l:match[4] is? 'Parse warning' if l:match[4] is? 'Parse warning'
let l:type = 'W' let l:type = 'W'
endif endif
call add(l:output, { call add(l:output, {
\ 'lnum': l:match[1] + 0, \ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0, \ 'col': l:match[2] + 0,

View file

@ -6,6 +6,7 @@ call ale#Set('cpp_clangd_options', '')
function! ale_linters#cpp#clangd#GetProjectRoot(buffer) abort function! ale_linters#cpp#clangd#GetProjectRoot(buffer) abort
let l:project_root = ale#path#FindNearestFile(a:buffer, 'compile_commands.json') let l:project_root = ale#path#FindNearestFile(a:buffer, 'compile_commands.json')
return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : '' return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : ''
endfunction endfunction

View file

@ -22,6 +22,7 @@ function! ale_linters#cucumber#cucumber#Handle(buffer, lines) abort
endtry endtry
let l:output = [] let l:output = []
for l:element in get(l:json, 'elements', []) for l:element in get(l:json, 'elements', [])
for l:step in l:element['steps'] for l:step in l:element['steps']
if l:step['result']['status'] is# 'undefined' if l:step['result']['status'] is# 'undefined'

View file

@ -8,7 +8,6 @@ function! ale_linters#cuda#nvcc#GetCommand(buffer) abort
" Unused: use ale#util#nul_file " Unused: use ale#util#nul_file
" let l:output_file = ale#util#Tempname() . '.ii' " let l:output_file = ale#util#Tempname() . '.ii'
" call ale#engine#ManageFile(a:buffer, l:output_file) " call ale#engine#ManageFile(a:buffer, l:output_file)
return '%e -cuda' return '%e -cuda'
\ . ale#Pad(ale#c#IncludeOptions(ale#c#FindLocalHeaderPaths(a:buffer))) \ . ale#Pad(ale#c#IncludeOptions(ale#c#FindLocalHeaderPaths(a:buffer)))
\ . ale#Pad(ale#Var(a:buffer, 'cuda_nvcc_options')) \ . ale#Pad(ale#Var(a:buffer, 'cuda_nvcc_options'))
@ -23,7 +22,6 @@ function! ale_linters#cuda#nvcc#HandleNVCCFormat(buffer, lines) abort
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:item = { let l:item = {
\ 'lnum': str2nr(l:match[2]), \ 'lnum': str2nr(l:match[2]),
\ 'type': l:match[4] =~# 'error' ? 'E' : 'W', \ 'type': l:match[4] =~# 'error' ? 'E' : 'W',

View file

@ -13,6 +13,7 @@ function! ale_linters#dafny#dafny#Handle(buffer, lines) abort
\ 'type': l:match[4] =~# '^Error' ? 'E' : 'W' \ 'type': l:match[4] =~# '^Error' ? 'E' : 'W'
\ }) \ })
endfor endfor
return l:output return l:output
endfunction endfunction

View file

@ -82,9 +82,11 @@ endfunction
function! ale_linters#dockerfile#hadolint#GetCommand(buffer) abort function! ale_linters#dockerfile#hadolint#GetCommand(buffer) abort
let l:command = ale_linters#dockerfile#hadolint#GetExecutable(a:buffer) let l:command = ale_linters#dockerfile#hadolint#GetExecutable(a:buffer)
if l:command is# 'docker' if l:command is# 'docker'
return 'docker run --rm -i ' . ale#Var(a:buffer, 'dockerfile_hadolint_docker_image') return 'docker run --rm -i ' . ale#Var(a:buffer, 'dockerfile_hadolint_docker_image')
endif endif
return 'hadolint -' return 'hadolint -'
endfunction endfunction

View file

@ -10,7 +10,6 @@ function! ale_linters#elixir#mix#Handle(buffer, lines) abort
" "
" TODO: Warning format " TODO: Warning format
" warning: variable "foobar" does not exist and is being expanded to "foobar()", please use parentheses to remove the ambiguity or change the variable name " warning: variable "foobar" does not exist and is being expanded to "foobar()", please use parentheses to remove the ambiguity or change the variable name
let l:pattern = '\v\(([^\)]+Error)\) ([^:]+):([^:]+): (.+)$' let l:pattern = '\v\(([^\)]+Error)\) ([^:]+):([^:]+): (.+)$'
let l:output = [] let l:output = []
@ -32,9 +31,11 @@ endfunction
function! ale_linters#elixir#mix#FindProjectRoot(buffer) abort function! ale_linters#elixir#mix#FindProjectRoot(buffer) abort
let l:mix_file = ale#path#FindNearestFile(a:buffer, 'mix.exs') let l:mix_file = ale#path#FindNearestFile(a:buffer, 'mix.exs')
if !empty(l:mix_file) if !empty(l:mix_file)
return fnamemodify(l:mix_file, ':p:h') return fnamemodify(l:mix_file, ':p:h')
endif endif
return '.' return '.'
endfunction endfunction

View file

@ -21,7 +21,6 @@ function! ale_linters#go#gobuild#GetMatches(lines) abort
" file.go:27: missing argument for Printf("%s"): format reads arg 2, have only 1 args " file.go:27: missing argument for Printf("%s"): format reads arg 2, have only 1 args
" file.go:53:10: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary) " file.go:53:10: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
" file.go:5:2: expected declaration, found 'STRING' "log" " file.go:5:2: expected declaration, found 'STRING' "log"
" go test returns relative paths so use tail of filename as part of pattern matcher " go test returns relative paths so use tail of filename as part of pattern matcher
let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):?(\d+)?:? (.+)$' let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):?(\d+)?:? (.+)$'

View file

@ -8,6 +8,7 @@ call ale#Set('go_govet_options', '')
function! ale_linters#go#govet#GetCommand(buffer) abort function! ale_linters#go#govet#GetCommand(buffer) abort
let l:options = ale#Var(a:buffer, 'go_govet_options') let l:options = ale#Var(a:buffer, 'go_govet_options')
return ale#path#BufferCdString(a:buffer) . ' go vet .' return ale#path#BufferCdString(a:buffer) . ' go vet .'
\ . (!empty(l:options) ? ' ' . l:options : '') \ . (!empty(l:options) ? ' ' . l:options : '')
endfunction endfunction

View file

@ -25,6 +25,7 @@ function! ale_linters#html#tidy#GetCommand(buffer) abort
" On macOS, old tidy (released on 31 Oct 2006) is installed. It does not " On macOS, old tidy (released on 31 Oct 2006) is installed. It does not
" consider HTML5 so we should avoid it. " consider HTML5 so we should avoid it.
let l:executable = ale#Var(a:buffer, 'html_tidy_executable') let l:executable = ale#Var(a:buffer, 'html_tidy_executable')
if has('mac') && l:executable is# 'tidy' && exists('*exepath') if has('mac') && l:executable is# 'tidy' && exists('*exepath')
\ && exepath(l:executable) is# '/usr/bin/tidy' \ && exepath(l:executable) is# '/usr/bin/tidy'
return '' return ''
@ -40,7 +41,6 @@ endfunction
function! ale_linters#html#tidy#Handle(buffer, lines) abort function! ale_linters#html#tidy#Handle(buffer, lines) abort
" Matches patterns lines like the following: " Matches patterns lines like the following:
" line 7 column 5 - Warning: missing </title> before </head> " line 7 column 5 - Warning: missing </title> before </head>
let l:pattern = '^line \(\d\+\) column \(\d\+\) - \(Warning\|Error\): \(.\+\)$' let l:pattern = '^line \(\d\+\) column \(\d\+\) - \(Warning\|Error\): \(.\+\)$'
let l:output = [] let l:output = []

View file

@ -12,7 +12,7 @@ endfunction
function! ale_linters#idris#idris#Handle(buffer, lines) abort function! ale_linters#idris#idris#Handle(buffer, lines) abort
" This was copied almost verbatim from ale#handlers#haskell#HandleGHCFormat " This was copied almost verbatim from ale#handlers#haskell#HandleGHCFormat
"
" Look for lines like the following: " Look for lines like the following:
" foo.idr:2:6:When checking right hand side of main with expected type " foo.idr:2:6:When checking right hand side of main with expected type
" bar.idr:11:11-13: " bar.idr:11:11-13:
@ -30,6 +30,7 @@ function! ale_linters#idris#idris#Handle(buffer, lines) abort
else else
let l:corrected_lines[-1] .= l:line let l:corrected_lines[-1] .= l:line
endif endif
let l:corrected_lines[-1] = substitute(l:corrected_lines[-1], '\s\+', ' ', 'g') let l:corrected_lines[-1] = substitute(l:corrected_lines[-1], '\s\+', ' ', 'g')
endif endif
endfor endfor

View file

@ -16,6 +16,7 @@ function! ale_linters#java#javac#GetImportPaths(buffer) abort
endif endif
let l:classpath_command = ale#gradle#BuildClasspathCommand(a:buffer) let l:classpath_command = ale#gradle#BuildClasspathCommand(a:buffer)
if !empty(l:classpath_command) if !empty(l:classpath_command)
return l:classpath_command return l:classpath_command
endif endif
@ -90,7 +91,6 @@ function! ale_linters#java#javac#Handle(buffer, lines) abort
" "
" Main.java:13: warning: [deprecation] donaught() in Testclass has been deprecated " Main.java:13: warning: [deprecation] donaught() in Testclass has been deprecated
" Main.java:16: error: ';' expected " Main.java:16: error: ';' expected
let l:directory = expand('#' . a:buffer . ':p:h') let l:directory = expand('#' . a:buffer . ':p:h')
let l:pattern = '\v^(.*):(\d+): (.+):(.+)$' let l:pattern = '\v^(.*):(\d+): (.+):(.+)$'
let l:col_pattern = '\v^(\s*\^)$' let l:col_pattern = '\v^(\s*\^)$'

View file

@ -9,6 +9,7 @@ endfunction
function! ale_linters#java#javalsp#Command(buffer) abort function! ale_linters#java#javalsp#Command(buffer) abort
let l:jar = ale#Var(a:buffer, 'java_javalsp_jar') let l:jar = ale#Var(a:buffer, 'java_javalsp_jar')
return ale#Escape('java -cp ' . l:jar . ' -Xverify:none org.javacs.Main') return ale#Escape('java -cp ' . l:jar . ' -Xverify:none org.javacs.Main')
endfunction endfunction

View file

@ -91,7 +91,6 @@ function! s:GetDetails(error) abort
let l:detail = '' let l:detail = ''
for l:extra_error in a:error.extra for l:extra_error in a:error.extra
if has_key(l:extra_error, 'message') if has_key(l:extra_error, 'message')
for l:extra_message in l:extra_error.message for l:extra_message in l:extra_error.message
let l:detail = s:ExtraErrorMsg(l:detail, l:extra_message.descr) let l:detail = s:ExtraErrorMsg(l:detail, l:extra_message.descr)
@ -105,7 +104,6 @@ function! s:GetDetails(error) abort
endfor endfor
endfor endfor
endif endif
endfor endfor
return l:detail return l:detail
@ -161,7 +159,6 @@ function! ale_linters#javascript#flow#Handle(buffer, lines) abort
endif endif
call add(l:output, l:errorToAdd) call add(l:output, l:errorToAdd)
endfor endfor
return l:output return l:output

View file

@ -3,7 +3,6 @@
function! ale_linters#json#jsonlint#Handle(buffer, lines) abort function! ale_linters#json#jsonlint#Handle(buffer, lines) abort
" Matches patterns like the following: " Matches patterns like the following:
" line 2, col 15, found: 'STRING' - expected: 'EOF', '}', ',', ']'. " line 2, col 15, found: 'STRING' - expected: 'EOF', '}', ',', ']'.
let l:pattern = '^line \(\d\+\), col \(\d*\), \(.\+\)$' let l:pattern = '^line \(\d\+\), col \(\d*\), \(.\+\)$'
let l:output = [] let l:output = []

View file

@ -17,12 +17,14 @@ function! ale_linters#kotlin#kotlinc#GetImportPaths(buffer) abort
return '' return ''
else else
let l:pom_path = ale#path#FindNearestFile(a:buffer, 'pom.xml') let l:pom_path = ale#path#FindNearestFile(a:buffer, 'pom.xml')
if !empty(l:pom_path) && executable('mvn') if !empty(l:pom_path) && executable('mvn')
return ale#path#CdString(fnamemodify(l:pom_path, ':h')) return ale#path#CdString(fnamemodify(l:pom_path, ':h'))
\ . 'mvn dependency:build-classpath' \ . 'mvn dependency:build-classpath'
endif endif
let l:classpath_command = ale#gradle#BuildClasspathCommand(a:buffer) let l:classpath_command = ale#gradle#BuildClasspathCommand(a:buffer)
if !empty(l:classpath_command) if !empty(l:classpath_command)
return l:classpath_command return l:classpath_command
endif endif
@ -78,12 +80,13 @@ function! ale_linters#kotlin#kotlinc#GetCommand(buffer, import_paths) abort
endif endif
let l:fname = '' let l:fname = ''
if ale#Var(a:buffer, 'kotlin_kotlinc_sourcepath') isnot# '' if ale#Var(a:buffer, 'kotlin_kotlinc_sourcepath') isnot# ''
let l:fname .= expand(ale#Var(a:buffer, 'kotlin_kotlinc_sourcepath'), 1) . ' ' let l:fname .= expand(ale#Var(a:buffer, 'kotlin_kotlinc_sourcepath'), 1) . ' '
else else
" Find the src directory for files in this project. " Find the src directory for files in this project.
let l:project_root = ale#gradle#FindProjectRoot(a:buffer) let l:project_root = ale#gradle#FindProjectRoot(a:buffer)
if !empty(l:project_root) if !empty(l:project_root)
let l:src_dir = l:project_root let l:src_dir = l:project_root
else else
@ -93,6 +96,7 @@ function! ale_linters#kotlin#kotlinc#GetCommand(buffer, import_paths) abort
let l:fname .= expand(l:src_dir, 1) . ' ' let l:fname .= expand(l:src_dir, 1) . ' '
endif endif
let l:fname .= ale#Escape(expand('#' . a:buffer . ':p')) let l:fname .= ale#Escape(expand('#' . a:buffer . ':p'))
let l:command .= l:kotlinc_opts . ' ' . l:fname let l:command .= l:kotlinc_opts . ' ' . l:fname
@ -124,6 +128,7 @@ function! ale_linters#kotlin#kotlinc#Handle(buffer, lines) abort
if l:buf_abspath isnot# l:curbuf_abspath if l:buf_abspath isnot# l:curbuf_abspath
continue continue
endif endif
let l:type_marker_str = l:type is# 'warning' ? 'W' : 'E' let l:type_marker_str = l:type is# 'warning' ? 'W' : 'E'
call add(l:output, { call add(l:output, {

View file

@ -13,6 +13,7 @@ function! ale_linters#make#checkmake#Handle(buffer, lines) abort
\ 'text': l:match[3], \ 'text': l:match[3],
\}) \})
endfor endfor
return l:output return l:output
endfunction endfunction

View file

@ -24,10 +24,12 @@ function! ale_linters#markdown#remark_lint#Handle(buffer, lines) abort
\ 'type': l:match[6] is# 'error' ? 'E' : 'W', \ 'type': l:match[6] is# 'error' ? 'E' : 'W',
\ 'text': l:match[7], \ 'text': l:match[7],
\} \}
if l:match[3] isnot# '' if l:match[3] isnot# ''
let l:item.end_lnum = l:match[4] + 0 let l:item.end_lnum = l:match[4] + 0
let l:item.end_col = l:match[5] + 0 let l:item.end_col = l:match[5] + 0
endif endif
call add(l:output, l:item) call add(l:output, l:item)
endfor endfor

View file

@ -6,6 +6,7 @@ call ale#Set('objc_clangd_options', '')
function! ale_linters#objc#clangd#GetProjectRoot(buffer) abort function! ale_linters#objc#clangd#GetProjectRoot(buffer) abort
let l:project_root = ale#path#FindNearestFile(a:buffer, 'compile_commands.json') let l:project_root = ale#path#FindNearestFile(a:buffer, 'compile_commands.json')
return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : '' return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : ''
endfunction endfunction

View file

@ -6,6 +6,7 @@ call ale#Set('objcpp_clangd_options', '')
function! ale_linters#objcpp#clangd#GetProjectRoot(buffer) abort function! ale_linters#objcpp#clangd#GetProjectRoot(buffer) abort
let l:project_root = ale#path#FindNearestFile(a:buffer, 'compile_commands.json') let l:project_root = ale#path#FindNearestFile(a:buffer, 'compile_commands.json')
return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : '' return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : ''
endfunction endfunction

View file

@ -19,6 +19,7 @@ function! ale_linters#perl#perl#Handle(buffer, lines) abort
let l:basename = expand('#' . a:buffer . ':t') let l:basename = expand('#' . a:buffer . ':t')
let l:type = 'E' let l:type = 'E'
if a:lines[-1] =~# 'syntax OK' if a:lines[-1] =~# 'syntax OK'
let l:type = 'W' let l:type = 'W'
endif endif

View file

@ -8,6 +8,7 @@ function! ale_linters#puppet#languageserver#GetProjectRoot(buffer) abort
" there's no requirement to have it, so fall back to the other possible " there's no requirement to have it, so fall back to the other possible
" Puppet module directories " Puppet module directories
let l:root_path = ale#path#FindNearestFile(a:buffer, 'metadata.json') let l:root_path = ale#path#FindNearestFile(a:buffer, 'metadata.json')
if !empty(l:root_path) if !empty(l:root_path)
return fnamemodify(l:root_path, ':h') return fnamemodify(l:root_path, ':h')
endif endif
@ -17,6 +18,7 @@ function! ale_linters#puppet#languageserver#GetProjectRoot(buffer) abort
\ 'templates', \ 'templates',
\] \]
let l:root_path = ale#path#FindNearestDirectory(a:buffer, l:test_path) let l:root_path = ale#path#FindNearestDirectory(a:buffer, l:test_path)
if !empty(l:root_path) if !empty(l:root_path)
return fnamemodify(l:root_path, ':h:h') return fnamemodify(l:root_path, ':h:h')
endif endif

View file

@ -8,7 +8,6 @@ function! ale_linters#puppet#puppet#Handle(buffer, lines) abort
" Error: Could not parse for environment production: Syntax error at ':' at /root/puppetcode/modules/nginx/manifests/init.pp:43:12 " Error: Could not parse for environment production: Syntax error at ':' at /root/puppetcode/modules/nginx/manifests/init.pp:43:12
" Error: Could not parse for environment production: Syntax error at '='; expected '}' at /root/puppetcode/modules/pancakes/manifests/init.pp:5" " Error: Could not parse for environment production: Syntax error at '='; expected '}' at /root/puppetcode/modules/pancakes/manifests/init.pp:5"
" Error: Could not parse for environment production: Syntax error at 'parameter1' (file: /tmp/modules/mariadb/manifests/slave.pp, line: 4, column: 5) " Error: Could not parse for environment production: Syntax error at 'parameter1' (file: /tmp/modules/mariadb/manifests/slave.pp, line: 4, column: 5)
let l:pattern = '^Error: .*: \(.\+\) \((file:\|at\) .\+\.pp\(, line: \|:\)\(\d\+\)\(, column: \|:\)\=\(\d*\)' let l:pattern = '^Error: .*: \(.\+\) \((file:\|at\) .\+\.pp\(, line: \|:\)\(\d\+\)\(, column: \|:\)\=\(\d*\)'
let l:output = [] let l:output = []

View file

@ -8,6 +8,7 @@ function! ale_linters#rst#rstcheck#Handle(buffer, lines) abort
let l:pattern = '\v^(.+):(\d*): \(([a-zA-Z]*)/\d*\) (.+)$' let l:pattern = '\v^(.+):(\d*): \(([a-zA-Z]*)/\d*\) (.+)$'
let l:dir = expand('#' . a:buffer . ':p:h') let l:dir = expand('#' . a:buffer . ':p:h')
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, { call add(l:output, {
\ 'filename': ale#path#GetAbsPath(l:dir, l:match[1]), \ 'filename': ale#path#GetAbsPath(l:dir, l:match[1]),

View file

@ -7,6 +7,7 @@ call ale#Set('ruby_solargraph_port', '7658')
function! ale_linters#ruby#solargraph#GetAddress(buffer) abort function! ale_linters#ruby#solargraph#GetAddress(buffer) abort
let l:host = ale#Var(a:buffer, 'ruby_solargraph_host') let l:host = ale#Var(a:buffer, 'ruby_solargraph_host')
let l:port = ale#Var(a:buffer, 'ruby_solargraph_port') let l:port = ale#Var(a:buffer, 'ruby_solargraph_port')
return l:host . ':' . l:port return l:host . ':' . l:port
endfunction endfunction

View file

@ -42,6 +42,7 @@ function! ale_linters#rust#cargo#GetCommand(buffer, version_output) abort
\ && ale#semver#GTE(l:version, [0, 22, 0]) \ && ale#semver#GTE(l:version, [0, 22, 0])
let l:include_features = ale#Var(a:buffer, 'rust_cargo_include_features') let l:include_features = ale#Var(a:buffer, 'rust_cargo_include_features')
if !empty(l:include_features) if !empty(l:include_features)
let l:include_features = ' --features ' . ale#Escape(l:include_features) let l:include_features = ' --features ' . ale#Escape(l:include_features)
endif endif
@ -59,6 +60,7 @@ function! ale_linters#rust#cargo#GetCommand(buffer, version_output) abort
endif endif
let l:default_feature_behavior = ale#Var(a:buffer, 'rust_cargo_default_feature_behavior') let l:default_feature_behavior = ale#Var(a:buffer, 'rust_cargo_default_feature_behavior')
if l:default_feature_behavior is# 'all' if l:default_feature_behavior is# 'all'
let l:include_features = '' let l:include_features = ''
let l:default_feature = ' --all-features' let l:default_feature = ' --all-features'

View file

@ -6,15 +6,19 @@ call ale#Set('scala_sbtserver_project_root', '')
function! ale_linters#scala#sbtserver#GetProjectRoot(buffer) abort function! ale_linters#scala#sbtserver#GetProjectRoot(buffer) abort
let l:project_root = ale#Var(a:buffer, 'scala_sbtserver_project_root') let l:project_root = ale#Var(a:buffer, 'scala_sbtserver_project_root')
if l:project_root is? '' if l:project_root is? ''
let l:project_root = ale#path#FindNearestFile(a:buffer, 'build.sbt') let l:project_root = ale#path#FindNearestFile(a:buffer, 'build.sbt')
return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : '' return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : ''
endif endif
return l:project_root return l:project_root
endfunction endfunction
function! ale_linters#scala#sbtserver#GetAddress(buffer) abort function! ale_linters#scala#sbtserver#GetAddress(buffer) abort
let l:address = ale#Var(a:buffer, 'scala_sbtserver_address') let l:address = ale#Var(a:buffer, 'scala_sbtserver_address')
return l:address return l:address
endfunction endfunction

View file

@ -53,12 +53,14 @@ function! ale_linters#scala#scalastyle#GetCommand(buffer) abort
\ 'scalastyle_config.xml', \ 'scalastyle_config.xml',
\ 'scalastyle-config.xml' \ 'scalastyle-config.xml'
\] \]
for l:config in l:potential_configs for l:config in l:potential_configs
let l:scalastyle_config = ale#path#ResolveLocalPath( let l:scalastyle_config = ale#path#ResolveLocalPath(
\ a:buffer, \ a:buffer,
\ l:config, \ l:config,
\ '' \ ''
\) \)
if !empty(l:scalastyle_config) if !empty(l:scalastyle_config)
break break
endif endif

View file

@ -3,6 +3,7 @@
function! ale_linters#sml#smlnj_cm#GetCommand(buffer) abort function! ale_linters#sml#smlnj_cm#GetCommand(buffer) abort
let l:cmfile = ale#handlers#sml#GetCmFile(a:buffer) let l:cmfile = ale#handlers#sml#GetCmFile(a:buffer)
return 'sml -m ' . l:cmfile . ' < /dev/null' return 'sml -m ' . l:cmfile . ' < /dev/null'
endfunction endfunction

View file

@ -4,7 +4,6 @@
function! ale_linters#solidity#solhint#Handle(buffer, lines) abort function! ale_linters#solidity#solhint#Handle(buffer, lines) abort
" Matches patterns like the following: " Matches patterns like the following:
" /path/to/file/file.sol: line 1, col 10, Error - 'addOne' is defined but never used. (no-unused-vars) " /path/to/file/file.sol: line 1, col 10, Error - 'addOne' is defined but never used. (no-unused-vars)
let l:pattern = '\v^[^:]+: line (\d+), col (\d+), (Error|Warning) - (.*) \((.*)\)$' let l:pattern = '\v^[^:]+: line (\d+), col (\d+), (Error|Warning) - (.*) \((.*)\)$'
let l:output = [] let l:output = []

View file

@ -15,7 +15,6 @@ function! ale_linters#tcl#nagelfar#Handle(buffer, lines) abort
" Line 5: W Found constant "bepa" which is also a variable. " Line 5: W Found constant "bepa" which is also a variable.
" Line 13: E Wrong number of arguments (3) to "set" " Line 13: E Wrong number of arguments (3) to "set"
" Line 93: N Close brace not aligned with line 90 (4 0) " Line 93: N Close brace not aligned with line 90 (4 0)
let l:pattern = '^Line\s\+\([0-9]\+\): \([NEW]\) \(.*\)$' let l:pattern = '^Line\s\+\([0-9]\+\): \([NEW]\) \(.*\)$'
let l:output = [] let l:output = []

View file

@ -40,6 +40,7 @@ function! ale_linters#terraform#tflint#GetCommand(buffer) abort
endif endif
let l:opts = ale#Var(a:buffer, 'terraform_tflint_options') let l:opts = ale#Var(a:buffer, 'terraform_tflint_options')
if !empty(l:opts) if !empty(l:opts)
let l:cmd .= ' ' . l:opts let l:cmd .= ' ' . l:opts
endif endif

View file

@ -8,7 +8,6 @@ function! ale_linters#tex#lacheck#Handle(buffer, lines) abort
" "
" "book.tex", line 37: possible unwanted space at "{" " "book.tex", line 37: possible unwanted space at "{"
" "book.tex", line 38: missing `\ ' after "etc." " "book.tex", line 38: missing `\ ' after "etc."
let l:pattern = '^".\+", line \(\d\+\): \(.\+\)$' let l:pattern = '^".\+", line \(\d\+\): \(.\+\)$'
let l:output = [] let l:output = []

View file

@ -42,12 +42,14 @@ function! ale_linters#thrift#thrift#Handle(buffer, lines) abort
let l:line = a:lines[l:index] let l:line = a:lines[l:index]
let l:match = matchlist(l:line, l:pattern) let l:match = matchlist(l:line, l:pattern)
if empty(l:match) if empty(l:match)
let l:index += 1 let l:index += 1
continue continue
endif endif
let l:severity = l:match[1] let l:severity = l:match[1]
if l:severity is# 'WARNING' if l:severity is# 'WARNING'
let l:type = 'W' let l:type = 'W'
else else
@ -57,6 +59,7 @@ function! ale_linters#thrift#thrift#Handle(buffer, lines) abort
" If our text looks like "(last token was ';')", the *next* line " If our text looks like "(last token was ';')", the *next* line
" should contain a more descriptive error message. " should contain a more descriptive error message.
let l:text = l:match[4] let l:text = l:match[4]
if l:text =~# '\(last token was .*\)' if l:text =~# '\(last token was .*\)'
let l:index += 1 let l:index += 1
let l:text = get(a:lines, l:index, 'Unknown error ' . l:text) let l:text = get(a:lines, l:index, 'Unknown error ' . l:text)

View file

@ -25,7 +25,13 @@ endfunction
function! ale_linters#vim#ale_custom_linting_rules#GetCommand(buffer) abort function! ale_linters#vim#ale_custom_linting_rules#GetCommand(buffer) abort
let l:dir = s:GetALEProjectDir(a:buffer) let l:dir = s:GetALEProjectDir(a:buffer)
return ale#path#CdString(l:dir) . '%e .' let l:temp_dir = ale#engine#CreateDirectory(a:buffer)
let l:temp_file = l:temp_dir . '/example.vim'
let l:lines = getbufline(a:buffer, 1, '$')
call ale#util#Writefile(a:buffer, l:lines, l:temp_file)
return ale#path#CdString(l:dir) . '%e ' . ale#Escape(l:temp_dir)
endfunction endfunction
function! ale_linters#vim#ale_custom_linting_rules#Handle(buffer, lines) abort function! ale_linters#vim#ale_custom_linting_rules#Handle(buffer, lines) abort
@ -34,15 +40,17 @@ function! ale_linters#vim#ale_custom_linting_rules#Handle(buffer, lines) abort
let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+) (.+)$' let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+) (.+)$'
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:filename = ale#path#GetAbsPath(l:dir, l:match[1]) " Ignore trailing whitespace errors if we've turned them off.
if !ale#Var(a:buffer, 'warn_about_trailing_whitespace')
if bufnr(l:filename) is a:buffer \&& l:match[3] is# 'Trailing whitespace'
call add(l:output, { continue
\ 'lnum': l:match[2],
\ 'text': l:match[3],
\ 'type': 'W',
\})
endif endif
call add(l:output, {
\ 'lnum': l:match[2],
\ 'text': l:match[3],
\ 'type': 'W',
\})
endfor endfor
return l:output return l:output
@ -53,5 +61,5 @@ call ale#linter#Define('vim', {
\ 'executable_callback': 'ale_linters#vim#ale_custom_linting_rules#GetExecutable', \ 'executable_callback': 'ale_linters#vim#ale_custom_linting_rules#GetExecutable',
\ 'command_callback': 'ale_linters#vim#ale_custom_linting_rules#GetCommand', \ 'command_callback': 'ale_linters#vim#ale_custom_linting_rules#GetCommand',
\ 'callback': 'ale_linters#vim#ale_custom_linting_rules#Handle', \ 'callback': 'ale_linters#vim#ale_custom_linting_rules#Handle',
\ 'lint_file': 1, \ 'read_buffer': 0,
\}) \})

View file

@ -25,9 +25,9 @@ function! ale_linters#xml#xmllint#Handle(buffer, lines) abort
let l:output = [] let l:output = []
for l:line in a:lines for l:line in a:lines
" Parse error/warning lines " Parse error/warning lines
let l:match_message = matchlist(l:line, l:pattern_message) let l:match_message = matchlist(l:line, l:pattern_message)
if !empty(l:match_message) if !empty(l:match_message)
let l:line = l:match_message[2] + 0 let l:line = l:match_message[2] + 0
let l:type = l:match_message[4] =~? 'warning' ? 'W' : 'E' let l:type = l:match_message[4] =~? 'warning' ? 'W' : 'E'
@ -44,13 +44,13 @@ function! ale_linters#xml#xmllint#Handle(buffer, lines) abort
" Parse column position " Parse column position
let l:match_column_token = matchlist(l:line, l:pattern_column_token) let l:match_column_token = matchlist(l:line, l:pattern_column_token)
if !empty(l:output) && !empty(l:match_column_token) if !empty(l:output) && !empty(l:match_column_token)
let l:previous = l:output[len(l:output) - 1] let l:previous = l:output[len(l:output) - 1]
let l:previous['col'] = len(l:match_column_token[0]) let l:previous['col'] = len(l:match_column_token[0])
continue continue
endif endif
endfor endfor
return l:output return l:output

View file

@ -2,6 +2,7 @@ call ale#Set('yang_lsp_executable', 'yang-language-server')
function! ale_linters#yang#yang_lsp#GetProjectRoot(buffer) abort function! ale_linters#yang#yang_lsp#GetProjectRoot(buffer) abort
let l:project_root = ale#path#FindNearestFile(a:buffer, 'yang.settings') let l:project_root = ale#path#FindNearestFile(a:buffer, 'yang.settings')
return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : '' return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : ''
endfunction endfunction

View file

@ -27,7 +27,7 @@ let s:getcmdwintype_exists = exists('*getcmdwintype')
function! ale#ShouldDoNothing(buffer) abort function! ale#ShouldDoNothing(buffer) abort
" The checks are split into separate if statements to make it possible to " The checks are split into separate if statements to make it possible to
" profile each check individually with Vim's profiling tools. " profile each check individually with Vim's profiling tools.
"
" Do nothing if ALE is disabled. " Do nothing if ALE is disabled.
if !getbufvar(a:buffer, 'ale_enabled', get(g:, 'ale_enabled', 0)) if !getbufvar(a:buffer, 'ale_enabled', get(g:, 'ale_enabled', 0))
return 1 return 1

View file

@ -54,6 +54,7 @@ function! ale#c#ParseCFlags(path_prefix, cflag_line) abort
call add(l:previous_options, l:option) call add(l:previous_options, l:option)
" Check if cflag contained a '-' and should not have been splitted " Check if cflag contained a '-' and should not have been splitted
let l:option_list = split(l:option, '\zs') let l:option_list = split(l:option, '\zs')
if l:option_list[-1] isnot# ' ' if l:option_list[-1] isnot# ' '
continue continue
endif endif

View file

@ -75,6 +75,7 @@ endfunction
" Check if we should look for completions for a language. " Check if we should look for completions for a language.
function! ale#completion#GetPrefix(filetype, line, column) abort function! ale#completion#GetPrefix(filetype, line, column) abort
let l:regex = s:GetFiletypeValue(s:should_complete_map, a:filetype) let l:regex = s:GetFiletypeValue(s:should_complete_map, a:filetype)
" The column we're using completions for is where we are inserting text, " The column we're using completions for is where we are inserting text,
" like so: " like so:
" abc " abc

View file

@ -231,6 +231,7 @@ function! s:HandleExit(job_id, exit_code) abort
if l:next_chain_index < len(get(l:linter, 'command_chain', [])) if l:next_chain_index < len(get(l:linter, 'command_chain', []))
call s:InvokeChain(l:buffer, l:executable, l:linter, l:next_chain_index, l:output) call s:InvokeChain(l:buffer, l:executable, l:linter, l:next_chain_index, l:output)
return return
endif endif
@ -595,9 +596,8 @@ function! ale#engine#ProcessChain(buffer, linter, chain_index, input) abort
\) \)
endif endif
" If we have a command to run, execute that.
if !empty(l:command) if !empty(l:command)
" We hit a command to run, so we'll execute that
" The chain item can override the output_stream option. " The chain item can override the output_stream option.
if has_key(l:chain_item, 'output_stream') if has_key(l:chain_item, 'output_stream')
let l:output_stream = l:chain_item.output_stream let l:output_stream = l:chain_item.output_stream

View file

@ -71,6 +71,7 @@ function! ale#fix#ApplyFixes(buffer, output) abort
if l:data.lines_before != l:lines if l:data.lines_before != l:lines
call remove(g:ale_fix_buffer_data, a:buffer) call remove(g:ale_fix_buffer_data, a:buffer)
execute 'echoerr ''The file was changed before fixing finished''' execute 'echoerr ''The file was changed before fixing finished'''
return return
endif endif
endif endif

View file

@ -17,6 +17,7 @@ function! ale#fixers#fixjson#Fix(buffer) abort
let l:command = l:executable . ' --stdin-filename ' . l:filename let l:command = l:executable . ' --stdin-filename ' . l:filename
let l:options = ale#Var(a:buffer, 'json_fixjson_options') let l:options = ale#Var(a:buffer, 'json_fixjson_options')
if l:options isnot# '' if l:options isnot# ''
let l:command .= ' ' . l:options let l:command .= ' ' . l:options
endif endif

View file

@ -5,6 +5,7 @@ call ale#Set('javascript_importjs_executable', 'importjs')
function! ale#fixers#importjs#ProcessOutput(buffer, output) abort function! ale#fixers#importjs#ProcessOutput(buffer, output) abort
let l:result = ale#util#FuzzyJSONDecode(a:output, []) let l:result = ale#util#FuzzyJSONDecode(a:output, [])
return split(get(l:result, 'fileContent', ''), "\n") return split(get(l:result, 'fileContent', ''), "\n")
endfunction endfunction

View file

@ -14,6 +14,7 @@ endfunction
function! ale#fixers#php_cs_fixer#Fix(buffer) abort function! ale#fixers#php_cs_fixer#Fix(buffer) abort
let l:executable = ale#fixers#php_cs_fixer#GetExecutable(a:buffer) let l:executable = ale#fixers#php_cs_fixer#GetExecutable(a:buffer)
return { return {
\ 'command': ale#Escape(l:executable) \ 'command': ale#Escape(l:executable)
\ . ' ' . ale#Var(a:buffer, 'php_cs_fixer_options') \ . ' ' . ale#Var(a:buffer, 'php_cs_fixer_options')

View file

@ -18,6 +18,7 @@ function! ale#fixers#phpcbf#Fix(buffer) abort
let l:standard_option = !empty(l:standard) let l:standard_option = !empty(l:standard)
\ ? '--standard=' . l:standard \ ? '--standard=' . l:standard
\ : '' \ : ''
return { return {
\ 'command': ale#Escape(l:executable) . ' --stdin-path=%s ' . l:standard_option . ' -' \ 'command': ale#Escape(l:executable) . ' --stdin-path=%s ' . l:standard_option . ' -'
\} \}

View file

@ -4,6 +4,7 @@
if !exists('g:ale_puppet_puppetlint_executable') if !exists('g:ale_puppet_puppetlint_executable')
let g:ale_puppet_puppetlint_executable = 'puppet-lint' let g:ale_puppet_puppetlint_executable = 'puppet-lint'
endif endif
if !exists('g:ale_puppet_puppetlint_options') if !exists('g:ale_puppet_puppetlint_options')
let g:ale_puppet_puppetlint_options = '' let g:ale_puppet_puppetlint_options = ''
endif endif

View file

@ -10,7 +10,6 @@ function! ale#fixers#rubocop#GetCommand(buffer) abort
\ . (!empty(l:config) ? ' --config ' . ale#Escape(l:config) : '') \ . (!empty(l:config) ? ' --config ' . ale#Escape(l:config) : '')
\ . (!empty(l:options) ? ' ' . l:options : '') \ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' --auto-correct %t' \ . ' --auto-correct %t'
endfunction endfunction
function! ale#fixers#rubocop#Fix(buffer) abort function! ale#fixers#rubocop#Fix(buffer) abort

View file

@ -15,7 +15,6 @@ function! ale#fixers#scalafmt#GetCommand(buffer) abort
return ale#Escape(l:executable) . l:exec_args return ale#Escape(l:executable) . l:exec_args
\ . (empty(l:options) ? '' : ' ' . l:options) \ . (empty(l:options) ? '' : ' ' . l:options)
\ . ' %t' \ . ' %t'
endfunction endfunction
function! ale#fixers#scalafmt#Fix(buffer) abort function! ale#fixers#scalafmt#Fix(buffer) abort

View file

@ -13,5 +13,4 @@ function! ale#fixers#shfmt#Fix(buffer) abort
\ 'command': ale#Escape(l:executable) \ 'command': ale#Escape(l:executable)
\ . (empty(l:options) ? '' : ' ' . l:options) \ . (empty(l:options) ? '' : ' ' . l:options)
\} \}
endfunction endfunction

View file

@ -11,12 +11,14 @@ function! ale#fixers#xmllint#Fix(buffer) abort
let l:command = l:executable . ' --format ' . l:filename let l:command = l:executable . ' --format ' . l:filename
let l:indent = ale#Var(a:buffer, 'xml_xmllint_indentsize') let l:indent = ale#Var(a:buffer, 'xml_xmllint_indentsize')
if l:indent isnot# '' if l:indent isnot# ''
let l:env = ale#Env('XMLLINT_INDENT', repeat(' ', l:indent)) let l:env = ale#Env('XMLLINT_INDENT', repeat(' ', l:indent))
let l:command = l:env . l:command let l:command = l:env . l:command
endif endif
let l:options = ale#Var(a:buffer, 'xml_xmllint_options') let l:options = ale#Var(a:buffer, 'xml_xmllint_options')
if l:options isnot# '' if l:options isnot# ''
let l:command .= ' ' . l:options let l:command .= ' ' . l:options
endif endif

View file

@ -9,9 +9,11 @@ function! ale#handlers#gawk#HandleGawkFormat(buffer, lines) abort
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:ecode = 'E' let l:ecode = 'E'
if l:match[2] is? 'warning:' if l:match[2] is? 'warning:'
let l:ecode = 'W' let l:ecode = 'W'
endif endif
call add(l:output, { call add(l:output, {
\ 'lnum': l:match[1] + 0, \ 'lnum': l:match[1] + 0,
\ 'col': 0, \ 'col': 0,

View file

@ -21,5 +21,6 @@ function! ale#handlers#go#Handler(buffer, lines) abort
\ 'type': 'E', \ 'type': 'E',
\}) \})
endfor endfor
return l:output return l:output
endfunction endfunction

View file

@ -3,6 +3,7 @@
function! ale#handlers#ols#GetExecutable(buffer) abort function! ale#handlers#ols#GetExecutable(buffer) abort
let l:ols_setting = ale#handlers#ols#GetLanguage(a:buffer) . '_ols' let l:ols_setting = ale#handlers#ols#GetLanguage(a:buffer) . '_ols'
return ale#node#FindExecutable(a:buffer, l:ols_setting, [ return ale#node#FindExecutable(a:buffer, l:ols_setting, [
\ 'node_modules/.bin/ocaml-language-server', \ 'node_modules/.bin/ocaml-language-server',
\]) \])

View file

@ -14,7 +14,6 @@ endfunction
function! ale#handlers#pony#HandlePonycFormat(buffer, lines) abort function! ale#handlers#pony#HandlePonycFormat(buffer, lines) abort
" Look for lines like the following. " Look for lines like the following.
" /home/code/pony/classes/Wombat.pony:22:30: can't lookup private fields from outside the type " /home/code/pony/classes/Wombat.pony:22:30: can't lookup private fields from outside the type
let l:pattern = '\v^([^:]+):(\d+):(\d+)?:? (.+)$' let l:pattern = '\v^([^:]+):(\d+):(\d+)?:? (.+)$'
let l:output = [] let l:output = []

View file

@ -6,15 +6,18 @@ function! ale#handlers#redpen#HandleRedpenOutput(buffer, lines) abort
" element. " element.
let l:res = json_decode(join(a:lines))[0] let l:res = json_decode(join(a:lines))[0]
let l:output = [] let l:output = []
for l:err in l:res.errors for l:err in l:res.errors
let l:item = { let l:item = {
\ 'text': l:err.message, \ 'text': l:err.message,
\ 'type': 'W', \ 'type': 'W',
\ 'code': l:err.validator, \ 'code': l:err.validator,
\} \}
if has_key(l:err, 'startPosition') if has_key(l:err, 'startPosition')
let l:item.lnum = l:err.startPosition.lineNum let l:item.lnum = l:err.startPosition.lineNum
let l:item.col = l:err.startPosition.offset + 1 let l:item.col = l:err.startPosition.offset + 1
if has_key(l:err, 'endPosition') if has_key(l:err, 'endPosition')
let l:item.end_lnum = l:err.endPosition.lineNum let l:item.end_lnum = l:err.endPosition.lineNum
let l:item.end_col = l:err.endPosition.offset let l:item.end_col = l:err.endPosition.offset
@ -28,29 +31,35 @@ function! ale#handlers#redpen#HandleRedpenOutput(buffer, lines) abort
" Adjust column number for multibyte string " Adjust column number for multibyte string
let l:line = getline(l:item.lnum) let l:line = getline(l:item.lnum)
if l:line is# '' if l:line is# ''
let l:line = l:err.sentence let l:line = l:err.sentence
endif endif
let l:line = split(l:line, '\zs') let l:line = split(l:line, '\zs')
if l:item.col >= 2 if l:item.col >= 2
let l:col = 0 let l:col = 0
for l:strlen in map(l:line[0:(l:item.col - 2)], 'strlen(v:val)') for l:strlen in map(l:line[0:(l:item.col - 2)], 'strlen(v:val)')
let l:col = l:col + l:strlen let l:col = l:col + l:strlen
endfor endfor
let l:item.col = l:col + 1 let l:item.col = l:col + 1
endif endif
if has_key(l:item, 'end_col') if has_key(l:item, 'end_col')
let l:col = 0 let l:col = 0
for l:strlen in map(l:line[0:(l:item.end_col - 1)], 'strlen(v:val)') for l:strlen in map(l:line[0:(l:item.end_col - 1)], 'strlen(v:val)')
let l:col = l:col + l:strlen let l:col = l:col + l:strlen
endfor endfor
let l:item.end_col = l:col let l:item.end_col = l:col
endif endif
call add(l:output, l:item) call add(l:output, l:item)
endfor endfor
return l:output return l:output
endfunction endfunction

View file

@ -13,8 +13,10 @@ function! s:HandleSyntaxError(buffer, lines) abort
for l:line in a:lines for l:line in a:lines
let l:match = matchlist(l:line, l:pattern) let l:match = matchlist(l:line, l:pattern)
if len(l:match) == 0 if len(l:match) == 0
let l:match = matchlist(l:line, l:column) let l:match = matchlist(l:line, l:column)
if len(l:match) != 0 if len(l:match) != 0
let l:output[len(l:output) - 1]['col'] = len(l:match[1]) let l:output[len(l:output) - 1]['col'] = len(l:match[1])
endif endif

View file

@ -11,8 +11,10 @@ function! ale#handlers#sml#GetCmFile(buffer) abort
let l:as_list = 1 let l:as_list = 1
let l:cmfile = '' let l:cmfile = ''
for l:path in ale#path#Upwards(expand('#' . a:buffer . ':p:h')) for l:path in ale#path#Upwards(expand('#' . a:buffer . ':p:h'))
let l:results = glob(l:path . '/' . l:pattern, 0, l:as_list) let l:results = glob(l:path . '/' . l:pattern, 0, l:as_list)
if len(l:results) > 0 if len(l:results) > 0
" If there is more than one CM file, we take the first one " If there is more than one CM file, we take the first one
" See :help ale-sml-smlnj for how to configure this. " See :help ale-sml-smlnj for how to configure this.
@ -46,6 +48,7 @@ endfunction
function! ale#handlers#sml#GetExecutableSmlnjCm(buffer) abort function! ale#handlers#sml#GetExecutableSmlnjCm(buffer) abort
return s:GetExecutable(a:buffer, 'smlnj-cm') return s:GetExecutable(a:buffer, 'smlnj-cm')
endfunction endfunction
function! ale#handlers#sml#GetExecutableSmlnjFile(buffer) abort function! ale#handlers#sml#GetExecutableSmlnjFile(buffer) abort
return s:GetExecutable(a:buffer, 'smlnj-file') return s:GetExecutable(a:buffer, 'smlnj-file')
endfunction endfunction
@ -53,7 +56,6 @@ endfunction
function! ale#handlers#sml#Handle(buffer, lines) abort function! ale#handlers#sml#Handle(buffer, lines) abort
" Try to match basic sml errors " Try to match basic sml errors
" TODO(jez) We can get better errorfmt strings from Syntastic " TODO(jez) We can get better errorfmt strings from Syntastic
let l:out = [] let l:out = []
let l:pattern = '^.*\:\([0-9\.]\+\)\ \(\w\+\)\:\ \(.*\)' let l:pattern = '^.*\:\([0-9\.]\+\)\ \(\w\+\)\:\ \(.*\)'
let l:pattern2 = '^.*\:\([0-9]\+\)\.\?\([0-9]\+\).* \(\(Warning\|Error\): .*\)' let l:pattern2 = '^.*\:\([0-9]\+\)\.\?\([0-9]\+\).* \(\(Warning\|Error\): .*\)'
@ -83,7 +85,6 @@ function! ale#handlers#sml#Handle(buffer, lines) abort
\}) \})
continue continue
endif endif
endfor endfor
return l:out return l:out

View file

@ -23,6 +23,7 @@ function! ale#handlers#vale#Handle(buffer, lines) abort
endif endif
let l:output = [] let l:output = []
for l:error in l:errors[keys(l:errors)[0]] for l:error in l:errors[keys(l:errors)[0]]
call add(l:output, { call add(l:output, {
\ 'lnum': l:error['Line'], \ 'lnum': l:error['Line'],

View file

@ -278,11 +278,13 @@ function! ale#job#IsRunning(job_id) abort
try try
" In NeoVim, if the job isn't running, jobpid() will throw. " In NeoVim, if the job isn't running, jobpid() will throw.
call jobpid(a:job_id) call jobpid(a:job_id)
return 1 return 1
catch catch
endtry endtry
elseif has_key(s:job_map, a:job_id) elseif has_key(s:job_map, a:job_id)
let l:job = s:job_map[a:job_id].job let l:job = s:job_map[a:job_id].job
return job_status(l:job) is# 'run' return job_status(l:job) is# 'run'
endif endif

View file

@ -25,6 +25,7 @@ function! ale#list#IsQuickfixOpen() abort
return 1 return 1
endif endif
endfor endfor
return 0 return 0
endfunction endfunction
@ -112,9 +113,11 @@ function! s:SetListsImpl(timer_id, buffer, loclist) abort
" open windows vertically instead of default horizontally " open windows vertically instead of default horizontally
let l:open_type = '' let l:open_type = ''
if ale#Var(a:buffer, 'list_vertical') == 1 if ale#Var(a:buffer, 'list_vertical') == 1
let l:open_type = 'vert ' let l:open_type = 'vert '
endif endif
if g:ale_set_quickfix if g:ale_set_quickfix
if !ale#list#IsQuickfixOpen() if !ale#list#IsQuickfixOpen()
silent! execute l:open_type . 'copen ' . str2nr(ale#Var(a:buffer, 'list_window_size')) silent! execute l:open_type . 'copen ' . str2nr(ale#Var(a:buffer, 'list_window_size'))

View file

@ -99,6 +99,7 @@ function! s:CreateTSServerMessageData(message) abort
endif endif
let l:data = json_encode(l:obj) . "\n" let l:data = json_encode(l:obj) . "\n"
return [l:is_notification ? 0 : l:obj.seq, l:data] return [l:is_notification ? 0 : l:obj.seq, l:data]
endfunction endfunction

View file

@ -104,6 +104,7 @@ function! ale#socket#IsOpen(channel_id) abort
endif endif
let l:channel = s:channel_map[a:channel_id].channel let l:channel = s:channel_map[a:channel_id].channel
return ch_status(l:channel) is# 'open' return ch_status(l:channel) is# 'open'
endfunction endfunction

View file

@ -76,6 +76,7 @@ function! ale#toggle#ToggleBuffer(buffer) abort
" linting locally when linting is disabled globally " linting locally when linting is disabled globally
if l:enabled && !g:ale_enabled if l:enabled && !g:ale_enabled
execute 'echom ''ALE cannot be enabled locally when disabled globally''' execute 'echom ''ALE cannot be enabled locally when disabled globally'''
return return
endif endif

View file

@ -54,6 +54,7 @@ endif
function! ale#util#JoinNeovimOutput(job, last_line, data, mode, callback) abort function! ale#util#JoinNeovimOutput(job, last_line, data, mode, callback) abort
if a:mode is# 'raw' if a:mode is# 'raw'
call a:callback(a:job, join(a:data, "\n")) call a:callback(a:job, join(a:data, "\n"))
return '' return ''
endif endif

117
test/script/block-padding-checker Executable file
View file

@ -0,0 +1,117 @@
#!/usr/bin/env python
"""
This script checks for missing or forbidden blank lines before or after
particular Vim commands. This script ensures that VimL scripts are padded
correctly, so they are easier to read.
"""
import sys
import re
INDENTATION_RE = re.compile(r'^ *')
COMMENT_LINE_RE = re.compile(r'^ *"')
COMMAND_RE = re.compile(r'^ *([a-zA-Z]+)')
START_BLOCKS = set(['if', 'for', 'while', 'try', 'function'])
END_BLOCKS = set(['endif', 'endfor', 'endwhile', 'endtry', 'endfunction'])
MIDDLE_BLOCKS = set(['else', 'elseif', 'catch', 'finally'])
TERMINATORS = set(['return', 'throw'])
WHITESPACE_BEFORE_SET = START_BLOCKS | TERMINATORS
WHITESPACE_FORBIDDEN_BEFORE_SET = END_BLOCKS | MIDDLE_BLOCKS
WHITESPACE_AFTER_SET = END_BLOCKS
WHITESPACE_FORBIDDEN_AFTER_SET = START_BLOCKS | MIDDLE_BLOCKS
def remove_comment_lines(line_iter):
for line_number, line in enumerate(line_iter, 1):
if not COMMENT_LINE_RE.match(line):
yield (line_number, line)
def check_lines(line_iter):
previous_indentation_level = None
previous_command = None
previous_line_blank = False
for line_number, line in remove_comment_lines(line_iter):
if len(line) == 0:
# Check for commands where we shouldn't have blank lines after
# them, like `else` or the start of blocks like `function`.
if (
previous_command is not None
and previous_command in WHITESPACE_FORBIDDEN_AFTER_SET
):
yield (
line_number,
'Blank line forbidden after `%s`' % (command,)
)
previous_line_blank = True
previous_command = None
else:
indentation_level = INDENTATION_RE.match(line).end()
command_match = COMMAND_RE.match(line)
if command_match:
command = command_match.group(1)
# Check for commands requiring blank lines before them, if they
# aren't at the start of a block.
if (
command in WHITESPACE_BEFORE_SET
and previous_indentation_level is not None
and indentation_level == previous_indentation_level
and previous_line_blank is False
):
yield (
line_number,
'Blank line required before `%s`' % (command,)
)
# Check for commands where we shouldn't have blank lines before
# them, like `else` or the end of blocks like `endfunction`.
if (
command in WHITESPACE_FORBIDDEN_BEFORE_SET
and previous_line_blank is True
):
yield (
line_number - 1,
'Blank line forbidden before `%s`' % (command,)
)
# Check for commands requiring blank lines after them, if they
# aren't at the end of a block.
if (
previous_command is not None
and previous_command in WHITESPACE_AFTER_SET
and previous_indentation_level is not None
and indentation_level == previous_indentation_level
and previous_line_blank is False
):
yield (
line_number - 1,
'Blank line required after `%s`' % (command,)
)
previous_command = command
previous_line_blank = False
previous_indentation_level = indentation_level
def main():
status = 0
for filename in sys.argv[1:]:
with open(filename) as vim_file:
line_iter = (line.rstrip() for line in vim_file)
for line_number, message in check_lines(line_iter):
print('%s:%d %s' % (filename, line_number, message))
status = 1
sys.exit(status)
if __name__ == "__main__":
main()

View file

@ -60,10 +60,10 @@ check_errors() {
for directory in "${directories[@]}"; do for directory in "${directories[@]}"; do
# shellcheck disable=SC2086 # shellcheck disable=SC2086
while IFS= read -r match; do while read -r; do
RETURN_CODE=1 RETURN_CODE=1
echo "$match $message" echo "$REPLY $message"
done < <(grep -n "$regex" $include_arg "$directory"/**/*.vim \ done < <(grep -H -n "$regex" $include_arg "$directory"/**/*.vim \
| grep -v 'no-custom-checks' \ | grep -v 'no-custom-checks' \
| grep -o '^[^:]\+:[0-9]\+' \ | grep -o '^[^:]\+:[0-9]\+' \
| sed 's:^\./::') | sed 's:^\./::')
@ -126,4 +126,13 @@ check_errors '\(!=.\?\|isnot\) type(\[\])' "Use 'isnot v:t_list' instead"
check_errors '\(!=.\?\|isnot\) type({})' "Use 'isnot v:t_dict' instead" check_errors '\(!=.\?\|isnot\) type({})' "Use 'isnot v:t_dict' instead"
check_errors '\(!=.\?\|isnot\) type(function([^)]\+))' "Use 'isnot v:t_func' instead" check_errors '\(!=.\?\|isnot\) type(function([^)]\+))' "Use 'isnot v:t_func' instead"
# Run a Python script to find lines that require padding around them. For
# users without Python installed, we'll skip these checks. Travis CI will run
# the script.
if command -v python > /dev/null; then
if ! test/script/block-padding-checker "$directory"/**/*.vim; then
RETURN_CODE=1
fi
fi
exit $RETURN_CODE exit $RETURN_CODE