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,
\ 'col': l:match[4] + 0,
\}
if l:match[5] isnot# ''
let l:item.end_lnum = l:match[6] + 0
let l:item.end_col = l:match[7] + 0
endif
call add(l:output, l:item)
endfor

View File

@ -6,6 +6,7 @@ call ale#Set('c_clangd_options', '')
function! ale_linters#c#clangd#GetProjectRoot(buffer) abort
let l:project_root = ale#path#FindNearestFile(a:buffer, 'compile_commands.json')
return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : ''
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)
let l:type = 'E'
if l:match[4] is? 'Parse warning'
let l:type = 'W'
endif
call add(l:output, {
\ 'lnum': l:match[1] + 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
let l:project_root = ale#path#FindNearestFile(a:buffer, 'compile_commands.json')
return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : ''
endfunction

View File

@ -22,6 +22,7 @@ function! ale_linters#cucumber#cucumber#Handle(buffer, lines) abort
endtry
let l:output = []
for l:element in get(l:json, 'elements', [])
for l:step in l:element['steps']
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
" let l:output_file = ale#util#Tempname() . '.ii'
" call ale#engine#ManageFile(a:buffer, l:output_file)
return '%e -cuda'
\ . ale#Pad(ale#c#IncludeOptions(ale#c#FindLocalHeaderPaths(a:buffer)))
\ . 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 = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:item = {
\ 'lnum': str2nr(l:match[2]),
\ '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'
\ })
endfor
return l:output
endfunction

View File

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

View File

@ -10,7 +10,6 @@ function! ale_linters#elixir#mix#Handle(buffer, lines) abort
"
" 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
let l:pattern = '\v\(([^\)]+Error)\) ([^:]+):([^:]+): (.+)$'
let l:output = []
@ -32,9 +31,11 @@ endfunction
function! ale_linters#elixir#mix#FindProjectRoot(buffer) abort
let l:mix_file = ale#path#FindNearestFile(a:buffer, 'mix.exs')
if !empty(l:mix_file)
return fnamemodify(l:mix_file, ':p:h')
endif
return '.'
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: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"
" go test returns relative paths so use tail of filename as part of pattern matcher
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
let l:options = ale#Var(a:buffer, 'go_govet_options')
return ale#path#BufferCdString(a:buffer) . ' go vet .'
\ . (!empty(l:options) ? ' ' . l:options : '')
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
" consider HTML5 so we should avoid it.
let l:executable = ale#Var(a:buffer, 'html_tidy_executable')
if has('mac') && l:executable is# 'tidy' && exists('*exepath')
\ && exepath(l:executable) is# '/usr/bin/tidy'
return ''
@ -40,7 +41,6 @@ endfunction
function! ale_linters#html#tidy#Handle(buffer, lines) abort
" Matches patterns lines like the following:
" line 7 column 5 - Warning: missing </title> before </head>
let l:pattern = '^line \(\d\+\) column \(\d\+\) - \(Warning\|Error\): \(.\+\)$'
let l:output = []

View File

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

View File

@ -16,6 +16,7 @@ function! ale_linters#java#javac#GetImportPaths(buffer) abort
endif
let l:classpath_command = ale#gradle#BuildClasspathCommand(a:buffer)
if !empty(l:classpath_command)
return l:classpath_command
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:16: error: ';' expected
let l:directory = expand('#' . a:buffer . ':p:h')
let l:pattern = '\v^(.*):(\d+): (.+):(.+)$'
let l:col_pattern = '\v^(\s*\^)$'

View File

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

View File

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

View File

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

View File

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

View File

@ -13,6 +13,7 @@ function! ale_linters#make#checkmake#Handle(buffer, lines) abort
\ 'text': l:match[3],
\})
endfor
return l:output
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',
\ 'text': l:match[7],
\}
if l:match[3] isnot# ''
let l:item.end_lnum = l:match[4] + 0
let l:item.end_col = l:match[5] + 0
endif
call add(l:output, l:item)
endfor

View File

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

View File

@ -6,6 +6,7 @@ call ale#Set('objcpp_clangd_options', '')
function! ale_linters#objcpp#clangd#GetProjectRoot(buffer) abort
let l:project_root = ale#path#FindNearestFile(a:buffer, 'compile_commands.json')
return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : ''
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:type = 'E'
if a:lines[-1] =~# 'syntax OK'
let l:type = 'W'
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
" Puppet module directories
let l:root_path = ale#path#FindNearestFile(a:buffer, 'metadata.json')
if !empty(l:root_path)
return fnamemodify(l:root_path, ':h')
endif
@ -17,6 +18,7 @@ function! ale_linters#puppet#languageserver#GetProjectRoot(buffer) abort
\ 'templates',
\]
let l:root_path = ale#path#FindNearestDirectory(a:buffer, l:test_path)
if !empty(l:root_path)
return fnamemodify(l:root_path, ':h:h')
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 '='; 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)
let l:pattern = '^Error: .*: \(.\+\) \((file:\|at\) .\+\.pp\(, line: \|:\)\(\d\+\)\(, column: \|:\)\=\(\d*\)'
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:dir = expand('#' . a:buffer . ':p:h')
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ '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
let l:host = ale#Var(a:buffer, 'ruby_solargraph_host')
let l:port = ale#Var(a:buffer, 'ruby_solargraph_port')
return l:host . ':' . l:port
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])
let l:include_features = ale#Var(a:buffer, 'rust_cargo_include_features')
if !empty(l:include_features)
let l:include_features = ' --features ' . ale#Escape(l:include_features)
endif
@ -59,6 +60,7 @@ function! ale_linters#rust#cargo#GetCommand(buffer, version_output) abort
endif
let l:default_feature_behavior = ale#Var(a:buffer, 'rust_cargo_default_feature_behavior')
if l:default_feature_behavior is# 'all'
let l:include_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
let l:project_root = ale#Var(a:buffer, 'scala_sbtserver_project_root')
if l:project_root is? ''
let l:project_root = ale#path#FindNearestFile(a:buffer, 'build.sbt')
return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : ''
endif
return l:project_root
endfunction
function! ale_linters#scala#sbtserver#GetAddress(buffer) abort
let l:address = ale#Var(a:buffer, 'scala_sbtserver_address')
return l:address
endfunction

View File

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

View File

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

View File

@ -4,7 +4,6 @@
function! ale_linters#solidity#solhint#Handle(buffer, lines) abort
" Matches patterns like the following:
" /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: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 13: E Wrong number of arguments (3) to "set"
" Line 93: N Close brace not aligned with line 90 (4 0)
let l:pattern = '^Line\s\+\([0-9]\+\): \([NEW]\) \(.*\)$'
let l:output = []

View File

@ -40,6 +40,7 @@ function! ale_linters#terraform#tflint#GetCommand(buffer) abort
endif
let l:opts = ale#Var(a:buffer, 'terraform_tflint_options')
if !empty(l:opts)
let l:cmd .= ' ' . l:opts
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 38: missing `\ ' after "etc."
let l:pattern = '^".\+", line \(\d\+\): \(.\+\)$'
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:match = matchlist(l:line, l:pattern)
if empty(l:match)
let l:index += 1
continue
endif
let l:severity = l:match[1]
if l:severity is# 'WARNING'
let l:type = 'W'
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
" should contain a more descriptive error message.
let l:text = l:match[4]
if l:text =~# '\(last token was .*\)'
let l:index += 1
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
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
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+) (.+)$'
for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:filename = ale#path#GetAbsPath(l:dir, l:match[1])
if bufnr(l:filename) is a:buffer
call add(l:output, {
\ 'lnum': l:match[2],
\ 'text': l:match[3],
\ 'type': 'W',
\})
" Ignore trailing whitespace errors if we've turned them off.
if !ale#Var(a:buffer, 'warn_about_trailing_whitespace')
\&& l:match[3] is# 'Trailing whitespace'
continue
endif
call add(l:output, {
\ 'lnum': l:match[2],
\ 'text': l:match[3],
\ 'type': 'W',
\})
endfor
return l:output
@ -53,5 +61,5 @@ call ale#linter#Define('vim', {
\ 'executable_callback': 'ale_linters#vim#ale_custom_linting_rules#GetExecutable',
\ 'command_callback': 'ale_linters#vim#ale_custom_linting_rules#GetCommand',
\ '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 = []
for l:line in a:lines
" Parse error/warning lines
let l:match_message = matchlist(l:line, l:pattern_message)
if !empty(l:match_message)
let l:line = l:match_message[2] + 0
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
let l:match_column_token = matchlist(l:line, l:pattern_column_token)
if !empty(l:output) && !empty(l:match_column_token)
let l:previous = l:output[len(l:output) - 1]
let l:previous['col'] = len(l:match_column_token[0])
continue
endif
endfor
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
let l:project_root = ale#path#FindNearestFile(a:buffer, 'yang.settings')
return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : ''
endfunction

View File

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

View File

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

View File

@ -75,6 +75,7 @@ endfunction
" Check if we should look for completions for a language.
function! ale#completion#GetPrefix(filetype, line, column) abort
let l:regex = s:GetFiletypeValue(s:should_complete_map, a:filetype)
" The column we're using completions for is where we are inserting text,
" like so:
" 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', []))
call s:InvokeChain(l:buffer, l:executable, l:linter, l:next_chain_index, l:output)
return
endif
@ -595,9 +596,8 @@ function! ale#engine#ProcessChain(buffer, linter, chain_index, input) abort
\)
endif
" If we have a command to run, execute that.
if !empty(l:command)
" We hit a command to run, so we'll execute that
" The chain item can override the output_stream option.
if has_key(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
call remove(g:ale_fix_buffer_data, a:buffer)
execute 'echoerr ''The file was changed before fixing finished'''
return
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:options = ale#Var(a:buffer, 'json_fixjson_options')
if l:options isnot# ''
let l:command .= ' ' . l:options
endif

View File

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

View File

@ -14,6 +14,7 @@ endfunction
function! ale#fixers#php_cs_fixer#Fix(buffer) abort
let l:executable = ale#fixers#php_cs_fixer#GetExecutable(a:buffer)
return {
\ 'command': ale#Escape(l:executable)
\ . ' ' . 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)
\ ? '--standard=' . l:standard
\ : ''
return {
\ 'command': ale#Escape(l:executable) . ' --stdin-path=%s ' . l:standard_option . ' -'
\}

View File

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

View File

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

View File

@ -11,12 +11,14 @@ function! ale#fixers#xmllint#Fix(buffer) abort
let l:command = l:executable . ' --format ' . l:filename
let l:indent = ale#Var(a:buffer, 'xml_xmllint_indentsize')
if l:indent isnot# ''
let l:env = ale#Env('XMLLINT_INDENT', repeat(' ', l:indent))
let l:command = l:env . l:command
endif
let l:options = ale#Var(a:buffer, 'xml_xmllint_options')
if l:options isnot# ''
let l:command .= ' ' . l:options
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)
let l:ecode = 'E'
if l:match[2] is? 'warning:'
let l:ecode = 'W'
endif
call add(l:output, {
\ 'lnum': l:match[1] + 0,
\ 'col': 0,

View File

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

View File

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

View File

@ -14,7 +14,6 @@ endfunction
function! ale#handlers#pony#HandlePonycFormat(buffer, lines) abort
" Look for lines like the following.
" /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:output = []

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -25,6 +25,7 @@ function! ale#list#IsQuickfixOpen() abort
return 1
endif
endfor
return 0
endfunction
@ -112,9 +113,11 @@ function! s:SetListsImpl(timer_id, buffer, loclist) abort
" open windows vertically instead of default horizontally
let l:open_type = ''
if ale#Var(a:buffer, 'list_vertical') == 1
let l:open_type = 'vert '
endif
if g:ale_set_quickfix
if !ale#list#IsQuickfixOpen()
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
let l:data = json_encode(l:obj) . "\n"
return [l:is_notification ? 0 : l:obj.seq, l:data]
endfunction

View File

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

View File

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

View File

@ -54,6 +54,7 @@ endif
function! ale#util#JoinNeovimOutput(job, last_line, data, mode, callback) abort
if a:mode is# 'raw'
call a:callback(a:job, join(a:data, "\n"))
return ''
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
# shellcheck disable=SC2086
while IFS= read -r match; do
while read -r; do
RETURN_CODE=1
echo "$match $message"
done < <(grep -n "$regex" $include_arg "$directory"/**/*.vim \
echo "$REPLY $message"
done < <(grep -H -n "$regex" $include_arg "$directory"/**/*.vim \
| grep -v 'no-custom-checks' \
| grep -o '^[^:]\+:[0-9]\+' \
| 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(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