diff options
47 files changed, 751 insertions, 97 deletions
@@ -1,4 +1,4 @@ -Copyright (c) 2016-2017, w0rp <devw0rp@gmail.com> +Copyright (c) 2016-2018, w0rp <devw0rp@gmail.com> All rights reserved. Redistribution and use in source and binary forms, with or without @@ -104,7 +104,7 @@ formatting. | FusionScript | [fusion-lint](https://github.com/RyanSquared/fusionscript) | | Git Commit Messages | [gitlint](https://github.com/jorisroovers/gitlint) | | GLSL | [glslang](https://github.com/KhronosGroup/glslang), [glslls](https://github.com/svenstaro/glsl-language-server) | -| Go | [gofmt](https://golang.org/cmd/gofmt/), [goimports](https://godoc.org/golang.org/x/tools/cmd/goimports), [go vet](https://golang.org/cmd/vet/) !!, [golint](https://godoc.org/github.com/golang/lint), [gotype](https://godoc.org/golang.org/x/tools/cmd/gotype), [gometalinter](https://github.com/alecthomas/gometalinter) !!, [go build](https://golang.org/cmd/go/) !!, [gosimple](https://github.com/dominikh/go-tools/tree/master/cmd/gosimple) !!, [staticcheck](https://github.com/dominikh/go-tools/tree/master/cmd/staticcheck) !! | +| Go | [gofmt](https://golang.org/cmd/gofmt/), [goimports](https://godoc.org/golang.org/x/tools/cmd/goimports), [go vet](https://golang.org/cmd/vet/) !!, [golint](https://godoc.org/github.com/golang/lint), [gotype](https://godoc.org/golang.org/x/tools/cmd/gotype) !!, [gometalinter](https://github.com/alecthomas/gometalinter) !!, [go build](https://golang.org/cmd/go/) !!, [gosimple](https://github.com/dominikh/go-tools/tree/master/cmd/gosimple) !!, [staticcheck](https://github.com/dominikh/go-tools/tree/master/cmd/staticcheck) !! | | GraphQL | [eslint](http://eslint.org/), [gqlint](https://github.com/happylinks/gqlint), [prettier](https://github.com/prettier/prettier) | | Haml | [haml-lint](https://github.com/brigade/haml-lint) | | Handlebars | [ember-template-lint](https://github.com/rwjblue/ember-template-lint) | @@ -121,7 +121,7 @@ formatting. | Lua | [luac](https://www.lua.org/manual/5.1/luac.html), [luacheck](https://github.com/mpeterv/luacheck) | | Mail | [alex](https://github.com/wooorm/alex) !!, [proselint](http://proselint.com/), [vale](https://github.com/ValeLint/vale) | | Make | [checkmake](https://github.com/mrtazz/checkmake) | -| Markdown | [alex](https://github.com/wooorm/alex) !!, [markdownlint](https://github.com/DavidAnson/markdownlint) !!, [mdl](https://github.com/mivok/markdownlint), [prettier](https://github.com/prettier/prettier), [proselint](http://proselint.com/), [redpen](http://redpen.cc/), [remark-lint](https://github.com/wooorm/remark-lint) !!, [vale](https://github.com/ValeLint/vale), [write-good](https://github.com/btford/write-good) | +| Markdown | [alex](https://github.com/wooorm/alex) !!, [markdownlint](https://github.com/DavidAnson/markdownlint) !!, [mdl](https://github.com/mivok/markdownlint), [prettier](https://github.com/prettier/prettier), [proselint](http://proselint.com/), [redpen](http://redpen.cc/), [remark-lint](https://github.com/wooorm/remark-lint) !!, [vale](https://github.com/ValeLint/vale), [write-good](https://github.com/btford/write-good) , [textlint](https://textlint.github.io/)| | MATLAB | [mlint](https://www.mathworks.com/help/matlab/ref/mlint.html) | | Nim | [nim check](https://nim-lang.org/docs/nimc.html) !! | | nix | [nix-instantiate](http://nixos.org/nix/manual/#sec-nix-instantiate) | @@ -143,7 +143,7 @@ formatting. | reStructuredText | [alex](https://github.com/wooorm/alex) !!, [proselint](http://proselint.com/), [redpen](http://redpen.cc/), [rstcheck](https://github.com/myint/rstcheck), [vale](https://github.com/ValeLint/vale), [write-good](https://github.com/btford/write-good) | | Re:VIEW | [redpen](http://redpen.cc/) | | RPM spec | [rpmlint](https://github.com/rpm-software-management/rpmlint) (disabled by default; see `:help ale-integration-spec`) | -| Ruby | [brakeman](http://brakemanscanner.org/) !!, [rails_best_practices](https://github.com/flyerhzm/rails_best_practices) !!, [reek](https://github.com/troessner/reek), [rubocop](https://github.com/bbatsov/rubocop), [ruby](https://www.ruby-lang.org) | +| Ruby | [brakeman](http://brakemanscanner.org/) !!, [rails_best_practices](https://github.com/flyerhzm/rails_best_practices) !!, [reek](https://github.com/troessner/reek), [rubocop](https://github.com/bbatsov/rubocop), [ruby](https://www.ruby-lang.org), [rufo](https://github.com/ruby-formatter/rufo) | | Rust | cargo !! (see `:help ale-integration-rust` for configuration instructions), [rls](https://github.com/rust-lang-nursery/rls), [rustc](https://www.rust-lang.org/), [rustfmt](https://github.com/rust-lang-nursery/rustfmt) | | SASS | [sass-lint](https://www.npmjs.com/package/sass-lint), [stylelint](https://github.com/stylelint/stylelint) | | SCSS | [prettier](https://github.com/prettier/prettier), [sass-lint](https://www.npmjs.com/package/sass-lint), [scss-lint](https://github.com/brigade/scss-lint), [stylelint](https://github.com/stylelint/stylelint) | @@ -502,15 +502,17 @@ Will give you: ### 5.viii. How can I execute some code when ALE starts or stops linting? ALE runs its own [autocmd](http://vimdoc.sourceforge.net/htmldoc/autocmd.html) -events whenever has a linter is started and has been successfully executed and -processed. These events can be used to call arbitrary functions before and after -ALE stops linting. +events when a lint or fix cycle are started and stopped. These events can be +used to call arbitrary functions before and after ALE stops linting. ```vim augroup YourGroup autocmd! autocmd User ALELintPre call YourFunction() autocmd User ALELintPost call YourFunction() + + autocmd User ALEFixPre call YourFunction() + autocmd User ALEFixPost call YourFunction() augroup END ``` diff --git a/ale_linters/awk/gawk.vim b/ale_linters/awk/gawk.vim index ac6e9154..3e9987b3 100644 --- a/ale_linters/awk/gawk.vim +++ b/ale_linters/awk/gawk.vim @@ -12,7 +12,11 @@ function! ale_linters#awk#gawk#GetExecutable(buffer) abort endfunction function! ale_linters#awk#gawk#GetCommand(buffer) abort + " note the --source 'BEGIN ...' is to prevent + " gawk from attempting to execute the body of the script + " it is linting. return ale_linters#awk#gawk#GetExecutable(a:buffer) + \ . " --source 'BEGIN { exit } END { exit 1 }'" \ . ' ' . ale#Var(a:buffer, 'awk_gawk_options') \ . ' ' . '-f %t --lint /dev/null' endfunction @@ -21,6 +25,6 @@ call ale#linter#Define('awk', { \ 'name': 'gawk', \ 'executable_callback': 'ale_linters#awk#gawk#GetExecutable', \ 'command_callback': 'ale_linters#awk#gawk#GetCommand', -\ 'callback': 'ale#handlers#cpplint#HandleCppLintFormat', +\ 'callback': 'ale#handlers#gawk#HandleGawkFormat', \ 'output_stream': 'both' \}) diff --git a/ale_linters/c/flawfinder.vim b/ale_linters/c/flawfinder.vim index 27f269f5..df6fbebe 100644 --- a/ale_linters/c/flawfinder.vim +++ b/ale_linters/c/flawfinder.vim @@ -4,6 +4,7 @@ call ale#Set('c_flawfinder_executable', 'flawfinder') call ale#Set('c_flawfinder_options', '') call ale#Set('c_flawfinder_minlevel', 1) +call ale#Set('c_flawfinder_error_severity', 6) function! ale_linters#c#flawfinder#GetExecutable(buffer) abort return ale#Var(a:buffer, 'c_flawfinder_executable') @@ -26,5 +27,5 @@ call ale#linter#Define('c', { \ 'output_stream': 'stdout', \ 'executable_callback': 'ale_linters#c#flawfinder#GetExecutable', \ 'command_callback': 'ale_linters#c#flawfinder#GetCommand', -\ 'callback': 'ale#handlers#gcc#HandleGCCFormat', +\ 'callback': 'ale#handlers#flawfinder#HandleFlawfinderFormat', \}) diff --git a/ale_linters/cpp/flawfinder.vim b/ale_linters/cpp/flawfinder.vim index a19f5962..c63ecb38 100644 --- a/ale_linters/cpp/flawfinder.vim +++ b/ale_linters/cpp/flawfinder.vim @@ -26,5 +26,5 @@ call ale#linter#Define('cpp', { \ 'output_stream': 'stdout', \ 'executable_callback': 'ale_linters#cpp#flawfinder#GetExecutable', \ 'command_callback': 'ale_linters#cpp#flawfinder#GetCommand', -\ 'callback': 'ale#handlers#gcc#HandleGCCFormat', +\ 'callback': 'ale#handlers#flawfinder#HandleFlawfinderFormat', \}) diff --git a/ale_linters/go/gosimple.vim b/ale_linters/go/gosimple.vim index 8a4c01e1..dbdc3fcf 100644 --- a/ale_linters/go/gosimple.vim +++ b/ale_linters/go/gosimple.vim @@ -1,11 +1,15 @@ " Author: Ben Reedy <https://github.com/breed808> " Description: gosimple for Go files +function! ale_linters#go#gosimple#GetCommand(buffer) abort + return ale#path#BufferCdString(a:buffer) . ' gosimple .' +endfunction + call ale#linter#Define('go', { \ 'name': 'gosimple', \ 'executable': 'gosimple', -\ 'command': 'gosimple %s', -\ 'callback': 'ale#handlers#unix#HandleAsWarning', +\ 'command_callback': 'ale_linters#go#gosimple#GetCommand', +\ 'callback': 'ale#handlers#go#Handler', \ 'output_stream': 'both', \ 'lint_file': 1, \}) diff --git a/ale_linters/go/gotype.vim b/ale_linters/go/gotype.vim index 731f4c92..f4bb274e 100644 --- a/ale_linters/go/gotype.vim +++ b/ale_linters/go/gotype.vim @@ -1,23 +1,20 @@ " Author: Jelte Fennema <github-public@jeltef.nl> " Description: gotype for Go files -call ale#linter#Define('go', { -\ 'name': 'gotype', -\ 'output_stream': 'stderr', -\ 'executable': 'gotype', -\ 'command_callback': 'ale_linters#go#gotype#GetCommand', -\ 'callback': 'ale#handlers#unix#HandleAsError', -\}) - -"\ 'command': function! ale_linters#go#gotype#GetCommand(buffer) abort - let l:cur_file = expand('#' . a:buffer . ':p') - if l:cur_file =~# '_test\.go$' + if expand('#' . a:buffer . ':p') =~# '_test\.go$' return endif - let l:module_files = globpath(expand('#' . a:buffer . ':p:h'), '*.go', 0, 1) - let l:other_module_files = filter(l:module_files, 'v:val isnot# ' . ale#util#EscapeVim(l:cur_file) . ' && v:val !~# "_test\.go$"') - return 'gotype %t ' . join(map(l:other_module_files, 'ale#Escape(v:val)')) + return ale#path#BufferCdString(a:buffer) . ' gotype .' endfunction + +call ale#linter#Define('go', { +\ 'name': 'gotype', +\ 'output_stream': 'stderr', +\ 'executable': 'gotype', +\ 'command_callback': 'ale_linters#go#gotype#GetCommand', +\ 'callback': 'ale#handlers#go#Handler', +\ 'lint_file': 1, +\}) diff --git a/ale_linters/go/govet.vim b/ale_linters/go/govet.vim index aae5969d..edf9eb66 100644 --- a/ale_linters/go/govet.vim +++ b/ale_linters/go/govet.vim @@ -8,28 +8,11 @@ function! ale_linters#go#govet#GetCommand(buffer) abort return ale#path#BufferCdString(a:buffer) . ' go vet .' endfunction -function! ale_linters#go#govet#Handler(buffer, lines) abort - let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):?(\d+)?:? ?(.+)$' - let l:output = [] - let l:dir = expand('#' . a:buffer . ':p:h') - - for l:match in ale#util#GetMatches(a:lines, l:pattern) - call add(l:output, { - \ 'filename': ale#path#GetAbsPath(l:dir, l:match[1]), - \ 'lnum': l:match[2] + 0, - \ 'col': l:match[3] + 0, - \ 'text': l:match[4], - \ 'type': 'E', - \}) - endfor - return l:output -endfunction - call ale#linter#Define('go', { \ 'name': 'go vet', \ 'output_stream': 'stderr', \ 'executable': 'go', \ 'command_callback': 'ale_linters#go#govet#GetCommand', -\ 'callback': 'ale_linters#go#govet#Handler', +\ 'callback': 'ale#handlers#go#Handler', \ 'lint_file': 1, \}) diff --git a/ale_linters/go/staticcheck.vim b/ale_linters/go/staticcheck.vim index ce9e6e38..a3464015 100644 --- a/ale_linters/go/staticcheck.vim +++ b/ale_linters/go/staticcheck.vim @@ -27,7 +27,7 @@ call ale#linter#Define('go', { \ 'name': 'staticcheck', \ 'executable': 'staticcheck', \ 'command_callback': 'ale_linters#go#staticcheck#GetCommand', -\ 'callback': 'ale#handlers#unix#HandleAsWarning', +\ 'callback': 'ale#handlers#go#Handler', \ 'output_stream': 'both', \ 'lint_file': 1, \}) diff --git a/ale_linters/markdown/textlint.vim b/ale_linters/markdown/textlint.vim new file mode 100644 index 00000000..4899fb53 --- /dev/null +++ b/ale_linters/markdown/textlint.vim @@ -0,0 +1,23 @@ +" Author: tokida https://rouger.info +" Description: textlint, a proofreading tool (https://textlint.github.io/) + +function! ale_linters#markdown#textlint#GetCommand(buffer) abort + let l:cmd_path = ale#path#FindNearestFile(a:buffer, '.textlintrc') + + if !empty(l:cmd_path) + return 'textlint' + \ . ' -c ' + \ . l:cmd_path + \ . ' -f json %t' + endif + + return '' +endfunction + + +call ale#linter#Define('markdown', { +\ 'name': 'textlint', +\ 'executable': 'textlint', +\ 'command_callback': 'ale_linters#markdown#textlint#GetCommand', +\ 'callback': 'ale#handlers#textlint#HandleTextlintOutput', +\}) diff --git a/ale_linters/typescript/tslint.vim b/ale_linters/typescript/tslint.vim index f4b48169..6f94fbae 100644 --- a/ale_linters/typescript/tslint.vim +++ b/ale_linters/typescript/tslint.vim @@ -70,7 +70,7 @@ function! ale_linters#typescript#tslint#GetCommand(buffer) abort \ : '' return ale#path#BufferCdString(a:buffer) - \ . ale_linters#typescript#tslint#GetExecutable(a:buffer) + \ . ale#Escape(ale_linters#typescript#tslint#GetExecutable(a:buffer)) \ . ' --format json' \ . l:tslint_config_option \ . l:tslint_rules_option diff --git a/autoload/ale/definition.vim b/autoload/ale/definition.vim index b20c01a0..521cd0b1 100644 --- a/autoload/ale/definition.vim +++ b/autoload/ale/definition.vim @@ -19,6 +19,10 @@ function! ale#definition#Execute(expr) abort execute a:expr endfunction +function! ale#definition#ClearLSPData() abort + let s:go_to_definition_map = {} +endfunction + function! ale#definition#Open(options, filename, line, column) abort if a:options.open_in_tab call ale#definition#Execute('tabedit ' . fnameescape(a:filename)) diff --git a/autoload/ale/engine.vim b/autoload/ale/engine.vim index 6ccc3a34..dd871c36 100644 --- a/autoload/ale/engine.vim +++ b/autoload/ale/engine.vim @@ -76,6 +76,11 @@ function! ale#engine#InitBufferInfo(buffer) abort return 0 endfunction +" Clear LSP linter data for the linting engine. +function! ale#engine#ClearLSPData() abort + let s:lsp_linter_map = {} +endfunction + " This function is documented and part of the public API. " " Return 1 if ALE is busy checking a given buffer @@ -144,7 +149,7 @@ function! s:GatherOutput(job_id, line) abort endif endfunction -function! s:HandleLoclist(linter_name, buffer, loclist) abort +function! ale#engine#HandleLoclist(linter_name, buffer, loclist) abort let l:info = get(g:ale_buffer_info, a:buffer, {}) if empty(l:info) @@ -223,7 +228,7 @@ function! s:HandleExit(job_id, exit_code) abort let l:loclist = ale#util#GetFunction(l:linter.callback)(l:buffer, l:output) - call s:HandleLoclist(l:linter.name, l:buffer, l:loclist) + call ale#engine#HandleLoclist(l:linter.name, l:buffer, l:loclist) endfunction function! s:HandleLSPDiagnostics(conn_id, response) abort @@ -237,7 +242,7 @@ function! s:HandleLSPDiagnostics(conn_id, response) abort let l:loclist = ale#lsp#response#ReadDiagnostics(a:response) - call s:HandleLoclist(l:linter_name, l:buffer, l:loclist) + call ale#engine#HandleLoclist(l:linter_name, l:buffer, l:loclist) endfunction function! s:HandleTSServerDiagnostics(response, error_type) abort @@ -262,7 +267,7 @@ function! s:HandleTSServerDiagnostics(response, error_type) abort let l:loclist = get(l:info, 'semantic_loclist', []) \ + get(l:info, 'syntax_loclist', []) - call s:HandleLoclist('tsserver', l:buffer, l:loclist) + call ale#engine#HandleLoclist('tsserver', l:buffer, l:loclist) endfunction function! s:HandleLSPErrorMessage(error_message) abort @@ -361,9 +366,6 @@ function! s:RemapItemTypes(type_map, loclist) abort endfor endfunction -" Save the temporary directory so we can figure out if files are in it. -let s:temp_dir = fnamemodify(tempname(), ':h') - function! ale#engine#FixLocList(buffer, linter_name, loclist) abort let l:bufnr_map = {} let l:new_loclist = [] diff --git a/autoload/ale/fix.vim b/autoload/ale/fix.vim index 9111db3d..398f57d0 100644 --- a/autoload/ale/fix.vim +++ b/autoload/ale/fix.vim @@ -54,6 +54,8 @@ function! ale#fix#ApplyQueuedFixes() abort let l:should_lint = l:data.changes_made endif + silent doautocmd <nomodeline> User ALEFixPost + " If ALE linting is enabled, check for problems with the file again after " fixing problems. if g:ale_enabled @@ -463,6 +465,8 @@ function! ale#fix#Fix(...) abort call ale#fix#RemoveManagedFiles(l:buffer) call ale#fix#InitBufferData(l:buffer, l:fixing_flag) + silent doautocmd <nomodeline> User ALEFixPre + call s:RunFixer({ \ 'buffer': l:buffer, \ 'input': g:ale_fix_buffer_data[l:buffer].lines_before, diff --git a/autoload/ale/fix/registry.vim b/autoload/ale/fix/registry.vim index 3e407c52..4c0703a5 100644 --- a/autoload/ale/fix/registry.vim +++ b/autoload/ale/fix/registry.vim @@ -23,6 +23,12 @@ let s:default_registry = { \ 'description': 'Apply prettier-standard to a file.', \ 'aliases': ['prettier-standard'], \ }, +\ 'elm-format': { +\ 'function': 'ale#fixers#elm_format#Fix', +\ 'suggested_filetypes': ['elm'], +\ 'description': 'Apply elm-format to a file.', +\ 'aliases': ['format'], +\ }, \ 'eslint': { \ 'function': 'ale#fixers#eslint#Fix', \ 'suggested_filetypes': ['javascript', 'typescript'], @@ -33,11 +39,6 @@ let s:default_registry = { \ 'suggested_filetypes': ['elixir'], \ 'description': 'Apply mix format to a file.', \ }, -\ 'format': { -\ 'function': 'ale#fixers#format#Fix', -\ 'suggested_filetypes': ['elm'], -\ 'description': 'Apply elm-format to a file.', -\ }, \ 'isort': { \ 'function': 'ale#fixers#isort#Fix', \ 'suggested_filetypes': ['python'], @@ -84,6 +85,11 @@ let s:default_registry = { \ 'suggested_filetypes': ['ruby'], \ 'description': 'Fix ruby files with rubocop --auto-correct.', \ }, +\ 'rufo': { +\ 'function': 'ale#fixers#rufo#Fix', +\ 'suggested_filetypes': ['ruby'], +\ 'description': 'Fix ruby files with rufo', +\ }, \ 'standard': { \ 'function': 'ale#fixers#standard#Fix', \ 'suggested_filetypes': ['javascript'], diff --git a/autoload/ale/fixers/format.vim b/autoload/ale/fixers/elm_format.vim index be130f00..b2119d2c 100644 --- a/autoload/ale/fixers/format.vim +++ b/autoload/ale/fixers/elm_format.vim @@ -5,17 +5,17 @@ call ale#Set('elm_format_executable', 'elm-format') call ale#Set('elm_format_use_global', 0) call ale#Set('elm_format_options', '--yes') -function! ale#fixers#format#GetExecutable(buffer) abort +function! ale#fixers#elm_format#GetExecutable(buffer) abort return ale#node#FindExecutable(a:buffer, 'elm_format', [ \ 'node_modules/.bin/elm-format', \]) endfunction -function! ale#fixers#format#Fix(buffer) abort +function! ale#fixers#elm_format#Fix(buffer) abort let l:options = ale#Var(a:buffer, 'elm_format_options') return { - \ 'command': ale#Escape(ale#fixers#format#GetExecutable(a:buffer)) + \ 'command': ale#Escape(ale#fixers#elm_format#GetExecutable(a:buffer)) \ . ' %t' \ . (empty(l:options) ? '' : ' ' . l:options), \ 'read_temporary_file': 1, diff --git a/autoload/ale/fixers/mix_format.vim b/autoload/ale/fixers/mix_format.vim index 04866408..7a091701 100644 --- a/autoload/ale/fixers/mix_format.vim +++ b/autoload/ale/fixers/mix_format.vim @@ -1,16 +1,25 @@ -" Author: carakan <carakan@gmail.com> +" Author: carakan <carakan@gmail.com>, Fernando Mendes <fernando@mendes.codes> " Description: Fixing files with elixir formatter 'mix format'. call ale#Set('elixir_mix_executable', 'mix') +call ale#Set('elixir_mix_format_options', '') function! ale#fixers#mix_format#GetExecutable(buffer) abort return ale#Var(a:buffer, 'elixir_mix_executable') endfunction +function! ale#fixers#mix_format#GetCommand(buffer) abort + let l:executable = ale#Escape(ale#fixers#mix_format#GetExecutable(a:buffer)) + let l:options = ale#Var(a:buffer, 'elixir_mix_format_options') + + return l:executable . ' format' + \ . (!empty(l:options) ? ' ' . l:options : '') + \ . ' %t' +endfunction + function! ale#fixers#mix_format#Fix(buffer) abort return { - \ 'command': ale#Escape(ale#fixers#mix_format#GetExecutable(a:buffer)) - \ . ' format %t', + \ 'command': ale#fixers#mix_format#GetCommand(a:buffer), \ 'read_temporary_file': 1, \} endfunction diff --git a/autoload/ale/fixers/rufo.vim b/autoload/ale/fixers/rufo.vim new file mode 100644 index 00000000..01d537a9 --- /dev/null +++ b/autoload/ale/fixers/rufo.vim @@ -0,0 +1,20 @@ +" Author: Fohte (Hayato Kawai) https://github.com/fohte +" Description: Integration of Rufo with ALE. + +call ale#Set('ruby_rufo_executable', 'rufo') + +function! ale#fixers#rufo#GetCommand(buffer) abort + let l:executable = ale#Var(a:buffer, 'ruby_rufo_executable') + let l:exec_args = l:executable =~? 'bundle$' + \ ? ' exec rufo' + \ : '' + + return ale#Escape(l:executable) . l:exec_args . ' %t' +endfunction + +function! ale#fixers#rufo#Fix(buffer) abort + return { + \ 'command': ale#fixers#rufo#GetCommand(a:buffer), + \ 'read_temporary_file': 1, + \} +endfunction diff --git a/autoload/ale/handlers/flawfinder.vim b/autoload/ale/handlers/flawfinder.vim new file mode 100644 index 00000000..a650d6dd --- /dev/null +++ b/autoload/ale/handlers/flawfinder.vim @@ -0,0 +1,47 @@ +" Author: Christian Gibbons <cgibbons@gmu.edu> +" Description: This file defines a handler function that should work for the +" flawfinder format with the -CDQS flags. + +" Swiped this function from the GCC handler. Not sure if needed, but doesn't +" hurt to have it. +function! s:RemoveUnicodeQuotes(text) abort + let l:text = a:text + let l:text = substitute(l:text, '[`´‘’]', '''', 'g') + let l:text = substitute(l:text, '\v\\u2018([^\\]+)\\u2019', '''\1''', 'g') + let l:text = substitute(l:text, '[“”]', '"', 'g') + + return l:text +endfunction + +function! ale#handlers#flawfinder#HandleFlawfinderFormat(buffer, lines) abort + " Look for lines like the following. + " + " <stdin>:12:4: [2] (buffer) char:Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120). Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length. + " <stdin>:31:4: [1] (buffer) strncpy:Easily used incorrectly; doesn't always \0-terminate or check for invalid pointers [MS-banned] (CWE-120). + let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):(\d+)?:? ( \[[0-5]\] [^:]+):(.+)$' + let l:output = [] + + for l:match in ale#util#GetMatches(a:lines, l:pattern) + " Use severity level to determine if it should be considered a warning + " or error. + let l:severity = str2nr(matchstr(split(l:match[4])[0], '[0-5]')) + + let l:item = { + \ 'lnum': str2nr(l:match[2]), + \ 'col': str2nr(l:match[3]), + \ 'type': (l:severity < ale#Var(a:buffer, 'c_flawfinder_error_severity')) + \ ? 'W' : 'E', + \ 'text': s:RemoveUnicodeQuotes(join(split(l:match[4])[1:]) . ': ' . l:match[5]), + \} + + " If the filename is something like <stdin>, <nofile> or -, then + " this is an error for the file we checked. + if l:match[1] isnot# '-' && l:match[1][0] isnot# '<' + let l:item['filename'] = l:match[1] + endif + + call add(l:output, l:item) + endfor + + return l:output +endfunction diff --git a/autoload/ale/handlers/gawk.vim b/autoload/ale/handlers/gawk.vim new file mode 100644 index 00000000..942bc2b2 --- /dev/null +++ b/autoload/ale/handlers/gawk.vim @@ -0,0 +1,25 @@ +" Author: Anthony DeDominic <adedomin@gmail.com> +" Description: Handle output from gawk's --lint option + +function! ale#handlers#gawk#HandleGawkFormat(buffer, lines) abort + " Look for lines like the following: + " gawk: /tmp/v0fddXz/1/something.awk:1: ^ invalid char ''' in expression + let l:pattern = '^.\{-}:\(\d\+\):\s\+\(warning:\|\^\)\s*\(.*\)' + let l:output = [] + + 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, + \ 'text': l:match[3], + \ 'code': 0, + \ 'type': l:ecode, + \}) + endfor + + return l:output +endfunction diff --git a/autoload/ale/handlers/gcc.vim b/autoload/ale/handlers/gcc.vim index 7f2078a4..9ec7b110 100644 --- a/autoload/ale/handlers/gcc.vim +++ b/autoload/ale/handlers/gcc.vim @@ -24,7 +24,7 @@ function! ale#handlers#gcc#HandleGCCFormat(buffer, lines) abort " <stdin>:8:5: warning: conversion lacks type at end of format [-Wformat=] " <stdin>:10:27: error: invalid operands to binary - (have ‘int’ and ‘char *’) " -:189:7: note: $/${} is unnecessary on arithmetic variables. [SC2004] - let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):(\d+)?:? ([^:]+): ?(.+)$' + let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):(\d+)?:? ([^:]+): (.+)$' let l:output = [] for l:match in ale#util#GetMatches(a:lines, l:pattern) diff --git a/autoload/ale/handlers/go.vim b/autoload/ale/handlers/go.vim new file mode 100644 index 00000000..224df664 --- /dev/null +++ b/autoload/ale/handlers/go.vim @@ -0,0 +1,25 @@ +" Author: neersighted <bjorn@neersighted.com> +" Description: go vet for Go files +" +" Author: John Eikenberry <jae@zhar.net> +" Description: updated to work with go1.10 +" +" Author: Ben Paxton <ben@gn32.uk> +" Description: moved to generic Golang file from govet + +function! ale#handlers#go#Handler(buffer, lines) abort + let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):?(\d+)?:? ?(.+)$' + let l:output = [] + let l:dir = expand('#' . a:buffer . ':p:h') + + for l:match in ale#util#GetMatches(a:lines, l:pattern) + call add(l:output, { + \ 'filename': ale#path#GetAbsPath(l:dir, l:match[1]), + \ 'lnum': l:match[2] + 0, + \ 'col': l:match[3] + 0, + \ 'text': l:match[4], + \ 'type': 'E', + \}) + endfor + return l:output +endfunction diff --git a/autoload/ale/handlers/redpen.vim b/autoload/ale/handlers/redpen.vim index 2fb05684..c136789c 100644 --- a/autoload/ale/handlers/redpen.vim +++ b/autoload/ale/handlers/redpen.vim @@ -25,6 +25,30 @@ function! ale#handlers#redpen#HandleRedpenOutput(buffer, lines) abort let l:item.lnum = l:err.lineNum let l:item.col = l:err.sentenceStartColumnNum + 1 endif + + " 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 diff --git a/autoload/ale/handlers/textlint.vim b/autoload/ale/handlers/textlint.vim new file mode 100644 index 00000000..0aae57ef --- /dev/null +++ b/autoload/ale/handlers/textlint.vim @@ -0,0 +1,19 @@ +" Author: tokida https://rouger.info +" Description: Redpen, a proofreading tool (http://redpen.cc) + +function! ale#handlers#textlint#HandleTextlintOutput(buffer, lines) abort + let l:res = get(ale#util#FuzzyJSONDecode(a:lines, []), 0, {'messages': []}) + let l:output = [] + + for l:err in l:res.messages + call add(l:output, { + \ 'text': l:err.message, + \ 'type': 'W', + \ 'code': l:err.ruleId, + \ 'lnum': l:err.line, + \ 'col' : l:err.column + \}) + endfor + + return l:output +endfunction diff --git a/autoload/ale/lsp.vim b/autoload/ale/lsp.vim index 126d6c18..8db9348f 100644 --- a/autoload/ale/lsp.vim +++ b/autoload/ale/lsp.vim @@ -325,6 +325,20 @@ function! ale#lsp#ConnectToAddress(address, project_root, callback) abort return 1 endfunction +" Stop all LSP connections, closing all jobs and channels, and removing any +" queued messages. +function! ale#lsp#StopAll() abort + for l:conn in s:connections + if has_key(l:conn, 'channel') + call ch_close(l:conn.channel) + else + call ale#job#Stop(l:conn.id) + endif + endfor + + let s:connections = [] +endfunction + function! s:SendMessageData(conn, data) abort if has_key(a:conn, 'executable') call ale#job#SendRaw(a:conn.id, a:data) diff --git a/autoload/ale/lsp/reset.vim b/autoload/ale/lsp/reset.vim new file mode 100644 index 00000000..c206ed08 --- /dev/null +++ b/autoload/ale/lsp/reset.vim @@ -0,0 +1,25 @@ +" Stop all LSPs and remove all of the data for them. +function! ale#lsp#reset#StopAllLSPs() abort + call ale#lsp#StopAll() + + if exists('*ale#definition#ClearLSPData') + " Clear the mapping for connections, etc. + call ale#definition#ClearLSPData() + endif + + if exists('*ale#engine#ClearLSPData') + " Clear the mapping for connections, etc. + call ale#engine#ClearLSPData() + + " Remove the problems for all of the LSP linters in every buffer. + for l:buffer_string in keys(g:ale_buffer_info) + let l:buffer = str2nr(l:buffer_string) + + for l:linter in ale#linter#Get(getbufvar(l:buffer, '&filetype')) + if !empty(l:linter.lsp) + call ale#engine#HandleLoclist(l:linter.name, l:buffer, []) + endif + endfor + endfor + endif +endfunction diff --git a/autoload/ale/path.vim b/autoload/ale/path.vim index 16dabf21..91832b35 100644 --- a/autoload/ale/path.vim +++ b/autoload/ale/path.vim @@ -84,12 +84,12 @@ function! ale#path#IsAbsolute(filename) abort return a:filename[:0] is# '/' || a:filename[1:2] is# ':\' endfunction -let s:temp_dir = fnamemodify(tempname(), ':h') +let s:temp_dir = ale#path#Simplify(fnamemodify(tempname(), ':h')) " Given a filename, return 1 if the file represents some temporary file " created by Vim. function! ale#path#IsTempName(filename) abort - return a:filename[:len(s:temp_dir) - 1] is# s:temp_dir + return ale#path#Simplify(a:filename)[:len(s:temp_dir) - 1] is# s:temp_dir endfunction " Given a base directory, which must not have a trailing slash, and a diff --git a/doc/ale-c.txt b/doc/ale-c.txt index cf483fb5..08b83e80 100644 --- a/doc/ale-c.txt +++ b/doc/ale-c.txt @@ -169,6 +169,14 @@ g:ale_c_flawfinder_options *g:ale-c-flawfinder* This variable can be used to pass extra options into the flawfinder command. +g:ale_c_flawfinder_error_severity *g:ale_c_flawfinder_error_severity* + *b:ale_c_flawfinder_error_severity* + Type: |Number| + Default: `6` + + This variable can be changed to set the minimum severity to be treated as an + error. This setting also applies to flawfinder for c++. + =============================================================================== gcc *ale-c-gcc* diff --git a/doc/ale-elixir.txt b/doc/ale-elixir.txt index b7d4922e..ac0ec605 100644 --- a/doc/ale-elixir.txt +++ b/doc/ale-elixir.txt @@ -14,6 +14,18 @@ g:ale_elixir_mix_options *g:ale_elixir_mix_options* This variable can be changed to specify the mix executable. =============================================================================== +mix_format *ale-elixir-mix-format* + +g:ale_elixir_mix_format_options *g:ale_elixir_mix_format_options* + *b:ale_elixir_mix_format_options* + Type: |String| + Default: `''` + + + This variable can be changed to specify the mix options passed to the + mix_format fixer + +=============================================================================== dialyxir *ale-elixir-dialyxir* Dialyzer, a DIscrepancy AnaLYZer for ERlang programs. diff --git a/doc/ale-ruby.txt b/doc/ale-ruby.txt index 94181ed4..85a3e137 100644 --- a/doc/ale-ruby.txt +++ b/doc/ale-ruby.txt @@ -87,4 +87,16 @@ g:ale_ruby_ruby_executable *g:ale_ruby_ruby_executable* =============================================================================== +rufo *ale-ruby-rufo* + +g:ale_ruby_rufo_executable *g:ale_ruby_rufo_executable* + *b:ale_ruby_rufo_executable* + Type: String + Default: `'rufo'` + + Override the invoked rufo binary. This is useful for running rufo from + binstubs or a bundle. + + +=============================================================================== vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl: diff --git a/doc/ale.txt b/doc/ale.txt index d411bb23..bfbad8a6 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -59,6 +59,7 @@ CONTENTS *ale-contents* hadolint............................|ale-dockerfile-hadolint| elixir................................|ale-elixir-options| mix.................................|ale-elixir-mix| + mix_format..........................|ale-elixir-mix-format| dialyxir............................|ale-elixir-dialyxir| elm...................................|ale-elm-options| elm-format..........................|ale-elm-elm-format| @@ -197,6 +198,7 @@ CONTENTS *ale-contents* reek................................|ale-ruby-reek| rubocop.............................|ale-ruby-rubocop| ruby................................|ale-ruby-ruby| + rufo................................|ale-ruby-rufo| rust..................................|ale-rust-options| cargo...............................|ale-rust-cargo| rls.................................|ale-rust-rls| @@ -327,7 +329,7 @@ Notes: * FusionScript: `fusion-lint` * Git Commit Messages: `gitlint` * GLSL: glslang, `glslls` -* Go: `gofmt`, `goimports`, `go vet`!!, `golint`, `gotype`, `gometalinter`!!, `go build`!!, `gosimple`!!, `staticcheck`!! +* Go: `gofmt`, `goimports`, `go vet`!!, `golint`, `gotype`!!, `gometalinter`!!, `go build`!!, `gosimple`!!, `staticcheck`!! * GraphQL: `eslint`, `gqlint`, `prettier` * Haml: `haml-lint` * Handlebars: `ember-template-lint` @@ -344,7 +346,7 @@ Notes: * Lua: `luac`, `luacheck` * Mail: `alex`!!, `proselint`, `vale` * Make: `checkmake` -* Markdown: `alex`!!, `markdownlint`!!, `mdl`, `prettier`, `proselint`, `redpen`, `remark-lint`, `vale`, `write-good` +* Markdown: `alex`!!, `markdownlint`!!, `mdl`, `prettier`, `proselint`, `redpen`, `remark-lint`, `vale`, `write-good`, `textlint` * MATLAB: `mlint` * Nim: `nim check`!! * nix: `nix-instantiate` @@ -366,7 +368,7 @@ Notes: * reStructuredText: `alex`!!, `proselint`, `redpen`, `rstcheck`, `vale`, `write-good` * Re:VIEW: `redpen` * RPM spec: `rpmlint` -* Ruby: `brakeman`, `rails_best_practices`!!, `reek`, `rubocop`, `ruby` +* Ruby: `brakeman`, `rails_best_practices`!!, `reek`, `rubocop`, `ruby`, `rufo` * Rust: `cargo`!!, `rls`, `rustc` (see |ale-integration-rust|), `rustfmt` * SASS: `sass-lint`, `stylelint` * SCSS: `prettier`, `sass-lint`, `scss-lint`, `stylelint` @@ -1871,6 +1873,15 @@ ALEResetBuffer *ALEResetBuffer* |ALEDisableBuffer|. +ALEStopAllLSPs *ALEStopAllLSPs* + + `ALEStopAllLSPs` will close and stop all channels and jobs for all LSP-like + clients, including tsserver, remove all of the data stored for them, and + delete all of the problems found for them, updating every linted buffer. + + This command can be used when LSP clients mess up and need to be restarted. + + =============================================================================== 9. API *ale-api* @@ -2295,9 +2306,11 @@ b:ale_linted *b:ale_linted* ALELintPre *ALELintPre-autocmd* ALELintPost *ALELintPost-autocmd* +ALEFixPre *ALEFixPre-autocmd* +ALEFixPost *ALEFixPost-autocmd* - These |User| autocommands are triggered before and after every lint cycle. - They can be used to update statuslines, send notifications, etc. + These |User| autocommands are triggered before and after every lint or fix + cycle. They can be used to update statuslines, send notifications, etc. The autocmd commands are run with |:silent|, so |:unsilent| is required for echoing messges. diff --git a/plugin/ale.vim b/plugin/ale.vim index 69c08496..1aa35826 100644 --- a/plugin/ale.vim +++ b/plugin/ale.vim @@ -249,6 +249,8 @@ command! -bar ALEToggleBuffer :call ale#toggle#ToggleBuffer(bufnr('')) command! -bar ALEEnableBuffer :call ale#toggle#EnableBuffer(bufnr('')) command! -bar ALEDisableBuffer :call ale#toggle#DisableBuffer(bufnr('')) command! -bar ALEResetBuffer :call ale#toggle#ResetBuffer(bufnr('')) +" A command to stop all LSP-like clients, including tsserver. +command! -bar ALEStopAllLSPs :call ale#lsp#reset#StopAllLSPs() " A command for linting manually. command! -bar ALELint :call ale#Queue(0, 'lint_file') diff --git a/test/command_callback/test_gawk_command_callback.vader b/test/command_callback/test_gawk_command_callback.vader new file mode 100644 index 00000000..ae128fe5 --- /dev/null +++ b/test/command_callback/test_gawk_command_callback.vader @@ -0,0 +1,40 @@ +Before: + Save g:ale_awk_gawk_executable + Save g:ale_awk_gawk_options + unlet! g:ale_awk_gawk_executable + unlet! g:ale_awk_gawk_options + + runtime ale_linters/awk/gawk.vim + +After: + Restore + unlet! b:command_tail + unlet! b:ale_awk_gawk_executable + unlet! b:ale_awk_gawk_options + + call ale#linter#Reset() + +Execute(The executable should be used in the command): + AssertEqual + \ 'gawk' + \ . " --source 'BEGIN { exit } END { exit 1 }'" + \ . ' ' . '-f %t --lint /dev/null', + \ ale_linters#awk#gawk#GetCommand(bufnr('')) + + let b:ale_awk_gawk_executable = '/other/gawk' + + AssertEqual + \ '/other/gawk' + \ . " --source 'BEGIN { exit } END { exit 1 }'" + \ . ' ' . '-f %t --lint /dev/null', + \ ale_linters#awk#gawk#GetCommand(bufnr('')) + + let b:ale_awk_gawk_executable = 'gawk' + let b:ale_awk_gawk_options = '--something' + + AssertEqual + \ 'gawk' + \ . " --source 'BEGIN { exit } END { exit 1 }'" + \ . ' --something' + \ . ' ' . '-f %t --lint /dev/null', + \ ale_linters#awk#gawk#GetCommand(bufnr('')) diff --git a/test/command_callback/test_gosimple_command_callback.vader b/test/command_callback/test_gosimple_command_callback.vader new file mode 100644 index 00000000..a0b1f468 --- /dev/null +++ b/test/command_callback/test_gosimple_command_callback.vader @@ -0,0 +1,12 @@ +Before: + runtime ale_linters/go/gosimple.vim + call ale#test#SetFilename('../go_files/testfile2.go') + +After: + call ale#linter#Reset() + +Execute(The default gosimple command should be correct): + AssertEqual 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ . ' gosimple .', + \ ale_linters#go#gosimple#GetCommand(bufnr('')) + diff --git a/test/command_callback/test_gotype_command_callback.vader b/test/command_callback/test_gotype_command_callback.vader index f95e8423..4fba3344 100644 --- a/test/command_callback/test_gotype_command_callback.vader +++ b/test/command_callback/test_gotype_command_callback.vader @@ -5,15 +5,11 @@ Before: After: call ale#linter#Reset() - -Execute(The gotype callback should include other files from the directory but exclude the file itself): - let dir = expand('#' . bufnr('') . ':p:h') - AssertEqual - \ "gotype %t ". ale#Escape(ale#path#Simplify(dir . "/testfile.go")), +Execute(The default gotype command should be correct): + AssertEqual 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ . ' gotype .', \ ale_linters#go#gotype#GetCommand(bufnr('')) Execute(The gotype callback should ignore test files): call ale#test#SetFilename('bla_test.go') - AssertEqual - \ 0, - \ ale_linters#go#gotype#GetCommand(bufnr('')) + AssertEqual 0, ale_linters#go#gotype#GetCommand(bufnr('')) diff --git a/test/command_callback/test_tslint_command_callback.vader b/test/command_callback/test_tslint_command_callback.vader index 4ad42fa5..edab72c8 100644 --- a/test/command_callback/test_tslint_command_callback.vader +++ b/test/command_callback/test_tslint_command_callback.vader @@ -17,7 +17,10 @@ Before: After: Restore + unlet! b:ale_typescript_tslint_executable + unlet! b:ale_typescript_tslint_config_path unlet! b:ale_typescript_tslint_rules_dir + unlet! b:ale_typescript_tslint_use_global call ale#test#RestoreDirectory() call ale#linter#Reset() @@ -25,7 +28,7 @@ After: Execute(The default tslint command should be correct): AssertEqual \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' - \ . 'tslint --format json %t', + \ . ale#Escape('tslint') . ' --format json %t', \ ale_linters#typescript#tslint#GetCommand(bufnr('')) Execute(The rules directory option should be included if set): @@ -33,7 +36,16 @@ Execute(The rules directory option should be included if set): AssertEqual \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' - \ . 'tslint --format json' + \ . ale#Escape('tslint') . ' --format json' \ . ' -r ' . ale#Escape('/foo/bar') \ . ' %t', \ ale_linters#typescript#tslint#GetCommand(bufnr('')) + +Execute(The executable should be configurable and escaped): + let b:ale_typescript_tslint_executable = 'foo bar' + + AssertEqual 'foo bar', ale_linters#typescript#tslint#GetExecutable(bufnr('')) + AssertEqual + \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ . ale#Escape('foo bar') . ' --format json %t', + \ ale_linters#typescript#tslint#GetCommand(bufnr('')) diff --git a/test/fix/test_ale_fix.vader b/test/fix/test_ale_fix.vader index 5b66c92c..0321cbae 100644 --- a/test/fix/test_ale_fix.vader +++ b/test/fix/test_ale_fix.vader @@ -17,6 +17,14 @@ Before: \ 'testft': [], \} + let g:pre_success = 0 + let g:post_success = 0 + augroup VaderTest + autocmd! + autocmd User ALEFixPre let g:pre_success = 1 + autocmd User ALEFixPost let g:post_success = 1 + augroup end + if !has('win32') let &shell = '/bin/bash' endif @@ -171,6 +179,7 @@ After: unlet! g:ale_emulate_job_failure unlet! b:ale_fixers unlet! b:ale_fix_on_save + augroup! VaderTest delfunction AddCarets delfunction AddDollars delfunction DoNothing @@ -664,3 +673,9 @@ Expect(The lines in the JSON should be used): x y z + +Execute(ALEFix should apply autocmds): + let g:ale_fixers.testft = ['AddCarets'] + ALEFix + AssertEqual g:pre_success, 1 + AssertEqual g:post_success, 1 diff --git a/test/fixers/test_elm_format_fixer_callback.vader b/test/fixers/test_elm_format_fixer_callback.vader index d613aa84..682c22ca 100644 --- a/test/fixers/test_elm_format_fixer_callback.vader +++ b/test/fixers/test_elm_format_fixer_callback.vader @@ -18,7 +18,7 @@ Execute(The elm-format command should have default params): \ ale#Escape(ale#path#Simplify(g:dir . '/../elm-test-files/node_modules/.bin/elm-format')) \ . ' %t --yes', \ }, - \ ale#fixers#format#Fix(bufnr('')) + \ ale#fixers#elm_format#Fix(bufnr('')) Execute(The elm-format command should manage use_global = 1 param): call ale#test#SetFilename('../elm-test-files/src/subdir/testfile.elm') @@ -31,7 +31,7 @@ Execute(The elm-format command should manage use_global = 1 param): \ ale#Escape('elm-format') \ . ' %t --yes', \ }, - \ ale#fixers#format#Fix(bufnr('')) + \ ale#fixers#elm_format#Fix(bufnr('')) Execute(The elm-format command should manage executable param): call ale#test#SetFilename('../elm-test-files/src/subdir/testfile.elm') @@ -45,7 +45,7 @@ Execute(The elm-format command should manage executable param): \ ale#Escape('elmformat') \ . ' %t --yes', \ }, - \ ale#fixers#format#Fix(bufnr('')) + \ ale#fixers#elm_format#Fix(bufnr('')) Execute(The elm-format command should manage empty options): call ale#test#SetFilename('../elm-test-files/src/subdir/testfile.elm') @@ -58,7 +58,7 @@ Execute(The elm-format command should manage empty options): \ ale#Escape(ale#path#Simplify(g:dir . '/../elm-test-files/node_modules/.bin/elm-format')) \ . ' %t', \ }, - \ ale#fixers#format#Fix(bufnr('')) + \ ale#fixers#elm_format#Fix(bufnr('')) Execute(The elm-format command should manage custom options): call ale#test#SetFilename('../elm-test-files/src/subdir/testfile.elm') @@ -71,4 +71,4 @@ Execute(The elm-format command should manage custom options): \ ale#Escape(ale#path#Simplify(g:dir . '/../elm-test-files/node_modules/.bin/elm-format')) \ . ' %t --param1 --param2', \ }, - \ ale#fixers#format#Fix(bufnr('')) + \ ale#fixers#elm_format#Fix(bufnr('')) diff --git a/test/fixers/test_mix_format_fixer_callback.vader b/test/fixers/test_mix_format_fixer_callback.vader index c6c97c57..365fbecf 100644 --- a/test/fixers/test_mix_format_fixer_callback.vader +++ b/test/fixers/test_mix_format_fixer_callback.vader @@ -1,10 +1,15 @@ Before: - call ale#test#SetDirectory('/testplugin/test/fixers') Save g:ale_elixir_mix_executable + Save g:ale_elixir_mix_format_options let g:ale_elixir_mix_executable = 'xxxinvalid' + let g:ale_elixir_mix_format_options = '' + + call ale#test#SetDirectory('/testplugin/test/fixers') After: + Restore + call ale#test#RestoreDirectory() Execute(The mix_format callback should return the correct default values): @@ -18,3 +23,14 @@ Execute(The mix_format callback should return the correct default values): \ }, \ ale#fixers#mix_format#Fix(bufnr('')) +Execute(The mix_format callback should include the correct format options): + let g:ale_elixir_mix_format_options = 'invalid_options' + call ale#test#SetFilename('../elixir-test-files/testfile.ex') + + AssertEqual + \ { + \ 'read_temporary_file': 1, + \ 'command': ale#Escape('xxxinvalid') + \ . ' format invalid_options %t', + \ }, + \ ale#fixers#mix_format#Fix(bufnr('')) diff --git a/test/fixers/test_rufo_fixer_callback.vader b/test/fixers/test_rufo_fixer_callback.vader new file mode 100644 index 00000000..a0828406 --- /dev/null +++ b/test/fixers/test_rufo_fixer_callback.vader @@ -0,0 +1,33 @@ +Before: + Save g:ale_ruby_rufo_executable + + " Use an invalid global executable, so we don't match it. + let g:ale_ruby_rufo_executable = 'xxxinvalid' + + call ale#test#SetDirectory('/testplugin/test/fixers') + silent cd .. + silent cd command_callback + let g:dir = getcwd() + +After: + Restore + + call ale#test#RestoreDirectory() + +Execute(The rufo command should contain `bundle exec` when executable is `bundle`): + let g:ale_ruby_rufo_executable = 'bundle' + call ale#test#SetFilename('ruby_paths/dummy.rb') + + AssertEqual + \ ale#Escape('bundle') . ' exec rufo %t', + \ ale#fixers#rufo#GetCommand(bufnr('')) + +Execute(The rufo callback should return the correct default values): + call ale#test#SetFilename('ruby_paths/dummy.rb') + + AssertEqual + \ { + \ 'read_temporary_file': 1, + \ 'command': ale#Escape('xxxinvalid') . ' %t' + \ }, + \ ale#fixers#rufo#Fix(bufnr('')) diff --git a/test/handler/test_flawfinder_handler.vader b/test/handler/test_flawfinder_handler.vader new file mode 100644 index 00000000..708bac2a --- /dev/null +++ b/test/handler/test_flawfinder_handler.vader @@ -0,0 +1,57 @@ +Before: + Save g:ale_c_flawfinder_error_severity + + unlet! g:ale_c_flawfinder_error_severity + unlet! b:ale_c_flawfinder_error_severity + + runtime ale_linters/c/flawfinder.vim + +After: + unlet! g:ale_c_flawfinder_error_severity + Restore + +Execute(The Flawfinder handler should ignore other lines of output): + AssertEqual + \ [], + \ ale#handlers#flawfinder#HandleFlawfinderFormat(347, [ + \ 'foo', + \ 'bar', + \ 'baz', + \ ]) + +Execute(The Flawfinder handler should work): + AssertEqual + \ [ + \ { + \ 'lnum': 31, + \ 'col': 4, + \ 'type': 'W', + \ 'text': "(buffer) strncpy: Easily used incorrectly", + \ }, + \ ], + \ ale#handlers#flawfinder#HandleFlawfinderFormat(347, [ + \ "<stdin>:31:4: [1] (buffer) strncpy:Easily used incorrectly", + \ ]) + +Execute(The Flawfinder error severity level should be configurable): + let b:ale_c_flawfinder_error_severity = 2 + + AssertEqual + \ [ + \ { + \ 'lnum': 12, + \ 'col': 4, + \ 'type': 'E', + \ 'text': "(buffer) char: Statically-sized arrays can be bad", + \ }, + \ { + \ 'lnum': 31, + \ 'col': 4, + \ 'type': 'W', + \ 'text': "(buffer) strncpy: Easily used incorrectly", + \ }, + \ ], + \ ale#handlers#flawfinder#HandleFlawfinderFormat(bufnr(''), [ + \ "<stdin>:12:4: [2] (buffer) char:Statically-sized arrays can be bad", + \ "<stdin>:31:4: [1] (buffer) strncpy:Easily used incorrectly", + \ ]) diff --git a/test/handler/test_gawk_handler.vader b/test/handler/test_gawk_handler.vader new file mode 100644 index 00000000..3a7b5457 --- /dev/null +++ b/test/handler/test_gawk_handler.vader @@ -0,0 +1,39 @@ +Before: + runtime ale_linters/awk/gawk.vim + +After: + call ale#linter#Reset() + +Execute(gawk syntax errors should be parsed correctly): + + AssertEqual + \ [ + \ { + \ 'lnum': 1, + \ 'col': 0, + \ 'text': "invalid char ''' in expression", + \ 'code': 0, + \ 'type': 'E', + \ }, + \ { + \ 'lnum': 5, + \ 'col': 0, + \ 'text': 'unterminated string', + \ 'code': 0, + \ 'type': 'E', + \ }, + \ { + \ 'lnum': 10, + \ 'col': 0, + \ 'text': "escape sequence `\u' treated as plain `u'", + \ 'code': 0, + \ 'type': 'W', + \ }, + \ ], + \ ale#handlers#gawk#HandleGawkFormat(347, [ + \ "gawk: something.awk:1: BEGIN { system('touch aaaaaaaaa') }", + \ "gawk: something.awk:1: ^ invalid char ''' in expression", + \ 'gawk: something.awk:5: { x = "aaaaaaaaaaa', + \ 'gawk: something.awk:5: ^ unterminated string', + \ "gawk: something.awk:10: warning: escape sequence `\u' treated as plain `u'", + \ ]) diff --git a/test/handler/test_govet_handler.vader b/test/handler/test_go_generic_handler.vader index b4bfdc93..624e56c1 100644 --- a/test/handler/test_govet_handler.vader +++ b/test/handler/test_go_generic_handler.vader @@ -1,10 +1,4 @@ -Before: - runtime ale_linters/go/govet.vim - -After: - call ale#linter#Reset() - -Execute(The govet handler should return the correct filenames): +Execute(The golang handler should return the correct filenames): AssertEqual \ [ \ { @@ -22,7 +16,7 @@ Execute(The govet handler should return the correct filenames): \ 'filename': ale#path#Simplify(expand('%:p:h') . '/other.go'), \ }, \ ], - \ ale_linters#go#govet#Handler(bufnr(''), [ + \ ale#handlers#go#Handler(bufnr(''), [ \ 'test.go:27: some error', \ 'other.go:27:5: some error with a column', \ ]) diff --git a/test/handler/test_redpen_handler.vader b/test/handler/test_redpen_handler.vader index f28d6923..4490bcba 100644 --- a/test/handler/test_redpen_handler.vader +++ b/test/handler/test_redpen_handler.vader @@ -23,6 +23,15 @@ Execute(redpen handler should handle errors output): \ 'type': 'W', \ 'code': 'Spelling', \ }, + \ { + \ 'lnum': 1, + \ 'col': 35, + \ 'end_lnum': 1, + \ 'end_col': 55, + \ 'text': 'Found possibly misspelled word "コードチェック".', + \ 'type': 'W', + \ 'code': 'Spelling', + \ }, \ ], \ ale#handlers#redpen#HandleRedpenOutput(bufnr(''), [ \ '[', @@ -50,6 +59,21 @@ Execute(redpen handler should handle errors output): \ ' "lineNum": 1,', \ ' "sentenceStartColumnNum": 0,', \ ' "message": "Found possibly misspelled word \"NeoVim\"."', + \ ' },', + \ ' {', + \ ' "sentence": "ALEはNeoVimとVim8で非同期のコードチェックを実現するプラグインです。",', + \ ' "endPosition": {', + \ ' "offset": 27,', + \ ' "lineNum": 1', + \ ' },', + \ ' "validator": "Spelling",', + \ ' "lineNum": 1,', + \ ' "sentenceStartColumnNum": 0,', + \ ' "message": "Found possibly misspelled word \"コードチェック\".",', + \ ' "startPosition": {', + \ ' "offset": 20,', + \ ' "lineNum": 1', + \ ' }', \ ' }', \ ' ]', \ ' }', diff --git a/test/handler/test_textlint_handler.vader b/test/handler/test_textlint_handler.vader new file mode 100644 index 00000000..c00d54de --- /dev/null +++ b/test/handler/test_textlint_handler.vader @@ -0,0 +1,41 @@ +Before: + runtime! ale_linters/markdown/textlint.vim + +After: + call ale#linter#Reset() + +Execute(textlint handler should handle errors output): + AssertEqual + \ [ + \ { + \ 'lnum': 16, + \ 'col': 50, + \ 'text': 'Found possibly misspelled word "NeoVim".', + \ 'type': 'W', + \ 'code': 'preset-japanese/no-doubled-joshi', + \ }, + \ ], + \ ale#handlers#textlint#HandleTextlintOutput(bufnr(''), [ + \ '[', + \ ' {', + \ ' "filePath": "test.md",', + \ ' "messages": [', + \ ' {', + \ ' "type": "lint",', + \ ' "ruleId": "preset-japanese/no-doubled-joshi",', + \ ' "index": 1332,', + \ ' "line": 16,', + \ ' "column": 50,', + \ ' "severity": 2,', + \ ' "message": "Found possibly misspelled word \"NeoVim\"."', + \ ' }', + \ ' ]', + \ ' }', + \ ']', + \ ]) + +Execute(textlint handler should no error output): + AssertEqual + \ [], + \ ale#handlers#textlint#HandleTextlintOutput(bufnr(''), [ + \ ]) diff --git a/test/lsp/test_reset_lsp.vader b/test/lsp/test_reset_lsp.vader new file mode 100644 index 00000000..2bec13dc --- /dev/null +++ b/test/lsp/test_reset_lsp.vader @@ -0,0 +1,90 @@ +Before: + Save g:ale_enabled + Save g:ale_set_signs + Save g:ale_set_quickfix + Save g:ale_set_loclist + Save g:ale_set_highlights + Save g:ale_echo_cursor + + let g:ale_enabled = 0 + let g:ale_set_signs = 0 + let g:ale_set_quickfix = 0 + let g:ale_set_loclist = 0 + let g:ale_set_highlights = 0 + let g:ale_echo_cursor = 0 + + function EmptyString() abort + return '' + endfunction + + call ale#engine#InitBufferInfo(bufnr('')) + + call ale#linter#Define('testft', { + \ 'name': 'lsplinter', + \ 'lsp': 'tsserver', + \ 'executable_callback': 'EmptyString', + \ 'command_callback': 'EmptyString', + \ 'project_root_callback': 'EmptyString', + \ 'language_callback': 'EmptyString', + \}) + + call ale#linter#Define('testft', { + \ 'name': 'otherlinter', + \ 'callback': 'TestCallback', + \ 'executable': has('win32') ? 'cmd': 'true', + \ 'command': 'true', + \ 'read_buffer': 0, + \}) + +After: + Restore + + unlet! b:ale_save_event_fired + + delfunction EmptyString + call ale#linter#Reset() + +Given testft(Some file with an imaginary filetype): +Execute(ALEStopAllLSPs should clear the loclist): + let g:ale_buffer_info[bufnr('')].loclist = [ + \ { + \ 'text': 'a', + \ 'lnum': 10, + \ 'col': 0, + \ 'bufnr': bufnr(''), + \ 'vcol': 0, + \ 'type': 'E', + \ 'nr': -1, + \ 'linter_name': 'lsplinter', + \ }, + \ { + \ 'text': 'a', + \ 'lnum': 10, + \ 'col': 0, + \ 'bufnr': bufnr(''), + \ 'vcol': 0, + \ 'type': 'E', + \ 'nr': -1, + \ 'linter_name': 'otherlinter', + \ }, + \] + let g:ale_buffer_info[bufnr('')].active_linter_list = ['lsplinter', 'otherlinter'] + + ALEStopAllLSPs + + " The loclist should be updated. + AssertEqual g:ale_buffer_info[bufnr('')].loclist, [ + \ { + \ 'text': 'a', + \ 'lnum': 10, + \ 'col': 0, + \ 'bufnr': bufnr(''), + \ 'vcol': 0, + \ 'type': 'E', + \ 'nr': -1, + \ 'linter_name': 'otherlinter', + \ }, + \] + + " The LSP linter should be removed from the active linter list. + AssertEqual g:ale_buffer_info[bufnr('')].active_linter_list, ['otherlinter'] diff --git a/test/test_loclist_corrections.vader b/test/test_loclist_corrections.vader index 6224d608..46c7e272 100644 --- a/test/test_loclist_corrections.vader +++ b/test/test_loclist_corrections.vader @@ -324,7 +324,7 @@ Execute(FixLocList should interpret temporary filenames as being the current buf \ 'foobar', \ [ \ {'text': 'a', 'lnum': 2, 'filename': b:temp_name}, - \ {'text': 'a', 'lnum': 3, 'filename': b:temp_name}, + \ {'text': 'a', 'lnum': 3, 'filename': substitute(b:temp_name, '\\', '/', 'g')}, \ ], \ ) |