From 9ee8067df6d965b169df5ebbee2b88a9237a5384 Mon Sep 17 00:00:00 2001 From: mynomoto Date: Tue, 6 Aug 2019 18:44:53 -0300 Subject: [PATCH 01/70] Use cache for clj-kondo linter --- ale_linters/clojure/clj_kondo.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ale_linters/clojure/clj_kondo.vim b/ale_linters/clojure/clj_kondo.vim index 5dd11c12..eb60ce77 100644 --- a/ale_linters/clojure/clj_kondo.vim +++ b/ale_linters/clojure/clj_kondo.vim @@ -29,6 +29,6 @@ call ale#linter#Define('clojure', { \ 'name': 'clj-kondo', \ 'output_stream': 'stdout', \ 'executable': 'clj-kondo', -\ 'command': 'clj-kondo --lint %t', +\ 'command': 'clj-kondo --cache --lint %t', \ 'callback': 'ale_linters#clojure#clj_kondo#HandleCljKondoFormat', \}) From c8c142b8812701eddab7b7fef10cfff0c44e2a64 Mon Sep 17 00:00:00 2001 From: Jerko Steiner Date: Wed, 9 Oct 2019 20:42:41 -0500 Subject: [PATCH 02/70] Do not save for ALERename and ALEOrganizeImports --- autoload/ale/code_action.vim | 20 ++++-- autoload/ale/completion.vim | 2 +- autoload/ale/fix.vim | 66 ++++++++++++-------- autoload/ale/organize_imports.vim | 2 +- autoload/ale/rename.vim | 4 +- test/completion/test_completion_events.vader | 3 +- test/test_code_action.vader | 48 +++++++++----- test/test_organize_imports.vader | 3 +- test/test_rename.vader | 3 +- 9 files changed, 97 insertions(+), 54 deletions(-) diff --git a/autoload/ale/code_action.vim b/autoload/ale/code_action.vim index 0af1bb70..466c023a 100644 --- a/autoload/ale/code_action.vim +++ b/autoload/ale/code_action.vim @@ -1,7 +1,7 @@ " Author: Jerko Steiner " Description: Code action support for LSP / tsserver -function! ale#code_action#HandleCodeAction(code_action) abort +function! ale#code_action#HandleCodeAction(code_action, should_save) abort let l:current_buffer = bufnr('') let l:changes = a:code_action.changes @@ -17,11 +17,14 @@ function! ale#code_action#HandleCodeAction(code_action) abort for l:file_code_edit in l:changes call ale#code_action#ApplyChanges( - \ l:file_code_edit.fileName, l:file_code_edit.textChanges) + \ l:file_code_edit.fileName, + \ l:file_code_edit.textChanges, + \ a:should_save, + \ ) endfor endfunction -function! ale#code_action#ApplyChanges(filename, changes) abort +function! ale#code_action#ApplyChanges(filename, changes, should_save) abort let l:current_buffer = bufnr('') " The buffer is used to determine the fileformat, if available. let l:buffer = bufnr(a:filename) @@ -106,10 +109,17 @@ function! ale#code_action#ApplyChanges(filename, changes) abort call remove(l:lines, -1) endif - call ale#util#Writefile(l:buffer, l:lines, a:filename) + if a:should_save + call ale#util#Writefile(l:buffer, l:lines, a:filename) + else + call ale#fix#SetBufferContents(l:buffer, l:lines) + endif if l:is_current_buffer - call ale#util#Execute(':e!') + if a:should_save + call ale#util#Execute(':e!') + endif + call setpos('.', [0, l:pos[0], l:pos[1], 0]) endif endfunction diff --git a/autoload/ale/completion.vim b/autoload/ale/completion.vim index a15ca514..896a3745 100644 --- a/autoload/ale/completion.vim +++ b/autoload/ale/completion.vim @@ -739,7 +739,7 @@ function! ale#completion#HandleUserData(completed_item) abort endif for l:code_action in get(l:user_data, 'codeActions', []) - call ale#code_action#HandleCodeAction(l:code_action) + call ale#code_action#HandleCodeAction(l:code_action, v:false) endfor endfunction diff --git a/autoload/ale/fix.vim b/autoload/ale/fix.vim index dad9e2bc..81f5a6d6 100644 --- a/autoload/ale/fix.vim +++ b/autoload/ale/fix.vim @@ -4,40 +4,15 @@ call ale#Set('fix_on_save_ignore', {}) " Vim doesn't let you modify hidden buffers. function! ale#fix#ApplyQueuedFixes(buffer) abort let l:data = get(g:ale_fix_buffer_data, a:buffer, {'done': 0}) - let l:has_bufline_api = exists('*deletebufline') && exists('*setbufline') - if !l:data.done || (!l:has_bufline_api && a:buffer isnot bufnr('')) + if !l:data.done return endif call remove(g:ale_fix_buffer_data, a:buffer) if l:data.changes_made - " If the file is in DOS mode, we have to remove carriage returns from - " the ends of lines before calling setline(), or we will see them - " twice. - let l:new_lines = getbufvar(a:buffer, '&fileformat') is# 'dos' - \ ? map(copy(l:data.output), 'substitute(v:val, ''\r\+$'', '''', '''')') - \ : l:data.output - let l:first_line_to_remove = len(l:new_lines) + 1 - - " Use a Vim API for setting lines in other buffers, if available. - if l:has_bufline_api - call setbufline(a:buffer, 1, l:new_lines) - call deletebufline(a:buffer, l:first_line_to_remove, '$') - " Fall back on setting lines the old way, for the current buffer. - else - let l:old_line_length = len(l:data.lines_before) - - if l:old_line_length >= l:first_line_to_remove - let l:save = winsaveview() - silent execute - \ l:first_line_to_remove . ',' . l:old_line_length . 'd_' - call winrestview(l:save) - endif - - call setline(1, l:new_lines) - endif + let l:new_lines = ale#fix#SetBufferContents(a:buffer, l:data.output) if l:data.should_save if a:buffer is bufnr('') @@ -71,6 +46,43 @@ function! ale#fix#ApplyQueuedFixes(buffer) abort endif endfunction +" Sets buffer contents to lines +function! ale#fix#SetBufferContents(buffer, lines) abort + let l:has_bufline_api = exists('*deletebufline') && exists('*setbufline') + + if !l:has_bufline_api && a:buffer isnot bufnr('') + return + endif + + " If the file is in DOS mode, we have to remove carriage returns from + " the ends of lines before calling setline(), or we will see them + " twice. + let l:new_lines = getbufvar(a:buffer, '&fileformat') is# 'dos' + \ ? map(copy(a:lines), 'substitute(v:val, ''\r\+$'', '''', '''')') + \ : a:lines + let l:first_line_to_remove = len(l:new_lines) + 1 + + " Use a Vim API for setting lines in other buffers, if available. + if l:has_bufline_api + call setbufline(a:buffer, 1, l:new_lines) + call deletebufline(a:buffer, l:first_line_to_remove, '$') + " Fall back on setting lines the old way, for the current buffer. + else + let l:old_line_length = line('$') + + if l:old_line_length >= l:first_line_to_remove + let l:save = winsaveview() + silent execute + \ l:first_line_to_remove . ',' . l:old_line_length . 'd_' + call winrestview(l:save) + endif + + call setline(1, l:new_lines) + endif + + return l:new_lines +endfunction + function! ale#fix#ApplyFixes(buffer, output) abort let l:data = g:ale_fix_buffer_data[a:buffer] let l:data.output = a:output diff --git a/autoload/ale/organize_imports.vim b/autoload/ale/organize_imports.vim index bc9b829e..e89c832c 100644 --- a/autoload/ale/organize_imports.vim +++ b/autoload/ale/organize_imports.vim @@ -15,7 +15,7 @@ function! ale#organize_imports#HandleTSServerResponse(conn_id, response) abort call ale#code_action#HandleCodeAction({ \ 'description': 'Organize Imports', \ 'changes': l:file_code_edits, - \}) + \}, v:false) endfunction function! s:OnReady(linter, lsp_details) abort diff --git a/autoload/ale/rename.vim b/autoload/ale/rename.vim index 02b7b579..fbd6c2ad 100644 --- a/autoload/ale/rename.vim +++ b/autoload/ale/rename.vim @@ -80,7 +80,7 @@ function! ale#rename#HandleTSServerResponse(conn_id, response) abort call ale#code_action#HandleCodeAction({ \ 'description': 'rename', \ 'changes': l:changes, - \}) + \}, v:true) endfunction function! ale#rename#HandleLSPResponse(conn_id, response) abort @@ -134,7 +134,7 @@ function! ale#rename#HandleLSPResponse(conn_id, response) abort call ale#code_action#HandleCodeAction({ \ 'description': 'rename', \ 'changes': l:changes, - \}) + \}, v:true) endif endfunction diff --git a/test/completion/test_completion_events.vader b/test/completion/test_completion_events.vader index e06ac98b..a6dcdac4 100644 --- a/test/completion/test_completion_events.vader +++ b/test/completion/test_completion_events.vader @@ -50,7 +50,8 @@ Before: let g:handle_code_action_called = 0 function! MockHandleCodeAction() abort " delfunction! ale#code_action#HandleCodeAction - function! ale#code_action#HandleCodeAction(action) abort + function! ale#code_action#HandleCodeAction(action, should_save) abort + AssertEqual v:false, a:should_save let g:handle_code_action_called += 1 endfunction endfunction diff --git a/test/test_code_action.vader b/test/test_code_action.vader index ffaca630..b47f24ff 100644 --- a/test/test_code_action.vader +++ b/test/test_code_action.vader @@ -37,10 +37,10 @@ Before: After: " Close the extra buffers if we opened it. if bufnr(g:file1) != -1 - execute ':bp | :bd ' . bufnr(g:file1) + execute ':bp! | :bd! ' . bufnr(g:file1) endif if bufnr(g:file2) != -1 - execute ':bp | :bd ' . bufnr(g:file2) + execute ':bp! | :bd! ' . bufnr(g:file2) endif if filereadable(g:file1) @@ -116,7 +116,7 @@ Execute(It should modify and save multiple files): \ 'newText': "import {A, B} from 'module'\n\n", \ }] \ }], - \}) + \}, v:true) AssertEqual [ \ 'class Value {', @@ -161,7 +161,7 @@ Execute(Beginning of file can be modified): \ 'newText': "type A: string\ntype B: number\n", \ }], \ }] - \}) + \}, v:true) AssertEqual [ \ 'type A: string', @@ -192,7 +192,7 @@ Execute(End of file can be modified): \ 'newText': "type A: string\ntype B: number\n", \ }], \ }] - \}) + \}, v:true) AssertEqual g:test.text + [ \ 'type A: string', @@ -227,7 +227,7 @@ Execute(Current buffer contents will be reloaded): \ 'newText': "type A: string\ntype B: number\n", \ }], \ }] - \}) + \}, v:true) AssertEqual [ \ 'type A: string', @@ -249,11 +249,11 @@ Execute(Cursor will not move when it is before text change): let g:test.changes = g:test.create_change(2, 3, 2, 8, 'value2') call setpos('.', [0, 1, 1, 0]) - call ale#code_action#HandleCodeAction(g:test.changes) + call ale#code_action#HandleCodeAction(g:test.changes, v:true) AssertEqual [1, 1], getpos('.')[1:2] call setpos('.', [0, 2, 2, 0]) - call ale#code_action#HandleCodeAction(g:test.changes) + call ale#code_action#HandleCodeAction(g:test.changes, v:true) AssertEqual [2, 2], getpos('.')[1:2] # ====C==== @@ -264,7 +264,7 @@ Execute(Cursor column will move to the change end when cursor between start/end) call WriteFileAndEdit() call setpos('.', [0, 2, r, 0]) AssertEqual ' value: string', getline('.') - call ale#code_action#HandleCodeAction(g:test.changes) + call ale#code_action#HandleCodeAction(g:test.changes, v:true) AssertEqual ' value2: string', getline('.') AssertEqual [2, 9], getpos('.')[1:2] endfor @@ -275,7 +275,8 @@ Execute(Cursor column will move back when new text is shorter): call WriteFileAndEdit() call setpos('.', [0, 2, 8, 0]) AssertEqual ' value: string', getline('.') - call ale#code_action#HandleCodeAction(g:test.create_change(2, 3, 2, 8, 'val')) + call ale#code_action#HandleCodeAction( + \ g:test.create_change(2, 3, 2, 8, 'val'), v:true) AssertEqual ' val: string', getline('.') AssertEqual [2, 6], getpos('.')[1:2] @@ -286,7 +287,8 @@ Execute(Cursor column will move forward when new text is longer): call setpos('.', [0, 2, 8, 0]) AssertEqual ' value: string', getline('.') - call ale#code_action#HandleCodeAction(g:test.create_change(2, 3, 2, 8, 'longValue')) + call ale#code_action#HandleCodeAction( + \ g:test.create_change(2, 3, 2, 8, 'longValue'), v:true) AssertEqual ' longValue: string', getline('.') AssertEqual [2, 12], getpos('.')[1:2] @@ -297,7 +299,8 @@ Execute(Cursor line will move when updates are happening on lines above): call WriteFileAndEdit() call setpos('.', [0, 3, 1, 0]) AssertEqual '}', getline('.') - call ale#code_action#HandleCodeAction(g:test.create_change(1, 1, 2, 1, "test\ntest\n")) + call ale#code_action#HandleCodeAction( + \ g:test.create_change(1, 1, 2, 1, "test\ntest\n"), v:true) AssertEqual '}', getline('.') AssertEqual [4, 1], getpos('.')[1:2] @@ -308,7 +311,8 @@ Execute(Cursor line and column will move when change on lines above and just bef call WriteFileAndEdit() call setpos('.', [0, 2, 2, 0]) AssertEqual ' value: string', getline('.') - call ale#code_action#HandleCodeAction(g:test.create_change(1, 1, 2, 1, "test\ntest\n123")) + call ale#code_action#HandleCodeAction( + \ g:test.create_change(1, 1, 2, 1, "test\ntest\n123"), v:true) AssertEqual '123 value: string', getline('.') AssertEqual [3, 5], getpos('.')[1:2] @@ -319,7 +323,8 @@ Execute(Cursor line and column will move at the end of changes): call WriteFileAndEdit() call setpos('.', [0, 2, 10, 0]) AssertEqual ' value: string', getline('.') - call ale#code_action#HandleCodeAction(g:test.create_change(1, 1, 3, 1, "test\n")) + call ale#code_action#HandleCodeAction( + \ g:test.create_change(1, 1, 3, 1, "test\n"), v:true) AssertEqual '}', getline('.') AssertEqual [2, 1], getpos('.')[1:2] @@ -329,6 +334,19 @@ Execute(Cursor will not move when changes happening on lines >= cursor, but afte call WriteFileAndEdit() call setpos('.', [0, 2, 3, 0]) AssertEqual ' value: string', getline('.') - call ale#code_action#HandleCodeAction(g:test.create_change(2, 10, 3, 1, "number\n")) + call ale#code_action#HandleCodeAction( + \ g:test.create_change(2, 10, 3, 1, "number\n"), v:true) AssertEqual ' value: number', getline('.') AssertEqual [2, 3], getpos('.')[1:2] + +Execute(It should just modify file when should_save is set to v:false): + call WriteFileAndEdit() + let g:test.change = g:test.create_change(1, 1, 1, 1, "import { writeFile } from 'fs';\n") + call ale#code_action#HandleCodeAction(g:test.change, v:false) + AssertEqual 1, getbufvar(bufnr(''), '&modified') + AssertEqual [ + \ 'import { writeFile } from ''fs'';', + \ 'class Name {', + \ ' value: string', + \ '}', + \], getline(1, '$') diff --git a/test/test_organize_imports.vader b/test/test_organize_imports.vader index 137326a9..c51ff1c0 100644 --- a/test/test_organize_imports.vader +++ b/test/test_organize_imports.vader @@ -57,8 +57,9 @@ Before: call add(g:expr_list, a:expr) endfunction - function! ale#code_action#HandleCodeAction(code_action) abort + function! ale#code_action#HandleCodeAction(code_action, should_save) abort let g:handle_code_action_called = 1 + AssertEqual v:false, a:should_save call add(g:code_actions, a:code_action) endfunction diff --git a/test/test_rename.vader b/test/test_rename.vader index 98e3ef30..3600df59 100644 --- a/test/test_rename.vader +++ b/test/test_rename.vader @@ -57,8 +57,9 @@ Before: call add(g:expr_list, a:expr) endfunction - function! ale#code_action#HandleCodeAction(code_action) abort + function! ale#code_action#HandleCodeAction(code_action, should_save) abort let g:handle_code_action_called = 1 + AssertEqual v:true, a:should_save call add(g:code_actions, a:code_action) endfunction From 31d6f72abf5c025374a60675e7db8d8c97c9f775 Mon Sep 17 00:00:00 2001 From: Ildar Akhmetgaleev Date: Sat, 12 Oct 2019 16:45:12 +0700 Subject: [PATCH 03/70] Add option to show hover messages in preview. Add new option 'ale_hover_to_preview' to show hover messages in preview window. --- autoload/ale/hover.vim | 10 ++++++++++ plugin/ale.vim | 3 +++ 2 files changed, 13 insertions(+) diff --git a/autoload/ale/hover.vim b/autoload/ale/hover.vim index 2af35aa4..8fdd288c 100644 --- a/autoload/ale/hover.vim +++ b/autoload/ale/hover.vim @@ -42,6 +42,11 @@ function! ale#hover#HandleTSServerResponse(conn_id, response) abort \&& exists('*balloon_show') \&& ale#Var(l:options.buffer, 'set_balloons') call balloon_show(a:response.body.displayString) + elseif g:ale_hover_to_preview + call ale#preview#Show(split(a:response.body.displayString, "\n"), { + \ 'filetype': 'ale-preview.message', + \ 'stay_here': 1, + \}) else call ale#util#ShowMessage(a:response.body.displayString) endif @@ -98,6 +103,11 @@ function! ale#hover#HandleLSPResponse(conn_id, response) abort \&& exists('*balloon_show') \&& ale#Var(l:options.buffer, 'set_balloons') call balloon_show(l:str) + elseif g:ale_hover_to_preview + call ale#preview#Show(split(l:str, "\n"), { + \ 'filetype': 'ale-preview.message', + \ 'stay_here': 1, + \}) else call ale#util#ShowMessage(l:str) endif diff --git a/plugin/ale.vim b/plugin/ale.vim index 1912a9c0..8fea3bb4 100644 --- a/plugin/ale.vim +++ b/plugin/ale.vim @@ -125,6 +125,9 @@ let g:ale_close_preview_on_insert = get(g:, 'ale_close_preview_on_insert', 0) " This flag can be set to 0 to disable balloon support. let g:ale_set_balloons = get(g:, 'ale_set_balloons', has('balloon_eval') && has('gui_running')) +" Use preview window for hover messages. +let g:ale_hover_to_preview = get(g:, 'ale_hover_to_preview', 0) + " This flag can be set to 0 to disable warnings for trailing whitespace let g:ale_warn_about_trailing_whitespace = get(g:, 'ale_warn_about_trailing_whitespace', 1) " This flag can be set to 0 to disable warnings for trailing blank lines From f5c289dce68f1592281b5d70539df91d4b3d2821 Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Wed, 16 Oct 2019 11:34:06 -0400 Subject: [PATCH 04/70] Add support for rust-analyzer Fixes #2832 --- ale_linters/rust/analyzer.vim | 24 +++++++++++++++++++ doc/ale-rust.txt | 24 +++++++++++++++++++ doc/ale.txt | 1 + supported-tools.md | 1 + .../test_rust_analyzer_callbacks.vader | 20 ++++++++++++++++ 5 files changed, 70 insertions(+) create mode 100644 ale_linters/rust/analyzer.vim create mode 100644 test/command_callback/test_rust_analyzer_callbacks.vader diff --git a/ale_linters/rust/analyzer.vim b/ale_linters/rust/analyzer.vim new file mode 100644 index 00000000..54a7cb1c --- /dev/null +++ b/ale_linters/rust/analyzer.vim @@ -0,0 +1,24 @@ +" Author: Jon Gjengset +" Description: The next generation language server for Rust + +call ale#Set('rust_analyzer_executable', 'ra_lsp_server') +call ale#Set('rust_analyzer_config', {}) + +function! ale_linters#rust#analyzer#GetCommand(buffer) abort + return '%e' +endfunction + +function! ale_linters#rust#analyzer#GetProjectRoot(buffer) abort + let l:cargo_file = ale#path#FindNearestFile(a:buffer, 'Cargo.toml') + + return !empty(l:cargo_file) ? fnamemodify(l:cargo_file, ':h') : '' +endfunction + +call ale#linter#Define('rust', { +\ 'name': 'rust-analyzer', +\ 'lsp': 'stdio', +\ 'lsp_config': {b -> ale#Var(b, 'rust_analyzer_config')}, +\ 'executable': {b -> ale#Var(b, 'rust_analyzer_executable')}, +\ 'command': function('ale_linters#rust#analyzer#GetCommand'), +\ 'project_root': function('ale_linters#rust#analyzer#GetProjectRoot'), +\}) diff --git a/doc/ale-rust.txt b/doc/ale-rust.txt index 44a79b18..05390225 100644 --- a/doc/ale-rust.txt +++ b/doc/ale-rust.txt @@ -23,6 +23,11 @@ Integration Information over cargo. rls implements the Language Server Protocol for incremental compilation of Rust code, and can check Rust files while you type. `rls` requires Rust files to contained in Cargo projects. + 3. analyzer -- If you have rust-analyzer installed, you might prefer using + this linter over cargo and rls. rust-analyzer also implements the + Language Server Protocol for incremental compilation of Rust code, and is + the next iteration of rls. rust-analyzer, like rls, requires Rust files + to contained in Cargo projects. 4. rustfmt -- If you have `rustfmt` installed, you can use it as a fixer to consistently reformat your Rust code. @@ -190,6 +195,25 @@ g:ale_rust_rls_config *g:ale_rust_rls_config* \ } +=============================================================================== +analyzer *ale-rust-analyzer* + +g:ale_rust_analyzer_executable *g:ale_rust_analyzer_executable* + *b:ale_rust_analyzer_executable* + Type: |String| + Default: `'ra_lsp_server'` + + This variable can be modified to change the executable path for + `rust-analyzer`. + + +g:ale_rust_analyzer_config *g:ale_rust_analyzer_config* + *b:ale_rust_analyzer_config* + Type: |Dictionary| + Default: `{}` + + Dictionary with configuration settings for rust-analyzer. + =============================================================================== rustc *ale-rust-rustc* diff --git a/doc/ale.txt b/doc/ale.txt index 01b6181d..e8716de1 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -2411,6 +2411,7 @@ documented in additional help files. rust....................................|ale-rust-options| cargo.................................|ale-rust-cargo| rls...................................|ale-rust-rls| + rust-analyzer.........................|ale-rust-analyzer| rustc.................................|ale-rust-rustc| rustfmt...............................|ale-rust-rustfmt| sass....................................|ale-sass-options| diff --git a/supported-tools.md b/supported-tools.md index 226baeaf..90dd719f 100644 --- a/supported-tools.md +++ b/supported-tools.md @@ -413,6 +413,7 @@ formatting. * Rust * [cargo](https://github.com/rust-lang/cargo) :floppy_disk: (see `:help ale-integration-rust` for configuration instructions) * [rls](https://github.com/rust-lang-nursery/rls) :warning: + * [rust-analyzer](https://github.com/rust-analyzer/rust-analyzer) :warning: * [rustc](https://www.rust-lang.org/) :warning: * [rustfmt](https://github.com/rust-lang-nursery/rustfmt) * Sass diff --git a/test/command_callback/test_rust_analyzer_callbacks.vader b/test/command_callback/test_rust_analyzer_callbacks.vader new file mode 100644 index 00000000..887cf127 --- /dev/null +++ b/test/command_callback/test_rust_analyzer_callbacks.vader @@ -0,0 +1,20 @@ +Before: + call ale#assert#SetUpLinterTest('rust', 'analyzer') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The default executable path should be correct): + AssertLinter 'analyzer', ale#Escape('ra_lsp_server') + +Execute(The project root should be detected correctly): + AssertLSPProject '' + + call ale#test#SetFilename('rust-rls-project/test.rs') + + AssertLSPProject ale#path#Simplify(g:dir . '/rust-rls-project') + +Execute(Should accept configuration settings): + AssertLSPConfig {} + let b:ale_rust_analyzer_config = {'rust': {'clippy_preference': 'on'}} + AssertLSPConfig {'rust': {'clippy_preference': 'on'}} From 81cb40ce4ba5d7fac7ebd9456f1d06af7fd902a0 Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Wed, 16 Oct 2019 11:54:43 -0400 Subject: [PATCH 05/70] minor test fix --- test/command_callback/test_rust_analyzer_callbacks.vader | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/command_callback/test_rust_analyzer_callbacks.vader b/test/command_callback/test_rust_analyzer_callbacks.vader index 887cf127..55af405b 100644 --- a/test/command_callback/test_rust_analyzer_callbacks.vader +++ b/test/command_callback/test_rust_analyzer_callbacks.vader @@ -5,7 +5,7 @@ After: call ale#assert#TearDownLinterTest() Execute(The default executable path should be correct): - AssertLinter 'analyzer', ale#Escape('ra_lsp_server') + AssertLinter 'ra_lsp_server', ale#Escape('ra_lsp_server') Execute(The project root should be detected correctly): AssertLSPProject '' From d74db90550f061b3609bb9fe9a04b936b1a16a1d Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Wed, 16 Oct 2019 13:44:01 -0400 Subject: [PATCH 06/70] Make TOC match up --- doc/ale.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ale.txt b/doc/ale.txt index e8716de1..28cb7907 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -2411,7 +2411,7 @@ documented in additional help files. rust....................................|ale-rust-options| cargo.................................|ale-rust-cargo| rls...................................|ale-rust-rls| - rust-analyzer.........................|ale-rust-analyzer| + analyzer..............................|ale-rust-analyzer| rustc.................................|ale-rust-rustc| rustfmt...............................|ale-rust-rustfmt| sass....................................|ale-sass-options| From 29d0987859695b60c3515feb45ff45ef6443d5ad Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Wed, 16 Oct 2019 14:01:57 -0400 Subject: [PATCH 07/70] Fix TOC sorting --- doc/ale.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ale.txt b/doc/ale.txt index 28cb7907..01b8f858 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -2409,9 +2409,9 @@ documented in additional help files. sorbet................................|ale-ruby-sorbet| standardrb............................|ale-ruby-standardrb| rust....................................|ale-rust-options| + analyzer..............................|ale-rust-analyzer| cargo.................................|ale-rust-cargo| rls...................................|ale-rust-rls| - analyzer..............................|ale-rust-analyzer| rustc.................................|ale-rust-rustc| rustfmt...............................|ale-rust-rustfmt| sass....................................|ale-sass-options| From 4b53d88cb83951cfd6b246dcf5d7ba0ad2b56d14 Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Wed, 16 Oct 2019 14:03:10 -0400 Subject: [PATCH 08/70] Also list analyzer in doc/ supported tools --- doc/ale-supported-languages-and-tools.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/ale-supported-languages-and-tools.txt b/doc/ale-supported-languages-and-tools.txt index a5b7c35e..2076617b 100644 --- a/doc/ale-supported-languages-and-tools.txt +++ b/doc/ale-supported-languages-and-tools.txt @@ -404,6 +404,7 @@ Notes: * Rust * `cargo`!! * `rls` + * `rust-analyzer` * `rustc` (see |ale-integration-rust|) * `rustfmt` * Sass From fedd3de59f3bea1ecb202250fc1d67a66b0a708f Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Wed, 16 Oct 2019 14:41:04 -0400 Subject: [PATCH 09/70] Place rust sections in alphabetical order --- doc/ale-rust.txt | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/doc/ale-rust.txt b/doc/ale-rust.txt index 05390225..b4efbb1b 100644 --- a/doc/ale-rust.txt +++ b/doc/ale-rust.txt @@ -41,6 +41,25 @@ Integration Information Also note that rustc 1.12. or later is needed. +=============================================================================== +analyzer *ale-rust-analyzer* + +g:ale_rust_analyzer_executable *g:ale_rust_analyzer_executable* + *b:ale_rust_analyzer_executable* + Type: |String| + Default: `'ra_lsp_server'` + + This variable can be modified to change the executable path for + `rust-analyzer`. + + +g:ale_rust_analyzer_config *g:ale_rust_analyzer_config* + *b:ale_rust_analyzer_config* + Type: |Dictionary| + Default: `{}` + + Dictionary with configuration settings for rust-analyzer. + =============================================================================== cargo *ale-rust-cargo* @@ -195,25 +214,6 @@ g:ale_rust_rls_config *g:ale_rust_rls_config* \ } -=============================================================================== -analyzer *ale-rust-analyzer* - -g:ale_rust_analyzer_executable *g:ale_rust_analyzer_executable* - *b:ale_rust_analyzer_executable* - Type: |String| - Default: `'ra_lsp_server'` - - This variable can be modified to change the executable path for - `rust-analyzer`. - - -g:ale_rust_analyzer_config *g:ale_rust_analyzer_config* - *b:ale_rust_analyzer_config* - Type: |Dictionary| - Default: `{}` - - Dictionary with configuration settings for rust-analyzer. - =============================================================================== rustc *ale-rust-rustc* From 9c797961faf8360edf27b40aa7d53a6f9aa0e993 Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Fri, 18 Oct 2019 12:01:31 -0400 Subject: [PATCH 10/70] Make more names match up --- ale_linters/rust/analyzer.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ale_linters/rust/analyzer.vim b/ale_linters/rust/analyzer.vim index 54a7cb1c..b964e4a2 100644 --- a/ale_linters/rust/analyzer.vim +++ b/ale_linters/rust/analyzer.vim @@ -15,7 +15,7 @@ function! ale_linters#rust#analyzer#GetProjectRoot(buffer) abort endfunction call ale#linter#Define('rust', { -\ 'name': 'rust-analyzer', +\ 'name': 'analyzer', \ 'lsp': 'stdio', \ 'lsp_config': {b -> ale#Var(b, 'rust_analyzer_config')}, \ 'executable': {b -> ale#Var(b, 'rust_analyzer_executable')}, From 9017d3ef9ce06a3662f6c87becffa7d7143fb571 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Fri, 26 Jul 2019 11:52:34 -0400 Subject: [PATCH 11/70] Add StandardJS for TypeScript linting and fixing. --- ale_linters/typescript/standard.vim | 30 +++++++++++++ autoload/ale/fix/registry.vim | 5 +++ autoload/ale/fixers/standardts.vim | 24 +++++++++++ doc/ale-typescript.txt | 27 ++++++++++++ doc/ale.txt | 1 + supported-tools.md | 1 + .../test_standardts_command_callback.vader | 43 +++++++++++++++++++ .../test_standardts_fixer_callback.vader | 31 +++++++++++++ 8 files changed, 162 insertions(+) create mode 100644 ale_linters/typescript/standard.vim create mode 100644 autoload/ale/fixers/standardts.vim create mode 100644 test/command_callback/test_standardts_command_callback.vader create mode 100644 test/fixers/test_standardts_fixer_callback.vader diff --git a/ale_linters/typescript/standard.vim b/ale_linters/typescript/standard.vim new file mode 100644 index 00000000..184d9727 --- /dev/null +++ b/ale_linters/typescript/standard.vim @@ -0,0 +1,30 @@ +" Author: Ahmed El Gabri <@ahmedelgabri> +" Description: standardjs for typescript files + +call ale#Set('typescript_standard_executable', 'standard') +call ale#Set('typescript_standard_use_global', get(g:, 'ale_use_global_executables', 0)) +call ale#Set('typescript_standard_options', '') + +function! ale_linters#typescript#standard#GetExecutable(buffer) abort + return ale#node#FindExecutable(a:buffer, 'typescript_standard', [ + \ 'node_modules/standard/bin/cmd.js', + \ 'node_modules/.bin/standard', + \]) +endfunction + +function! ale_linters#typescript#standard#GetCommand(buffer) abort + let l:executable = ale_linters#typescript#standard#GetExecutable(a:buffer) + let l:options = ale#Var(a:buffer, 'typescript_standard_options') + + return ale#node#Executable(a:buffer, l:executable) + \ . (!empty(l:options) ? ' ' . l:options : '') + \ . ' --stdin %s' +endfunction + +" standard uses eslint and the output format is the same +call ale#linter#Define('typescript', { +\ 'name': 'standard', +\ 'executable': function('ale_linters#typescript#standard#GetExecutable'), +\ 'command': function('ale_linters#typescript#standard#GetCommand'), +\ 'callback': 'ale#handlers#eslint#Handle', +\}) diff --git a/autoload/ale/fix/registry.vim b/autoload/ale/fix/registry.vim index 2a96a7d6..4f795dba 100644 --- a/autoload/ale/fix/registry.vim +++ b/autoload/ale/fix/registry.vim @@ -135,6 +135,11 @@ let s:default_registry = { \ 'suggested_filetypes': ['ruby'], \ 'description': 'Fix ruby files with standardrb --fix', \ }, +\ 'standardts': { +\ 'function': 'ale#fixers#standardts#Fix', +\ 'suggested_filetypes': ['typescript'], +\ 'description': 'Fix TypeScript files using standard --fix', +\ }, \ 'stylelint': { \ 'function': 'ale#fixers#stylelint#Fix', \ 'suggested_filetypes': ['css', 'sass', 'scss', 'sugarss', 'stylus'], diff --git a/autoload/ale/fixers/standardts.vim b/autoload/ale/fixers/standardts.vim new file mode 100644 index 00000000..5ab8771d --- /dev/null +++ b/autoload/ale/fixers/standardts.vim @@ -0,0 +1,24 @@ +" Description: Fixing files with Standard for typescript. + +call ale#Set('typescript_standard_executable', 'standard') +call ale#Set('typescript_standard_use_global', get(g:, 'ale_use_global_executables', 0)) +call ale#Set('typescript_standard_options', '') + +function! ale#fixers#standardts#GetExecutable(buffer) abort + return ale#node#FindExecutable(a:buffer, 'typescript_standard', [ + \ 'node_modules/standard/bin/cmd.js', + \ 'node_modules/.bin/standard', + \]) +endfunction + +function! ale#fixers#standardts#Fix(buffer) abort + let l:executable = ale#fixers#standardts#GetExecutable(a:buffer) + let l:options = ale#Var(a:buffer, 'typescript_standard_options') + + return { + \ 'command': ale#node#Executable(a:buffer, l:executable) + \ . (!empty(l:options) ? ' ' . l:options : '') + \ . ' --fix %t', + \ 'read_temporary_file': 1, + \} +endfunction diff --git a/doc/ale-typescript.txt b/doc/ale-typescript.txt index 7dc59820..2c50d119 100644 --- a/doc/ale-typescript.txt +++ b/doc/ale-typescript.txt @@ -16,6 +16,33 @@ prettier *ale-typescript-prettier* See |ale-javascript-prettier| for information about the available options. +=============================================================================== +standard *ale-typescript-standard* + +g:ale_typescript_standard_executable *g:ale_typescript_standard_executable* + *b:ale_typescript_standard_executable* + Type: |String| + Default: `'standard'` + + See |ale-integrations-local-executables| + + +g:ale_typescript_standard_options *g:ale_typescript_standard_options* + *b:ale_typescript_standard_options* + Type: |String| + Default: `''` + + This variable can be set to pass additional options to standard. + + +g:ale_typescript_standard_use_global *g:ale_typescript_standard_use_global* + *b:ale_typescript_standard_use_global* + Type: |Number| + Default: `get(g:, 'ale_use_global_executables', 0)` + + See |ale-integrations-local-executables| + + =============================================================================== tslint *ale-typescript-tslint* diff --git a/doc/ale.txt b/doc/ale.txt index 291e90fb..8b4aabfb 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -2522,6 +2522,7 @@ documented in additional help files. typescript..............................|ale-typescript-options| eslint................................|ale-typescript-eslint| prettier..............................|ale-typescript-prettier| + standard..............................|ale-typescript-standard| tslint................................|ale-typescript-tslint| tsserver..............................|ale-typescript-tsserver| vala....................................|ale-vala-options| diff --git a/supported-tools.md b/supported-tools.md index c302d38c..c52b84eb 100644 --- a/supported-tools.md +++ b/supported-tools.md @@ -475,6 +475,7 @@ formatting. * [eslint](http://eslint.org/) * [fecs](http://fecs.baidu.com/) * [prettier](https://github.com/prettier/prettier) + * [standard](http://standardjs.com/) * [tslint](https://github.com/palantir/tslint) * [tsserver](https://github.com/Microsoft/TypeScript/wiki/Standalone-Server-%28tsserver%29) * typecheck diff --git a/test/command_callback/test_standardts_command_callback.vader b/test/command_callback/test_standardts_command_callback.vader new file mode 100644 index 00000000..d769e712 --- /dev/null +++ b/test/command_callback/test_standardts_command_callback.vader @@ -0,0 +1,43 @@ +Before: + call ale#assert#SetUpLinterTest('typescript', 'standard') + call ale#test#SetFilename('testfile.js') + unlet! b:executable + +After: + call ale#assert#TearDownLinterTest() + +Execute(bin/cmd.js paths should be preferred): + call ale#test#SetFilename('standard-test-files/with-cmd/testfile.js') + + let b:executable = ale#path#Simplify( + \ g:dir + \ . '/standard-test-files/with-cmd/node_modules/standard/bin/cmd.js' + \) + + AssertLinter b:executable, + \ (has('win32') ? 'node.exe ' : '') + \ . ale#Escape(b:executable) + \ . ' --stdin %s' + +Execute(.bin directories should be used too): + call ale#test#SetFilename('standard-test-files/with-bin/testfile.js') + + let b:executable = ale#path#Simplify( + \ g:dir + \ . '/standard-test-files/with-bin/node_modules/.bin/standard' + \) + + AssertLinter b:executable, ale#Escape(b:executable) . ' --stdin %s' + +Execute(The global executable should be used otherwise): + AssertLinter 'standard', ale#Escape('standard') . ' --stdin %s' + +Execute(The global executable should be configurable): + let b:ale_typescript_standard_executable = 'foobar' + + AssertLinter 'foobar', ale#Escape('foobar') . ' --stdin %s' + +Execute(The options should be configurable): + let b:ale_typescript_standard_options = '--wat' + + AssertLinter 'standard', ale#Escape('standard') . ' --wat --stdin %s' diff --git a/test/fixers/test_standardts_fixer_callback.vader b/test/fixers/test_standardts_fixer_callback.vader new file mode 100644 index 00000000..092465f5 --- /dev/null +++ b/test/fixers/test_standardts_fixer_callback.vader @@ -0,0 +1,31 @@ +Before: + call ale#test#SetDirectory('/testplugin/test/fixers') + + unlet! b:ale_typescript_standard_executable + unlet! b:ale_typescript_standard_options + +After: + call ale#test#RestoreDirectory() + +Execute(The executable path should be correct): + call ale#test#SetFilename('../eslint-test-files/react-app/subdir/testfile.js') + + AssertEqual + \ { + \ 'read_temporary_file': 1, + \ 'command': (has('win32') ? 'node.exe ' : '') + \ . ale#Escape(ale#path#Simplify(g:dir . '/../eslint-test-files/react-app/node_modules/standard/bin/cmd.js')) + \ . ' --fix %t', + \ }, + \ ale#fixers#standardts#Fix(bufnr('')) + +Execute(Custom options should be supported): + let b:ale_typescript_standard_use_global = 1 + let b:ale_typescript_standard_options = '--foo-bar' + + AssertEqual + \ { + \ 'read_temporary_file': 1, + \ 'command': ale#Escape('standard') . ' --foo-bar --fix %t', + \ }, + \ ale#fixers#standardts#Fix(bufnr('')) From 79e9ae45507aab97d8f40063cf07a4ea6e69b6f7 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Fri, 26 Jul 2019 12:37:50 -0400 Subject: [PATCH 12/70] Make sure README and docs are synced. --- doc/ale-supported-languages-and-tools.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/ale-supported-languages-and-tools.txt b/doc/ale-supported-languages-and-tools.txt index e2379b70..227b6461 100644 --- a/doc/ale-supported-languages-and-tools.txt +++ b/doc/ale-supported-languages-and-tools.txt @@ -466,6 +466,7 @@ Notes: * `eslint` * `fecs` * `prettier` + * `standard` * `tslint` * `tsserver` * `typecheck` From cf5120ba756b339ef78a285d46814fa13b04aafd Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Mon, 21 Oct 2019 20:23:33 -0400 Subject: [PATCH 13/70] Remove standardts fixer in favor of allowing standard.vim fixer to handle JavaScript or TypeScript options. --- autoload/ale/fix/registry.vim | 5 --- autoload/ale/fixers/standard.vim | 9 +++++- autoload/ale/fixers/standardts.vim | 24 -------------- .../test_standardts_fixer_callback.vader | 31 ------------------- 4 files changed, 8 insertions(+), 61 deletions(-) delete mode 100644 autoload/ale/fixers/standardts.vim delete mode 100644 test/fixers/test_standardts_fixer_callback.vader diff --git a/autoload/ale/fix/registry.vim b/autoload/ale/fix/registry.vim index 4f795dba..2a96a7d6 100644 --- a/autoload/ale/fix/registry.vim +++ b/autoload/ale/fix/registry.vim @@ -135,11 +135,6 @@ let s:default_registry = { \ 'suggested_filetypes': ['ruby'], \ 'description': 'Fix ruby files with standardrb --fix', \ }, -\ 'standardts': { -\ 'function': 'ale#fixers#standardts#Fix', -\ 'suggested_filetypes': ['typescript'], -\ 'description': 'Fix TypeScript files using standard --fix', -\ }, \ 'stylelint': { \ 'function': 'ale#fixers#stylelint#Fix', \ 'suggested_filetypes': ['css', 'sass', 'scss', 'sugarss', 'stylus'], diff --git a/autoload/ale/fixers/standard.vim b/autoload/ale/fixers/standard.vim index 77712d40..731a4f46 100644 --- a/autoload/ale/fixers/standard.vim +++ b/autoload/ale/fixers/standard.vim @@ -14,7 +14,14 @@ endfunction function! ale#fixers#standard#Fix(buffer) abort let l:executable = ale#fixers#standard#GetExecutable(a:buffer) - let l:options = ale#Var(a:buffer, 'javascript_standard_options') + let l:filetype = getbufvar(a:buffer, '&filetype') + let l:options_type = 'javascript_standard_options' + + if l:filetype =~# 'typescript' + let l:options_type = 'typescript_standard_options' + endif + + let l:options = ale#Var(a:buffer, l:options_type) return { \ 'command': ale#node#Executable(a:buffer, l:executable) diff --git a/autoload/ale/fixers/standardts.vim b/autoload/ale/fixers/standardts.vim deleted file mode 100644 index 5ab8771d..00000000 --- a/autoload/ale/fixers/standardts.vim +++ /dev/null @@ -1,24 +0,0 @@ -" Description: Fixing files with Standard for typescript. - -call ale#Set('typescript_standard_executable', 'standard') -call ale#Set('typescript_standard_use_global', get(g:, 'ale_use_global_executables', 0)) -call ale#Set('typescript_standard_options', '') - -function! ale#fixers#standardts#GetExecutable(buffer) abort - return ale#node#FindExecutable(a:buffer, 'typescript_standard', [ - \ 'node_modules/standard/bin/cmd.js', - \ 'node_modules/.bin/standard', - \]) -endfunction - -function! ale#fixers#standardts#Fix(buffer) abort - let l:executable = ale#fixers#standardts#GetExecutable(a:buffer) - let l:options = ale#Var(a:buffer, 'typescript_standard_options') - - return { - \ 'command': ale#node#Executable(a:buffer, l:executable) - \ . (!empty(l:options) ? ' ' . l:options : '') - \ . ' --fix %t', - \ 'read_temporary_file': 1, - \} -endfunction diff --git a/test/fixers/test_standardts_fixer_callback.vader b/test/fixers/test_standardts_fixer_callback.vader deleted file mode 100644 index 092465f5..00000000 --- a/test/fixers/test_standardts_fixer_callback.vader +++ /dev/null @@ -1,31 +0,0 @@ -Before: - call ale#test#SetDirectory('/testplugin/test/fixers') - - unlet! b:ale_typescript_standard_executable - unlet! b:ale_typescript_standard_options - -After: - call ale#test#RestoreDirectory() - -Execute(The executable path should be correct): - call ale#test#SetFilename('../eslint-test-files/react-app/subdir/testfile.js') - - AssertEqual - \ { - \ 'read_temporary_file': 1, - \ 'command': (has('win32') ? 'node.exe ' : '') - \ . ale#Escape(ale#path#Simplify(g:dir . '/../eslint-test-files/react-app/node_modules/standard/bin/cmd.js')) - \ . ' --fix %t', - \ }, - \ ale#fixers#standardts#Fix(bufnr('')) - -Execute(Custom options should be supported): - let b:ale_typescript_standard_use_global = 1 - let b:ale_typescript_standard_options = '--foo-bar' - - AssertEqual - \ { - \ 'read_temporary_file': 1, - \ 'command': ale#Escape('standard') . ' --foo-bar --fix %t', - \ }, - \ ale#fixers#standardts#Fix(bufnr('')) From ea91209a6685faa0275dc5f8735836ced8b08e4b Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Mon, 21 Oct 2019 20:24:22 -0400 Subject: [PATCH 14/70] Allow the use of StandardX for StandardJS linting and fixing. See https://github.com/standard/standardx --- ale_linters/javascript/standard.vim | 1 + ale_linters/typescript/standard.vim | 1 + autoload/ale/fixers/standard.vim | 1 + 3 files changed, 3 insertions(+) diff --git a/ale_linters/javascript/standard.vim b/ale_linters/javascript/standard.vim index 203a803e..1990adce 100644 --- a/ale_linters/javascript/standard.vim +++ b/ale_linters/javascript/standard.vim @@ -7,6 +7,7 @@ call ale#Set('javascript_standard_options', '') function! ale_linters#javascript#standard#GetExecutable(buffer) abort return ale#node#FindExecutable(a:buffer, 'javascript_standard', [ + \ 'node_modules/standardx/bin/cmd.js', \ 'node_modules/standard/bin/cmd.js', \ 'node_modules/semistandard/bin/cmd.js', \ 'node_modules/.bin/standard', diff --git a/ale_linters/typescript/standard.vim b/ale_linters/typescript/standard.vim index 184d9727..da8f14eb 100644 --- a/ale_linters/typescript/standard.vim +++ b/ale_linters/typescript/standard.vim @@ -7,6 +7,7 @@ call ale#Set('typescript_standard_options', '') function! ale_linters#typescript#standard#GetExecutable(buffer) abort return ale#node#FindExecutable(a:buffer, 'typescript_standard', [ + \ 'node_modules/standardx/bin/cmd.js', \ 'node_modules/standard/bin/cmd.js', \ 'node_modules/.bin/standard', \]) diff --git a/autoload/ale/fixers/standard.vim b/autoload/ale/fixers/standard.vim index 731a4f46..cffa9f9d 100644 --- a/autoload/ale/fixers/standard.vim +++ b/autoload/ale/fixers/standard.vim @@ -7,6 +7,7 @@ call ale#Set('javascript_standard_options', '') function! ale#fixers#standard#GetExecutable(buffer) abort return ale#node#FindExecutable(a:buffer, 'javascript_standard', [ + \ 'node_modules/standardx/bin/cmd.js', \ 'node_modules/standard/bin/cmd.js', \ 'node_modules/.bin/standard', \]) From 40890cfcf38a91e75176d39748a7e4ccb24aeb6b Mon Sep 17 00:00:00 2001 From: Jerko Steiner Date: Tue, 22 Oct 2019 16:39:43 -0500 Subject: [PATCH 15/70] Rename ale#fix#SetBufferContents to ale#util#SetBufferContents --- autoload/ale/code_action.vim | 2 +- autoload/ale/fix.vim | 39 +----------------------------------- autoload/ale/util.vim | 37 ++++++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 39 deletions(-) diff --git a/autoload/ale/code_action.vim b/autoload/ale/code_action.vim index 466c023a..60c3bbef 100644 --- a/autoload/ale/code_action.vim +++ b/autoload/ale/code_action.vim @@ -112,7 +112,7 @@ function! ale#code_action#ApplyChanges(filename, changes, should_save) abort if a:should_save call ale#util#Writefile(l:buffer, l:lines, a:filename) else - call ale#fix#SetBufferContents(l:buffer, l:lines) + call ale#util#SetBufferContents(l:buffer, l:lines) endif if l:is_current_buffer diff --git a/autoload/ale/fix.vim b/autoload/ale/fix.vim index 81f5a6d6..d2c1cb98 100644 --- a/autoload/ale/fix.vim +++ b/autoload/ale/fix.vim @@ -12,7 +12,7 @@ function! ale#fix#ApplyQueuedFixes(buffer) abort call remove(g:ale_fix_buffer_data, a:buffer) if l:data.changes_made - let l:new_lines = ale#fix#SetBufferContents(a:buffer, l:data.output) + let l:new_lines = ale#util#SetBufferContents(a:buffer, l:data.output) if l:data.should_save if a:buffer is bufnr('') @@ -46,43 +46,6 @@ function! ale#fix#ApplyQueuedFixes(buffer) abort endif endfunction -" Sets buffer contents to lines -function! ale#fix#SetBufferContents(buffer, lines) abort - let l:has_bufline_api = exists('*deletebufline') && exists('*setbufline') - - if !l:has_bufline_api && a:buffer isnot bufnr('') - return - endif - - " If the file is in DOS mode, we have to remove carriage returns from - " the ends of lines before calling setline(), or we will see them - " twice. - let l:new_lines = getbufvar(a:buffer, '&fileformat') is# 'dos' - \ ? map(copy(a:lines), 'substitute(v:val, ''\r\+$'', '''', '''')') - \ : a:lines - let l:first_line_to_remove = len(l:new_lines) + 1 - - " Use a Vim API for setting lines in other buffers, if available. - if l:has_bufline_api - call setbufline(a:buffer, 1, l:new_lines) - call deletebufline(a:buffer, l:first_line_to_remove, '$') - " Fall back on setting lines the old way, for the current buffer. - else - let l:old_line_length = line('$') - - if l:old_line_length >= l:first_line_to_remove - let l:save = winsaveview() - silent execute - \ l:first_line_to_remove . ',' . l:old_line_length . 'd_' - call winrestview(l:save) - endif - - call setline(1, l:new_lines) - endif - - return l:new_lines -endfunction - function! ale#fix#ApplyFixes(buffer, output) abort let l:data = g:ale_fix_buffer_data[a:buffer] let l:data.output = a:output diff --git a/autoload/ale/util.vim b/autoload/ale/util.vim index 99cd856a..b781971c 100644 --- a/autoload/ale/util.vim +++ b/autoload/ale/util.vim @@ -480,3 +480,40 @@ endfunction function! ale#util#Input(message, value) abort return input(a:message, a:value) endfunction + +" Sets buffer contents to lines +function! ale#util#SetBufferContents(buffer, lines) abort + let l:has_bufline_api = exists('*deletebufline') && exists('*setbufline') + + if !l:has_bufline_api && a:buffer isnot bufnr('') + return + endif + + " If the file is in DOS mode, we have to remove carriage returns from + " the ends of lines before calling setline(), or we will see them + " twice. + let l:new_lines = getbufvar(a:buffer, '&fileformat') is# 'dos' + \ ? map(copy(a:lines), 'substitute(v:val, ''\r\+$'', '''', '''')') + \ : a:lines + let l:first_line_to_remove = len(l:new_lines) + 1 + + " Use a Vim API for setting lines in other buffers, if available. + if l:has_bufline_api + call setbufline(a:buffer, 1, l:new_lines) + call deletebufline(a:buffer, l:first_line_to_remove, '$') + " Fall back on setting lines the old way, for the current buffer. + else + let l:old_line_length = line('$') + + if l:old_line_length >= l:first_line_to_remove + let l:save = winsaveview() + silent execute + \ l:first_line_to_remove . ',' . l:old_line_length . 'd_' + call winrestview(l:save) + endif + + call setline(1, l:new_lines) + endif + + return l:new_lines +endfunction From 0b5fcbad1f304e99187bfdb9767f67e2f19a67f5 Mon Sep 17 00:00:00 2001 From: Donnie West Date: Thu, 17 Oct 2019 21:35:38 -0500 Subject: [PATCH 16/70] Allow the user to set their own completion values --- autoload/ale/completion.vim | 153 ++++++++++++++---- .../test_lsp_completion_parsing.vader | 22 +-- .../test_tsserver_completion_parsing.vader | 10 +- 3 files changed, 142 insertions(+), 43 deletions(-) diff --git a/autoload/ale/completion.vim b/autoload/ale/completion.vim index fb87f1bb..66c456b2 100644 --- a/autoload/ale/completion.vim +++ b/autoload/ale/completion.vim @@ -39,6 +39,109 @@ let s:LSP_COMPLETION_SNIPPET_KIND = 15 let s:LSP_COMPLETION_COLOR_KIND = 16 let s:LSP_COMPLETION_FILE_KIND = 17 let s:LSP_COMPLETION_REFERENCE_KIND = 18 +let s:LSP_COMPLETION_FOLDER_KIND = 19 +let s:LSP_COMPLETION_ENUM_MEMBER_KIND = 20 +let s:LSP_COMPLETION_CONSTANT_KIND = 21 +let s:LSP_COMPLETION_STRUCT_KIND = 22 +let s:LSP_COMPLETION_EVENT_KIND = 23 +let s:LSP_COMPLETION_OPERATOR_KIND = 24 +let s:LSP_COMPLETION_TYPE_PARAMETER_KIND = 25 + +let g:ale_lsp_types = { +\ s:LSP_COMPLETION_TEXT_KIND: 'text', +\ s:LSP_COMPLETION_METHOD_KIND: 'method', +\ s:LSP_COMPLETION_FUNCTION_KIND: 'function', +\ s:LSP_COMPLETION_CONSTRUCTOR_KIND: 'constructor', +\ s:LSP_COMPLETION_FIELD_KIND: 'field', +\ s:LSP_COMPLETION_VARIABLE_KIND: 'variable', +\ s:LSP_COMPLETION_CLASS_KIND: 'class', +\ s:LSP_COMPLETION_INTERFACE_KIND: 'interface', +\ s:LSP_COMPLETION_MODULE_KIND: 'module', +\ s:LSP_COMPLETION_PROPERTY_KIND: 'property', +\ s:LSP_COMPLETION_UNIT_KIND: 'unit', +\ s:LSP_COMPLETION_VALUE_KIND: 'value', +\ s:LSP_COMPLETION_ENUM_KIND: 'enum', +\ s:LSP_COMPLETION_KEYWORD_KIND: 'keyword', +\ s:LSP_COMPLETION_SNIPPET_KIND: 'snippet', +\ s:LSP_COMPLETION_COLOR_KIND: 'color', +\ s:LSP_COMPLETION_FILE_KIND: 'file', +\ s:LSP_COMPLETION_REFERENCE_KIND: 'reference', +\ s:LSP_COMPLETION_FOLDER_KIND: 'folder', +\ s:LSP_COMPLETION_ENUM_MEMBER_KIND: 'enum_member', +\ s:LSP_COMPLETION_CONSTANT_KIND: 'constant', +\ s:LSP_COMPLETION_STRUCT_KIND: 'struct', +\ s:LSP_COMPLETION_EVENT_KIND: 'event', +\ s:LSP_COMPLETION_OPERATOR_KIND: 'operator', +\ s:LSP_COMPLETION_TYPE_PARAMETER_KIND: 'type_parameter', +\ } + +" from https://github.com/microsoft/TypeScript/blob/29becf05012bfa7ba20d50b0d16813971e46b8a6/lib/protocol.d.ts#L2472 +let g:ale_tsserver_types = { +\ 'warning': 'text', +\ 'keyword': 'keyword', +\ 'script': 'file', +\ 'module': 'module', +\ 'class': 'class', +\ 'local class': 'class', +\ 'interface': 'interface', +\ 'type': 'class', +\ 'enum': 'enum', +\ 'enum member': 'enum_member', +\ 'var': 'variable', +\ 'local var': 'variable', +\ 'function': 'function', +\ 'local function': 'function', +\ 'method': 'method', +\ 'getter': 'property', +\ 'setter': 'method', +\ 'property': 'property', +\ 'constructor': 'constructor', +\ 'call': 'method', +\ 'index': 'index', +\ 'construct': 'constructor', +\ 'parameter': 'parameter', +\ 'type parameter': 'type_parameter', +\ 'primitive type': 'unit', +\ 'label': 'text', +\ 'alias': 'class', +\ 'const': 'constant', +\ 'let': 'variable', +\ 'directory': 'folder', +\ 'external module name': 'text', +\ 'JSX attribute': 'parameter', +\ 'string': 'text' +\ } + +" For compatibility reasons, we only use built in VIM completion kinds +" See :help complete-items for Vim completion kinds +let g:ale_completion_symbols = get(g:, 'ale_completion_symbols', { +\ 'text': 'v', +\ 'method': 'f', +\ 'function': 'f', +\ 'constructor': 'f', +\ 'field': 'm', +\ 'variable': 'v', +\ 'class': 't', +\ 'interface': 't', +\ 'module': 'd', +\ 'property': 'm', +\ 'unit': 'v', +\ 'value': 'v', +\ 'enum': 't', +\ 'keyword': 'v', +\ 'snippet': 'v', +\ 'color': 'v', +\ 'file': 'v', +\ 'reference': 'v', +\ 'folder': 'v', +\ 'enum_member': 'm', +\ 'constant': 'm', +\ 'struct': 't', +\ 'event': 'v', +\ 'operator': 'f', +\ 'type_parameter': 'p', +\ '': 'v' +\ }) let s:LSP_INSERT_TEXT_FORMAT_PLAIN = 1 let s:LSP_INSERT_TEXT_FORMAT_SNIPPET = 2 @@ -278,6 +381,27 @@ function! ale#completion#GetAllTriggers() abort return deepcopy(s:trigger_character_map) endfunction +function! ale#completion#GetCompletionKind(kind) abort + let l:lsp_symbol = get(g:ale_lsp_types, a:kind, '') + + if !empty(l:lsp_symbol) + return l:lsp_symbol + endif + + return get(g:ale_tsserver_types, a:kind, '') +endfunction + +function! ale#completion#GetCompletionSymbols(kind) abort + let l:kind = ale#completion#GetCompletionKind(a:kind) + let l:symbol = get(g:ale_completion_symbols, l:kind, '') + + if !empty(l:symbol) + return l:symbol + endif + + return get(g:ale_completion_symbols, '', 'v') +endfunction + function! s:CompletionStillValid(request_id) abort let [l:line, l:column] = getpos('.')[1:2] @@ -329,18 +453,10 @@ function! ale#completion#ParseTSServerCompletionEntryDetails(response) abort call add(l:documentationParts, l:part.text) endfor - if l:suggestion.kind is# 'className' - let l:kind = 'f' - elseif l:suggestion.kind is# 'parameterName' - let l:kind = 'f' - else - let l:kind = 'v' - endif - " See :help complete-items let l:result = { \ 'word': l:suggestion.name, - \ 'kind': l:kind, + \ 'kind': ale#completion#GetCompletionSymbols(l:suggestion.kind), \ 'icase': 1, \ 'menu': join(l:displayParts, ''), \ 'dup': g:ale_completion_tsserver_autoimport, @@ -425,23 +541,6 @@ function! ale#completion#ParseLSPCompletions(response) abort continue endif - " See :help complete-items for Vim completion kinds - if !has_key(l:item, 'kind') - let l:kind = 'v' - elseif l:item.kind is s:LSP_COMPLETION_METHOD_KIND - let l:kind = 'm' - elseif l:item.kind is s:LSP_COMPLETION_CONSTRUCTOR_KIND - let l:kind = 'm' - elseif l:item.kind is s:LSP_COMPLETION_FUNCTION_KIND - let l:kind = 'f' - elseif l:item.kind is s:LSP_COMPLETION_CLASS_KIND - let l:kind = 'f' - elseif l:item.kind is s:LSP_COMPLETION_INTERFACE_KIND - let l:kind = 'f' - else - let l:kind = 'v' - endif - let l:doc = get(l:item, 'documentation', '') if type(l:doc) is v:t_dict && has_key(l:doc, 'value') @@ -450,7 +549,7 @@ function! ale#completion#ParseLSPCompletions(response) abort call add(l:results, { \ 'word': l:word, - \ 'kind': l:kind, + \ 'kind': ale#completion#GetCompletionSymbols(get(l:item, 'kind', '')), \ 'icase': 1, \ 'menu': get(l:item, 'detail', ''), \ 'info': (type(l:doc) is v:t_string ? l:doc : ''), diff --git a/test/completion/test_lsp_completion_parsing.vader b/test/completion/test_lsp_completion_parsing.vader index ef954564..96b92a6e 100644 --- a/test/completion/test_lsp_completion_parsing.vader +++ b/test/completion/test_lsp_completion_parsing.vader @@ -1,7 +1,7 @@ After: unlet! b:ale_completion_info -Execute(Should handle Rust completion results correctly): +Execute(uhould handle Rust completion results correctly): AssertEqual \ [ \ {'word': 'new', 'menu': 'pub fn new() -> String', 'info': '', 'kind': 'f', 'icase': 1}, @@ -17,17 +17,17 @@ Execute(Should handle Rust completion results correctly): \ {'word': 'from_iter', 'menu': 'fn from_iter>(iter: I) -> String', 'info': '', 'kind': 'f', 'icase': 1}, \ {'word': 'from_iter', 'menu': 'fn from_iter>(iter: I) -> String', 'info': '', 'kind': 'f', 'icase': 1}, \ {'word': 'from_iter', 'menu': 'fn from_iter>>(iter: I) -> String', 'info': '', 'kind': 'f', 'icase': 1}, - \ {'word': 'Searcher', 'menu': 'type Searcher = <&''b str as Pattern<''a>>::Searcher;', 'info': '', 'kind': 'f', 'icase': 1}, + \ {'word': 'Searcher', 'menu': 'type Searcher = <&''b str as Pattern<''a>>::Searcher;', 'info': '', 'kind': 't', 'icase': 1}, \ {'word': 'default', 'menu': 'fn default() -> String', 'info': '', 'kind': 'f', 'icase': 1}, - \ {'word': 'Output', 'menu': 'type Output = String;', 'info': '', 'kind': 'f', 'icase': 1}, - \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 'f', 'icase': 1}, - \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 'f', 'icase': 1}, - \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 'f', 'icase': 1}, - \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 'f', 'icase': 1}, - \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 'f', 'icase': 1}, - \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 'f', 'icase': 1}, - \ {'word': 'Target', 'menu': 'type Target = str;', 'info': '', 'kind': 'f', 'icase': 1}, - \ {'word': 'Err', 'menu': 'type Err = ParseError;', 'info': '', 'kind': 'f', 'icase': 1}, + \ {'word': 'Output', 'menu': 'type Output = String;', 'info': '', 'kind': 't', 'icase': 1}, + \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 't', 'icase': 1}, + \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 't', 'icase': 1}, + \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 't', 'icase': 1}, + \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 't', 'icase': 1}, + \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 't', 'icase': 1}, + \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 't', 'icase': 1}, + \ {'word': 'Target', 'menu': 'type Target = str;', 'info': '', 'kind': 't', 'icase': 1}, + \ {'word': 'Err', 'menu': 'type Err = ParseError;', 'info': '', 'kind': 't', 'icase': 1}, \ {'word': 'from_str', 'menu': 'fn from_str(s: &str) -> Result', 'info': '', 'kind': 'f', 'icase': 1}, \ {'word': 'from', 'menu': 'fn from(s: &''a str) -> String', 'info': '', 'kind': 'f', 'icase': 1}, \ {'word': 'from', 'menu': 'fn from(s: Box) -> String', 'info': '', 'kind': 'f', 'icase': 1}, diff --git a/test/completion/test_tsserver_completion_parsing.vader b/test/completion/test_tsserver_completion_parsing.vader index dbb8de32..6beb7b0a 100644 --- a/test/completion/test_tsserver_completion_parsing.vader +++ b/test/completion/test_tsserver_completion_parsing.vader @@ -36,7 +36,7 @@ Execute(TypeScript completion details responses should be parsed correctly): \ 'word': 'abc', \ 'menu': '(property) Foo.abc: number', \ 'info': '', - \ 'kind': 'f', + \ 'kind': 'v', \ 'icase': 1, \ 'dup': g:ale_completion_tsserver_autoimport, \ }, @@ -44,7 +44,7 @@ Execute(TypeScript completion details responses should be parsed correctly): \ 'word': 'def', \ 'menu': '(property) Foo.def: number', \ 'info': 'foo bar baz', - \ 'kind': 'f', + \ 'kind': 'v', \ 'icase': 1, \ 'dup': g:ale_completion_tsserver_autoimport, \ }, @@ -52,7 +52,7 @@ Execute(TypeScript completion details responses should be parsed correctly): \ 'word': 'ghi', \ 'menu': '(class) Foo', \ 'info': '', - \ 'kind': 'f', + \ 'kind': 'v', \ 'icase': 1, \ 'dup': g:ale_completion_tsserver_autoimport, \ }, @@ -124,7 +124,7 @@ Execute(Entries without details should be included in the responses): \ 'word': 'abc', \ 'menu': 'import { def } from "./Foo"; (property) Foo.abc: number', \ 'info': '', - \ 'kind': 'f', + \ 'kind': 'v', \ 'icase': 1, \ 'user_data': json_encode({ \ 'codeActions': [{ @@ -138,7 +138,7 @@ Execute(Entries without details should be included in the responses): \ 'word': 'def', \ 'menu': '(property) Foo.def: number', \ 'info': 'foo bar baz', - \ 'kind': 'f', + \ 'kind': 'v', \ 'icase': 1, \ 'dup': g:ale_completion_tsserver_autoimport, \ }, From 977921461daf3a28f6005142b992e6ca18a06a95 Mon Sep 17 00:00:00 2001 From: Donnie West Date: Thu, 17 Oct 2019 23:39:41 -0500 Subject: [PATCH 17/70] Add documentation for ale-symbols feature --- doc/ale.txt | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/doc/ale.txt b/doc/ale.txt index f1c2efbb..f2f915c8 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -432,7 +432,42 @@ vimrc, and your issues should go away. > set completeopt=menu,menuone,preview,noselect,noinsert < + *ale-symbols* +ALE provides a set of basic completion symbols. If you want to replace those +symbols with others, you can set the variable |g:ale_completion_symbols| with +a mapping of the type of completion to the symbol or other string that you +would like to use. An example here shows the available options for symbols > + + let g:ale_completion_symbols = { + \ 'text': '', + \ 'method': '', + \ 'function': '', + \ 'constructor': '', + \ 'field': '', + \ 'variable': '', + \ 'class': '', + \ 'interface': '', + \ 'module': '', + \ 'property': '', + \ 'unit': 'unit', + \ 'value': 'val', + \ 'enum': '', + \ 'keyword': 'keyword', + \ 'snippet': '', + \ 'color': 'color', + \ 'file': '', + \ 'reference': 'ref', + \ 'folder': '', + \ 'enum member': '', + \ 'constant': '', + \ 'struct': '', + \ 'event': 'event', + \ 'operator': '', + \ 'type_parameter': 'type param', + \ '': 'v' + \ } +< ------------------------------------------------------------------------------- 5.2 Go To Definition *ale-go-to-definition* From 5985f8bd639e85c383f7c894629a0530ccdee9d9 Mon Sep 17 00:00:00 2001 From: Donnie West Date: Fri, 18 Oct 2019 10:48:34 -0500 Subject: [PATCH 18/70] Fix typo --- test/completion/test_lsp_completion_parsing.vader | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/completion/test_lsp_completion_parsing.vader b/test/completion/test_lsp_completion_parsing.vader index 96b92a6e..1fdbbd96 100644 --- a/test/completion/test_lsp_completion_parsing.vader +++ b/test/completion/test_lsp_completion_parsing.vader @@ -1,7 +1,7 @@ After: unlet! b:ale_completion_info -Execute(uhould handle Rust completion results correctly): +Execute(Should handle Rust completion results correctly): AssertEqual \ [ \ {'word': 'new', 'menu': 'pub fn new() -> String', 'info': '', 'kind': 'f', 'icase': 1}, From 6637de46c2230c5bab8f8c1e64ca13b2c7980ec3 Mon Sep 17 00:00:00 2001 From: Donnie West Date: Fri, 18 Oct 2019 10:49:05 -0500 Subject: [PATCH 19/70] Add scriptencoding to `completion.vim` --- autoload/ale/completion.vim | 1 + 1 file changed, 1 insertion(+) diff --git a/autoload/ale/completion.vim b/autoload/ale/completion.vim index 66c456b2..7f9d696b 100644 --- a/autoload/ale/completion.vim +++ b/autoload/ale/completion.vim @@ -1,5 +1,6 @@ " Author: w0rp " Description: Completion support for LSP linters +scriptencoding utf-8 " The omnicompletion menu is shown through a special Plug mapping which is " only valid in Insert mode. This way, feedkeys() won't send these keys if you From e6ee613e001bdf94bd4ba75d03fd8deaf0d0e5b5 Mon Sep 17 00:00:00 2001 From: Donnie West Date: Fri, 18 Oct 2019 13:07:05 -0500 Subject: [PATCH 20/70] Switch variables to dictionary key --- autoload/ale/completion.vim | 76 ++++++++++++------------------------- 1 file changed, 25 insertions(+), 51 deletions(-) diff --git a/autoload/ale/completion.vim b/autoload/ale/completion.vim index 7f9d696b..da24e839 100644 --- a/autoload/ale/completion.vim +++ b/autoload/ale/completion.vim @@ -22,58 +22,32 @@ let s:timer_id = -1 let s:last_done_pos = [] " CompletionItemKind values from the LSP protocol. -let s:LSP_COMPLETION_TEXT_KIND = 1 -let s:LSP_COMPLETION_METHOD_KIND = 2 -let s:LSP_COMPLETION_FUNCTION_KIND = 3 -let s:LSP_COMPLETION_CONSTRUCTOR_KIND = 4 -let s:LSP_COMPLETION_FIELD_KIND = 5 -let s:LSP_COMPLETION_VARIABLE_KIND = 6 -let s:LSP_COMPLETION_CLASS_KIND = 7 -let s:LSP_COMPLETION_INTERFACE_KIND = 8 -let s:LSP_COMPLETION_MODULE_KIND = 9 -let s:LSP_COMPLETION_PROPERTY_KIND = 10 -let s:LSP_COMPLETION_UNIT_KIND = 11 -let s:LSP_COMPLETION_VALUE_KIND = 12 -let s:LSP_COMPLETION_ENUM_KIND = 13 -let s:LSP_COMPLETION_KEYWORD_KIND = 14 -let s:LSP_COMPLETION_SNIPPET_KIND = 15 -let s:LSP_COMPLETION_COLOR_KIND = 16 -let s:LSP_COMPLETION_FILE_KIND = 17 -let s:LSP_COMPLETION_REFERENCE_KIND = 18 -let s:LSP_COMPLETION_FOLDER_KIND = 19 -let s:LSP_COMPLETION_ENUM_MEMBER_KIND = 20 -let s:LSP_COMPLETION_CONSTANT_KIND = 21 -let s:LSP_COMPLETION_STRUCT_KIND = 22 -let s:LSP_COMPLETION_EVENT_KIND = 23 -let s:LSP_COMPLETION_OPERATOR_KIND = 24 -let s:LSP_COMPLETION_TYPE_PARAMETER_KIND = 25 - let g:ale_lsp_types = { -\ s:LSP_COMPLETION_TEXT_KIND: 'text', -\ s:LSP_COMPLETION_METHOD_KIND: 'method', -\ s:LSP_COMPLETION_FUNCTION_KIND: 'function', -\ s:LSP_COMPLETION_CONSTRUCTOR_KIND: 'constructor', -\ s:LSP_COMPLETION_FIELD_KIND: 'field', -\ s:LSP_COMPLETION_VARIABLE_KIND: 'variable', -\ s:LSP_COMPLETION_CLASS_KIND: 'class', -\ s:LSP_COMPLETION_INTERFACE_KIND: 'interface', -\ s:LSP_COMPLETION_MODULE_KIND: 'module', -\ s:LSP_COMPLETION_PROPERTY_KIND: 'property', -\ s:LSP_COMPLETION_UNIT_KIND: 'unit', -\ s:LSP_COMPLETION_VALUE_KIND: 'value', -\ s:LSP_COMPLETION_ENUM_KIND: 'enum', -\ s:LSP_COMPLETION_KEYWORD_KIND: 'keyword', -\ s:LSP_COMPLETION_SNIPPET_KIND: 'snippet', -\ s:LSP_COMPLETION_COLOR_KIND: 'color', -\ s:LSP_COMPLETION_FILE_KIND: 'file', -\ s:LSP_COMPLETION_REFERENCE_KIND: 'reference', -\ s:LSP_COMPLETION_FOLDER_KIND: 'folder', -\ s:LSP_COMPLETION_ENUM_MEMBER_KIND: 'enum_member', -\ s:LSP_COMPLETION_CONSTANT_KIND: 'constant', -\ s:LSP_COMPLETION_STRUCT_KIND: 'struct', -\ s:LSP_COMPLETION_EVENT_KIND: 'event', -\ s:LSP_COMPLETION_OPERATOR_KIND: 'operator', -\ s:LSP_COMPLETION_TYPE_PARAMETER_KIND: 'type_parameter', +\ 1: 'text', +\ 2: 'method', +\ 3: 'function', +\ 4: 'constructor', +\ 5: 'field', +\ 6: 'variable', +\ 7: 'class', +\ 8: 'interface', +\ 9: 'module', +\ 10: 'property', +\ 11: 'unit', +\ 12: 'value', +\ 13: 'enum', +\ 14: 'keyword', +\ 15: 'snippet', +\ 16: 'color', +\ 17: 'file', +\ 18: 'reference', +\ 19: 'folder', +\ 20: 'enum_member', +\ 21: 'constant', +\ 22: 'struct', +\ 23: 'event', +\ 24: 'operator', +\ 25: 'type_parameter', \ } " from https://github.com/microsoft/TypeScript/blob/29becf05012bfa7ba20d50b0d16813971e46b8a6/lib/protocol.d.ts#L2472 From e2a67812de81f9316710ce4ad52c2c461f2a1787 Mon Sep 17 00:00:00 2001 From: Donnie West Date: Tue, 29 Oct 2019 20:12:05 -0500 Subject: [PATCH 21/70] Add tagged entry for symbols to documentation --- doc/ale.txt | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/doc/ale.txt b/doc/ale.txt index f2f915c8..64e8a574 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -706,6 +706,47 @@ g:ale_completion_excluded_words *g:ale_completion_excluded_words* let b:ale_completion_excluded_words = ['it', 'describe'] < +g:ale_completion_symbols *g:ale_completion_symbols* + + Type: |Dictionary| + + + A mapping from completion types to symbols for completions. See + |ale-symbols| for more information. + + By default, this mapping only uses built in Vim completion kinds, but it can + be updated to use any unicode character for the completion kind. For + example: > + let g:ale_completion_symbols = { + \ 'text': '', + \ 'method': '', + \ 'function': '', + \ 'constructor': '', + \ 'field': '', + \ 'variable': '', + \ 'class': '', + \ 'interface': '', + \ 'module': '', + \ 'property': '', + \ 'unit': 'v', + \ 'value': 'v', + \ 'enum': 't', + \ 'keyword': 'v', + \ 'snippet': 'v', + \ 'color': 'v', + \ 'file': 'v', + \ 'reference': 'v', + \ 'folder': 'v', + \ 'enum_member': 'm', + \ 'constant': 'm', + \ 'struct': 't', + \ 'event': 'v', + \ 'operator': 'f', + \ 'type_parameter': 'p', + \ '': 'v' + \ }) +< + g:ale_completion_max_suggestions *g:ale_completion_max_suggestions* Type: |Number| From f09cc26f8793fc65647ed90b61f9845de0e9d126 Mon Sep 17 00:00:00 2001 From: Jesse Harris Date: Sat, 9 Nov 2019 13:43:00 +1000 Subject: [PATCH 22/70] Default errorview in pwsh7 now concise --- ale_linters/powershell/powershell.vim | 1 + 1 file changed, 1 insertion(+) diff --git a/ale_linters/powershell/powershell.vim b/ale_linters/powershell/powershell.vim index a63191fd..5f49f72c 100644 --- a/ale_linters/powershell/powershell.vim +++ b/ale_linters/powershell/powershell.vim @@ -12,6 +12,7 @@ endfunction " https://rkeithhill.wordpress.com/2007/10/30/powershell-quicktip-preparsing-scripts-to-check-for-syntax-errors/ function! ale_linters#powershell#powershell#GetCommand(buffer) abort let l:script = ['Param($Script); + \ $ErrorView = "Normal"; \ trap {$_;continue} & { \ $Contents = Get-Content -Path $Script; \ $Contents = [string]::Join([Environment]::NewLine, $Contents); From abad8e474bf3f096dc96eb4020ab52d35908725d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=B9i=20Th=C3=A0nh=20Nh=C3=A2n?= Date: Sat, 9 Nov 2019 15:34:15 +0700 Subject: [PATCH 23/70] add nimpretty fixer --- autoload/ale/fix/registry.vim | 5 ++++ autoload/ale/fixers/nimpretty.vim | 21 +++++++++++++++ .../test_nimpretty_fixer_callback.vader | 27 +++++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 autoload/ale/fixers/nimpretty.vim create mode 100644 test/fixers/test_nimpretty_fixer_callback.vader diff --git a/autoload/ale/fix/registry.vim b/autoload/ale/fix/registry.vim index 5ec27a10..1b3ca1a8 100644 --- a/autoload/ale/fix/registry.vim +++ b/autoload/ale/fix/registry.vim @@ -54,6 +54,11 @@ let s:default_registry = { \ 'description': 'Apply elm-format to a file.', \ 'aliases': ['format'], \ }, +\ 'nimpretty': { +\ 'function': 'ale#fixers#nimpretty#Fix', +\ 'suggested_filetypes': ['nim'], +\ 'description': 'Apply nimpretty to a file.', +\ }, \ 'eslint': { \ 'function': 'ale#fixers#eslint#Fix', \ 'suggested_filetypes': ['javascript', 'typescript'], diff --git a/autoload/ale/fixers/nimpretty.vim b/autoload/ale/fixers/nimpretty.vim new file mode 100644 index 00000000..be6df470 --- /dev/null +++ b/autoload/ale/fixers/nimpretty.vim @@ -0,0 +1,21 @@ +" Author: Nhan +" Description: Integration of nimpretty with ALE. + +call ale#Set('nim_nimpretty_executable', 'nimpretty') +call ale#Set('nim_nimpretty_options', '--maxLineLen:80') +call ale#Set('nim_nimpretty_use_global', get(g:, 'ale_use_global_executables', 0)) + +function! ale#fixers#nimpretty#GetExecutable(buffer) abort + return ale#node#FindExecutable(a:buffer, 'nim_nimpretty', ['nimpretty']) +endfunction + +function! ale#fixers#nimpretty#Fix(buffer) abort + let l:options = ale#Var(a:buffer, 'nim_nimpretty_options') + + return { + \ 'command': ale#Escape(ale#fixers#nimpretty#GetExecutable(a:buffer)) + \ . ' %t' + \ . (empty(l:options) ? '' : ' ' . l:options), + \ 'read_temporary_file': 1, + \} +endfunction diff --git a/test/fixers/test_nimpretty_fixer_callback.vader b/test/fixers/test_nimpretty_fixer_callback.vader new file mode 100644 index 00000000..b05139f0 --- /dev/null +++ b/test/fixers/test_nimpretty_fixer_callback.vader @@ -0,0 +1,27 @@ +Before: + call ale#assert#SetUpFixerTest('nim', 'nimpretty') + +After: + call ale#test#RestoreDirectory() + +Execute(The nimpretty callback should return the correct default values): + + AssertEqual + \ { + \ 'read_temporary_file': 1, + \ 'command': ale#Escape(g:ale_nim_nimpretty_executable) + \ . ' %t --maxLineLen:80' + \ }, + \ ale#fixers#nimpretty#Fix(bufnr('')) + +Execute(The nimpretty callback should include any additional options): + let g:ale_nim_nimpretty_options = '--some-option' + + AssertEqual + \ { + \ 'read_temporary_file': 1, + \ 'command': ale#Escape(g:ale_nim_nimpretty_executable) + \ . ' %t' + \ . ' --some-option', + \ }, + \ ale#fixers#nimpretty#Fix(bufnr('')) From 9005a62dc2080327a0f2164d765f837e90e963dc Mon Sep 17 00:00:00 2001 From: w0rp Date: Thu, 14 Nov 2019 14:50:16 +0000 Subject: [PATCH 24/70] Clean up the nimpretty code --- autoload/ale/fixers/nimpretty.vim | 10 ++-------- doc/ale-nim.txt | 20 +++++++++++++++++++ doc/ale-supported-languages-and-tools.txt | 1 + doc/ale.txt | 1 + supported-tools.md | 1 + .../test_nimpretty_fixer_callback.vader | 10 +++------- 6 files changed, 28 insertions(+), 15 deletions(-) diff --git a/autoload/ale/fixers/nimpretty.vim b/autoload/ale/fixers/nimpretty.vim index be6df470..fe2e7136 100644 --- a/autoload/ale/fixers/nimpretty.vim +++ b/autoload/ale/fixers/nimpretty.vim @@ -3,19 +3,13 @@ call ale#Set('nim_nimpretty_executable', 'nimpretty') call ale#Set('nim_nimpretty_options', '--maxLineLen:80') -call ale#Set('nim_nimpretty_use_global', get(g:, 'ale_use_global_executables', 0)) - -function! ale#fixers#nimpretty#GetExecutable(buffer) abort - return ale#node#FindExecutable(a:buffer, 'nim_nimpretty', ['nimpretty']) -endfunction function! ale#fixers#nimpretty#Fix(buffer) abort + let l:executable = ale#Var(a:buffer, 'nim_nimpretty_executable') let l:options = ale#Var(a:buffer, 'nim_nimpretty_options') return { - \ 'command': ale#Escape(ale#fixers#nimpretty#GetExecutable(a:buffer)) - \ . ' %t' - \ . (empty(l:options) ? '' : ' ' . l:options), + \ 'command': ale#Escape(l:executable) . ' %t' . ale#Pad(l:options), \ 'read_temporary_file': 1, \} endfunction diff --git a/doc/ale-nim.txt b/doc/ale-nim.txt index ad7aa686..8985aeb8 100644 --- a/doc/ale-nim.txt +++ b/doc/ale-nim.txt @@ -21,5 +21,25 @@ g:nim_nimlsp_nim_sources *g:nim_nimlsp_nim_sources* command. +=============================================================================== +nimpretty *ale-nim-nimpretty* + + +g:ale_nim_nimpretty_executable *g:ale_nim_nimpretty_executable* + *b:ale_nim_nimpretty_executable* + Type: |String| + Default: `'nimpretty'` + + This variable can be changed to use a different executable for nimpretty. + + +g:ale_nim_nimpretty_options *g:ale_nim_nimpretty_options* + *b:ale_nim_nimpretty_options* + Type: |String| + Default: `'--maxLineLen:80'` + + This variable can be changed to modify flags given to nimpretty. + + =============================================================================== vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl: diff --git a/doc/ale-supported-languages-and-tools.txt b/doc/ale-supported-languages-and-tools.txt index de1be1a2..29dabab7 100644 --- a/doc/ale-supported-languages-and-tools.txt +++ b/doc/ale-supported-languages-and-tools.txt @@ -284,6 +284,7 @@ Notes: * Nim * `nim check`!! * `nimlsp` + * `nimpretty` * nix * `nix-instantiate` * `nixpkgs-fmt` diff --git a/doc/ale.txt b/doc/ale.txt index 515c5f2c..593aae11 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -2361,6 +2361,7 @@ documented in additional help files. nim.....................................|ale-nim-options| nimcheck..............................|ale-nim-nimcheck| nimlsp................................|ale-nim-nimlsp| + nimpretty.............................|ale-nim-nimpretty| nix.....................................|ale-nix-options| nixpkgs-fmt...........................|ale-nix-nixpkgs-fmt| nroff...................................|ale-nroff-options| diff --git a/supported-tools.md b/supported-tools.md index 5a3376d4..0abc6b75 100644 --- a/supported-tools.md +++ b/supported-tools.md @@ -293,6 +293,7 @@ formatting. * Nim * [nim check](https://nim-lang.org/docs/nimc.html) :floppy_disk: * [nimlsp](https://github.com/PMunch/nimlsp) + * nimpretty * nix * [nix-instantiate](http://nixos.org/nix/manual/#sec-nix-instantiate) * [nixpkgs-fmt](https://github.com/nix-community/nixpkgs-fmt) diff --git a/test/fixers/test_nimpretty_fixer_callback.vader b/test/fixers/test_nimpretty_fixer_callback.vader index b05139f0..a26f649a 100644 --- a/test/fixers/test_nimpretty_fixer_callback.vader +++ b/test/fixers/test_nimpretty_fixer_callback.vader @@ -2,15 +2,13 @@ Before: call ale#assert#SetUpFixerTest('nim', 'nimpretty') After: - call ale#test#RestoreDirectory() + call ale#assert#TearDownFixerTest() Execute(The nimpretty callback should return the correct default values): - AssertEqual \ { \ 'read_temporary_file': 1, - \ 'command': ale#Escape(g:ale_nim_nimpretty_executable) - \ . ' %t --maxLineLen:80' + \ 'command': ale#Escape('nimpretty') . ' %t --maxLineLen:80' \ }, \ ale#fixers#nimpretty#Fix(bufnr('')) @@ -20,8 +18,6 @@ Execute(The nimpretty callback should include any additional options): AssertEqual \ { \ 'read_temporary_file': 1, - \ 'command': ale#Escape(g:ale_nim_nimpretty_executable) - \ . ' %t' - \ . ' --some-option', + \ 'command': ale#Escape('nimpretty') . ' %t --some-option' \ }, \ ale#fixers#nimpretty#Fix(bufnr('')) From 31715ff22768a87be2b8db592be5e7eb499ced30 Mon Sep 17 00:00:00 2001 From: Aaron Franks <25241+af@users.noreply.github.com> Date: Sun, 24 Nov 2019 15:47:07 -0800 Subject: [PATCH 25/70] Fix for incorrect eslint output parsing for graphql files The output is configured to be JSON, but the handler was parsing it as 'lines' --- ale_linters/graphql/eslint.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ale_linters/graphql/eslint.vim b/ale_linters/graphql/eslint.vim index 654b8c17..aed1a371 100644 --- a/ale_linters/graphql/eslint.vim +++ b/ale_linters/graphql/eslint.vim @@ -5,5 +5,5 @@ call ale#linter#Define('graphql', { \ 'name': 'eslint', \ 'executable': function('ale#handlers#eslint#GetExecutable'), \ 'command': function('ale#handlers#eslint#GetCommand'), -\ 'callback': 'ale#handlers#eslint#Handle', +\ 'callback': 'ale#handlers#eslint#HandleJSON', \}) From 5f95d032ee4eec6399c131c1cca124ef98d28e7e Mon Sep 17 00:00:00 2001 From: Horacio Sanson Date: Tue, 26 Nov 2019 13:37:25 +0900 Subject: [PATCH 26/70] Fix 2891 - eslint not showing errors. ESLint errors are contained in an array that can contain different stuff other than JSON error messages. This patch iterates over the whole array ignoring any non-json data. --- autoload/ale/handlers/eslint.vim | 13 ++++++++----- test/handler/test_eslint_json_handler.vader | 20 ++++++++++++++++++-- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/autoload/ale/handlers/eslint.vim b/autoload/ale/handlers/eslint.vim index 4d533ff2..7ef63785 100644 --- a/autoload/ale/handlers/eslint.vim +++ b/autoload/ale/handlers/eslint.vim @@ -84,11 +84,14 @@ function! s:CheckForBadConfig(buffer, lines) abort endfunction function! s:parseJSON(buffer, lines) abort - try - let l:parsed = json_decode(a:lines[-1]) - catch - return [] - endtry + let l:parsed = [] + + for l:line in a:lines + try + let l:parsed = extend(l:parsed, json_decode(l:line)) + catch + endtry + endfor if type(l:parsed) != v:t_list || empty(l:parsed) return [] diff --git a/test/handler/test_eslint_json_handler.vader b/test/handler/test_eslint_json_handler.vader index 8e07bd80..6235794a 100644 --- a/test/handler/test_eslint_json_handler.vader +++ b/test/handler/test_eslint_json_handler.vader @@ -21,6 +21,7 @@ After: unlet! g:config_error_lines Execute(The eslint handler should parse json correctly): + call ale#test#SetFilename('foo.js') AssertEqual \ [ \ { @@ -53,6 +54,21 @@ Execute(The eslint handler should parse json correctly): \ '[{"filePath":"foo.js","messages":[{"ruleId":"no-unused-vars","severity":1,"message":"''variable'' is assigned a value but never used.","line":1,"column":7,"nodeType":"Identifier","endLine":1,"endColumn":15},{"ruleId":"semi","severity":1,"message":"Missing semicolon.","line":5,"column":15,"nodeType":"ExpressionStatement","fix":{"range":[46,46],"text":";"}},{"ruleId":"no-redeclare","severity":2,"message":"''variable'' is already defined.","line":7,"column":7,"nodeType":"Identifier","endLine":7,"endColumn":15}],"errorCount":1,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":1,"source":"const variable = {\n a: 3\n};\n\nconsole.log(1)\n\nclass variable {\n}\n"}]' \ ]) +Execute(The eslint handler should suppress deprecation warnings): + call ale#test#SetFilename('foo.js') + AssertEqual + \ [ + \ { + \ 'lnum': 1, + \ 'col': 9, + \ 'text': 'Parsing error: Unexpected token Controller', + \ 'type': 'E', + \ } + \ ], + \ ale#handlers#eslint#HandleJSON(bufnr(''), [ + \ '[{"filePath":"foo.js","messages":[{"ruleId":null,"fatal":true,"severity":2 ,"message":"Parsing error: Unexpected token Controller","line":1,"column":9}],"errorCount":1,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount": 0,"source":"i:mport Controller from \"@ember/controller\";\nimport listViewControllerMixin from \"elearning/mixins/list-view-controller\";\nimport { inject as service } from \"@ember/service\";\n\nexport default Controller.extend(listViewControllerMixin(), {\n modelName: \"notification\",\n intl: service(),\n\n flatpickrLocale: computed(\"intl.locale\", function() {\n return this.intl.locale.firstObject.split(\"-\")[0];\n })\n});\n"}]', '(node:616989) [ESLINT_LEGACY_OBJECT_REST_SPREAD] DeprecationWarning: The ''parserOptions.ecmaFeatures.experimentalObjectRestSpread'' option is deprecated. Use ''parser Options.ecmaVersion'' instead. (found in "node_modules/eslint-plugin-ember/lib/config/base.js")]' + \ ]) + Execute(The eslint handler should print a message about a missing configuration file): let g:config_error_lines = [ \ '', @@ -262,7 +278,7 @@ Execute(Suppressing missing configs shouldn't suppress module import errors): \ ale#handlers#eslint#HandleJSON(bufnr(''), g:config_error_lines[:]) Execute(The eslint handler should hint about using typescript-eslint-parser): - silent! noautocmd file foo.ts + call ale#test#SetFilename('foo.ts') AssertEqual \ [ @@ -326,7 +342,7 @@ Execute(Failing to connect to eslint_d should be handled correctly): \ ]) Execute(Disabling warnings about trailing spaces should work): - silent! noautocmd file foo.ts + call ale#test#SetFilename('foo.js') AssertEqual \ [ From 5f84325cd811ec179b7f3642652438c6a45b174d Mon Sep 17 00:00:00 2001 From: w0rp Date: Tue, 3 Dec 2019 11:47:26 +0000 Subject: [PATCH 27/70] Add a Help Wanted message in case people are interested --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 1488d756..14bc58ef 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,10 @@ If you don't care about Language Server Protocol, ALE won't load any of the code for working with it unless needed. One of ALE's general missions is that you won't pay for the features that you don't use. +**Help Wanted:** If you would like to help maintain this plugin by managing the +many issues and pull requests that are submitted, please send the author an +email at [dev@w0rp.com](mailto:dev@w0rp.com?subject=Helping%20with%20ALE). + If you enjoy this plugin, feel free to contribute or check out the author's other content at [w0rp.com](https://w0rp.com). From 715733f44def5e162d90184ae12886c54adeeb5b Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Wed, 11 Dec 2019 12:01:28 -0500 Subject: [PATCH 28/70] Fix Rust linter/fixer listing --- doc/ale-rust.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/ale-rust.txt b/doc/ale-rust.txt index b4efbb1b..2e0f3474 100644 --- a/doc/ale-rust.txt +++ b/doc/ale-rust.txt @@ -9,7 +9,7 @@ Integration Information files for Rust distributed in Vim >=8.0.0501 or upstream: https://github.com/rust-lang/rust.vim - Note that there are three possible linters for Rust files: + Note that there are several possible linters and fixers for Rust files: 1. rustc -- The Rust compiler is used to check the currently edited file. So, if your project consists of multiple files, you will get some errors @@ -23,12 +23,12 @@ Integration Information over cargo. rls implements the Language Server Protocol for incremental compilation of Rust code, and can check Rust files while you type. `rls` requires Rust files to contained in Cargo projects. - 3. analyzer -- If you have rust-analyzer installed, you might prefer using + 4. analyzer -- If you have rust-analyzer installed, you might prefer using this linter over cargo and rls. rust-analyzer also implements the Language Server Protocol for incremental compilation of Rust code, and is the next iteration of rls. rust-analyzer, like rls, requires Rust files to contained in Cargo projects. - 4. rustfmt -- If you have `rustfmt` installed, you can use it as a fixer to + 5. rustfmt -- If you have `rustfmt` installed, you can use it as a fixer to consistently reformat your Rust code. Only cargo is enabled by default. To switch to using rustc instead of cargo, From 9ee57d4362918b7b21d5b22eb46a33a32f44ccda Mon Sep 17 00:00:00 2001 From: Kevin Locke Date: Tue, 17 Dec 2019 10:43:09 -0700 Subject: [PATCH 29/70] Run ESLint from project root dir where possible ESLint 6 loads all plugins/configs/parsers relative to the project root which, by default, is the directory in which ESLint is invoked, as described in [ESLint RFC 2018-simplified-package-loading]. Therefore, ALE should run ESLint from the project root, when possible, so that dependencies will load. This commit does so. [ESLint RFC 2018-simplified-package-loading]: https://github.com/eslint/rfcs/blob/master/designs/2018-simplified-package-loading/README.md Fixes: #2787 Signed-off-by: Kevin Locke --- autoload/ale/handlers/eslint.vim | 13 ++++++++++++- test/test_eslint_executable_detection.vader | 16 ++++++++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/autoload/ale/handlers/eslint.vim b/autoload/ale/handlers/eslint.vim index 7ef63785..156b939f 100644 --- a/autoload/ale/handlers/eslint.vim +++ b/autoload/ale/handlers/eslint.vim @@ -42,7 +42,18 @@ function! ale#handlers#eslint#GetCommand(buffer) abort let l:options = ale#Var(a:buffer, 'javascript_eslint_options') - return ale#node#Executable(a:buffer, l:executable) + " ESLint 6 loads plugins/configs/parsers from the project root + " By default, the project root is simply the CWD of the running process. + " https://github.com/eslint/rfcs/blob/master/designs/2018-simplified-package-loading/README.md + " https://github.com/dense-analysis/ale/issues/2787 + " Identify project root from presence of node_modules dir. + " Note: If node_modules not present yet, can't load local deps anyway. + let l:modules_dir = ale#path#FindNearestDirectory(a:buffer, 'node_modules') + let l:project_dir = !empty(l:modules_dir) ? fnamemodify(l:modules_dir, ':h:h') : '' + let l:cd_command = !empty(l:project_dir) ? ale#path#CdString(l:project_dir) : '' + + return l:cd_command + \ . ale#node#Executable(a:buffer, l:executable) \ . (!empty(l:options) ? ' ' . l:options : '') \ . ' -f json --stdin --stdin-filename %s' endfunction diff --git a/test/test_eslint_executable_detection.vader b/test/test_eslint_executable_detection.vader index 64383dcb..c2071131 100644 --- a/test/test_eslint_executable_detection.vader +++ b/test/test_eslint_executable_detection.vader @@ -57,13 +57,25 @@ Execute(eslint.js executables should be run with node on Windows): " We have to execute the file with node. if has('win32') AssertEqual - \ ale#Escape('node.exe') . ' ' + \ ale#path#CdString(ale#path#Simplify(g:dir . '/eslint-test-files/react-app')) + \ . ale#Escape('node.exe') . ' ' \ . ale#Escape(ale#path#Simplify(g:dir . '/eslint-test-files/react-app/node_modules/eslint/bin/eslint.js')) \ . ' -f json --stdin --stdin-filename %s', \ ale#handlers#eslint#GetCommand(bufnr('')) else AssertEqual - \ ale#Escape(ale#path#Simplify(g:dir . '/eslint-test-files/react-app/node_modules/eslint/bin/eslint.js')) + \ ale#path#CdString(ale#path#Simplify(g:dir . '/eslint-test-files/react-app')) + \ . ale#Escape(ale#path#Simplify(g:dir . '/eslint-test-files/react-app/node_modules/eslint/bin/eslint.js')) \ . ' -f json --stdin --stdin-filename %s', \ ale#handlers#eslint#GetCommand(bufnr('')) endif + +Execute(eslint.js executables can be run outside project dir): + " Set filename above eslint-test-files (which contains node_modules) + call ale#test#SetFilename('testfile.js') + + " cd "..." not present, since project root not found (from node_modules) + AssertEqual + \ ale#Escape(ale#handlers#eslint#GetExecutable(bufnr(''))) + \ . ' -f json --stdin --stdin-filename %s', + \ ale#handlers#eslint#GetCommand(bufnr('')) From 4cbe16197cbcdc3752aad6e596c6f910b8cff63c Mon Sep 17 00:00:00 2001 From: Zander Lee Date: Sun, 22 Dec 2019 09:35:29 +0100 Subject: [PATCH 30/70] Allow popup to be used instead of preview in completeopt --- autoload/ale/completion.vim | 2 ++ 1 file changed, 2 insertions(+) diff --git a/autoload/ale/completion.vim b/autoload/ale/completion.vim index da24e839..d18de59d 100644 --- a/autoload/ale/completion.vim +++ b/autoload/ale/completion.vim @@ -261,6 +261,8 @@ function! s:ReplaceCompletionOptions() abort if &l:completeopt =~# 'preview' let &l:completeopt = 'menu,menuone,preview,noselect,noinsert' + elseif &l:completeopt =~# 'popup' + let &l:completeopt = 'menu,menuone,popup,noselect,noinsert' else let &l:completeopt = 'menu,menuone,noselect,noinsert' endif From 493705336c06e47df70c194c4aabb2a927e36d81 Mon Sep 17 00:00:00 2001 From: Jerko Steiner Date: Sun, 29 Dec 2019 15:08:22 +0100 Subject: [PATCH 31/70] Add old check for bufline api --- autoload/ale/fix.vim | 2 +- autoload/ale/util.vim | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/autoload/ale/fix.vim b/autoload/ale/fix.vim index d2c1cb98..69817b36 100644 --- a/autoload/ale/fix.vim +++ b/autoload/ale/fix.vim @@ -5,7 +5,7 @@ call ale#Set('fix_on_save_ignore', {}) function! ale#fix#ApplyQueuedFixes(buffer) abort let l:data = get(g:ale_fix_buffer_data, a:buffer, {'done': 0}) - if !l:data.done + if !l:data.done || (!ale#util#HasBuflineApi() && a:buffer isnot bufnr('')) return endif diff --git a/autoload/ale/util.vim b/autoload/ale/util.vim index b781971c..b7594167 100644 --- a/autoload/ale/util.vim +++ b/autoload/ale/util.vim @@ -481,9 +481,13 @@ function! ale#util#Input(message, value) abort return input(a:message, a:value) endfunction +function! ale#util#HasBuflineApi() abort + return exists('*deletebufline') && exists('*setbufline') +endfunction + " Sets buffer contents to lines function! ale#util#SetBufferContents(buffer, lines) abort - let l:has_bufline_api = exists('*deletebufline') && exists('*setbufline') + let l:has_bufline_api = ale#util#HasBuflineApi() if !l:has_bufline_api && a:buffer isnot bufnr('') return From 8148a67b377050c7d60e5fd0aa46e0b4781edd6e Mon Sep 17 00:00:00 2001 From: w0rp Date: Wed, 1 Jan 2020 18:25:04 +0000 Subject: [PATCH 32/70] Documented g:ale_hover_to_preview --- doc/ale.txt | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/doc/ale.txt b/doc/ale.txt index 847a9777..e58b01bf 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -525,6 +525,9 @@ the mouse over a symbol in a buffer. Diagnostic information will take priority over hover information for balloons. If a line contains a problem, that problem will be displayed in a balloon instead of hover information. +Hover information can be displayed in the preview window instead by setting +|g:ale_hover_to_preview| to `1`. + For Vim 8.1+ terminals, mouse hovering is disabled by default. Enabling |balloonexpr| commands in terminals can cause scrolling issues in terminals, so ALE will not attempt to show balloons unless |g:ale_set_balloons| is set to @@ -1023,6 +1026,16 @@ g:ale_history_log_output *g:ale_history_log_output* if you want to save on some memory usage. +g:ale_hover_to_preview *g:ale_hover_to_preview* + *b:ale_hover_to_preview* + + Type: |Number| + Default: `0` + + If set to `1`, hover messages will be displayed in the preview window, + instead of in balloons or the message line. + + g:ale_keep_list_window_open *g:ale_keep_list_window_open* *b:ale_keep_list_window_open* Type: |Number| @@ -1337,7 +1350,7 @@ b:ale_loclist_msg_format *b:ale_loclist_msg_format* The strings for configuring `%severity%` are also used for this option. -g:ale_lsp_show_message_format *g:ale_lsp_show_message_format* +g:ale_lsp_show_message_format *g:ale_lsp_show_message_format* Type: |String| Default: `'%severity%:%linter%: %s'` @@ -1359,7 +1372,7 @@ g:ale_lsp_show_message_format *g:ale_lsp_show_message_ separately for each buffer like |g:ale_echo_msg_format| can. -g:ale_lsp_show_message_severity *g:ale_lsp_show_message_severity* +g:ale_lsp_show_message_severity *g:ale_lsp_show_message_severity* Type: |String| Default: `'error'` From 874c98b96d913299fd61b3125211d299b012572c Mon Sep 17 00:00:00 2001 From: w0rp Date: Wed, 1 Jan 2020 18:48:58 +0000 Subject: [PATCH 33/70] Make it more obvious you can use popup in completeopt now --- doc/ale.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/ale.txt b/doc/ale.txt index e58b01bf..eafbc119 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -432,6 +432,11 @@ vimrc, and your issues should go away. > set completeopt=menu,menuone,preview,noselect,noinsert < + +Or alternatively, if you want to show documentation in popups: > + + set completeopt=menu,menuone,popup,noselect,noinsert +< *ale-symbols* ALE provides a set of basic completion symbols. If you want to replace those From 0cb432cb825e80c5a6f6dc9bc9c52a38f9b45319 Mon Sep 17 00:00:00 2001 From: Jerko Steiner Date: Wed, 1 Jan 2020 20:00:41 +0100 Subject: [PATCH 34/70] Add TypeScript autoimport support for deoplete (#2779) * Add autoimport support for deoplete * Fix test_deoplete_source.py * Use callback instead of is_async for deoplete Shuogo, the author of Deoplete, does not recommend using the `is_async` option: > I think is_async is not recommended. It is not so useful and broken. > You should use callback system instead. Link: https://github.com/Shougo/deoplete.nvim/issues/1006#issuecomment-526797857 Incidentally, the same thread mentiones an issue started by w0rp: https://github.com/Shougo/deoplete.nvim/issues/976 The deoplete docs also say is_async is deprecated: > is_async (Bool) > If the gather is asynchronous, the source must set > it to "True". A typical strategy for an asynchronous > gather_candidates method to use this flag is to > set is_async flag to True while results are being > produced in the background (optionally, returning them > as they become ready). Once background processing > has completed, is_async flag should be set to False > indicating that this is the last portion of the > candidates. > > Note: The feature is deprecated and not recommended. > You should use callback system by > |deoplete#auto_complete()| instead. Link: https://github.com/Shougo/deoplete.nvim/blob/master/doc/deoplete.txt Co-authored-by: w0rp --- autoload/ale/completion.vim | 5 +- rplugin/python3/deoplete/sources/ale.py | 22 +++--- test/completion/test_completion_events.vader | 6 +- test/python/test_deoplete_source.py | 72 ++++++-------------- 4 files changed, 34 insertions(+), 71 deletions(-) diff --git a/autoload/ale/completion.vim b/autoload/ale/completion.vim index d18de59d..80684a30 100644 --- a/autoload/ale/completion.vim +++ b/autoload/ale/completion.vim @@ -388,7 +388,6 @@ function! s:CompletionStillValid(request_id) abort \&& b:ale_completion_info.line == l:line \&& ( \ b:ale_completion_info.column == l:column - \ || b:ale_completion_info.source is# 'deoplete' \ || b:ale_completion_info.source is# 'ale-omnifunc' \ || b:ale_completion_info.source is# 'ale-callback' \) @@ -805,7 +804,9 @@ endfunction function! ale#completion#HandleUserData(completed_item) abort let l:source = get(get(b:, 'ale_completion_info', {}), 'source', '') - if l:source isnot# 'ale-automatic' && l:source isnot# 'ale-manual' && l:source isnot# 'ale-callback' + if l:source isnot# 'ale-automatic' + \&& l:source isnot# 'ale-manual' + \&& l:source isnot# 'ale-callback' return endif diff --git a/rplugin/python3/deoplete/sources/ale.py b/rplugin/python3/deoplete/sources/ale.py index 3955ed2d..ae1f4039 100644 --- a/rplugin/python3/deoplete/sources/ale.py +++ b/rplugin/python3/deoplete/sources/ale.py @@ -24,6 +24,7 @@ class Source(Base): self.rank = 1000 self.is_bytepos = True self.min_pattern_length = 1 + self.is_volatile = True # Do not forget to update s:trigger_character_map in completion.vim in # updating entries in this map. self.input_patterns = { @@ -44,21 +45,16 @@ class Source(Base): if not self.vim.call('ale#completion#CanProvideCompletions'): return None - if context.get('is_refresh'): - context['is_async'] = False + event = context.get('event') - if context['is_async']: - # Result is the same as for omnifunc, or None. + if event == 'Async': result = self.vim.call('ale#completion#GetCompletionResult') + return result or [] - if result is not None: - context['is_async'] = False - - return result - else: - context['is_async'] = True - - # Request some completion results. - self.vim.call('ale#completion#GetCompletions', 'deoplete') + if context.get('is_refresh'): + self.vim.command( + "call ale#completion#GetCompletions('ale-callback', " + \ + "{'callback': {completions -> deoplete#auto_complete() }})" + ) return [] diff --git a/test/completion/test_completion_events.vader b/test/completion/test_completion_events.vader index d70fefeb..2ac2b15c 100644 --- a/test/completion/test_completion_events.vader +++ b/test/completion/test_completion_events.vader @@ -233,7 +233,7 @@ Execute(ale#completion#Show() should make the correct feedkeys() call for manual AssertEqual [["\(ale_show_completion_menu)"]], g:feedkeys_calls Execute(ale#completion#Show() should not call feedkeys() for other sources): - let b:ale_completion_info = {'source': 'deoplete'} + let b:ale_completion_info = {'source': 'other-source'} call ale#completion#Show([{'word': 'x', 'kind': 'v', 'icase': 1}]) sleep 1ms @@ -334,7 +334,7 @@ Execute(b:ale_completion_info should be set up correctly when requesting complet Execute(b:ale_completion_info should be set up correctly for other sources): let b:ale_completion_result = [] call setpos('.', [bufnr(''), 3, 14, 0]) - call ale#completion#GetCompletions('deoplete') + call ale#completion#GetCompletions('ale-callback') AssertEqual \ { @@ -344,7 +344,7 @@ Execute(b:ale_completion_info should be set up correctly for other sources): \ 'line_length': 14, \ 'line': 3, \ 'prefix': 'ab', - \ 'source': 'deoplete', + \ 'source': 'ale-callback', \ }, \ b:ale_completion_info Assert !exists('b:ale_completion_result') diff --git a/test/python/test_deoplete_source.py b/test/python/test_deoplete_source.py index 9e56a10d..8304fa25 100644 --- a/test/python/test_deoplete_source.py +++ b/test/python/test_deoplete_source.py @@ -8,15 +8,20 @@ ale_module = imp.load_source( class VimMock(object): - def __init__(self, call_list, call_results): + def __init__(self, call_list, call_results, commands): self.__call_list = call_list self.__call_results = call_results + self.__commands = commands + def call(self, function, *args): self.__call_list.append((function, args)) return self.__call_results.get(function, 0) + def command(self, command): + self.__commands.append(command) + class DeopleteSourceTest(unittest.TestCase): def setUp(self): @@ -24,8 +29,10 @@ class DeopleteSourceTest(unittest.TestCase): self.call_list = [] self.call_results = {'ale#completion#CanProvideCompletions': 1} + self.commands = [] self.source = ale_module.Source('vim') - self.source.vim = VimMock(self.call_list, self.call_results) + self.source.vim = VimMock( + self.call_list, self.call_results, self.commands) def test_attributes(self): """ @@ -48,6 +55,7 @@ class DeopleteSourceTest(unittest.TestCase): 'cpp': r'(\.|::|->)\w*$', }, 'is_bytepos': True, + 'is_volatile': True, 'mark': '[L]', 'min_pattern_length': 1, 'name': 'ale', @@ -64,70 +72,28 @@ class DeopleteSourceTest(unittest.TestCase): ]) def test_request_completion_results(self): - context = {'is_async': False} + context = {'event': 'TextChangedI', 'is_refresh': True} self.assertEqual(self.source.gather_candidates(context), []) - self.assertEqual(context, {'is_async': True}) self.assertEqual(self.call_list, [ ('ale#completion#CanProvideCompletions', ()), - ('ale#completion#GetCompletions', ('deoplete',)), + ]) + self.assertEqual(self.commands, [ + "call ale#completion#GetCompletions('ale-callback', " + \ + "{'callback': {completions -> deoplete#auto_complete() }})" ]) def test_request_completion_results_from_buffer_without_providers(self): self.call_results['ale#completion#CanProvideCompletions'] = 0 - context = {'is_async': False} + context = {'event': 'TextChangedI', 'is_refresh': True} self.assertIsNone(self.source.gather_candidates(context), []) - self.assertEqual(context, {'is_async': False}) self.assertEqual(self.call_list, [ ('ale#completion#CanProvideCompletions', ()), ]) - def test_refresh_completion_results(self): - context = {'is_async': False} - - self.assertEqual(self.source.gather_candidates(context), []) - self.assertEqual(context, {'is_async': True}) - self.assertEqual(self.call_list, [ - ('ale#completion#CanProvideCompletions', ()), - ('ale#completion#GetCompletions', ('deoplete',)), - ]) - - context = {'is_async': True, 'is_refresh': True} - - self.assertEqual(self.source.gather_candidates(context), []) - self.assertEqual(context, {'is_async': True, 'is_refresh': True}) - self.assertEqual(self.call_list, [ - ('ale#completion#CanProvideCompletions', ()), - ('ale#completion#GetCompletions', ('deoplete',)), - ('ale#completion#CanProvideCompletions', ()), - ('ale#completion#GetCompletions', ('deoplete',)), - ]) - - def test_poll_no_result(self): - context = {'is_async': True} - self.call_results['ale#completion#GetCompletionResult'] = None - - self.assertEqual(self.source.gather_candidates(context), []) - self.assertEqual(context, {'is_async': True}) - self.assertEqual(self.call_list, [ - ('ale#completion#CanProvideCompletions', ()), - ('ale#completion#GetCompletionResult', ()), - ]) - - def test_poll_empty_result_ready(self): - context = {'is_async': True} - self.call_results['ale#completion#GetCompletionResult'] = [] - - self.assertEqual(self.source.gather_candidates(context), []) - self.assertEqual(context, {'is_async': False}) - self.assertEqual(self.call_list, [ - ('ale#completion#CanProvideCompletions', ()), - ('ale#completion#GetCompletionResult', ()), - ]) - - def test_poll_non_empty_result_ready(self): - context = {'is_async': True} + def test_async_event(self): + context = {'event': 'Async', 'is_refresh': True} self.call_results['ale#completion#GetCompletionResult'] = [ { 'word': 'foobar', @@ -147,7 +113,7 @@ class DeopleteSourceTest(unittest.TestCase): 'info': '', }, ]) - self.assertEqual(context, {'is_async': False}) + self.assertEqual(self.call_list, [ ('ale#completion#CanProvideCompletions', ()), ('ale#completion#GetCompletionResult', ()), From 8c4c8dfd97b6a7d24b490f8645d7c54461c45d52 Mon Sep 17 00:00:00 2001 From: w0rp Date: Thu, 2 Jan 2020 14:19:21 +0000 Subject: [PATCH 35/70] Fix #2704 - Show mypy notes; can be disabled --- ale_linters/python/mypy.vim | 14 +++++++++++-- doc/ale-python.txt | 30 ++++++++++++++++++---------- test/handler/test_mypy_handler.vader | 27 +++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 12 deletions(-) diff --git a/ale_linters/python/mypy.vim b/ale_linters/python/mypy.vim index dc4044e6..d4778e40 100644 --- a/ale_linters/python/mypy.vim +++ b/ale_linters/python/mypy.vim @@ -3,6 +3,7 @@ call ale#Set('python_mypy_executable', 'mypy') call ale#Set('python_mypy_ignore_invalid_syntax', 0) +call ale#Set('python_mypy_show_notes', 1) call ale#Set('python_mypy_options', '') call ale#Set('python_mypy_use_global', get(g:, 'ale_use_global_executables', 0)) call ale#Set('python_mypy_auto_pipenv', 0) @@ -51,7 +52,16 @@ function! ale_linters#python#mypy#Handle(buffer, lines) abort " Lines like these should be ignored below: " " file.py:4: note: (Stub files are from https://github.com/python/typeshed) - let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):?(\d+)?: (error|warning): (.+)$' + + let l:types = 'error|warning' + + if ale#Var(a:buffer, 'python_mypy_show_notes') + let l:types = 'error|warning|note' + endif + + let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):?(\d+)?: (' + \ . l:types + \ . '): (.+)$' let l:output = [] for l:match in ale#util#GetMatches(a:lines, l:pattern) @@ -65,7 +75,7 @@ function! ale_linters#python#mypy#Handle(buffer, lines) abort \ 'filename': ale#path#GetAbsPath(l:dir, l:match[1]), \ 'lnum': l:match[2] + 0, \ 'col': l:match[3] + 0, - \ 'type': l:match[4] is# 'error' ? 'E' : 'W', + \ 'type': l:match[4] is# 'error' ? 'E' : (l:match[4] is# 'note' ? 'I': 'W'), \ 'text': l:match[5], \}) endfor diff --git a/doc/ale-python.txt b/doc/ale-python.txt index 9d5846d2..93f1d668 100644 --- a/doc/ale-python.txt +++ b/doc/ale-python.txt @@ -145,8 +145,8 @@ g:ale_python_black_use_global *g:ale_python_black_use_global* See |ale-integrations-local-executables| -g:ale_python_black_auto_pipenv *g:ale_python_black_auto_pipenv* - *b:ale_python_black_auto_pipenv* +g:ale_python_black_auto_pipenv *g:ale_python_black_auto_pipenv* + *b:ale_python_black_auto_pipenv* Type: |Number| Default: `0` @@ -263,6 +263,15 @@ to check for errors while you type. `mypy` will be run from a detected project root, per |ale-python-root|. +g:ale_python_mypy_auto_pipenv *g:ale_python_mypy_auto_pipenv* + *b:ale_python_mypy_auto_pipenv* + Type: |Number| + Default: `0` + + Detect whether the file is inside a pipenv, and set the executable to `pipenv` + if true. This is overridden by a manually-set executable. + + g:ale_python_mypy_executable *g:ale_python_mypy_executable* *b:ale_python_mypy_executable* Type: |String| @@ -272,6 +281,7 @@ g:ale_python_mypy_executable *g:ale_python_mypy_executable* Set this to `'pipenv'` to invoke `'pipenv` `run` `mypy'`. + g:ale_python_mypy_ignore_invalid_syntax *g:ale_python_mypy_ignore_invalid_syntax* *b:ale_python_mypy_ignore_invalid_syntax* @@ -292,6 +302,14 @@ g:ale_python_mypy_options *g:ale_python_mypy_options* invocation. +g:ale_python_mypy_show_notes *g:ale_python_mypy_show_notes* + *b:ale_python_mypy_show_notes* + Type: |Number| + Default: `1` + + If enabled, notes on lines will be displayed as 'I' (info) messages. + + g:ale_python_mypy_use_global *g:ale_python_mypy_use_global* *b:ale_python_mypy_use_global* Type: |Number| @@ -300,14 +318,6 @@ g:ale_python_mypy_use_global *g:ale_python_mypy_use_global* See |ale-integrations-local-executables| -g:ale_python_mypy_auto_pipenv *g:ale_python_mypy_auto_pipenv* - *b:ale_python_mypy_auto_pipenv* - Type: |Number| - Default: `0` - - Detect whether the file is inside a pipenv, and set the executable to `pipenv` - if true. This is overridden by a manually-set executable. - =============================================================================== prospector *ale-python-prospector* diff --git a/test/handler/test_mypy_handler.vader b/test/handler/test_mypy_handler.vader index 6e96f3f3..58d2b69e 100644 --- a/test/handler/test_mypy_handler.vader +++ b/test/handler/test_mypy_handler.vader @@ -1,6 +1,8 @@ Before: Save g:ale_python_mypy_ignore_invalid_syntax + Save g:ale_python_mypy_show_notes + unlet! g:ale_python_mypy_show_notes unlet! g:ale_python_mypy_ignore_invalid_syntax runtime ale_linters/python/mypy.vim @@ -69,6 +71,31 @@ Execute(The mypy handler should parse lines correctly): \ '__init__.py:72:1: warning: Some warning', \ ]) +Execute(The mypy handler should show notes if enabled): + call ale#test#SetFilename('__init__.py') + + AssertEqual + \ [ + \ { + \ 'lnum': 72, + \ 'col': 1, + \ 'filename': ale#path#Simplify(g:dir . '/__init__.py'), + \ 'type': 'I', + \ 'text': 'A note', + \ }, + \ ], + \ ale_linters#python#mypy#Handle(bufnr(''), [ + \ '__init__.py:72:1: note: A note', + \ ]) + + let g:ale_python_mypy_show_notes = 0 + + AssertEqual + \ [], + \ ale_linters#python#mypy#Handle(bufnr(''), [ + \ '__init__.py:72:1: note: A note', + \ ]) + Execute(The mypy handler should handle Windows names with spaces): " This test works on Unix, where this is seen as a single filename silent file C:\\something\\with\ spaces.py From 57eba1afacc5c0889767d85c8304066ac91856b5 Mon Sep 17 00:00:00 2001 From: w0rp Date: Thu, 2 Jan 2020 14:23:28 +0000 Subject: [PATCH 36/70] Fix the build --- test/handler/test_mypy_handler.vader | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/handler/test_mypy_handler.vader b/test/handler/test_mypy_handler.vader index 58d2b69e..039155a2 100644 --- a/test/handler/test_mypy_handler.vader +++ b/test/handler/test_mypy_handler.vader @@ -18,6 +18,8 @@ After: Execute(The mypy handler should parse lines correctly): call ale#test#SetFilename('__init__.py') + let g:ale_python_mypy_show_notes = 0 + AssertEqual \ [ \ { From 72d2c55479c29e550c27f20e903c882dcc68639b Mon Sep 17 00:00:00 2001 From: Harry Percival Date: Thu, 2 Jan 2020 14:35:21 +0000 Subject: [PATCH 37/70] Mypy: try to find folder containing mypy.ini to use as cwd. (#2385) * When deciding which directory to run mypy from, prefer a folder with mypy.ini in it * Add a test for mypy.ini-finding behaviour --- ale_linters/python/mypy.vim | 9 +++++++++ .../python_paths/with_mypy_ini_and_pytest_ini/mypy.ini | 0 .../with_mypy_ini_and_pytest_ini/tests/pytest.ini | 0 .../tests/testsubfolder/my_tests.py | 0 test/command_callback/test_mypy_command_callback.vader | 9 +++++++++ 5 files changed, 18 insertions(+) create mode 100644 test/command_callback/python_paths/with_mypy_ini_and_pytest_ini/mypy.ini create mode 100644 test/command_callback/python_paths/with_mypy_ini_and_pytest_ini/tests/pytest.ini create mode 100644 test/command_callback/python_paths/with_mypy_ini_and_pytest_ini/tests/testsubfolder/my_tests.py diff --git a/ale_linters/python/mypy.vim b/ale_linters/python/mypy.vim index d4778e40..94dfae7d 100644 --- a/ale_linters/python/mypy.vim +++ b/ale_linters/python/mypy.vim @@ -19,6 +19,15 @@ endfunction " The directory to change to before running mypy function! s:GetDir(buffer) abort + " If we find a directory with "mypy.ini" in it use that, + " else try and find the "python project" root, or failing + " that, run from the same folder as the current file + for l:path in ale#path#Upwards(expand('#' . a:buffer . ':p:h')) + if filereadable(l:path . '/mypy.ini') + return l:path + endif + endfor + let l:project_root = ale#python#FindProjectRoot(a:buffer) return !empty(l:project_root) diff --git a/test/command_callback/python_paths/with_mypy_ini_and_pytest_ini/mypy.ini b/test/command_callback/python_paths/with_mypy_ini_and_pytest_ini/mypy.ini new file mode 100644 index 00000000..e69de29b diff --git a/test/command_callback/python_paths/with_mypy_ini_and_pytest_ini/tests/pytest.ini b/test/command_callback/python_paths/with_mypy_ini_and_pytest_ini/tests/pytest.ini new file mode 100644 index 00000000..e69de29b diff --git a/test/command_callback/python_paths/with_mypy_ini_and_pytest_ini/tests/testsubfolder/my_tests.py b/test/command_callback/python_paths/with_mypy_ini_and_pytest_ini/tests/testsubfolder/my_tests.py new file mode 100644 index 00000000..e69de29b diff --git a/test/command_callback/test_mypy_command_callback.vader b/test/command_callback/test_mypy_command_callback.vader index 8ca35207..afa9f9af 100644 --- a/test/command_callback/test_mypy_command_callback.vader +++ b/test/command_callback/test_mypy_command_callback.vader @@ -52,6 +52,15 @@ Execute(The mypy callbacks should detect virtualenv directories and switch to th \ . ' --show-column-numbers ' \ . '--shadow-file %s %t %s' +Execute(The mypy callbacks should cd to directory containing mypy.ini if found): + silent execute 'file ' . fnameescape(g:dir . '/python_paths/with_mypy_ini_and_pytest_ini/tests/testsubfolder/my_tests.py') + + AssertLinter 'mypy', + \ ale#path#CdString(ale#path#Simplify(g:dir . '/python_paths/with_mypy_ini_and_pytest_ini')) + \ . ale#Escape('mypy') + \ . ' --show-column-numbers ' + \ . '--shadow-file %s %t %s' + Execute(You should able able to use the global mypy instead): silent execute 'file ' . fnameescape(g:dir . '/python_paths/with_virtualenv/subdir/foo/bar.py') let g:ale_python_mypy_use_global = 1 From 07ee4d39c5f14a0a389a9317035188852362406f Mon Sep 17 00:00:00 2001 From: Andrew Lee Date: Tue, 28 Jan 2020 10:47:37 -0800 Subject: [PATCH 38/70] misc: change email address for @ndrewtl This is kind of a peculiar reason for a PR, but I no longer control the email listed. I want to change it to avoid people getting the wrong email for me. Also, I still control the domain, but if at any point I don't, I want to put down in writing that if you get an email from this, it's not from me. --- autoload/ale/ant.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/ale/ant.vim b/autoload/ale/ant.vim index 689b444b..7d02484e 100644 --- a/autoload/ale/ant.vim +++ b/autoload/ale/ant.vim @@ -1,4 +1,4 @@ -" Author: Andrew Lee . +" Author: Andrew Lee . " Inspired by ale/gradle.vim by Michael Pardo " Description: Functions for working with Ant projects. From 8012809c3f30a767db8395c5b8e3651cdb995635 Mon Sep 17 00:00:00 2001 From: w0rp Date: Sat, 22 Feb 2020 10:26:03 +0000 Subject: [PATCH 39/70] Add default labels to issue templates --- .github/ISSUE_TEMPLATE/report-a-bug.md | 1 + .github/ISSUE_TEMPLATE/suggest-a-new-linter-or-fixer.md | 1 + .github/ISSUE_TEMPLATE/suggest-an-improvement.md | 1 + 3 files changed, 3 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/report-a-bug.md b/.github/ISSUE_TEMPLATE/report-a-bug.md index 6d345c4a..4169029d 100644 --- a/.github/ISSUE_TEMPLATE/report-a-bug.md +++ b/.github/ISSUE_TEMPLATE/report-a-bug.md @@ -1,5 +1,6 @@ --- name: Report a bug +labels: bug about: Report a bug with ALE. --- diff --git a/.github/ISSUE_TEMPLATE/suggest-a-new-linter-or-fixer.md b/.github/ISSUE_TEMPLATE/suggest-a-new-linter-or-fixer.md index 75c7637f..ad235e57 100644 --- a/.github/ISSUE_TEMPLATE/suggest-a-new-linter-or-fixer.md +++ b/.github/ISSUE_TEMPLATE/suggest-a-new-linter-or-fixer.md @@ -1,5 +1,6 @@ --- name: Suggest a new linter or fixer +labels: new tool about: Suggest a new tool ALE can officially integrate with. --- diff --git a/.github/ISSUE_TEMPLATE/suggest-an-improvement.md b/.github/ISSUE_TEMPLATE/suggest-an-improvement.md index 855a6493..d39d0ac8 100644 --- a/.github/ISSUE_TEMPLATE/suggest-an-improvement.md +++ b/.github/ISSUE_TEMPLATE/suggest-an-improvement.md @@ -1,5 +1,6 @@ --- name: Suggest an improvement +labels: enhancement about: Suggest some way to improve ALE, or add a new feature. --- From 634c81fd465269f59e3db878fe8405828e6d2da9 Mon Sep 17 00:00:00 2001 From: w0rp Date: Tue, 25 Feb 2020 13:50:44 +0000 Subject: [PATCH 40/70] Mention using 'hidden' in combination with ALEGoToDefinition --- doc/ale.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/ale.txt b/doc/ale.txt index eafbc119..0d92d6d9 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -2715,6 +2715,10 @@ ALEGoToDefinition *ALEGoToDefinition* You can jump back to the position you were at before going to the definition of something with jump motions like CTRL-O. See |jump-motions|. + You should consider using the 'hidden' option in combination with this + command. Otherwise, Vim will refuse to leave the buffer you're jumping from + unless you have saved your edits. + A plug mapping `(ale_go_to_definition)` is defined for this command. From 8f7ccdc5e95302223c516a0113f5af7e075dc041 Mon Sep 17 00:00:00 2001 From: w0rp Date: Wed, 4 Mar 2020 20:56:22 +0000 Subject: [PATCH 41/70] Refactor the "s:LoadArgCount()" function (#3025) * Refactor the "s:LoadArgCount()" function Previously, this function would always set "v:errmsg" on the first call with a given function. This is because autoloaded functions are not defined on the first call. A number of improvements have been made: - a useless local function ("l:Function") is removed - the "execute()" builtin captures the output, instead of ":redir" - a ":try" block handles the case where a function is not defined - a useless ":if" is removed since ":redir" always defines the var - confusing quoting is re-written (remove double "'" chars) Fixes: #3021 --- autoload/ale/util.vim | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/autoload/ale/util.vim b/autoload/ale/util.vim index 99cd856a..8d166625 100644 --- a/autoload/ale/util.vim +++ b/autoload/ale/util.vim @@ -336,15 +336,11 @@ function! ale#util#GetMatches(lines, patterns) abort endfunction function! s:LoadArgCount(function) abort - let l:Function = a:function - - redir => l:output - silent! function Function - redir END - - if !exists('l:output') + try + let l:output = execute('function a:function') + catch /E123/ return 0 - endif + endtry let l:match = matchstr(split(l:output, "\n")[0], '\v\([^)]+\)')[1:-2] let l:arg_list = filter(split(l:match, ', '), 'v:val isnot# ''...''') From 46d7ee564fcc496e0e6681a657ccad4cb7c2838c Mon Sep 17 00:00:00 2001 From: Tho Nguyen Duc Date: Fri, 6 Mar 2020 13:44:30 +0900 Subject: [PATCH 42/70] Fix 3011 - not catching kotlinc output on stderr --- ale_linters/kotlin/kotlinc.vim | 1 + 1 file changed, 1 insertion(+) diff --git a/ale_linters/kotlin/kotlinc.vim b/ale_linters/kotlin/kotlinc.vim index 3c6854fa..66c075be 100644 --- a/ale_linters/kotlin/kotlinc.vim +++ b/ale_linters/kotlin/kotlinc.vim @@ -174,6 +174,7 @@ endfunction call ale#linter#Define('kotlin', { \ 'name': 'kotlinc', \ 'executable': 'kotlinc', +\ 'output_stream': 'stderr', \ 'command': function('ale_linters#kotlin#kotlinc#RunWithImportPaths'), \ 'callback': 'ale_linters#kotlin#kotlinc#Handle', \ 'lint_file': 1, From bbe5153fcb36dec9860ced33ae8ff0b5d76ac02a Mon Sep 17 00:00:00 2001 From: w0rp Date: Wed, 11 Mar 2020 12:52:41 -0400 Subject: [PATCH 43/70] Fixes #2982 - Implement g:ale_exclude_highlights Particular highlights can now be excluded by providing Lists of regular expressions. --- autoload/ale/highlight.vim | 6 ++++++ doc/ale.txt | 17 +++++++++++++++++ plugin/ale.vim | 3 +++ test/test_highlight_placement.vader | 21 +++++++++++++++++++++ 4 files changed, 47 insertions(+) diff --git a/autoload/ale/highlight.vim b/autoload/ale/highlight.vim index 82ad57e0..473ad354 100644 --- a/autoload/ale/highlight.vim +++ b/autoload/ale/highlight.vim @@ -210,6 +210,12 @@ function! ale#highlight#SetHighlights(buffer, loclist) abort " Set the list in the buffer variable. call setbufvar(str2nr(a:buffer), 'ale_highlight_items', l:new_list) + let l:exclude_list = ale#Var(a:buffer, 'exclude_highlights') + + if !empty(l:exclude_list) + call filter(l:new_list, 'empty(ale#util#GetMatches(v:val.text, l:exclude_list))') + endif + " Update highlights for the current buffer, which may or may not " be the buffer we just set highlights for. call ale#highlight#UpdateHighlights() diff --git a/doc/ale.txt b/doc/ale.txt index 0d92d6d9..da4328d9 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -923,6 +923,21 @@ g:ale_enabled *g:ale_enabled* See |g:ale_pattern_options| for more information on that option. +g:ale_exclude_highlights *g:ale_exclude_highlights* +b:ale_exclude_highlights *b:ale_exclude_highlights* + + Type: |List| + Default: `[]` + + A list of regular expressions for matching against highlight messages to + remove. For example: > + + " Do not highlight messages matching strings like these. + let b:ale_exclude_highlights = ['line too long', 'foo.*bar'] +< + See also: |g:ale_set_highlights| + + g:ale_fixers *g:ale_fixers* *b:ale_fixers* @@ -1609,6 +1624,8 @@ g:ale_set_highlights *g:ale_set_highlights* match highlights, whereas the line highlights when signs are enabled will run to the edge of the screen. + Highlights can be excluded with the |g:ale_exclude_highlights| option. + g:ale_set_loclist *g:ale_set_loclist* diff --git a/plugin/ale.vim b/plugin/ale.vim index 8fea3bb4..19c86ea6 100644 --- a/plugin/ale.vim +++ b/plugin/ale.vim @@ -109,6 +109,9 @@ let g:ale_set_signs = get(g:, 'ale_set_signs', has('signs')) " This flag can be set to 0 to disable setting error highlights. let g:ale_set_highlights = get(g:, 'ale_set_highlights', has('syntax')) +" This List can be configured to exclude particular highlights. +let g:ale_exclude_highlights = get(g:, 'ale_exclude_highlights', []) + " This flag can be set to 0 to disable echoing when the cursor moves. let g:ale_echo_cursor = get(g:, 'ale_echo_cursor', 1) diff --git a/test/test_highlight_placement.vader b/test/test_highlight_placement.vader index 3b259655..dab73073 100644 --- a/test/test_highlight_placement.vader +++ b/test/test_highlight_placement.vader @@ -7,6 +7,8 @@ Before: Save g:ale_set_loclist Save g:ale_set_quickfix Save g:ale_set_signs + Save g:ale_exclude_highlights + Save b:ale_exclude_highlights runtime autoload/ale/highlight.vim @@ -20,6 +22,8 @@ Before: let g:ale_set_quickfix = 0 let g:ale_set_loclist = 0 let g:ale_echo_cursor = 0 + let g:ale_exclude_highlights = [] + let b:ale_exclude_highlights = [] function! GenerateResults(buffer, output) return [ @@ -363,6 +367,23 @@ Execute(Highlights should always be cleared when the buffer highlight list is em \ GetMatchesWithoutIDs() endif +Execute(Highlights should be hidden when excluded): + let b:ale_exclude_highlights = ['ig.*ore', 'nope'] + + call ale#highlight#SetHighlights(bufnr('%'), [ + \ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 1, 'col': 1, 'text': 'hello'}, + \ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 2, 'col': 1, 'text': 'ignore'}, + \ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 3, 'col': 1, 'text': 'nope'}, + \ {'bufnr': bufnr('%'), 'type': 'E', 'lnum': 4, 'col': 1, 'text': 'world'}, + \]) + + AssertEqual + \ [ + \ {'group': 'ALEError', 'priority': 10, 'pos1': [1, 1, 1]}, + \ {'group': 'ALEError', 'priority': 10, 'pos1': [4, 1, 1]}, + \ ], + \ GetMatchesWithoutIDs() + Execute(Highlights should be cleared when ALE is disabled): let g:ale_enabled = 1 call ale#highlight#SetHighlights(bufnr(''), [ From 302ce71931e961e8588ea2e475b1714081ee1831 Mon Sep 17 00:00:00 2001 From: StarryLeo Date: Sun, 15 Mar 2020 14:58:38 +0800 Subject: [PATCH 44/70] Fix vim sign priority patch check With Vim 8.2 released, the previous check method is not accurate enough. --- autoload/ale/sign.vim | 2 +- test/sign/test_linting_sets_signs.vader | 2 +- test/sign/test_sign_parsing.vader | 14 +++++++------- test/sign/test_sign_placement.vader | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/autoload/ale/sign.vim b/autoload/ale/sign.vim index db0e1ab6..8109c60e 100644 --- a/autoload/ale/sign.vim +++ b/autoload/ale/sign.vim @@ -23,7 +23,7 @@ let g:ale_sign_offset = get(g:, 'ale_sign_offset', 1000000) let g:ale_sign_column_always = get(g:, 'ale_sign_column_always', 0) let g:ale_sign_highlight_linenrs = get(g:, 'ale_sign_highlight_linenrs', 0) -let s:supports_sign_groups = has('nvim-0.4.2') || (v:version >= 801 && has('patch614')) +let s:supports_sign_groups = has('nvim-0.4.2') || has('patch-8.1.614') if !hlexists('ALEErrorSign') highlight link ALEErrorSign error diff --git a/test/sign/test_linting_sets_signs.vader b/test/sign/test_linting_sets_signs.vader index 60ae0a83..1d1f9802 100644 --- a/test/sign/test_linting_sets_signs.vader +++ b/test/sign/test_linting_sets_signs.vader @@ -32,7 +32,7 @@ Before: function! CollectSigns() redir => l:output - if has('nvim-0.4.2') || (v:version >= 801 && has('patch614')) + if has('nvim-0.4.2') || has('patch-8.1.614') silent exec 'sign place group=ale' else silent exec 'sign place' diff --git a/test/sign/test_sign_parsing.vader b/test/sign/test_sign_parsing.vader index 157ff2f4..c0967f43 100644 --- a/test/sign/test_sign_parsing.vader +++ b/test/sign/test_sign_parsing.vader @@ -1,5 +1,5 @@ Execute (Parsing English signs should work): - if has('nvim-0.4.2') || (v:version >= 801 && has('patch614')) + if has('nvim-0.4.2') || has('patch-8.1.614') AssertEqual \ [0, [[9, 1000001, 'ALEWarningSign']]], \ ale#sign#ParseSigns([ @@ -16,7 +16,7 @@ Execute (Parsing English signs should work): endif Execute (Parsing Russian signs should work): - if has('nvim-0.4.2') || (v:version >= 801 && has('patch614')) + if has('nvim-0.4.2') || has('patch-8.1.614') AssertEqual \ [0, [[1, 1000001, 'ALEErrorSign']]], \ ale#sign#ParseSigns([' строка=1 id=1000001 группа=ale имя=ALEErrorSign']) @@ -27,7 +27,7 @@ Execute (Parsing Russian signs should work): endif Execute (Parsing Japanese signs should work): - if has('nvim-0.4.2') || (v:version >= 801 && has('patch614')) + if has('nvim-0.4.2') || has('patch-8.1.614') AssertEqual \ [0, [[1, 1000001, 'ALEWarningSign']]], \ ale#sign#ParseSigns([' 行=1 識別子=1000001 グループ=ale 名前=ALEWarningSign']) @@ -38,7 +38,7 @@ Execute (Parsing Japanese signs should work): endif Execute (Parsing Spanish signs should work): - if has('nvim-0.4.2') || (v:version >= 801 && has('patch614')) + if has('nvim-0.4.2') || has('patch-8.1.614') AssertEqual \ [0, [[12, 1000001, 'ALEWarningSign']]], \ ale#sign#ParseSigns([' línea=12 id=1000001 grupo=ale nombre=ALEWarningSign']) @@ -49,7 +49,7 @@ Execute (Parsing Spanish signs should work): endif Execute (Parsing Italian signs should work): - if has('nvim-0.4.2') || (v:version >= 801 && has('patch614')) + if has('nvim-0.4.2') || has('patch-8.1.614') AssertEqual \ [0, [[1, 1000001, 'ALEWarningSign']]], \ ale#sign#ParseSigns([' riga=1 id=1000001, gruppo=ale nome=ALEWarningSign']) @@ -60,7 +60,7 @@ Execute (Parsing Italian signs should work): endif Execute (Parsing German signs should work): - if has('nvim-0.4.2') || (v:version >= 801 && has('patch614')) + if has('nvim-0.4.2') || has('patch-8.1.614') AssertEqual \ [0, [[235, 1000001, 'ALEErrorSign']]], \ ale#sign#ParseSigns([' Zeile=235 id=1000001 Gruppe=ale Name=ALEErrorSign']) @@ -71,7 +71,7 @@ Execute (Parsing German signs should work): endif Execute (The sign parser should indicate if the dummy sign is set): - if has('nvim-0.4.2') || (v:version >= 801 && has('patch614')) + if has('nvim-0.4.2') || has('patch-8.1.614') AssertEqual \ [1, [[1, 1000001, 'ALEErrorSign']]], \ ale#sign#ParseSigns([ diff --git a/test/sign/test_sign_placement.vader b/test/sign/test_sign_placement.vader index 80153b22..d8d05b28 100644 --- a/test/sign/test_sign_placement.vader +++ b/test/sign/test_sign_placement.vader @@ -68,7 +68,7 @@ Before: function! ParseSigns() redir => l:output - if has('nvim-0.4.2') || (v:version >= 801 && has('patch614')) + if has('nvim-0.4.2') || has('patch-8.1.614') silent sign place group=ale else silent sign place @@ -152,7 +152,7 @@ Execute(The current signs should be set for running a job): \ ParseSigns() Execute(Loclist items with sign_id values should be kept): - if has('nvim-0.4.2') || (v:version >= 801 && has('patch614')) + if has('nvim-0.4.2') || has('patch-8.1.614') exec 'sign place 1000347 group=ale line=3 name=ALEErrorSign buffer=' . bufnr('') exec 'sign place 1000348 group=ale line=15 name=ALEErrorSign buffer=' . bufnr('') exec 'sign place 1000349 group=ale line=16 name=ALEWarningSign buffer=' . bufnr('') @@ -297,7 +297,7 @@ Execute(No exceptions should be thrown when setting signs for invalid buffers): Execute(Signs should be removed when lines have multiple sign IDs on them): " We can fail to remove signs if there are multiple signs on one line, " say after deleting lines in Vim, etc. - if has('nvim-0.4.2') || (v:version >= 801 && has('patch614')) + if has('nvim-0.4.2') || has('patch-8.1.614') exec 'sign place 1000347 group=ale line=3 name=ALEErrorSign buffer=' . bufnr('') exec 'sign place 1000348 group=ale line=3 name=ALEWarningSign buffer=' . bufnr('') exec 'sign place 1000349 group=ale line=10 name=ALEErrorSign buffer=' . bufnr('') From fa19bca80e742eb1ea8498bf48f75a3fb886c539 Mon Sep 17 00:00:00 2001 From: puritys Date: Thu, 26 Mar 2020 06:40:07 +0000 Subject: [PATCH 45/70] To support javaagent on eclipselsp --- ale_linters/java/eclipselsp.vim | 17 +++++++++++++++++ doc/ale-java.txt | 11 +++++++++++ .../test_eclipselsp_command_callback.vader | 7 ++++++- 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/ale_linters/java/eclipselsp.vim b/ale_linters/java/eclipselsp.vim index 2648893b..2e472cfc 100644 --- a/ale_linters/java/eclipselsp.vim +++ b/ale_linters/java/eclipselsp.vim @@ -7,6 +7,7 @@ call ale#Set('java_eclipselsp_path', ale#path#Simplify($HOME . '/eclipse.jdt.ls' call ale#Set('java_eclipselsp_config_path', '') call ale#Set('java_eclipselsp_workspace_path', '') call ale#Set('java_eclipselsp_executable', 'java') +call ale#Set('java_eclipselsp_javaagent', '') function! ale_linters#java#eclipselsp#Executable(buffer) abort return ale#Var(a:buffer, 'java_eclipselsp_executable') @@ -100,12 +101,28 @@ function! ale_linters#java#eclipselsp#WorkspacePath(buffer) abort return ale#path#Dirname(ale#java#FindProjectRoot(a:buffer)) endfunction +function! ale_linters#java#eclipselsp#Javaagent(buffer) abort + let l:rets = [] + let l:raw = ale#Var(a:buffer, 'java_eclipselsp_javaagent') + if empty(l:raw) + return '' + endif + + let l:jars = split(l:raw) + for l:jar in l:jars + call add(l:rets, ale#Escape('-javaagent:' . l:jar)) + endfor + + return join(l:rets, ' ') +endfunction + function! ale_linters#java#eclipselsp#Command(buffer, version) abort let l:path = ale#Var(a:buffer, 'java_eclipselsp_path') let l:executable = ale_linters#java#eclipselsp#Executable(a:buffer) let l:cmd = [ ale#Escape(l:executable), + \ ale_linters#java#eclipselsp#Javaagent(a:buffer), \ '-Declipse.application=org.eclipse.jdt.ls.core.id1', \ '-Dosgi.bundles.defaultStartLevel=4', \ '-Declipse.product=org.eclipse.jdt.ls.core.product', diff --git a/doc/ale-java.txt b/doc/ale-java.txt index 32f0e6eb..d5a3eef6 100644 --- a/doc/ale-java.txt +++ b/doc/ale-java.txt @@ -222,6 +222,17 @@ g:ale_java_eclipselsp_workspace_path *g:ale_java_eclipselsp_workspace_path* absolute path of the Eclipse workspace. If not set this value will be set to the parent folder of the project root. +g:ale_java_eclipselsp_javaagent *g:ale_java_eclipselsp_javaagent* + *b:ale_java_eclipselsp_javaagent* + + Type: |String| + Default: `''` + + A variable to add java agent for annotation processing such as Lombok. + If you have multiple java agent files, use space to separate them. For example: +> + let g:ale_java_eclipselsp_javaagent='/eclipse/lombok.jar /eclipse/jacoco.jar' +< =============================================================================== uncrustify *ale-java-uncrustify* diff --git a/test/command_callback/test_eclipselsp_command_callback.vader b/test/command_callback/test_eclipselsp_command_callback.vader index f25ed5fc..6bbc4053 100644 --- a/test/command_callback/test_eclipselsp_command_callback.vader +++ b/test/command_callback/test_eclipselsp_command_callback.vader @@ -54,6 +54,7 @@ Execute(VersionCheck should return correct version): Execute(The eclipselsp callback should return the correct default value): let cmd = [ ale#Escape('java'), + \ '', \ '-Declipse.application=org.eclipse.jdt.ls.core.id1', \ '-Dosgi.bundles.defaultStartLevel=4', \ '-Declipse.product=org.eclipse.jdt.ls.core.product', @@ -72,6 +73,7 @@ Execute(The eclipselsp callback should return the correct default value): Execute(The eclipselsp callback should allow custom executable): let b:ale_java_eclipselsp_executable='/bin/foobar' let cmd = [ ale#Escape('/bin/foobar'), + \ '', \ '-Declipse.application=org.eclipse.jdt.ls.core.id1', \ '-Dosgi.bundles.defaultStartLevel=4', \ '-Declipse.product=org.eclipse.jdt.ls.core.product', @@ -87,9 +89,12 @@ Execute(The eclipselsp callback should allow custom executable): \] AssertLinter '/bin/foobar', join(cmd, ' ') -Execute(The eclipselsp callback should allow custom configuration path): +Execute(The eclipselsp callback should allow custom configuration path and javaagent): let b:ale_java_eclipselsp_config_path = '/home/config' + let b:ale_java_eclipselsp_javaagent = '/home/lombok.jar /home/lombok2.jar' let cmd = [ ale#Escape('java'), + \ ale#Escape('-javaagent:/home/lombok.jar'), + \ ale#Escape('-javaagent:/home/lombok2.jar'), \ '-Declipse.application=org.eclipse.jdt.ls.core.id1', \ '-Dosgi.bundles.defaultStartLevel=4', \ '-Declipse.product=org.eclipse.jdt.ls.core.product', From 9edefa724b87805ed05246362173f2f5c6285793 Mon Sep 17 00:00:00 2001 From: puritys Date: Thu, 26 Mar 2020 07:54:12 +0000 Subject: [PATCH 46/70] Fix code convention --- ale_linters/java/eclipselsp.vim | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ale_linters/java/eclipselsp.vim b/ale_linters/java/eclipselsp.vim index 2e472cfc..2bfec043 100644 --- a/ale_linters/java/eclipselsp.vim +++ b/ale_linters/java/eclipselsp.vim @@ -104,11 +104,13 @@ endfunction function! ale_linters#java#eclipselsp#Javaagent(buffer) abort let l:rets = [] let l:raw = ale#Var(a:buffer, 'java_eclipselsp_javaagent') + if empty(l:raw) return '' endif let l:jars = split(l:raw) + for l:jar in l:jars call add(l:rets, ale#Escape('-javaagent:' . l:jar)) endfor From 852a6a1753353da2aa66386c452232b232849cb1 Mon Sep 17 00:00:00 2001 From: puritys Date: Thu, 26 Mar 2020 08:14:06 +0000 Subject: [PATCH 47/70] Fix code convention --- doc/ale-java.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/ale-java.txt b/doc/ale-java.txt index d5a3eef6..15e9e679 100644 --- a/doc/ale-java.txt +++ b/doc/ale-java.txt @@ -222,8 +222,8 @@ g:ale_java_eclipselsp_workspace_path *g:ale_java_eclipselsp_workspace_path* absolute path of the Eclipse workspace. If not set this value will be set to the parent folder of the project root. -g:ale_java_eclipselsp_javaagent *g:ale_java_eclipselsp_javaagent* - *b:ale_java_eclipselsp_javaagent* +g:ale_java_eclipselsp_javaagent *g:ale_java_eclipselsp_javaagent* + *b:ale_java_eclipselsp_javaagent* Type: |String| Default: `''` From 58404b5b83ff08dd32b93cae57c2bae088a989e0 Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Thu, 9 Apr 2020 08:57:02 -0400 Subject: [PATCH 48/70] rust-analyzer server binary changed name --- ale_linters/rust/analyzer.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ale_linters/rust/analyzer.vim b/ale_linters/rust/analyzer.vim index b964e4a2..3666ec03 100644 --- a/ale_linters/rust/analyzer.vim +++ b/ale_linters/rust/analyzer.vim @@ -1,7 +1,7 @@ " Author: Jon Gjengset " Description: The next generation language server for Rust -call ale#Set('rust_analyzer_executable', 'ra_lsp_server') +call ale#Set('rust_analyzer_executable', 'rust-analyzer') call ale#Set('rust_analyzer_config', {}) function! ale_linters#rust#analyzer#GetCommand(buffer) abort From 6087765cad9271a54d3a29c0c0e6582332461451 Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Thu, 9 Apr 2020 13:23:03 -0400 Subject: [PATCH 49/70] Move to rust-analyzer everywhere --- doc/ale-rust.txt | 2 +- test/command_callback/test_rust_analyzer_callbacks.vader | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/ale-rust.txt b/doc/ale-rust.txt index 2e0f3474..46d4714b 100644 --- a/doc/ale-rust.txt +++ b/doc/ale-rust.txt @@ -47,7 +47,7 @@ analyzer *ale-rust-analyzer* g:ale_rust_analyzer_executable *g:ale_rust_analyzer_executable* *b:ale_rust_analyzer_executable* Type: |String| - Default: `'ra_lsp_server'` + Default: `'rust-analyzer'` This variable can be modified to change the executable path for `rust-analyzer`. diff --git a/test/command_callback/test_rust_analyzer_callbacks.vader b/test/command_callback/test_rust_analyzer_callbacks.vader index 55af405b..95866076 100644 --- a/test/command_callback/test_rust_analyzer_callbacks.vader +++ b/test/command_callback/test_rust_analyzer_callbacks.vader @@ -5,7 +5,7 @@ After: call ale#assert#TearDownLinterTest() Execute(The default executable path should be correct): - AssertLinter 'ra_lsp_server', ale#Escape('ra_lsp_server') + AssertLinter 'rust-analyzer', ale#Escape('rust-analyzer') Execute(The project root should be detected correctly): AssertLSPProject '' From 82f734a7c286d8705c9a6e2879b4173fe18a6356 Mon Sep 17 00:00:00 2001 From: w0rp Date: Wed, 15 Apr 2020 16:50:13 +0100 Subject: [PATCH 50/70] Closes #3019 - Implement default navigation Default navigation for commands that jump to new locations has been implemented with the `ale_default_navigation` variable, and all commands that jump to locations now support `-tab`, `-split`, or `-vsplit` arguments for overriding the default navigation behavior. --- autoload/ale/definition.vim | 39 ++++++++ autoload/ale/preview.vim | 37 ++++++-- autoload/ale/references.vim | 19 +++- autoload/ale/util.vim | 8 +- doc/ale.txt | 142 +++++++++++++---------------- ftplugin/ale-preview-selection.vim | 2 +- plugin/ale.vim | 38 +++++--- test/test_find_references.vader | 68 +++++++++++++- test/test_go_to_definition.vader | 38 +++++++- 9 files changed, 278 insertions(+), 113 deletions(-) diff --git a/autoload/ale/definition.vim b/autoload/ale/definition.vim index 3915cac1..ffcd9d10 100644 --- a/autoload/ale/definition.vim +++ b/autoload/ale/definition.vim @@ -5,6 +5,7 @@ let s:go_to_definition_map = {} " Enable automatic updates of the tagstack let g:ale_update_tagstack = get(g:, 'ale_update_tagstack', 1) +let g:ale_default_navigation = get(g:, 'ale_default_navigation', 'buffer') " Used to get the definition map in tests. function! ale#definition#GetMap() abort @@ -134,6 +135,10 @@ function! s:GoToLSPDefinition(linter, options, capability) abort endfunction function! ale#definition#GoTo(options) abort + if !get(g:, 'ale_ignore_2_7_warnings') && has_key(a:options, 'deprecated_command') + execute 'echom '':' . a:options.deprecated_command . ' is deprecated. Use `let g:ale_ignore_2_7_warnings = 1` to disable this message.''' + endif + for l:linter in ale#linter#Get(&filetype) if !empty(l:linter.lsp) call s:GoToLSPDefinition(l:linter, a:options, 'definition') @@ -142,6 +147,10 @@ function! ale#definition#GoTo(options) abort endfunction function! ale#definition#GoToType(options) abort + if !get(g:, 'ale_ignore_2_7_warnings') && has_key(a:options, 'deprecated_command') + execute 'echom '':' . a:options.deprecated_command . ' is deprecated. Use `let g:ale_ignore_2_7_warnings = 1` to disable this message.''' + endif + for l:linter in ale#linter#Get(&filetype) if !empty(l:linter.lsp) " TODO: handle typeDefinition for tsserver if supported by the @@ -154,3 +163,33 @@ function! ale#definition#GoToType(options) abort endif endfor endfunction + +function! ale#definition#GoToCommandHandler(command, ...) abort + let l:options = {} + + if len(a:000) > 0 + for l:option in a:000 + if l:option is? '-tab' + let l:options.open_in = 'tab' + elseif l:option is? '-split' + let l:options.open_in = 'split' + elseif l:option is? '-vsplit' + let l:options.open_in = 'vsplit' + endif + endfor + endif + + if !has_key(l:options, 'open_in') + let l:default_navigation = ale#Var(bufnr(''), 'default_navigation') + + if index(['tab', 'split', 'vsplit'], l:default_navigation) >= 0 + let l:options.open_in = l:default_navigation + endif + endif + + if a:command is# 'type' + call ale#definition#GoToType(l:options) + else + call ale#definition#GoTo(l:options) + endif +endfunction diff --git a/autoload/ale/preview.vim b/autoload/ale/preview.vim index 6d58aca9..7902ec63 100644 --- a/autoload/ale/preview.vim +++ b/autoload/ale/preview.vim @@ -1,6 +1,14 @@ " Author: w0rp " Description: Preview windows for showing whatever information in. +if !has_key(s:, 'last_selection_list') + let s:last_selection_list = [] +endif + +if !has_key(s:, 'last_selection_open_in') + let s:last_selection_open_in = 'current-buffer' +endif + " Open a preview window and show some lines in it. " A second argument can be passed as a Dictionary with options. They are... " @@ -67,9 +75,24 @@ function! ale#preview#ShowSelection(item_list, ...) abort call ale#preview#Show(l:lines, {'filetype': 'ale-preview-selection'}) let b:ale_preview_item_list = a:item_list + let b:ale_preview_item_open_in = get(l:options, 'open_in', 'current-buffer') + + " Remove the last preview + let s:last_selection_list = b:ale_preview_item_list + let s:last_selection_open_in = b:ale_preview_item_open_in endfunction -function! s:Open(open_in_tab) abort +function! ale#preview#RepeatSelection() abort + if empty(s:last_selection_list) + return + endif + + call ale#preview#ShowSelection(s:last_selection_list, { + \ 'open_in': s:last_selection_open_in, + \}) +endfunction + +function! s:Open(open_in) abort let l:item_list = get(b:, 'ale_preview_item_list', []) let l:item = get(l:item_list, getpos('.')[1] - 1, {}) @@ -77,22 +100,20 @@ function! s:Open(open_in_tab) abort return endif - if !a:open_in_tab - :q! - endif + :q! call ale#util#Open( \ l:item.filename, \ l:item.line, \ l:item.column, - \ {'open_in_tab': a:open_in_tab}, + \ {'open_in': a:open_in}, \) endfunction -function! ale#preview#OpenSelectionInBuffer() abort - call s:Open(0) +function! ale#preview#OpenSelection() abort + call s:Open(b:ale_preview_item_open_in) endfunction function! ale#preview#OpenSelectionInTab() abort - call s:Open(1) + call s:Open('tab') endfunction diff --git a/autoload/ale/references.vim b/autoload/ale/references.vim index b9725e1e..38ff0d3d 100644 --- a/autoload/ale/references.vim +++ b/autoload/ale/references.vim @@ -1,3 +1,5 @@ +let g:ale_default_navigation = get(g:, 'ale_default_navigation', 'buffer') + let s:references_map = {} " Used to get the references map in tests. @@ -99,7 +101,8 @@ function! s:OnReady(line, column, options, linter, lsp_details) abort let l:request_id = ale#lsp#Send(l:id, l:message) let s:references_map[l:request_id] = { - \ 'use_relative_paths': has_key(a:options, 'use_relative_paths') ? a:options.use_relative_paths : 0 + \ 'use_relative_paths': has_key(a:options, 'use_relative_paths') ? a:options.use_relative_paths : 0, + \ 'open_in': get(a:options, 'open_in', 'current-buffer'), \} endfunction @@ -110,10 +113,24 @@ function! ale#references#Find(...) abort for l:option in a:000 if l:option is? '-relative' let l:options.use_relative_paths = 1 + elseif l:option is? '-tab' + let l:options.open_in = 'tab' + elseif l:option is? '-split' + let l:options.open_in = 'split' + elseif l:option is? '-vsplit' + let l:options.open_in = 'vsplit' endif endfor endif + if !has_key(l:options, 'open_in') + let l:default_navigation = ale#Var(bufnr(''), 'default_navigation') + + if index(['tab', 'split', 'vsplit'], l:default_navigation) >= 0 + let l:options.open_in = l:default_navigation + endif + endif + let l:buffer = bufnr('') let [l:line, l:column] = getpos('.')[1:2] let l:column = min([l:column, len(getline(l:line))]) diff --git a/autoload/ale/util.vim b/autoload/ale/util.vim index 8d166625..3ca9ea08 100644 --- a/autoload/ale/util.vim +++ b/autoload/ale/util.vim @@ -91,17 +91,17 @@ endfunction " options['open_in'] can be: " current-buffer (default) " tab -" vertical-split -" horizontal-split +" split +" vsplit function! ale#util#Open(filename, line, column, options) abort let l:open_in = get(a:options, 'open_in', 'current-buffer') let l:args_to_open = '+' . a:line . ' ' . fnameescape(a:filename) if l:open_in is# 'tab' call ale#util#Execute('tabedit ' . l:args_to_open) - elseif l:open_in is# 'horizontal-split' + elseif l:open_in is# 'split' call ale#util#Execute('split ' . l:args_to_open) - elseif l:open_in is# 'vertical-split' + elseif l:open_in is# 'vsplit' call ale#util#Execute('vsplit ' . l:args_to_open) elseif bufnr(a:filename) isnot bufnr('') " Open another file only if we need to. diff --git a/doc/ale.txt b/doc/ale.txt index da4328d9..469fa106 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -478,12 +478,9 @@ would like to use. An example here shows the available options for symbols > ALE supports jumping to the files and locations where symbols are defined through any enabled LSP linters. The locations ALE will jump to depend on the -information returned by LSP servers. The following commands are supported: - -|ALEGoToDefinition| - Open the definition of the symbol under the cursor. -|ALEGoToDefinitionInTab| - The same, but for opening the file in a new tab. -|ALEGoToDefinitionInSplit| - The same, but in a new split. -|ALEGoToDefinitionInVSplit| - The same, but in a new vertical split. +information returned by LSP servers. The |ALEGoToDefinition| command will jump +to the definition of symbols under the cursor. See the documentation for the +command for configuring how the location will be displayed. ALE will update Vim's |tagstack| automatically unless |g:ale_update_tagstack| is set to `0`. @@ -493,15 +490,10 @@ set to `0`. ALE supports jumping to the files and locations where symbols' types are defined through any enabled LSP linters. The locations ALE will jump to depend -on the information returned by LSP servers. The following commands are -supported: - -|ALEGoToTypeDefinition| - Open the definition of the symbol's type under - the cursor. -|ALEGoToTypeDefinitionInTab| - The same, but for opening the file in a new tab. -|ALEGoToTypeDefinitionInSplit| - The same, but in a new split. -|ALEGoToTypeDefinitionInVSplit| - The same, but in a new vertical split. - +on the information returned by LSP servers. The |ALEGoToTypeDefinition| +command will jump to the definition of symbols under the cursor. See the +documentation for the command for configuring how the location will be +displayed. ------------------------------------------------------------------------------- 5.4 Find References *ale-find-references* @@ -666,7 +658,7 @@ g:ale_completion_delay *g:ale_completion_delay* g:ale_completion_enabled *g:ale_completion_enabled* -b:ale_completion_enabled *b:ale_completion_enabled* + *b:ale_completion_enabled* Type: |Number| Default: `0` @@ -793,6 +785,16 @@ g:ale_cursor_detail *g:ale_cursor_detail* loaded for messages to be displayed. See |ale-lint-settings-on-startup|. +g:ale_default_navigation *g:ale_default_navigation* + *b:ale_default_navigation* + + Type: |String| + Default: `'buffer'` + + The default method for navigating away from the current buffer to another + buffer, such as for |ALEFindReferences:|, or |ALEGoToDefinition|. + + g:ale_disable_lsp *g:ale_disable_lsp* *b:ale_disable_lsp* @@ -845,7 +847,7 @@ g:ale_echo_msg_error_str *g:ale_echo_msg_error_str* g:ale_echo_msg_format *g:ale_echo_msg_format* -b:ale_echo_msg_format *b:ale_echo_msg_format* + *b:ale_echo_msg_format* Type: |String| Default: `'%code: %%s'` @@ -924,7 +926,7 @@ g:ale_enabled *g:ale_enabled* g:ale_exclude_highlights *g:ale_exclude_highlights* -b:ale_exclude_highlights *b:ale_exclude_highlights* + *b:ale_exclude_highlights* Type: |List| Default: `[]` @@ -961,7 +963,7 @@ g:ale_fixers *g:ale_fixers* < g:ale_fix_on_save *g:ale_fix_on_save* -b:ale_fix_on_save *b:ale_fix_on_save* + *b:ale_fix_on_save* Type: |Number| Default: `0` @@ -983,7 +985,7 @@ b:ale_fix_on_save *b:ale_fix_on_save* g:ale_fix_on_save_ignore *g:ale_fix_on_save_ignore* -b:ale_fix_on_save_ignore *b:ale_fix_on_save_ignore* + *b:ale_fix_on_save_ignore* Type: |Dictionary| or |List| Default: `{}` @@ -1359,7 +1361,7 @@ g:ale_list_vertical *g:ale_list_vertical* g:ale_loclist_msg_format *g:ale_loclist_msg_format* -b:ale_loclist_msg_format *b:ale_loclist_msg_format* + *b:ale_loclist_msg_format* Type: |String| Default: `g:ale_echo_msg_format` @@ -1411,7 +1413,7 @@ g:ale_lsp_show_message_severity *g:ale_lsp_show_message_severity* g:ale_lsp_root *g:ale_lsp_root* -b:ale_lsp_root *b:ale_lsp_root* + *b:ale_lsp_root* Type: |Dictionary| or |String| Default: {} @@ -1892,7 +1894,8 @@ g:ale_virtualtext_cursor *g:ale_virtualtext_cursor* g:ale_virtualtext_delay *g:ale_virtualtext_delay* -b:ale_virtualtext_delay *b:ale_virtualtext_delay* + *b:ale_virtualtext_delay* + Type: |Number| Default: `10` @@ -1911,7 +1914,7 @@ g:ale_virtualtext_prefix *g:ale_virtualtext_prefix* Prefix to be used with |g:ale_virtualtext_cursor|. g:ale_virtualenv_dir_names *g:ale_virtualenv_dir_names* -b:ale_virtualenv_dir_names *b:ale_virtualenv_dir_names* + *b:ale_virtualenv_dir_names* Type: |List| Default: `['.env', '.venv', 'env', 've-py3', 've', 'virtualenv', 'venv']` @@ -1925,7 +1928,7 @@ b:ale_virtualenv_dir_names *b:ale_virtualenv_dir_names* g:ale_warn_about_trailing_blank_lines *g:ale_warn_about_trailing_blank_lines* -b:ale_warn_about_trailing_blank_lines *b:ale_warn_about_trailing_blank_lines* + *b:ale_warn_about_trailing_blank_lines* Type: |Number| Default: `1` @@ -1937,7 +1940,7 @@ b:ale_warn_about_trailing_blank_lines *b:ale_warn_about_trailing_blank_lines* g:ale_warn_about_trailing_whitespace *g:ale_warn_about_trailing_whitespace* -b:ale_warn_about_trailing_whitespace *b:ale_warn_about_trailing_whitespace* + *b:ale_warn_about_trailing_whitespace* Type: |Number| Default: `1` @@ -2704,11 +2707,23 @@ ALEFindReferences *ALEFindReferences* Enter key (``) can be used to jump to a referencing location, or the `t` key can be used to jump to the location in a new tab. + The locations opened in different ways using the following variations. + + `:ALEFindReferences -tab` - Open the location in a new tab. + `:ALEFindReferences -split` - Open the location in a horizontal split. + `:ALEFindReferences -vsplit` - Open the location in a vertical split. + + The default method used for navigating to a new location can be changed + by modifying |g:ale_default_navigation|. + + The selection can be opened again with the |ALERepeatSelection| command. + You can jump back to the position you were at before going to a reference of something with jump motions like CTRL-O. See |jump-motions|. A plug mapping `(ale_find_references)` is defined for this command. + ALEFix *ALEFix* Fix problems with the current buffer. See |ale-fix| for more information. @@ -2723,12 +2738,21 @@ ALEFixSuggest *ALEFixSuggest* See |ale-fix| for more information. -ALEGoToDefinition *ALEGoToDefinition* +ALEGoToDefinition `` *ALEGoToDefinition* Jump to the definition of a symbol under the cursor using the enabled LSP linters for the buffer. ALE will jump to a definition if an LSP server provides a location to jump to. Otherwise, ALE will do nothing. + The locations opened in different ways using the following variations. + + `:ALEGoToDefinition -tab` - Open the location in a new tab. + `:ALEGoToDefinition -split` - Open the location in a horizontal split. + `:ALEGoToDefinition -vsplit` - Open the location in a vertical split. + + The default method used for navigating to a new location can be changed + by modifying |g:ale_default_navigation|. + You can jump back to the position you were at before going to the definition of something with jump motions like CTRL-O. See |jump-motions|. @@ -2739,30 +2763,6 @@ ALEGoToDefinition *ALEGoToDefinition* A plug mapping `(ale_go_to_definition)` is defined for this command. -ALEGoToDefinitionInTab *ALEGoToDefinitionInTab* - - The same as |ALEGoToDefinition|, but opens results in a new tab. - - A plug mapping `(ale_go_to_definition_in_tab)` is defined for this - command. - - -ALEGoToDefinitionInSplit *ALEGoToDefinitionInSplit* - - The same as |ALEGoToDefinition|, but opens results in a new split. - - A plug mapping `(ale_go_to_definition_in_split)` is defined for this - command. - - -ALEGoToDefinitionInVSplit *ALEGoToDefinitionInVSplit* - - The same as |ALEGoToDefinition|, but opens results in a new vertical split. - - A plug mapping `(ale_go_to_definition_in_vsplit)` is defined for this - command. - - ALEGoToTypeDefinition *ALEGoToTypeDefinition* This works similar to |ALEGoToDefinition| but instead jumps to the @@ -2770,6 +2770,15 @@ ALEGoToTypeDefinition *ALEGoToTypeDefinition* definition if an LSP server provides a location to jump to. Otherwise, ALE will do nothing. + The locations opened in different ways using the following variations. + + `:ALEGoToTypeDefinition -tab` - Open the location in a new tab. + `:ALEGoToTypeDefinition -split` - Open the location in a horizontal split. + `:ALEGoToTypeDefinition -vsplit` - Open the location in a vertical split. + + The default method used for navigating to a new location can be changed + by modifying |g:ale_default_navigation|. + You can jump back to the position you were at before going to the definition of something with jump motions like CTRL-O. See |jump-motions|. @@ -2777,31 +2786,6 @@ ALEGoToTypeDefinition *ALEGoToTypeDefinition* command. -ALEGoToTypeDefinitionInTab *ALEGoToTypeDefinitionInTab* - - The same as |ALEGoToTypeDefinition|, but opens results in a new tab. - - A plug mapping `(ale_go_to_type_definition_in_tab)` is defined for - this command. - - -ALEGoToTypeDefinitionInSplit *ALEGoToTypeDefinitionInSplit* - - The same as |ALEGoToTypeDefinition|, but opens results in a new split. - - A plug mapping `(ale_go_to_type_definition_in_split)` is defined for - this command. - - -ALEGoToTypeDefinitionInVSplit *ALEGoToTypeDefinitionInVSplit* - - The same as |ALEGoToTypeDefinition|, but opens results in a new vertical - split. - - A plug mapping `(ale_go_to_type_definition_in_vsplit)` is defined for - this command. - - ALEHover *ALEHover* Print brief information about the symbol under the cursor, taken from any @@ -2827,6 +2811,11 @@ ALERename *ALERename* The user will be prompted for a new name. +ALERepeatSelection *ALERepeatSelection* + + Repeat the last selection displayed in the preview window. + + ALESymbolSearch `` *ALESymbolSearch* Search for symbols in the workspace, taken from any available LSP linters. @@ -3135,7 +3124,6 @@ ale#command#Run(buffer, command, callback, [options]) *ale#command#Run()* 'command': {b -> ale#command#Run(b, 'foo', function('s:GetCommand'))} < - The following `options` can be provided. `output_stream` - Either `'stdout'`, `'stderr'`, `'both'`, or `'none`' for diff --git a/ftplugin/ale-preview-selection.vim b/ftplugin/ale-preview-selection.vim index d77b4f98..7ec84068 100644 --- a/ftplugin/ale-preview-selection.vim +++ b/ftplugin/ale-preview-selection.vim @@ -12,5 +12,5 @@ noremap A noremap o noremap O " Keybinds for opening selection items. -noremap :call ale#preview#OpenSelectionInBuffer() +noremap :call ale#preview#OpenSelection() noremap t :call ale#preview#OpenSelectionInTab() diff --git a/plugin/ale.vim b/plugin/ale.vim index 19c86ea6..e1ddf7b7 100644 --- a/plugin/ale.vim +++ b/plugin/ale.vim @@ -202,16 +202,23 @@ command! -bar -nargs=* -complete=customlist,ale#fix#registry#CompleteFixers ALEF command! -bar ALEFixSuggest :call ale#fix#registry#Suggest(&filetype) " Go to definition for tsserver and LSP -command! -bar ALEGoToDefinition :call ale#definition#GoTo({}) -command! -bar ALEGoToDefinitionInTab :call ale#definition#GoTo({'open_in': 'tab'}) -command! -bar ALEGoToDefinitionInSplit :call ale#definition#GoTo({'open_in': 'horizontal-split'}) -command! -bar ALEGoToDefinitionInVSplit :call ale#definition#GoTo({'open_in': 'vertical-split'}) +command! -bar -nargs=* ALEGoToDefinition :call ale#definition#GoToCommandHandler('', ) + +" Deprecated commands we have to keep for now. +command! -bar ALEGoToDefinitionInTab :call ale#definition#GoTo({'open_in': 'tab', 'deprecated_command': 'ALEGoToDefinitionInTab'}) +command! -bar ALEGoToDefinitionInSplit :call ale#definition#GoTo({'open_in': 'split', 'deprecated_command': 'ALEGoToDefinitionInSplit'}) +command! -bar ALEGoToDefinitionInVSplit :call ale#definition#GoTo({'open_in': 'vsplit', 'deprecated_command': 'ALEGoToDefinitionInVSplit'}) " Go to type definition for tsserver and LSP -command! -bar ALEGoToTypeDefinition :call ale#definition#GoToType({}) -command! -bar ALEGoToTypeDefinitionInTab :call ale#definition#GoToType({'open_in': 'tab'}) -command! -bar ALEGoToTypeDefinitionInSplit :call ale#definition#GoToType({'open_in': 'horizontal-split'}) -command! -bar ALEGoToTypeDefinitionInVSplit :call ale#definition#GoToType({'open_in': 'vertical-split'}) +command! -bar -nargs=* ALEGoToTypeDefinition :call ale#definition#GoToCommandHandler('type', ) + +" Deprecated commands we have to keep for now. +command! -bar ALEGoToTypeDefinitionInTab :call ale#definition#GoToType({'open_in': 'tab', 'deprecated_command': 'ALEGoToTypeDefinitionInTab'}) +command! -bar ALEGoToTypeDefinitionInSplit :call ale#definition#GoToType({'open_in': 'split', 'deprecated_command': 'ALEGoToTypeDefinitionInSplit'}) +command! -bar ALEGoToTypeDefinitionInVSplit :call ale#definition#GoToType({'open_in': 'vsplit', 'deprecated_command': 'ALEGoToTypeDefinitionInVSplit'}) + +" Repeat a previous selection in the preview window +command! -bar ALERepeatSelection :call ale#preview#RepeatSelection() " Find references for tsserver and LSP command! -bar -nargs=* ALEFindReferences :call ale#references#Find() @@ -260,18 +267,21 @@ nnoremap (ale_lint) :ALELint nnoremap (ale_detail) :ALEDetail nnoremap (ale_fix) :ALEFix nnoremap (ale_go_to_definition) :ALEGoToDefinition -nnoremap (ale_go_to_definition_in_tab) :ALEGoToDefinitionInTab -nnoremap (ale_go_to_definition_in_split) :ALEGoToDefinitionInSplit -nnoremap (ale_go_to_definition_in_vsplit) :ALEGoToDefinitionInVSplit nnoremap (ale_go_to_type_definition) :ALEGoToTypeDefinition -nnoremap (ale_go_to_type_definition_in_tab) :ALEGoToTypeDefinitionInTab -nnoremap (ale_go_to_type_definition_in_split) :ALEGoToTypeDefinitionInSplit -nnoremap (ale_go_to_type_definition_in_vsplit) :ALEGoToTypeDefinitionInVSplit nnoremap (ale_find_references) :ALEFindReferences nnoremap (ale_hover) :ALEHover nnoremap (ale_documentation) :ALEDocumentation inoremap (ale_complete) :ALEComplete nnoremap (ale_rename) :ALERename +nnoremap (ale_repeat_selection) :ALERepeatSelection + +" Deprecated mappings +nnoremap (ale_go_to_definition_in_tab) :ALEGoToDefinitionInTab +nnoremap (ale_go_to_definition_in_split) :ALEGoToDefinitionInSplit +nnoremap (ale_go_to_definition_in_vsplit) :ALEGoToDefinitionInVSplit +nnoremap (ale_go_to_type_definition_in_tab) :ALEGoToTypeDefinitionInTab +nnoremap (ale_go_to_type_definition_in_split) :ALEGoToTypeDefinitionInSplit +nnoremap (ale_go_to_type_definition_in_vsplit) :ALEGoToTypeDefinitionInVSplit " Set up autocmd groups now. call ale#events#Init() diff --git a/test/test_find_references.vader b/test/test_find_references.vader index 1a147849..9949362a 100644 --- a/test/test_find_references.vader +++ b/test/test_find_references.vader @@ -2,6 +2,8 @@ Before: call ale#test#SetDirectory('/testplugin/test') call ale#test#SetFilename('dummy.txt') + Save g:ale_default_navigation + let g:old_filename = expand('%:p') let g:Callback = '' let g:expr_list = [] @@ -12,6 +14,7 @@ Before: let g:capability_checked = '' let g:conn_id = v:null let g:InitCallback = v:null + let g:ale_default_navigation = 'buffer' runtime autoload/ale/lsp_linter.vim runtime autoload/ale/lsp.vim @@ -63,6 +66,8 @@ Before: endfunction After: + Restore + if g:conn_id isnot v:null call ale#lsp#RemoveConnectionWithID(g:conn_id) endif @@ -152,6 +157,20 @@ Execute(Results should be shown for tsserver responses): \ g:item_list AssertEqual {}, ale#references#GetMap() + " We should be able to repeat selections with ALERepeatSelection + let g:ale_item_list = [] + + ALERepeatSelection + + AssertEqual + \ [ + \ {'filename': '/foo/bar/app.ts', 'column': 9, 'line': 9, 'match': 'import {doSomething} from ''./whatever'''}, + \ {'filename': '/foo/bar/app.ts', 'column': 3, 'line': 804, 'match': 'doSomething()'}, + \ {'filename': '/foo/bar/other/app.ts', 'column': 3, 'line': 51, 'match': 'doSomething()'}, + \ ], + \ g:item_list + AssertEqual {}, ale#references#GetMap() + Execute(The preview window should not be opened for empty tsserver responses): call ale#references#SetMap({3: {}}) call ale#references#HandleTSServerResponse(1, { @@ -195,7 +214,7 @@ Execute(tsserver reference requests should be sent): \ [0, 'ts@references', {'file': expand('%:p'), 'line': 2, 'offset': 5}] \ ], \ g:message_list - AssertEqual {'42': {'use_relative_paths': 0}}, ale#references#GetMap() + AssertEqual {'42': {'open_in': 'current-buffer', 'use_relative_paths': 0}}, ale#references#GetMap() Execute('-relative' argument should enable 'use_relative_paths' in HandleTSServerResponse): runtime ale_linters/typescript/tsserver.vim @@ -205,7 +224,48 @@ Execute('-relative' argument should enable 'use_relative_paths' in HandleTSServe call g:InitCallback() - AssertEqual {'42': {'use_relative_paths': 1}}, ale#references#GetMap() + AssertEqual {'42': {'open_in': 'current-buffer', 'use_relative_paths': 1}}, ale#references#GetMap() + +Execute(`-tab` should display results in tabs): + runtime ale_linters/typescript/tsserver.vim + call setpos('.', [bufnr(''), 2, 5, 0]) + + ALEFindReferences -tab + + call g:InitCallback() + + AssertEqual {'42': {'open_in': 'tab', 'use_relative_paths': 0}}, ale#references#GetMap() + +Execute(The default navigation type should be used): + runtime ale_linters/typescript/tsserver.vim + call setpos('.', [bufnr(''), 2, 5, 0]) + + let g:ale_default_navigation = 'tab' + ALEFindReferences + + call g:InitCallback() + + AssertEqual {'42': {'open_in': 'tab', 'use_relative_paths': 0}}, ale#references#GetMap() + +Execute(`-split` should display results in splits): + runtime ale_linters/typescript/tsserver.vim + call setpos('.', [bufnr(''), 2, 5, 0]) + + ALEFindReferences -split + + call g:InitCallback() + + AssertEqual {'42': {'open_in': 'split', 'use_relative_paths': 0}}, ale#references#GetMap() + +Execute(`-vsplit` should display results in vsplits): + runtime ale_linters/typescript/tsserver.vim + call setpos('.', [bufnr(''), 2, 5, 0]) + + ALEFindReferences -vsplit + + call g:InitCallback() + + AssertEqual {'42': {'open_in': 'vsplit', 'use_relative_paths': 0}}, ale#references#GetMap() Given python(Some Python file): foo @@ -302,7 +362,7 @@ Execute(LSP reference requests should be sent): \ ], \ g:message_list - AssertEqual {'42': {'use_relative_paths': 0}}, ale#references#GetMap() + AssertEqual {'42': {'open_in': 'current-buffer', 'use_relative_paths': 0}}, ale#references#GetMap() Execute('-relative' argument should enable 'use_relative_paths' in HandleLSPResponse): runtime ale_linters/python/pyls.vim @@ -313,4 +373,4 @@ Execute('-relative' argument should enable 'use_relative_paths' in HandleLSPResp call g:InitCallback() - AssertEqual {'42': {'use_relative_paths': 1}}, ale#references#GetMap() + AssertEqual {'42': {'open_in': 'current-buffer', 'use_relative_paths': 1}}, ale#references#GetMap() diff --git a/test/test_go_to_definition.vader b/test/test_go_to_definition.vader index 3479d7b5..a517bd54 100644 --- a/test/test_go_to_definition.vader +++ b/test/test_go_to_definition.vader @@ -2,6 +2,8 @@ Before: call ale#test#SetDirectory('/testplugin/test') call ale#test#SetFilename('dummy.txt') + Save g:ale_default_navigation + let g:old_filename = expand('%:p') let g:Callback = '' let g:message_list = [] @@ -9,6 +11,7 @@ Before: let g:capability_checked = '' let g:conn_id = v:null let g:InitCallback = v:null + let g:ale_default_navigation = 'buffer' runtime autoload/ale/linter.vim runtime autoload/ale/lsp_linter.vim @@ -54,6 +57,8 @@ Before: endfunction After: + Restore + if g:conn_id isnot v:null call ale#lsp#RemoveConnectionWithID(g:conn_id) endif @@ -164,7 +169,7 @@ Execute(Other files should be jumped to for definition responses in tabs too): AssertEqual {}, ale#definition#GetMap() Execute(Other files should be jumped to for definition responses in splits too): - call ale#definition#SetMap({3: {'open_in': 'horizontal-split'}}) + call ale#definition#SetMap({3: {'open_in': 'split'}}) call ale#definition#HandleTSServerResponse( \ 1, \ { @@ -189,7 +194,7 @@ Execute(Other files should be jumped to for definition responses in splits too): AssertEqual {}, ale#definition#GetMap() Execute(Other files should be jumped to for definition responses in vsplits too): - call ale#definition#SetMap({3: {'open_in': 'vertical-split'}}) + call ale#definition#SetMap({3: {'open_in': 'vsplit'}}) call ale#definition#HandleTSServerResponse( \ 1, \ { @@ -241,7 +246,32 @@ Execute(tsserver tab definition requests should be sent): runtime ale_linters/typescript/tsserver.vim call setpos('.', [bufnr(''), 2, 5, 0]) - ALEGoToDefinitionInTab + ALEGoToDefinition -tab + + " We shouldn't register the callback yet. + AssertEqual '''''', string(g:Callback) + + AssertEqual type(function('type')), type(g:InitCallback) + call g:InitCallback() + + AssertEqual 'definition', g:capability_checked + AssertEqual + \ 'function(''ale#definition#HandleTSServerResponse'')', + \ string(g:Callback) + AssertEqual + \ [ + \ ale#lsp#tsserver_message#Change(bufnr('')), + \ [0, 'ts@definition', {'file': expand('%:p'), 'line': 2, 'offset': 5}] + \ ], + \ g:message_list + AssertEqual {'42': {'open_in': 'tab'}}, ale#definition#GetMap() + +Execute(The default navigation type should be used): + runtime ale_linters/typescript/tsserver.vim + call setpos('.', [bufnr(''), 2, 5, 0]) + + let g:ale_default_navigation = 'tab' + ALEGoToDefinition " We shouldn't register the callback yet. AssertEqual '''''', string(g:Callback) @@ -448,7 +478,7 @@ Execute(LSP tab definition requests should be sent): let b:ale_linters = ['pyls'] call setpos('.', [bufnr(''), 1, 5, 0]) - ALEGoToDefinitionInTab + ALEGoToDefinition -tab " We shouldn't register the callback yet. AssertEqual '''''', string(g:Callback) From 00eee550ea5d494172bd83fbbc221aa221c956b9 Mon Sep 17 00:00:00 2001 From: TG Date: Wed, 8 Apr 2020 14:30:23 +0200 Subject: [PATCH 51/70] Adds column number to the verilator verilog linter Since version 4.032 (04/2020) verilator linter messages also contain the column number, and look like: %Error: /tmp/test.sv:3:1: syntax error, unexpected endmodule, expecting ';' To stay compatible with old versions of the tool, the column number is optional in the researched pattern regular expression. See commit: https://github.com/verilator/verilator/commit/81c659957e89f28861fde870f000cce2d5f76729 --- ale_linters/verilog/verilator.vim | 27 ++++++++----- test/handler/test_verilator_handler.vader | 48 +++++++++++++++++++++++ 2 files changed, 66 insertions(+), 9 deletions(-) create mode 100644 test/handler/test_verilator_handler.vader diff --git a/ale_linters/verilog/verilator.vim b/ale_linters/verilog/verilator.vim index 64bb6e41..029dd4c9 100644 --- a/ale_linters/verilog/verilator.vim +++ b/ale_linters/verilog/verilator.vim @@ -28,21 +28,30 @@ function! ale_linters#verilog#verilator#Handle(buffer, lines) abort " %Warning-UNDRIVEN: test.v:3: Signal is not driven: clk " %Warning-UNUSED: test.v:4: Signal is not used: dout " %Warning-BLKSEQ: test.v:10: Blocking assignments (=) in sequential (flop or latch) block; suggest delayed assignments (<=). - let l:pattern = '^%\(Warning\|Error\)[^:]*:\([^:]\+\):\(\d\+\): \(.\+\)$' + " Since version 4.032 (04/2020) verilator linter messages also contain the column number, + " and look like: + " %Error: /tmp/test.sv:3:1: syntax error, unexpected endmodule, expecting ';' + " + " to stay compatible with old versions of the tool, the column number is + " optional in the researched pattern + let l:pattern = '^%\(Warning\|Error\)[^:]*:\([^:]\+\):\(\d\+\):\(\d\+\)\?:\? \(.\+\)$' let l:output = [] for l:match in ale#util#GetMatches(a:lines, l:pattern) - let l:line = l:match[3] + 0 - let l:type = l:match[1] is# 'Error' ? 'E' : 'W' - let l:text = l:match[4] + let l:item = { + \ 'lnum': str2nr(l:match[3]), + \ 'text': l:match[5], + \ 'type': l:match[1] is# 'Error' ? 'E' : 'W', + \} + + if !empty(l:match[4]) + let l:item.col = str2nr(l:match[4]) + endif + let l:file = l:match[2] if l:file =~# '_verilator_linted.v' - call add(l:output, { - \ 'lnum': l:line, - \ 'text': l:text, - \ 'type': l:type, - \}) + call add(l:output, l:item) endif endfor diff --git a/test/handler/test_verilator_handler.vader b/test/handler/test_verilator_handler.vader new file mode 100644 index 00000000..5e51b5c9 --- /dev/null +++ b/test/handler/test_verilator_handler.vader @@ -0,0 +1,48 @@ +Before: + runtime ale_linters/verilog/verilator.vim + +After: + call ale#linter#Reset() + + +Execute (The verilator handler should parse legacy messages with only line numbers): + AssertEqual + \ [ + \ { + \ 'lnum': 3, + \ 'type': 'E', + \ 'text': 'syntax error, unexpected IDENTIFIER' + \ }, + \ { + \ 'lnum': 10, + \ 'type': 'W', + \ 'text': 'Blocking assignments (=) in sequential (flop or latch) block; suggest delayed assignments (<=).' + \ }, + \ ], + \ ale_linters#verilog#verilator#Handle(bufnr(''), [ + \ '%Error: foo_verilator_linted.v:3: syntax error, unexpected IDENTIFIER', + \ '%Warning-BLKSEQ: bar_verilator_linted.v:10: Blocking assignments (=) in sequential (flop or latch) block; suggest delayed assignments (<=).', + \ ]) + + +Execute (The verilator handler should parse new format messages with line and column numbers): + AssertEqual + \ [ + \ { + \ 'lnum': 3, + \ 'col' : 1, + \ 'type': 'E', + \ 'text': 'syntax error, unexpected endmodule, expecting ;' + \ }, + \ { + \ 'lnum': 4, + \ 'col' : 6, + \ 'type': 'W', + \ 'text': 'Signal is not used: r' + \ }, + \ ], + \ ale_linters#verilog#verilator#Handle(bufnr(''), [ + \ '%Error: bar_verilator_linted.v:3:1: syntax error, unexpected endmodule, expecting ;', + \ '%Warning-UNUSED: foo_verilator_linted.v:4:6: Signal is not used: r', + \ ]) + From 93a13d73538c05cdf26183bf96be29155e780dd2 Mon Sep 17 00:00:00 2001 From: Yuto Date: Sat, 18 Apr 2020 19:59:26 +0900 Subject: [PATCH 52/70] Broken message in pycodestyle (or any other Linters whose name include 'code') (#3114) * Swap substitution order for echoed message This prevents 'code' string in liter_name to be substituted by accident. Linters including pycodestyle have been affected by this problem. * Add test for linter whose name contains 'code' Test for c525db8cb4088d02448c5ddcf4a80ffa028c3181 --- autoload/ale.vim | 2 +- test/test_cursor_warnings.vader | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/autoload/ale.vim b/autoload/ale.vim index ee1a0d54..01e17b15 100644 --- a/autoload/ale.vim +++ b/autoload/ale.vim @@ -258,9 +258,9 @@ function! ale#GetLocItemMessage(item, format_string) abort " Replace special markers with certain information. " \=l:variable is used to avoid escaping issues. + let l:msg = substitute(l:msg, '\v\%([^\%]*)code([^\%]*)\%', l:code_repl, 'g') let l:msg = substitute(l:msg, '\V%severity%', '\=l:severity', 'g') let l:msg = substitute(l:msg, '\V%linter%', '\=l:linter_name', 'g') - let l:msg = substitute(l:msg, '\v\%([^\%]*)code([^\%]*)\%', l:code_repl, 'g') " Replace %s with the text. let l:msg = substitute(l:msg, '\V%s', '\=a:item.text', 'g') diff --git a/test/test_cursor_warnings.vader b/test/test_cursor_warnings.vader index 2a6156f0..6156fd65 100644 --- a/test/test_cursor_warnings.vader +++ b/test/test_cursor_warnings.vader @@ -75,6 +75,17 @@ Before: \ 'type': 'E', \ 'text': 'lowercase error', \ }, + \ { + \ 'lnum': 3, + \ 'col': 5, + \ 'bufnr': bufnr('%'), + \ 'vcol': 0, + \ 'linter_name': 'fakecodelinter', + \ 'nr': -1, + \ 'type': 'E', + \ 'code': 'E001', + \ 'text': 'This error does not exist', + \ }, \ ], \ }, \} @@ -237,6 +248,14 @@ Execute(The %code% and %ifcode% should be removed when there's no code): AssertEqual 'Some information', GetLastMessage() +Execute(The %code% should be formatted correctly when other variables contain 'code'): + let g:ale_echo_msg_format = '%s (%linter%% code%)' + + call cursor(3, 5) + call ale#cursor#EchoCursorWarning() + + AssertEqual 'This error does not exist (fakecodelinter E001)', GetLastMessage() + Execute(The buffer message format option should take precedence): let g:ale_echo_msg_format = '%(code) %%s' let b:ale_echo_msg_format = 'FOO %s' From 1f9ac1c6dcfcb07d5e992e2117bf186490e9d439 Mon Sep 17 00:00:00 2001 From: w0rp Date: Sat, 18 Apr 2020 12:26:38 +0100 Subject: [PATCH 53/70] Fix the cursor tests, that stop tests running --- test/test_cursor_warnings.vader | 33 +++++++-------------------------- 1 file changed, 7 insertions(+), 26 deletions(-) diff --git a/test/test_cursor_warnings.vader b/test/test_cursor_warnings.vader index 6156fd65..339cd71e 100644 --- a/test/test_cursor_warnings.vader +++ b/test/test_cursor_warnings.vader @@ -15,7 +15,7 @@ Before: \ 'col': 10, \ 'bufnr': bufnr('%'), \ 'vcol': 0, - \ 'linter_name': 'eslint', + \ 'linter_name': 'bettercode', \ 'nr': -1, \ 'type': 'W', \ 'code': 'semi', @@ -26,7 +26,7 @@ Before: \ 'col': 10, \ 'bufnr': bufnr('%'), \ 'vcol': 0, - \ 'linter_name': 'eslint', + \ 'linter_name': 'bettercode', \ 'nr': -1, \ 'type': 'E', \ 'code': 'semi', @@ -38,7 +38,7 @@ Before: \ 'col': 14, \ 'bufnr': bufnr('%'), \ 'vcol': 0, - \ 'linter_name': 'eslint', + \ 'linter_name': 'bettercode', \ 'nr': -1, \ 'type': 'I', \ 'text': 'Some information', @@ -48,7 +48,7 @@ Before: \ 'col': 10, \ 'bufnr': bufnr('%'), \ 'vcol': 0, - \ 'linter_name': 'eslint', + \ 'linter_name': 'bettercode', \ 'nr': -1, \ 'type': 'W', \ 'code': 'space-infix-ops', @@ -59,7 +59,7 @@ Before: \ 'col': 15, \ 'bufnr': bufnr('%'), \ 'vcol': 0, - \ 'linter_name': 'eslint', + \ 'linter_name': 'bettercode', \ 'nr': -1, \ 'type': 'E', \ 'code': 'radix', @@ -70,22 +70,11 @@ Before: \ 'col': 1, \ 'bufnr': bufnr('%'), \ 'vcol': 0, - \ 'linter_name': 'eslint', + \ 'linter_name': 'bettercode', \ 'nr': -1, \ 'type': 'E', \ 'text': 'lowercase error', \ }, - \ { - \ 'lnum': 3, - \ 'col': 5, - \ 'bufnr': bufnr('%'), - \ 'vcol': 0, - \ 'linter_name': 'fakecodelinter', - \ 'nr': -1, - \ 'type': 'E', - \ 'code': 'E001', - \ 'text': 'This error does not exist', - \ }, \ ], \ }, \} @@ -207,7 +196,7 @@ Execute(The linter name should be formatted into the message correctly): call ale#cursor#EchoCursorWarning() AssertEqual - \ 'eslint: Infix operators must be spaced.', + \ 'bettercode: Infix operators must be spaced.', \ GetLastMessage() Execute(The severity should be formatted into the message correctly): @@ -248,14 +237,6 @@ Execute(The %code% and %ifcode% should be removed when there's no code): AssertEqual 'Some information', GetLastMessage() -Execute(The %code% should be formatted correctly when other variables contain 'code'): - let g:ale_echo_msg_format = '%s (%linter%% code%)' - - call cursor(3, 5) - call ale#cursor#EchoCursorWarning() - - AssertEqual 'This error does not exist (fakecodelinter E001)', GetLastMessage() - Execute(The buffer message format option should take precedence): let g:ale_echo_msg_format = '%(code) %%s' let b:ale_echo_msg_format = 'FOO %s' From e0181f88320e7cf47aa117c843523a4d6c22c2de Mon Sep 17 00:00:00 2001 From: Jeffrey Lau Date: Sat, 18 Apr 2020 17:25:15 +0800 Subject: [PATCH 54/70] linter/scala/metals: Fix return value of GetProjectRoot() It was returning 0 when it should be returning an empty string. The 'AssertEqual' in the ale image is from an old version so it does not check the types of the arguments. This is already fixed in https://github.com/junegunn/vader.vim/commit/427fe19104c15066e4c1d5d385076e8e07a0dee8 Closes #3120 --- ale_linters/scala/metals.vim | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ale_linters/scala/metals.vim b/ale_linters/scala/metals.vim index f78c7119..da9e855d 100644 --- a/ale_linters/scala/metals.vim +++ b/ale_linters/scala/metals.vim @@ -32,6 +32,8 @@ function! ale_linters#scala#metals#GetProjectRoot(buffer) abort \) endif endfor + + return '' endfunction function! ale_linters#scala#metals#GetCommand(buffer) abort From 36b50058bb6b37c5a336c01cf3d9a61f16f323c7 Mon Sep 17 00:00:00 2001 From: Oliver Ford Date: Mon, 20 Apr 2020 15:02:31 +0000 Subject: [PATCH 55/70] Add terraform-lsp integration (#2758) * Add terraform-lsp integration https://github.com/juliosueiras/terraform-lsp * Add tests & docs for terraform-lsp integration terraform_langserver_options setting added to send custom flags to terraform-lsp. Vader tests have been added to test custom executable, custom flags, and finding the project root. All tests pass. Initial documentation has been added for the above. Resolves dense-analysis/ale#2758, juliosueiras#57 * Fix tag alignment Co-authored-by: = Co-authored-by: w0rp --- ale_linters/terraform/terraform_lsp.vim | 25 ++++++++++ doc/ale-terraform.txt | 19 ++++++++ doc/ale.txt | 1 + .../test_terraform_lsp_command_callback.vader | 48 +++++++++++++++++++ test/terraform_files/main.tf | 0 5 files changed, 93 insertions(+) create mode 100644 ale_linters/terraform/terraform_lsp.vim create mode 100644 test/command_callback/test_terraform_lsp_command_callback.vader create mode 100644 test/terraform_files/main.tf diff --git a/ale_linters/terraform/terraform_lsp.vim b/ale_linters/terraform/terraform_lsp.vim new file mode 100644 index 00000000..e2408c15 --- /dev/null +++ b/ale_linters/terraform/terraform_lsp.vim @@ -0,0 +1,25 @@ +" Author: OJFord +" Description: terraform-lsp integration for ALE (cf. https://github.com/juliosueiras/terraform-lsp) + +call ale#Set('terraform_langserver_executable', 'terraform-lsp') +call ale#Set('terraform_langserver_options', '') + +function! ale_linters#terraform#terraform_lsp#GetCommand(buffer) abort + return '%e' + \ . ale#Pad(ale#Var(a:buffer, 'terraform_langserver_options')) +endfunction + +function! ale_linters#terraform#terraform_lsp#GetProjectRoot(buffer) abort + let l:tf_dir = ale#path#FindNearestDirectory(a:buffer, '.terraform') + + return !empty(l:tf_dir) ? fnamemodify(l:tf_dir, ':h:h') : '' +endfunction + +call ale#linter#Define('terraform', { +\ 'name': 'terraform_lsp', +\ 'lsp': 'stdio', +\ 'executable': {b -> ale#Var(b, 'terraform_langserver_executable')}, +\ 'command': function('ale_linters#terraform#terraform_lsp#GetCommand'), +\ 'project_root': function('ale_linters#terraform#terraform_lsp#GetProjectRoot'), +\ 'language': 'terraform', +\}) diff --git a/doc/ale-terraform.txt b/doc/ale-terraform.txt index 387fd732..f62db190 100644 --- a/doc/ale-terraform.txt +++ b/doc/ale-terraform.txt @@ -32,6 +32,25 @@ g:ale_terraform_terraform_executable *g:ale_terraform_terraform_executable* This variable can be changed to use a different executable for terraform. +=============================================================================== +terraform-lsp *ale-terraform-terraform-lsp* + +g:ale_terraform_langserver_executable *g:ale_terraform_langserver_executable* + *b:ale_terraform_langserver_executable* + Type: |String| + Default: `'terraform-lsp'` + + This variable can be changed to use a different executable for terraform-lsp. + + +g:ale_terraform_langserver_options *g:ale_terraform_langserver_options* + *b:ale_terraform_langserver_options* + Type: |String| + Default: `''` + + This variable can be changed to pass custom CLI flags to terraform-lsp. + + =============================================================================== tflint *ale-terraform-tflint* diff --git a/doc/ale.txt b/doc/ale.txt index 469fa106..81212029 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -2623,6 +2623,7 @@ documented in additional help files. terraform...............................|ale-terraform-options| terraform-fmt-fixer...................|ale-terraform-fmt-fixer| terraform.............................|ale-terraform-terraform| + terraform-lsp.........................|ale-terraform-terraform-lsp| tflint................................|ale-terraform-tflint| tex.....................................|ale-tex-options| chktex................................|ale-tex-chktex| diff --git a/test/command_callback/test_terraform_lsp_command_callback.vader b/test/command_callback/test_terraform_lsp_command_callback.vader new file mode 100644 index 00000000..7a491d54 --- /dev/null +++ b/test/command_callback/test_terraform_lsp_command_callback.vader @@ -0,0 +1,48 @@ +Before: + call ale#assert#SetUpLinterTest('terraform', 'terraform_lsp') + +After: + if isdirectory(g:dir . '/.terraform') + call delete(g:dir . '/.terraform', 'd') + endif + + unlet! b:ale_terraform_langserver_executable + unlet! b:ale_terraform_langserver_options + + call ale#assert#TearDownLinterTest() + +Execute(Should send correct LSP language): + AssertLSPLanguage 'terraform' + +Execute(Should load default executable): + AssertLinter 'terraform-lsp', ale#Escape('terraform-lsp') + +Execute(Should configure custom executable): + let b:ale_terraform_langserver_executable = 'foo' + AssertLinter 'foo', ale#Escape('foo') + +Execute(Should set custom options): + let b:ale_terraform_langserver_options = '--bar' + + AssertLinter 'terraform-lsp', + \ ale#Escape('terraform-lsp') . ' --bar' + +Execute(Should return current directory if it contains .terraform directory): + call mkdir(g:dir . '/.terraform') + AssertLSPProject g:dir + +Execute(Should return nearest directory with .terraform if found in parent directory): + call ale#test#SetFilename('../terraform_files/main.tf') + + let b:parent_dir = ale#path#Simplify(g:dir . '/..') + let b:tf_dir = b:parent_dir . '/.terraform' + + if !isdirectory(b:tf_dir) + call mkdir(b:tf_dir) + endif + + AssertLSPProject b:parent_dir + + call delete(b:tf_dir, 'd') + unlet!b:parent_dir + unlet!b:tf_dir diff --git a/test/terraform_files/main.tf b/test/terraform_files/main.tf new file mode 100644 index 00000000..e69de29b From 60d683da3bfe3440cac4faa5072ecba4a1d2af98 Mon Sep 17 00:00:00 2001 From: Jeffrey Lau Date: Sat, 18 Apr 2020 01:45:01 +0800 Subject: [PATCH 56/70] Add vim-language-server linter support --- ale_linters/vim/vimls.vim | 61 +++++++++++++++ doc/ale-supported-languages-and-tools.txt | 1 + doc/ale-vim.txt | 55 ++++++++++++++ doc/ale.txt | 1 + supported-tools.md | 1 + test/command_callback/test_vim_vimls.vader | 76 +++++++++++++++++++ .../vim_fixtures/invalid_vim_project/test.vim | 0 .../node_modules/.bin/vim-language-server | 0 .../path_with_autoload/autoload/test.vim | 0 .../vim_fixtures/path_with_autoload/test.vim | 0 .../vim_fixtures/path_with_initvim/init.vim | 0 .../path_with_plugin/plugin/test.vim | 0 .../vim_fixtures/path_with_plugin/test.vim | 0 .../vim_fixtures/path_with_vimrc/.vimrc | 0 14 files changed, 195 insertions(+) create mode 100644 ale_linters/vim/vimls.vim create mode 100644 test/command_callback/test_vim_vimls.vader create mode 100644 test/command_callback/vim_fixtures/invalid_vim_project/test.vim create mode 100644 test/command_callback/vim_fixtures/node_modules/.bin/vim-language-server create mode 100644 test/command_callback/vim_fixtures/path_with_autoload/autoload/test.vim create mode 100644 test/command_callback/vim_fixtures/path_with_autoload/test.vim create mode 100644 test/command_callback/vim_fixtures/path_with_initvim/init.vim create mode 100644 test/command_callback/vim_fixtures/path_with_plugin/plugin/test.vim create mode 100644 test/command_callback/vim_fixtures/path_with_plugin/test.vim create mode 100644 test/command_callback/vim_fixtures/path_with_vimrc/.vimrc diff --git a/ale_linters/vim/vimls.vim b/ale_linters/vim/vimls.vim new file mode 100644 index 00000000..26014d66 --- /dev/null +++ b/ale_linters/vim/vimls.vim @@ -0,0 +1,61 @@ +" Author: Jeffrey Lau - https://github.com/zoonfafer +" Description: Vim Language Server integration for ALE + +call ale#Set('vim_vimls_executable', 'vim-language-server') +call ale#Set('vim_vimls_use_global', get(g:, 'ale_use_global_executables', 0)) +call ale#Set('vim_vimls_config', {}) + +function! ale_linters#vim#vimls#GetProjectRoot(buffer) abort + let l:trigger_file_candidates = [ + \ '.vimrc', + \ 'init.vim', + \] + + for l:candidate in l:trigger_file_candidates + let l:trigger_file = fnamemodify(bufname(a:buffer), ':t') + + if l:trigger_file is# l:candidate + return fnamemodify( + \ bufname(a:buffer), + \ ':h', + \) + endif + endfor + + let l:trigger_dir_candidates = [ + \ 'autoload', + \ 'plugin', + \ '.git', + \] + + let l:path_upwards = ale#path#Upwards(fnamemodify(bufname(a:buffer), ':p:h')) + + for l:path in l:path_upwards + for l:candidate in l:trigger_dir_candidates + let l:trigger_dir = ale#path#Simplify( + \ l:path . '/' . l:candidate, + \) + + if isdirectory(l:trigger_dir) + return fnamemodify( + \ l:trigger_dir, + \ ':p:h:h', + \) + endif + endfor + endfor + + return '' +endfunction + +call ale#linter#Define('vim', { +\ 'name': 'vimls', +\ 'lsp': 'stdio', +\ 'lsp_config': {b -> ale#Var(b, 'vim_vimls_config')}, +\ 'executable': {b -> ale#node#FindExecutable(b, 'vim_vimls', [ +\ 'node_modules/.bin/vim-language-server', +\ ])}, +\ 'command': '%e --stdio', +\ 'language': 'vim', +\ 'project_root': function('ale_linters#vim#vimls#GetProjectRoot'), +\}) diff --git a/doc/ale-supported-languages-and-tools.txt b/doc/ale-supported-languages-and-tools.txt index 29dabab7..636985fb 100644 --- a/doc/ale-supported-languages-and-tools.txt +++ b/doc/ale-supported-languages-and-tools.txt @@ -485,6 +485,7 @@ Notes: * `vcom` * `xvhdl` * Vim + * `vimls` * `vint` * Vim help^ * `alex`!! diff --git a/doc/ale-vim.txt b/doc/ale-vim.txt index 772bad23..f85b43eb 100644 --- a/doc/ale-vim.txt +++ b/doc/ale-vim.txt @@ -2,6 +2,61 @@ ALE Vim Integration *ale-vim-options* +=============================================================================== +vimls *ale-vim-vimls* + + The `vim-language-server` is the engine that powers VimL editor support + using the Language Server Protocol. See the installation instructions: + https://github.com/iamcco/vim-language-server#install + +g:ale_vim_vimls_executable *g:ale_vim_vimls_executable* + *b:ale_vim_vimls_executable* + Type: |String| + Default: `'vim-language-server'` + + This option can be set to change the executable path for vimls. + + +g:ale_vim_vimls_config *g:ale_vim_vimls_config* + *b:ale_vim_vimls_config* + Type: |Dictionary| + Default: `{}` + + Dictionary containing configuration settings that will be passed to the + language server. For example: > + { + \ 'vim': { + \ 'iskeyword': '@,48-57,_,192-255,-#', + \ 'vimruntime': '', + \ 'runtimepath': '', + \ 'diagnostic': { + \ 'enable': v:true + \ }, + \ 'indexes': { + \ 'runtimepath': v:true, + \ 'gap': 100, + \ 'count': 3, + \ 'projectRootPatterns' : ['.git', 'autoload', 'plugin'] + \ }, + \ 'suggest': { + \ 'fromVimruntime': v:true, + \ 'fromRuntimepath': v:false + \ }, + \ } + \} +< + Consult the vim-language-server documentation for more information about + settings. + + +g:ale_vim_vimls_use_global *g:ale_vim_vimls_use_global* + *b:ale_vim_vimls_use_global* + Type: |Number| + Default: `get(g:, 'ale_use_global_executables', 0)` + + See |ale-integrations-local-executables| + + =============================================================================== vint *ale-vim-vint* diff --git a/doc/ale.txt b/doc/ale.txt index 81212029..16b204a4 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -2655,6 +2655,7 @@ documented in additional help files. vcom..................................|ale-vhdl-vcom| xvhdl.................................|ale-vhdl-xvhdl| vim.....................................|ale-vim-options| + vimls.................................|ale-vim-vimls| vint..................................|ale-vim-vint| vim help................................|ale-vim-help-options| write-good............................|ale-vim-help-write-good| diff --git a/supported-tools.md b/supported-tools.md index 0abc6b75..d5c0c9d4 100644 --- a/supported-tools.md +++ b/supported-tools.md @@ -494,6 +494,7 @@ formatting. * [vcom](https://www.mentor.com/products/fv/questa/) * [xvhdl](https://www.xilinx.com/products/design-tools/vivado.html) * Vim + * [vimls](https://github.com/iamcco/vim-language-server) * [vint](https://github.com/Kuniwak/vint) * Vim help * [alex](https://github.com/wooorm/alex) :warning: :floppy_disk: diff --git a/test/command_callback/test_vim_vimls.vader b/test/command_callback/test_vim_vimls.vader new file mode 100644 index 00000000..ab12b637 --- /dev/null +++ b/test/command_callback/test_vim_vimls.vader @@ -0,0 +1,76 @@ +" Author: Jeffrey Lau https://github.com/zoonfafer +" Description: Tests for the Vim vimls linter + +Before: + call ale#assert#SetUpLinterTest('vim', 'vimls') + +After: + if isdirectory(g:dir . '/.git') + call delete(g:dir . '/.git', 'd') + endif + + call ale#assert#TearDownLinterTest() + +Execute(should set correct defaults): + AssertLinter 'vim-language-server', ale#Escape('vim-language-server') . ' --stdio' + +Execute(should set correct LSP values): + call ale#test#SetFilename('vim_fixtures/path_with_autoload/test.vim') + AssertLSPLanguage 'vim' + AssertLSPOptions {} + AssertLSPConfig {} + AssertLSPProject ale#path#Simplify(g:dir . '/vim_fixtures/path_with_autoload') + +Execute(should set correct project for .git/): + let b:parent_dir = ale#path#Simplify(g:dir . '/..') + let b:git_dir = b:parent_dir . '/.git' + + call ale#test#SetFilename('vim_fixtures/test.vim') + + if !isdirectory(b:git_dir) + call mkdir(b:git_dir) + endif + + AssertLSPProject ale#path#Simplify(b:parent_dir) + + call delete(b:git_dir, 'd') + unlet! b:git_dir + +Execute(should set correct project for plugin/): + call ale#test#SetFilename('vim_fixtures/path_with_plugin/test.vim') + + AssertLSPProject ale#path#Simplify(g:dir . '/vim_fixtures/path_with_plugin') + +Execute(should accept configuration settings): + AssertLSPConfig {} + + let b:ale_vim_vimls_config = {'vim': {'foobar': v:true}} + AssertLSPConfig {'vim': {'foobar': v:true}} + +Execute(should set correct project for .vimrc): + call ale#test#SetFilename('vim_fixtures/path_with_vimrc/.vimrc') + + AssertLSPProject ale#path#Simplify(g:dir . '/vim_fixtures/path_with_vimrc') + +Execute(should set correct project for init.vim): + call ale#test#SetFilename('vim_fixtures/path_with_initvim/init.vim') + + AssertLSPProject ale#path#Simplify(g:dir . '/vim_fixtures/path_with_initvim') + +Execute(should use the local executable when available): + call ale#test#SetFilename('vim_fixtures/file.vim') + + AssertLinter ale#path#Simplify(g:dir . '/vim_fixtures/node_modules/.bin/vim-language-server'), + \ ale#Escape(ale#path#Simplify(g:dir . '/vim_fixtures/node_modules/.bin/vim-language-server')) . ' --stdio' + +Execute(should let the global executable to be used): + let g:ale_vim_vimls_use_global = 1 + call ale#test#SetFilename('vim_fixtures/file.vim') + + AssertLinter 'vim-language-server', + \ ale#Escape('vim-language-server') . ' --stdio' + +Execute(should let the executable to be configured): + let g:ale_vim_vimls_executable = 'foobar' + + AssertLinter 'foobar', ale#Escape('foobar') . ' --stdio' diff --git a/test/command_callback/vim_fixtures/invalid_vim_project/test.vim b/test/command_callback/vim_fixtures/invalid_vim_project/test.vim new file mode 100644 index 00000000..e69de29b diff --git a/test/command_callback/vim_fixtures/node_modules/.bin/vim-language-server b/test/command_callback/vim_fixtures/node_modules/.bin/vim-language-server new file mode 100644 index 00000000..e69de29b diff --git a/test/command_callback/vim_fixtures/path_with_autoload/autoload/test.vim b/test/command_callback/vim_fixtures/path_with_autoload/autoload/test.vim new file mode 100644 index 00000000..e69de29b diff --git a/test/command_callback/vim_fixtures/path_with_autoload/test.vim b/test/command_callback/vim_fixtures/path_with_autoload/test.vim new file mode 100644 index 00000000..e69de29b diff --git a/test/command_callback/vim_fixtures/path_with_initvim/init.vim b/test/command_callback/vim_fixtures/path_with_initvim/init.vim new file mode 100644 index 00000000..e69de29b diff --git a/test/command_callback/vim_fixtures/path_with_plugin/plugin/test.vim b/test/command_callback/vim_fixtures/path_with_plugin/plugin/test.vim new file mode 100644 index 00000000..e69de29b diff --git a/test/command_callback/vim_fixtures/path_with_plugin/test.vim b/test/command_callback/vim_fixtures/path_with_plugin/test.vim new file mode 100644 index 00000000..e69de29b diff --git a/test/command_callback/vim_fixtures/path_with_vimrc/.vimrc b/test/command_callback/vim_fixtures/path_with_vimrc/.vimrc new file mode 100644 index 00000000..e69de29b From 47d941b491844153304b3c87664f847df9d5dae4 Mon Sep 17 00:00:00 2001 From: Ian2020 Date: Fri, 24 Apr 2020 11:39:45 +0100 Subject: [PATCH 57/70] Add shellcheck as linter for bats files --- ale_linters/bats/shellcheck.vim | 78 +++++++++++++++++++++++ doc/ale-bats.txt | 48 ++++++++++++++ doc/ale-supported-languages-and-tools.txt | 2 + supported-tools.md | 2 + 4 files changed, 130 insertions(+) create mode 100644 ale_linters/bats/shellcheck.vim create mode 100644 doc/ale-bats.txt diff --git a/ale_linters/bats/shellcheck.vim b/ale_linters/bats/shellcheck.vim new file mode 100644 index 00000000..64130a2d --- /dev/null +++ b/ale_linters/bats/shellcheck.vim @@ -0,0 +1,78 @@ +" Author: Ian2020 +" Description: This file adds support for using the shellcheck linter with +" bats scripts. Heavily inspired by/copied from work by w0rp on shellcheck +" for sh files. + +" This global variable can be set with a string of comma-separated error +" codes to exclude from shellcheck. For example: +" +" let g:ale_bats_shellcheck_exclusions = 'SC2002,SC2004' +call ale#Set('bats_shellcheck_exclusions', get(g:, 'ale_linters_bats_shellcheck_exclusions', '')) +call ale#Set('bats_shellcheck_executable', 'shellcheck') +call ale#Set('bats_shellcheck_options', '') +call ale#Set('bats_shellcheck_change_directory', 1) + +function! ale_linters#bats#shellcheck#GetCommand(buffer, version) abort + let l:options = ale#Var(a:buffer, 'bats_shellcheck_options') + let l:exclude_option = ale#Var(a:buffer, 'bats_shellcheck_exclusions') + let l:external_option = ale#semver#GTE(a:version, [0, 4, 0]) ? ' -x' : '' + let l:cd_string = ale#Var(a:buffer, 'bats_shellcheck_change_directory') + \ ? ale#path#BufferCdString(a:buffer) + \ : '' + + return l:cd_string + \ . '%e' + \ . ' -s bats' + \ . (!empty(l:options) ? ' ' . l:options : '') + \ . (!empty(l:exclude_option) ? ' -e ' . l:exclude_option : '') + \ . l:external_option + \ . ' -f gcc -' +endfunction + +function! ale_linters#bats#shellcheck#Handle(buffer, lines) abort + let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):(\d+)?:? ([^:]+): (.+) \[([^\]]+)\]$' + let l:output = [] + + for l:match in ale#util#GetMatches(a:lines, l:pattern) + if l:match[4] is# 'error' + let l:type = 'E' + elseif l:match[4] is# 'note' + let l:type = 'I' + else + let l:type = 'W' + endif + + let l:item = { + \ 'lnum': str2nr(l:match[2]), + \ 'type': l:type, + \ 'text': l:match[5], + \ 'code': l:match[6], + \} + + if !empty(l:match[3]) + let l:item.col = str2nr(l:match[3]) + endif + + " If the filename is something like , 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 + +call ale#linter#Define('bats', { +\ 'name': 'shellcheck', +\ 'executable': {buffer -> ale#Var(buffer, 'bats_shellcheck_executable')}, +\ 'command': {buffer -> ale#semver#RunWithVersionCheck( +\ buffer, +\ ale#Var(buffer, 'bats_shellcheck_executable'), +\ '%e --version', +\ function('ale_linters#bats#shellcheck#GetCommand'), +\ )}, +\ 'callback': 'ale_linters#bats#shellcheck#Handle', +\}) diff --git a/doc/ale-bats.txt b/doc/ale-bats.txt new file mode 100644 index 00000000..2ad98402 --- /dev/null +++ b/doc/ale-bats.txt @@ -0,0 +1,48 @@ +=============================================================================== +ALE Bats Integration *ale-bats-options* + + +=============================================================================== +shellcheck *ale-bats-shellcheck* + +g:ale_bats_shellcheck_executable *g:ale_bats_shellcheck_executable* + *b:ale_bats_shellcheck_executable* + Type: |String| + Default: `'shellcheck'` + + This variable sets executable used for shellcheck. + + +g:ale_bats_shellcheck_options *g:ale_bats_shellcheck_options* + *b:ale_bats_shellcheck_options* + Type: |String| + Default: `''` + + With this variable we are able to pass extra arguments for shellcheck + for shellcheck invocation. + + For example, if we want shellcheck to follow external sources (`see SC1091`) + we can set the variable as such: +> + let g:ale_bats_shellcheck_options = '-x' +< + + +g:ale_bats_shellcheck_change_directory *g:ale_bats_shellcheck_change_directory* + *b:ale_bats_shellcheck_change_directory* + Type: |Number| + Default: `1` + + If set to `1`, ALE will switch to the directory the shell file being + checked with `shellcheck` is in before checking it. This helps `shellcheck` + determine the path to sourced files more easily. This option can be turned + off if you want to control the directory `shellcheck` is executed from + yourself. + + + autocmd BufEnter PKGBUILD,.env + \ let b:ale_bats_shellcheck_exclusions = 'SC2034,SC2154,SC2164' +< + +=============================================================================== + vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl: diff --git a/doc/ale-supported-languages-and-tools.txt b/doc/ale-supported-languages-and-tools.txt index 636985fb..9fe7bfe5 100644 --- a/doc/ale-supported-languages-and-tools.txt +++ b/doc/ale-supported-languages-and-tools.txt @@ -35,6 +35,8 @@ Notes: * `shell` (-n flag) * `shellcheck` * `shfmt` +* Bats + * `shellcheck` * BibTeX * `bibclean` * Bourne Shell diff --git a/supported-tools.md b/supported-tools.md index d5c0c9d4..f7dd9676 100644 --- a/supported-tools.md +++ b/supported-tools.md @@ -44,6 +44,8 @@ formatting. * shell [-n flag](https://www.gnu.org/software/bash/manual/bash.html#index-set) * [shellcheck](https://www.shellcheck.net/) * [shfmt](https://github.com/mvdan/sh) +* Bats + * [shellcheck](https://www.shellcheck.net/) * BibTeX * [bibclean](http://ftp.math.utah.edu/pub/bibclean/) * Bourne Shell From 76cd6b0f92e7e3baffe0dc83c6d8a75ccb517a1f Mon Sep 17 00:00:00 2001 From: Ian2020 Date: Tue, 28 Apr 2020 16:02:46 +0100 Subject: [PATCH 58/70] Fix documentation oversights --- doc/ale-bats.txt | 2 +- doc/ale.txt | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/ale-bats.txt b/doc/ale-bats.txt index 2ad98402..8554d186 100644 --- a/doc/ale-bats.txt +++ b/doc/ale-bats.txt @@ -1,5 +1,5 @@ =============================================================================== -ALE Bats Integration *ale-bats-options* +ALE Bats Integration *ale-bats-options* =============================================================================== diff --git a/doc/ale.txt b/doc/ale.txt index 16b204a4..acca23f8 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -2279,6 +2279,8 @@ documented in additional help files. gcc...................................|ale-asm-gcc| awk.....................................|ale-awk-options| gawk..................................|ale-awk-gawk| + bats....................................|ale-bats-options| + shellcheck............................|ale-bats-shellcheck| bib.....................................|ale-bib-options| bibclean..............................|ale-bib-bibclean| c.......................................|ale-c-options| From d4e1c57026395c53547e18ab290fc588e0645d22 Mon Sep 17 00:00:00 2001 From: Ian2020 Date: Tue, 28 Apr 2020 17:46:15 +0100 Subject: [PATCH 59/70] Moved common code to ale handlers, updated bats doc --- ale_linters/bats/shellcheck.vim | 73 +----------------- ale_linters/sh/shellcheck.vim | 103 +------------------------- autoload/ale/handlers/shellcheck.vim | 107 +++++++++++++++++++++++++++ doc/ale-bats.txt | 39 +--------- 4 files changed, 115 insertions(+), 207 deletions(-) create mode 100644 autoload/ale/handlers/shellcheck.vim diff --git a/ale_linters/bats/shellcheck.vim b/ale_linters/bats/shellcheck.vim index 64130a2d..b5a1184b 100644 --- a/ale_linters/bats/shellcheck.vim +++ b/ale_linters/bats/shellcheck.vim @@ -3,76 +3,9 @@ " bats scripts. Heavily inspired by/copied from work by w0rp on shellcheck " for sh files. -" This global variable can be set with a string of comma-separated error -" codes to exclude from shellcheck. For example: -" -" let g:ale_bats_shellcheck_exclusions = 'SC2002,SC2004' -call ale#Set('bats_shellcheck_exclusions', get(g:, 'ale_linters_bats_shellcheck_exclusions', '')) -call ale#Set('bats_shellcheck_executable', 'shellcheck') -call ale#Set('bats_shellcheck_options', '') -call ale#Set('bats_shellcheck_change_directory', 1) - -function! ale_linters#bats#shellcheck#GetCommand(buffer, version) abort - let l:options = ale#Var(a:buffer, 'bats_shellcheck_options') - let l:exclude_option = ale#Var(a:buffer, 'bats_shellcheck_exclusions') - let l:external_option = ale#semver#GTE(a:version, [0, 4, 0]) ? ' -x' : '' - let l:cd_string = ale#Var(a:buffer, 'bats_shellcheck_change_directory') - \ ? ale#path#BufferCdString(a:buffer) - \ : '' - - return l:cd_string - \ . '%e' - \ . ' -s bats' - \ . (!empty(l:options) ? ' ' . l:options : '') - \ . (!empty(l:exclude_option) ? ' -e ' . l:exclude_option : '') - \ . l:external_option - \ . ' -f gcc -' -endfunction - -function! ale_linters#bats#shellcheck#Handle(buffer, lines) abort - let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):(\d+)?:? ([^:]+): (.+) \[([^\]]+)\]$' - let l:output = [] - - for l:match in ale#util#GetMatches(a:lines, l:pattern) - if l:match[4] is# 'error' - let l:type = 'E' - elseif l:match[4] is# 'note' - let l:type = 'I' - else - let l:type = 'W' - endif - - let l:item = { - \ 'lnum': str2nr(l:match[2]), - \ 'type': l:type, - \ 'text': l:match[5], - \ 'code': l:match[6], - \} - - if !empty(l:match[3]) - let l:item.col = str2nr(l:match[3]) - endif - - " If the filename is something like , 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 - call ale#linter#Define('bats', { \ 'name': 'shellcheck', -\ 'executable': {buffer -> ale#Var(buffer, 'bats_shellcheck_executable')}, -\ 'command': {buffer -> ale#semver#RunWithVersionCheck( -\ buffer, -\ ale#Var(buffer, 'bats_shellcheck_executable'), -\ '%e --version', -\ function('ale_linters#bats#shellcheck#GetCommand'), -\ )}, -\ 'callback': 'ale_linters#bats#shellcheck#Handle', +\ 'executable': function('ale#handlers#shellcheck#GetExecutable'), +\ 'command': function('ale#handlers#shellcheck#GetCommand'), +\ 'callback': 'ale#handlers#shellcheck#Handle', \}) diff --git a/ale_linters/sh/shellcheck.vim b/ale_linters/sh/shellcheck.vim index 1d8b6096..fbd7e49b 100644 --- a/ale_linters/sh/shellcheck.vim +++ b/ale_linters/sh/shellcheck.vim @@ -2,106 +2,9 @@ " Description: This file adds support for using the shellcheck linter with " shell scripts. -" This global variable can be set with a string of comma-separated error -" codes to exclude from shellcheck. For example: -" -" let g:ale_sh_shellcheck_exclusions = 'SC2002,SC2004' -call ale#Set('sh_shellcheck_exclusions', get(g:, 'ale_linters_sh_shellcheck_exclusions', '')) -call ale#Set('sh_shellcheck_executable', 'shellcheck') -call ale#Set('sh_shellcheck_dialect', 'auto') -call ale#Set('sh_shellcheck_options', '') -call ale#Set('sh_shellcheck_change_directory', 1) - -function! ale_linters#sh#shellcheck#GetDialectArgument(buffer) abort - let l:shell_type = ale#handlers#sh#GetShellType(a:buffer) - - if !empty(l:shell_type) - " Use the dash dialect for /bin/ash, etc. - if l:shell_type is# 'ash' - return 'dash' - endif - - return l:shell_type - endif - - " If there's no hashbang, try using Vim's buffer variables. - if getbufvar(a:buffer, 'is_bash', 0) - return 'bash' - elseif getbufvar(a:buffer, 'is_sh', 0) - return 'sh' - elseif getbufvar(a:buffer, 'is_kornshell', 0) - return 'ksh' - endif - - return '' -endfunction - -function! ale_linters#sh#shellcheck#GetCommand(buffer, version) abort - let l:options = ale#Var(a:buffer, 'sh_shellcheck_options') - let l:exclude_option = ale#Var(a:buffer, 'sh_shellcheck_exclusions') - let l:dialect = ale#Var(a:buffer, 'sh_shellcheck_dialect') - let l:external_option = ale#semver#GTE(a:version, [0, 4, 0]) ? ' -x' : '' - let l:cd_string = ale#Var(a:buffer, 'sh_shellcheck_change_directory') - \ ? ale#path#BufferCdString(a:buffer) - \ : '' - - if l:dialect is# 'auto' - let l:dialect = ale_linters#sh#shellcheck#GetDialectArgument(a:buffer) - endif - - return l:cd_string - \ . '%e' - \ . (!empty(l:dialect) ? ' -s ' . l:dialect : '') - \ . (!empty(l:options) ? ' ' . l:options : '') - \ . (!empty(l:exclude_option) ? ' -e ' . l:exclude_option : '') - \ . l:external_option - \ . ' -f gcc -' -endfunction - -function! ale_linters#sh#shellcheck#Handle(buffer, lines) abort - let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):(\d+)?:? ([^:]+): (.+) \[([^\]]+)\]$' - let l:output = [] - - for l:match in ale#util#GetMatches(a:lines, l:pattern) - if l:match[4] is# 'error' - let l:type = 'E' - elseif l:match[4] is# 'note' - let l:type = 'I' - else - let l:type = 'W' - endif - - let l:item = { - \ 'lnum': str2nr(l:match[2]), - \ 'type': l:type, - \ 'text': l:match[5], - \ 'code': l:match[6], - \} - - if !empty(l:match[3]) - let l:item.col = str2nr(l:match[3]) - endif - - " If the filename is something like , 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 - call ale#linter#Define('sh', { \ 'name': 'shellcheck', -\ 'executable': {buffer -> ale#Var(buffer, 'sh_shellcheck_executable')}, -\ 'command': {buffer -> ale#semver#RunWithVersionCheck( -\ buffer, -\ ale#Var(buffer, 'sh_shellcheck_executable'), -\ '%e --version', -\ function('ale_linters#sh#shellcheck#GetCommand'), -\ )}, -\ 'callback': 'ale_linters#sh#shellcheck#Handle', +\ 'executable': function('ale#handlers#shellcheck#GetExecutable'), +\ 'command': function('ale#handlers#shellcheck#GetCommand'), +\ 'callback': 'ale#handlers#shellcheck#Handle', \}) diff --git a/autoload/ale/handlers/shellcheck.vim b/autoload/ale/handlers/shellcheck.vim new file mode 100644 index 00000000..b2de4eef --- /dev/null +++ b/autoload/ale/handlers/shellcheck.vim @@ -0,0 +1,107 @@ +" Author: w0rp +" Description: This file adds support for using the shellcheck linter with +" shell scripts. + +" This global variable can be set with a string of comma-separated error +" codes to exclude from shellcheck. For example: +" +" let g:ale_sh_shellcheck_exclusions = 'SC2002,SC2004' +call ale#Set('sh_shellcheck_exclusions', get(g:, 'ale_linters_sh_shellcheck_exclusions', '')) +call ale#Set('sh_shellcheck_executable', 'shellcheck') +call ale#Set('sh_shellcheck_dialect', 'auto') +call ale#Set('sh_shellcheck_options', '') +call ale#Set('sh_shellcheck_change_directory', 1) + +function! ale#handlers#shellcheck#GetDialectArgument(buffer) abort + let l:shell_type = ale#handlers#sh#GetShellType(a:buffer) + + if !empty(l:shell_type) + " Use the dash dialect for /bin/ash, etc. + if l:shell_type is# 'ash' + return 'dash' + endif + + return l:shell_type + endif + + " If there's no hashbang, try using Vim's buffer variables. + if getbufvar(a:buffer, 'is_bash', 0) + return 'bash' + elseif getbufvar(a:buffer, 'is_sh', 0) + return 'sh' + elseif getbufvar(a:buffer, 'is_kornshell', 0) + return 'ksh' + endif + + return '' +endfunction + +function! ale#handlers#shellcheck#GetCommandWithVersion(buffer, version) abort + let l:options = ale#Var(a:buffer, 'sh_shellcheck_options') + let l:exclude_option = ale#Var(a:buffer, 'sh_shellcheck_exclusions') + let l:dialect = ale#Var(a:buffer, 'sh_shellcheck_dialect') + let l:external_option = ale#semver#GTE(a:version, [0, 4, 0]) ? ' -x' : '' + let l:cd_string = ale#Var(a:buffer, 'sh_shellcheck_change_directory') + \ ? ale#path#BufferCdString(a:buffer) + \ : '' + + if l:dialect is# 'auto' + let l:dialect = ale#handlers#shellcheck#GetDialectArgument(a:buffer) + endif + + return l:cd_string + \ . '%e' + \ . (!empty(l:dialect) ? ' -s ' . l:dialect : '') + \ . (!empty(l:options) ? ' ' . l:options : '') + \ . (!empty(l:exclude_option) ? ' -e ' . l:exclude_option : '') + \ . l:external_option + \ . ' -f gcc -' +endfunction + +function! ale#handlers#shellcheck#Handle(buffer, lines) abort + let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):(\d+)?:? ([^:]+): (.+) \[([^\]]+)\]$' + let l:output = [] + + for l:match in ale#util#GetMatches(a:lines, l:pattern) + if l:match[4] is# 'error' + let l:type = 'E' + elseif l:match[4] is# 'note' + let l:type = 'I' + else + let l:type = 'W' + endif + + let l:item = { + \ 'lnum': str2nr(l:match[2]), + \ 'type': l:type, + \ 'text': l:match[5], + \ 'code': l:match[6], + \} + + if !empty(l:match[3]) + let l:item.col = str2nr(l:match[3]) + endif + + " If the filename is something like , 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 + +function! ale#handlers#shellcheck#GetExecutable(buffer) abort + return ale#Var(a:buffer, 'sh_shellcheck_executable') +endfunction + +function! ale#handlers#shellcheck#GetCommand(buffer) abort + return ale#semver#RunWithVersionCheck(a:buffer, +\ ale#Var(a:buffer, 'sh_shellcheck_executable'), +\ '%e --version', +\ function('ale#handlers#shellcheck#GetCommandWithVersion'), +\ ) +endfunction diff --git a/doc/ale-bats.txt b/doc/ale-bats.txt index 8554d186..cf2199ec 100644 --- a/doc/ale-bats.txt +++ b/doc/ale-bats.txt @@ -5,44 +5,9 @@ ALE Bats Integration *ale-bats-options =============================================================================== shellcheck *ale-bats-shellcheck* -g:ale_bats_shellcheck_executable *g:ale_bats_shellcheck_executable* - *b:ale_bats_shellcheck_executable* - Type: |String| - Default: `'shellcheck'` +The `shellcheck` linter for Bats uses the sh options for `shellcheck`; see: +|ale-sh-shellcheck|. - This variable sets executable used for shellcheck. - - -g:ale_bats_shellcheck_options *g:ale_bats_shellcheck_options* - *b:ale_bats_shellcheck_options* - Type: |String| - Default: `''` - - With this variable we are able to pass extra arguments for shellcheck - for shellcheck invocation. - - For example, if we want shellcheck to follow external sources (`see SC1091`) - we can set the variable as such: -> - let g:ale_bats_shellcheck_options = '-x' -< - - -g:ale_bats_shellcheck_change_directory *g:ale_bats_shellcheck_change_directory* - *b:ale_bats_shellcheck_change_directory* - Type: |Number| - Default: `1` - - If set to `1`, ALE will switch to the directory the shell file being - checked with `shellcheck` is in before checking it. This helps `shellcheck` - determine the path to sourced files more easily. This option can be turned - off if you want to control the directory `shellcheck` is executed from - yourself. - - - autocmd BufEnter PKGBUILD,.env - \ let b:ale_bats_shellcheck_exclusions = 'SC2034,SC2154,SC2164' -< =============================================================================== vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl: From 3f3426515107ae62b2e0d158ab192fcec95cfd10 Mon Sep 17 00:00:00 2001 From: Ian2020 Date: Tue, 28 Apr 2020 18:13:34 +0100 Subject: [PATCH 60/70] Fix handler test, function name has changed --- test/handler/test_shellcheck_handler.vader | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/handler/test_shellcheck_handler.vader b/test/handler/test_shellcheck_handler.vader index bfb73ffa..33f12989 100644 --- a/test/handler/test_shellcheck_handler.vader +++ b/test/handler/test_shellcheck_handler.vader @@ -22,7 +22,7 @@ Execute(The shellcheck handler should handle basic errors or warnings): \ 'code': 'SC1068', \ }, \ ], - \ ale_linters#sh#shellcheck#Handle(bufnr(''), [ + \ ale#handlers#shellcheck#Handle(bufnr(''), [ \ '-:2:1: warning: In POSIX sh, ''let'' is not supported. [SC2039]', \ '-:2:3: error: Don''t put spaces around the = in assignments. [SC1068]', \ ]) @@ -38,6 +38,6 @@ Execute(The shellcheck handler should handle notes): \ 'code': 'SC2086', \ }, \ ], - \ ale_linters#sh#shellcheck#Handle(bufnr(''), [ + \ ale#handlers#shellcheck#Handle(bufnr(''), [ \ '-:3:3: note: Double quote to prevent globbing and word splitting. [SC2086]', \ ]) From f67cb56e5e73f00da643b050bfb6ab6e4416c5a2 Mon Sep 17 00:00:00 2001 From: Ian2020 Date: Tue, 28 Apr 2020 18:20:10 +0100 Subject: [PATCH 61/70] Fix shell detection test, shellcheck function name has changed --- test/test_shell_detection.vader | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/test/test_shell_detection.vader b/test/test_shell_detection.vader index 88ee462d..6452287f 100644 --- a/test/test_shell_detection.vader +++ b/test/test_shell_detection.vader @@ -15,7 +15,7 @@ Given(A file with a Bash hashbang): Execute(/bin/bash should be detected appropriately): AssertEqual 'bash', ale#handlers#sh#GetShellType(bufnr('')) AssertEqual 'bash', ale_linters#sh#shell#GetExecutable(bufnr('')) - AssertEqual 'bash', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) + AssertEqual 'bash', ale#handlers#shellcheck#GetDialectArgument(bufnr('')) Given(A file with /bin/sh): #!/usr/bin/env sh -eu --foobar @@ -23,7 +23,7 @@ Given(A file with /bin/sh): Execute(/bin/sh should be detected appropriately): AssertEqual 'sh', ale#handlers#sh#GetShellType(bufnr('')) AssertEqual 'sh', ale_linters#sh#shell#GetExecutable(bufnr('')) - AssertEqual 'sh', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) + AssertEqual 'sh', ale#handlers#shellcheck#GetDialectArgument(bufnr('')) Given(A file with bash as an argument to env): #!/usr/bin/env bash @@ -31,7 +31,7 @@ Given(A file with bash as an argument to env): Execute(/usr/bin/env bash should be detected appropriately): AssertEqual 'bash', ale#handlers#sh#GetShellType(bufnr('')) AssertEqual 'bash', ale_linters#sh#shell#GetExecutable(bufnr('')) - AssertEqual 'bash', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) + AssertEqual 'bash', ale#handlers#shellcheck#GetDialectArgument(bufnr('')) Given(A file with a tcsh hash bang and arguments): #!/usr/bin/env tcsh -eu --foobar @@ -39,7 +39,7 @@ Given(A file with a tcsh hash bang and arguments): Execute(tcsh should be detected appropriately): AssertEqual 'tcsh', ale#handlers#sh#GetShellType(bufnr('')) AssertEqual 'tcsh', ale_linters#sh#shell#GetExecutable(bufnr('')) - AssertEqual 'tcsh', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) + AssertEqual 'tcsh', ale#handlers#shellcheck#GetDialectArgument(bufnr('')) Given(A file with a zsh hash bang and arguments): #!/usr/bin/env zsh -eu --foobar @@ -47,7 +47,7 @@ Given(A file with a zsh hash bang and arguments): Execute(zsh should be detected appropriately): AssertEqual 'zsh', ale#handlers#sh#GetShellType(bufnr('')) AssertEqual 'zsh', ale_linters#sh#shell#GetExecutable(bufnr('')) - AssertEqual 'zsh', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) + AssertEqual 'zsh', ale#handlers#shellcheck#GetDialectArgument(bufnr('')) Given(A file with a csh hash bang and arguments): #!/usr/bin/env csh -eu --foobar @@ -55,7 +55,7 @@ Given(A file with a csh hash bang and arguments): Execute(csh should be detected appropriately): AssertEqual 'csh', ale#handlers#sh#GetShellType(bufnr('')) AssertEqual 'csh', ale_linters#sh#shell#GetExecutable(bufnr('')) - AssertEqual 'csh', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) + AssertEqual 'csh', ale#handlers#shellcheck#GetDialectArgument(bufnr('')) Given(A file with a ksh hashbang): #!/bin/ksh @@ -63,7 +63,7 @@ Given(A file with a ksh hashbang): Execute(/bin/ksh should be detected appropriately): AssertEqual 'ksh', ale#handlers#sh#GetShellType(bufnr('')) AssertEqual 'ksh', ale_linters#sh#shell#GetExecutable(bufnr('')) - AssertEqual 'ksh', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) + AssertEqual 'ksh', ale#handlers#shellcheck#GetDialectArgument(bufnr('')) Given(A file with a ksh as an argument to env): #!/usr/bin/env ksh @@ -71,7 +71,7 @@ Given(A file with a ksh as an argument to env): Execute(ksh should be detected appropriately): AssertEqual 'ksh', ale#handlers#sh#GetShellType(bufnr('')) AssertEqual 'ksh', ale_linters#sh#shell#GetExecutable(bufnr('')) - AssertEqual 'ksh', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) + AssertEqual 'ksh', ale#handlers#shellcheck#GetDialectArgument(bufnr('')) Given(A file with a sh hash bang and arguments): #!/usr/bin/env sh -eu --foobar @@ -79,24 +79,24 @@ Given(A file with a sh hash bang and arguments): Execute(sh should be detected appropriately): AssertEqual 'sh', ale#handlers#sh#GetShellType(bufnr('')) AssertEqual 'sh', ale_linters#sh#shell#GetExecutable(bufnr('')) - AssertEqual 'sh', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) + AssertEqual 'sh', ale#handlers#shellcheck#GetDialectArgument(bufnr('')) Given(A file without a hashbang): Execute(The bash dialect should be used for shellcheck if b:is_bash is 1): let b:is_bash = 1 - AssertEqual 'bash', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) + AssertEqual 'bash', ale#handlers#shellcheck#GetDialectArgument(bufnr('')) Execute(The sh dialect should be used for shellcheck if b:is_sh is 1): let b:is_sh = 1 - AssertEqual 'sh', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) + AssertEqual 'sh', ale#handlers#shellcheck#GetDialectArgument(bufnr('')) Execute(The ksh dialect should be used for shellcheck if b:is_kornshell is 1): let b:is_kornshell = 1 - AssertEqual 'ksh', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) + AssertEqual 'ksh', ale#handlers#shellcheck#GetDialectArgument(bufnr('')) Given(A file with /bin/ash): #!/bin/ash @@ -106,7 +106,7 @@ Execute(The ash dialect should be used for the shell and the base function): AssertEqual 'ash', ale_linters#sh#shell#GetExecutable(bufnr('')) Execute(dash should be used for shellcheck, which has no ash dialect): - AssertEqual 'dash', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) + AssertEqual 'dash', ale#handlers#shellcheck#GetDialectArgument(bufnr('')) Given(A file with /bin/dash): #!/bin/dash @@ -116,4 +116,4 @@ Execute(The dash dialect should be used for the shell and the base function): AssertEqual 'dash', ale_linters#sh#shell#GetExecutable(bufnr('')) Execute(dash should be used for shellcheck): - AssertEqual 'dash', ale_linters#sh#shellcheck#GetDialectArgument(bufnr('')) + AssertEqual 'dash', ale#handlers#shellcheck#GetDialectArgument(bufnr('')) From 716f9a9bbb46162e967cb95b892d0516a06ef129 Mon Sep 17 00:00:00 2001 From: Ian2020 Date: Tue, 28 Apr 2020 20:53:42 +0100 Subject: [PATCH 62/70] Fix linting issue - indentation incorrect --- autoload/ale/handlers/shellcheck.vim | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/autoload/ale/handlers/shellcheck.vim b/autoload/ale/handlers/shellcheck.vim index b2de4eef..2a5eadc3 100644 --- a/autoload/ale/handlers/shellcheck.vim +++ b/autoload/ale/handlers/shellcheck.vim @@ -100,8 +100,8 @@ endfunction function! ale#handlers#shellcheck#GetCommand(buffer) abort return ale#semver#RunWithVersionCheck(a:buffer, -\ ale#Var(a:buffer, 'sh_shellcheck_executable'), -\ '%e --version', -\ function('ale#handlers#shellcheck#GetCommandWithVersion'), -\ ) + \ ale#Var(a:buffer, 'sh_shellcheck_executable'), + \ '%e --version', + \ function('ale#handlers#shellcheck#GetCommandWithVersion'), + \) endfunction From 65bea1a5cbbc8ff2557410263c87c2e02cb4a42c Mon Sep 17 00:00:00 2001 From: Ian2020 Date: Wed, 29 Apr 2020 17:45:16 +0100 Subject: [PATCH 63/70] Main logic of shellcheck has moved, updated backward compat test --- test/test_backwards_compatibility.vader | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_backwards_compatibility.vader b/test/test_backwards_compatibility.vader index e4e3756f..e0e52bd4 100644 --- a/test/test_backwards_compatibility.vader +++ b/test/test_backwards_compatibility.vader @@ -8,7 +8,7 @@ After: Execute(Old variable name for the 'shellcheck' linter should still work): let g:ale_linters_sh_shellcheck_exclusions = 'SC1234' - runtime ale_linters/sh/shellcheck.vim + runtime autoload/ale/handlers/shellcheck.vim AssertEqual 'SC1234', g:ale_sh_shellcheck_exclusions From ca97f32258cc6e3f32b5f7605801f053e7dbe320 Mon Sep 17 00:00:00 2001 From: Ian2020 Date: Fri, 8 May 2020 12:55:54 +0100 Subject: [PATCH 64/70] Use a function to define shellcheck linters and vars needed, fixes tests --- ale_linters/bats/shellcheck.vim | 11 ++----- ale_linters/sh/shellcheck.vim | 10 ++---- autoload/ale/handlers/shellcheck.vim | 44 ++++++++++++------------- test/test_backwards_compatibility.vader | 2 +- 4 files changed, 27 insertions(+), 40 deletions(-) diff --git a/ale_linters/bats/shellcheck.vim b/ale_linters/bats/shellcheck.vim index b5a1184b..5c2a0ea9 100644 --- a/ale_linters/bats/shellcheck.vim +++ b/ale_linters/bats/shellcheck.vim @@ -1,11 +1,4 @@ " Author: Ian2020 -" Description: This file adds support for using the shellcheck linter with -" bats scripts. Heavily inspired by/copied from work by w0rp on shellcheck -" for sh files. +" Description: shellcheck linter for bats scripts. -call ale#linter#Define('bats', { -\ 'name': 'shellcheck', -\ 'executable': function('ale#handlers#shellcheck#GetExecutable'), -\ 'command': function('ale#handlers#shellcheck#GetCommand'), -\ 'callback': 'ale#handlers#shellcheck#Handle', -\}) +call ale#handlers#shellcheck#DefineLinter('bats') diff --git a/ale_linters/sh/shellcheck.vim b/ale_linters/sh/shellcheck.vim index fbd7e49b..d9945126 100644 --- a/ale_linters/sh/shellcheck.vim +++ b/ale_linters/sh/shellcheck.vim @@ -1,10 +1,4 @@ " Author: w0rp -" Description: This file adds support for using the shellcheck linter with -" shell scripts. +" Description: shellcheck linter for shell scripts. -call ale#linter#Define('sh', { -\ 'name': 'shellcheck', -\ 'executable': function('ale#handlers#shellcheck#GetExecutable'), -\ 'command': function('ale#handlers#shellcheck#GetCommand'), -\ 'callback': 'ale#handlers#shellcheck#Handle', -\}) +call ale#handlers#shellcheck#DefineLinter('sh') diff --git a/autoload/ale/handlers/shellcheck.vim b/autoload/ale/handlers/shellcheck.vim index 2a5eadc3..b16280f0 100644 --- a/autoload/ale/handlers/shellcheck.vim +++ b/autoload/ale/handlers/shellcheck.vim @@ -1,16 +1,5 @@ " Author: w0rp -" Description: This file adds support for using the shellcheck linter with -" shell scripts. - -" This global variable can be set with a string of comma-separated error -" codes to exclude from shellcheck. For example: -" -" let g:ale_sh_shellcheck_exclusions = 'SC2002,SC2004' -call ale#Set('sh_shellcheck_exclusions', get(g:, 'ale_linters_sh_shellcheck_exclusions', '')) -call ale#Set('sh_shellcheck_executable', 'shellcheck') -call ale#Set('sh_shellcheck_dialect', 'auto') -call ale#Set('sh_shellcheck_options', '') -call ale#Set('sh_shellcheck_change_directory', 1) +" Description: This file adds support for using the shellcheck linter function! ale#handlers#shellcheck#GetDialectArgument(buffer) abort let l:shell_type = ale#handlers#sh#GetShellType(a:buffer) @@ -36,7 +25,7 @@ function! ale#handlers#shellcheck#GetDialectArgument(buffer) abort return '' endfunction -function! ale#handlers#shellcheck#GetCommandWithVersion(buffer, version) abort +function! ale#handlers#shellcheck#GetCommand(buffer, version) abort let l:options = ale#Var(a:buffer, 'sh_shellcheck_options') let l:exclude_option = ale#Var(a:buffer, 'sh_shellcheck_exclusions') let l:dialect = ale#Var(a:buffer, 'sh_shellcheck_dialect') @@ -94,14 +83,25 @@ function! ale#handlers#shellcheck#Handle(buffer, lines) abort return l:output endfunction -function! ale#handlers#shellcheck#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'sh_shellcheck_executable') -endfunction +function! ale#handlers#shellcheck#DefineLinter(filetype) abort + " This global variable can be set with a string of comma-separated error + " codes to exclude from shellcheck. For example: + " let g:ale_sh_shellcheck_exclusions = 'SC2002,SC2004' + call ale#Set('sh_shellcheck_exclusions', get(g:, 'ale_linters_sh_shellcheck_exclusions', '')) + call ale#Set('sh_shellcheck_executable', 'shellcheck') + call ale#Set('sh_shellcheck_dialect', 'auto') + call ale#Set('sh_shellcheck_options', '') + call ale#Set('sh_shellcheck_change_directory', 1) -function! ale#handlers#shellcheck#GetCommand(buffer) abort - return ale#semver#RunWithVersionCheck(a:buffer, - \ ale#Var(a:buffer, 'sh_shellcheck_executable'), - \ '%e --version', - \ function('ale#handlers#shellcheck#GetCommandWithVersion'), - \) + call ale#linter#Define(a:filetype, { + \ 'name': 'shellcheck', + \ 'executable': {buffer -> ale#Var(buffer, 'sh_shellcheck_executable')}, + \ 'command': {buffer -> ale#semver#RunWithVersionCheck( + \ buffer, + \ ale#Var(buffer, 'sh_shellcheck_executable'), + \ '%e --version', + \ function('ale#handlers#shellcheck#GetCommand'), + \ )}, + \ 'callback': 'ale#handlers#shellcheck#Handle', + \}) endfunction diff --git a/test/test_backwards_compatibility.vader b/test/test_backwards_compatibility.vader index e0e52bd4..e4e3756f 100644 --- a/test/test_backwards_compatibility.vader +++ b/test/test_backwards_compatibility.vader @@ -8,7 +8,7 @@ After: Execute(Old variable name for the 'shellcheck' linter should still work): let g:ale_linters_sh_shellcheck_exclusions = 'SC1234' - runtime autoload/ale/handlers/shellcheck.vim + runtime ale_linters/sh/shellcheck.vim AssertEqual 'SC1234', g:ale_sh_shellcheck_exclusions From 3b4193175ed75d099e40aad8d60033ab20b44521 Mon Sep 17 00:00:00 2001 From: NiBo Date: Fri, 15 May 2020 10:48:03 +0800 Subject: [PATCH 65/70] feat(javac): Add java_javac_sourcepath variable This variable can set multiple source code paths, the source code path is a relative path (relative to the project root directory) --- ale_linters/java/javac.vim | 11 +++++++++++ doc/ale-java.txt | 15 +++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/ale_linters/java/javac.vim b/ale_linters/java/javac.vim index 8bb52c0b..e166bea4 100644 --- a/ale_linters/java/javac.vim +++ b/ale_linters/java/javac.vim @@ -6,6 +6,7 @@ let s:classpath_sep = has('unix') ? ':' : ';' call ale#Set('java_javac_executable', 'javac') call ale#Set('java_javac_options', '') call ale#Set('java_javac_classpath', '') +call ale#Set('java_javac_sourcepath', []) function! ale_linters#java#javac#RunWithImportPaths(buffer) abort let l:command = '' @@ -79,6 +80,16 @@ function! ale_linters#java#javac#GetCommand(buffer, import_paths, meta) abort endif endif + let l:sourcepath_item = ale#Var(a:buffer, 'java_javac_sourcepath') + if !empty(l:sourcepath_item) + for l:sourcepath in l:sourcepath_item + let l:sp_path = ale#path#FindNearestDirectory(a:buffer, l:sourcepath) + if !empty(l:sp_path) + call add(l:sp_dirs, l:sp_path) + endif + endfor + endif + if !empty(l:sp_dirs) let l:sp_option = '-sourcepath ' \ . ale#Escape(join(l:sp_dirs, s:classpath_sep)) diff --git a/doc/ale-java.txt b/doc/ale-java.txt index 15e9e679..ea426f0d 100644 --- a/doc/ale-java.txt +++ b/doc/ale-java.txt @@ -67,6 +67,21 @@ g:ale_java_javac_options *g:ale_java_javac_options* This variable can be set to pass additional options to javac. +g:ale_java_javac_sourcepath *g:ale_java_javac_sourcepath* + *b:ale_java_javac_sourcepath* + Type: |List| + Default: `[]` + + This variable can set multiple source code paths, the source code path is a + relative path (relative to the project root directory). + + Example: + > + let g:ale_java_javac_sourcepath = [ + \ 'build/generated/source/querydsl/main', + \ 'target/generated-sources/source/querydsl/main' + \ ] + =============================================================================== google-java-format *ale-java-google-java-format* From 3635285c022ebaa0fe3d54ca74cac1207dda555b Mon Sep 17 00:00:00 2001 From: NiBo Date: Fri, 15 May 2020 11:19:06 +0800 Subject: [PATCH 66/70] style(javac): Code formatting --- ale_linters/java/javac.vim | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ale_linters/java/javac.vim b/ale_linters/java/javac.vim index e166bea4..928f555f 100644 --- a/ale_linters/java/javac.vim +++ b/ale_linters/java/javac.vim @@ -81,9 +81,11 @@ function! ale_linters#java#javac#GetCommand(buffer, import_paths, meta) abort endif let l:sourcepath_item = ale#Var(a:buffer, 'java_javac_sourcepath') + if !empty(l:sourcepath_item) for l:sourcepath in l:sourcepath_item let l:sp_path = ale#path#FindNearestDirectory(a:buffer, l:sourcepath) + if !empty(l:sp_path) call add(l:sp_dirs, l:sp_path) endif From ff6bfc3d374706ab80d3dc40a4d3a15baffa8ad2 Mon Sep 17 00:00:00 2001 From: NiBo Date: Mon, 18 May 2020 17:35:16 +0800 Subject: [PATCH 67/70] refactor(javac): ale_java_javac_sourcepath variable supports String and List types --- ale_linters/java/javac.vim | 17 +++- doc/ale-java.txt | 27 ++++-- .../build/gen/main/java/com/something/dummy | 0 .../build/gen2/main/java/com/something/dummy | 0 .../test_javac_command_callback.vader | 86 +++++++++++++++++++ 5 files changed, 117 insertions(+), 13 deletions(-) create mode 100644 test/command_callback/java_paths/build/gen/main/java/com/something/dummy create mode 100644 test/command_callback/java_paths/build/gen2/main/java/com/something/dummy diff --git a/ale_linters/java/javac.vim b/ale_linters/java/javac.vim index 928f555f..5ea40026 100644 --- a/ale_linters/java/javac.vim +++ b/ale_linters/java/javac.vim @@ -80,11 +80,20 @@ function! ale_linters#java#javac#GetCommand(buffer, import_paths, meta) abort endif endif - let l:sourcepath_item = ale#Var(a:buffer, 'java_javac_sourcepath') + let l:source_paths = [] + let l:source_path = ale#Var(a:buffer, 'java_javac_sourcepath') - if !empty(l:sourcepath_item) - for l:sourcepath in l:sourcepath_item - let l:sp_path = ale#path#FindNearestDirectory(a:buffer, l:sourcepath) + if !empty(l:source_path) && type(l:source_path) is v:t_string + let l:source_paths = split(l:source_path, s:classpath_sep) + endif + + if !empty(l:source_path) && type(l:source_path) is v:t_list + let l:source_paths = l:source_path + endif + + if !empty(l:source_paths) + for l:path in l:source_paths + let l:sp_path = ale#path#FindNearestDirectory(a:buffer, l:path) if !empty(l:sp_path) call add(l:sp_dirs, l:sp_path) diff --git a/doc/ale-java.txt b/doc/ale-java.txt index ea426f0d..3016aede 100644 --- a/doc/ale-java.txt +++ b/doc/ale-java.txt @@ -69,18 +69,27 @@ g:ale_java_javac_options *g:ale_java_javac_options* g:ale_java_javac_sourcepath *g:ale_java_javac_sourcepath* *b:ale_java_javac_sourcepath* - Type: |List| + Type: |String| or |List| Default: `[]` - This variable can set multiple source code paths, the source code path is a - relative path (relative to the project root directory). +This variable can set multiple source code paths, the source code path is a +relative path (relative to the project root directory). - Example: - > - let g:ale_java_javac_sourcepath = [ - \ 'build/generated/source/querydsl/main', - \ 'target/generated-sources/source/querydsl/main' - \ ] +Example: + +String type: +Note that the unix system separator is a colon(`:`) window system +is a semicolon(`;`). +> + let g:ale_java_javac_sourcepath = 'build/gen/source/xx/main:build/gen/source' +< +List type: +> + let g:ale_java_javac_sourcepath = [ + \ 'build/generated/source/querydsl/main', + \ 'target/generated-sources/source/querydsl/main' + \ ] +< =============================================================================== diff --git a/test/command_callback/java_paths/build/gen/main/java/com/something/dummy b/test/command_callback/java_paths/build/gen/main/java/com/something/dummy new file mode 100644 index 00000000..e69de29b diff --git a/test/command_callback/java_paths/build/gen2/main/java/com/something/dummy b/test/command_callback/java_paths/build/gen2/main/java/com/something/dummy new file mode 100644 index 00000000..e69de29b diff --git a/test/command_callback/test_javac_command_callback.vader b/test/command_callback/test_javac_command_callback.vader index 42c64e54..7e612ae2 100644 --- a/test/command_callback/test_javac_command_callback.vader +++ b/test/command_callback/test_javac_command_callback.vader @@ -108,6 +108,92 @@ Execute(The javac callback should combine discovered classpaths and manual ones) \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t', \ substitute(b:command, '%e', '\=ale#Escape(''javac'')', 'g') +Execute(The javac callback should use string type g:ale_java_javac_sourcepath correctly): + let g:ale_java_javac_sourcepath = 'java_paths/build/gen/main' + + AssertLinter 'javac', + \ g:prefix + \ . ' -sourcepath ' . ale#Escape( + \ ale#path#Simplify(g:dir . '/java_paths/build/gen/main/') + \ ) + \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t' + +Execute(The javac callback should use list type g:ale_java_javac_sourcepath correctly): + let g:ale_java_javac_sourcepath = ['java_paths/build/gen/main'] + + AssertLinter 'javac', + \ g:prefix + \ . ' -sourcepath ' . ale#Escape( + \ ale#path#Simplify(g:dir . '/java_paths/build/gen/main/') + \ ) + \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t' + +Execute(The javac callback shouldn't add -sourcepath when g:ale_java_javac_sourcepath variable path doesn't exist): + let g:ale_java_javac_sourcepath = 'java_paths/build/gen3/main' + + AssertLinter 'javac', + \ g:prefix + \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t' + +Execute(The javac callback should combine discovered sourcepath and manual ones): + call ale#engine#Cleanup(bufnr('')) + call ale#test#SetFilename('java_paths/src/main/java/com/something/dummy.java') + call ale#engine#InitBufferInfo(bufnr('')) + + let g:ale_java_javac_sourcepath = 'java_paths/build/gen/main' + let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [], {}) + + AssertEqual + \ ale#path#CdString(expand('%:p:h')) . ale#Escape('javac') . ' -Xlint' + \ . ' -sourcepath ' . ale#Escape(join([ + \ ale#path#Simplify(g:dir . '/java_paths/src/main/java/'), + \ ale#path#Simplify(g:dir . '/java_paths/build/gen/main/'), + \ ], g:cp_sep)) + \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t', + \ substitute(b:command, '%e', '\=ale#Escape(''javac'')', 'g') + + let g:ale_java_javac_sourcepath = 'java_paths/build/gen/main' + \ . g:cp_sep . 'java_paths/build/gen2/main' + let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [], {}) + + AssertEqual + \ ale#path#CdString(expand('%:p:h')) . ale#Escape('javac') . ' -Xlint' + \ . ' -sourcepath ' . ale#Escape(join([ + \ ale#path#Simplify(g:dir . '/java_paths/src/main/java/'), + \ ale#path#Simplify(g:dir . '/java_paths/build/gen/main/'), + \ ale#path#Simplify(g:dir . '/java_paths/build/gen2/main/') + \ ], g:cp_sep)) + \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t', + \ substitute(b:command, '%e', '\=ale#Escape(''javac'')', 'g') + + let g:ale_java_javac_sourcepath = ['java_paths/build/gen/main'] + let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [], {}) + + AssertEqual + \ ale#path#CdString(expand('%:p:h')) . ale#Escape('javac') . ' -Xlint' + \ . ' -sourcepath ' . ale#Escape(join([ + \ ale#path#Simplify(g:dir . '/java_paths/src/main/java/'), + \ ale#path#Simplify(g:dir . '/java_paths/build/gen/main/') + \ ], g:cp_sep)) + \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t', + \ substitute(b:command, '%e', '\=ale#Escape(''javac'')', 'g') + + let g:ale_java_javac_sourcepath = [ + \ 'java_paths/build/gen/main', + \ 'java_paths/build/gen2/main' + \ ] + let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [], {}) + + AssertEqual + \ ale#path#CdString(expand('%:p:h')) . ale#Escape('javac') . ' -Xlint' + \ . ' -sourcepath ' . ale#Escape(join([ + \ ale#path#Simplify(g:dir . '/java_paths/src/main/java/'), + \ ale#path#Simplify(g:dir . '/java_paths/build/gen/main/'), + \ ale#path#Simplify(g:dir . '/java_paths/build/gen2/main/') + \ ], g:cp_sep)) + \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t', + \ substitute(b:command, '%e', '\=ale#Escape(''javac'')', 'g') + Execute(The javac callback should detect source directories): call ale#engine#Cleanup(bufnr('')) noautocmd e! java_paths/src/main/java/com/something/dummy From e61e1147b0cc33039c96f9518e22363d3d63d5a9 Mon Sep 17 00:00:00 2001 From: NiBo Date: Tue, 19 May 2020 10:43:16 +0800 Subject: [PATCH 68/70] refactor(javac): ale_java_javac_classpath variable supports String and List types --- ale_linters/java/javac.vim | 13 +++-- doc/ale-java.txt | 2 +- .../test_javac_command_callback.vader | 55 ++++++++++++++++++- 3 files changed, 64 insertions(+), 6 deletions(-) diff --git a/ale_linters/java/javac.vim b/ale_linters/java/javac.vim index 5ea40026..949733f8 100644 --- a/ale_linters/java/javac.vim +++ b/ale_linters/java/javac.vim @@ -41,10 +41,15 @@ endfunction function! s:BuildClassPathOption(buffer, import_paths) abort " Filter out lines like [INFO], etc. let l:class_paths = filter(a:import_paths[:], 'v:val !~# ''[''') - call extend( - \ l:class_paths, - \ split(ale#Var(a:buffer, 'java_javac_classpath'), s:classpath_sep), - \) + let l:cls_path = ale#Var(a:buffer, 'java_javac_classpath') + + if !empty(l:cls_path) && type(l:cls_path) is v:t_string + call extend(l:class_paths, split(l:cls_path, s:classpath_sep)) + endif + + if !empty(l:cls_path) && type(l:cls_path) is v:t_list + call extend(l:class_paths, l:cls_path) + endif return !empty(l:class_paths) \ ? '-cp ' . ale#Escape(join(l:class_paths, s:classpath_sep)) diff --git a/doc/ale-java.txt b/doc/ale-java.txt index 3016aede..1fcd663b 100644 --- a/doc/ale-java.txt +++ b/doc/ale-java.txt @@ -46,7 +46,7 @@ javac *ale-java-javac* g:ale_java_javac_classpath *g:ale_java_javac_classpath* *b:ale_java_javac_classpath* - Type: |String| + Type: |String| or |List| Default: `''` This variable can be set to change the global classpath for Java. diff --git a/test/command_callback/test_javac_command_callback.vader b/test/command_callback/test_javac_command_callback.vader index 7e612ae2..d2eebf7a 100644 --- a/test/command_callback/test_javac_command_callback.vader +++ b/test/command_callback/test_javac_command_callback.vader @@ -31,7 +31,7 @@ After: Execute(The javac callback should return the correct default value): AssertLinter 'javac', g:prefix . ' -d ' . ale#Escape('TEMP_DIR') . ' %t' -Execute(The javac callback should use g:ale_java_javac_classpath correctly): +Execute(The javac callback should use string type g:ale_java_javac_classpath correctly): let g:ale_java_javac_classpath = 'foo.jar' AssertLinter 'javac', @@ -39,6 +39,14 @@ Execute(The javac callback should use g:ale_java_javac_classpath correctly): \ . ' -cp ' . ale#Escape('foo.jar') \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t' +Execute(The javac callback should use list type g:ale_java_javac_classpath correctly): + let g:ale_java_javac_classpath = ['foo.jar'] + + AssertLinter 'javac', + \ g:prefix + \ . ' -cp ' . ale#Escape('foo.jar') + \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t' + Execute(The executable should be configurable): let g:ale_java_javac_executable = 'foobar' @@ -108,6 +116,51 @@ Execute(The javac callback should combine discovered classpaths and manual ones) \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t', \ substitute(b:command, '%e', '\=ale#Escape(''javac'')', 'g') + let g:ale_java_javac_classpath = ['configured.jar'] + let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [ + \ '[DEBUG] Ignore this.', + \ '[INFO] Something we should ignore.', + \ '/foo/bar.jar', + \ '/xyz/abc.jar', + \], {}) + + AssertEqual + \ g:prefix + \ . ' -cp ' + \ . ale#Escape(join( + \ [ + \ '/foo/bar.jar', + \ '/xyz/abc.jar', + \ 'configured.jar', + \ ], + \ g:cp_sep + \ )) + \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t', + \ substitute(b:command, '%e', '\=ale#Escape(''javac'')', 'g') + + let g:ale_java_javac_classpath = ['configured.jar', 'configured2.jar'] + let b:command = ale_linters#java#javac#GetCommand(bufnr(''), [ + \ '[DEBUG] Ignore this.', + \ '[INFO] Something we should ignore.', + \ '/foo/bar.jar', + \ '/xyz/abc.jar', + \], {}) + + AssertEqual + \ g:prefix + \ . ' -cp ' + \ . ale#Escape(join( + \ [ + \ '/foo/bar.jar', + \ '/xyz/abc.jar', + \ 'configured.jar', + \ 'configured2.jar', + \ ], + \ g:cp_sep + \ )) + \ . ' -d ' . ale#Escape('TEMP_DIR') . ' %t', + \ substitute(b:command, '%e', '\=ale#Escape(''javac'')', 'g') + Execute(The javac callback should use string type g:ale_java_javac_sourcepath correctly): let g:ale_java_javac_sourcepath = 'java_paths/build/gen/main' From 0b5d72fecdbb50e9c6b72af7356a10f755e1a764 Mon Sep 17 00:00:00 2001 From: NiBo Date: Tue, 19 May 2020 11:17:17 +0800 Subject: [PATCH 69/70] refactor(javac): ale_java_javac_sourcepath variable defaults to String --- ale_linters/java/javac.vim | 2 +- doc/ale-java.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ale_linters/java/javac.vim b/ale_linters/java/javac.vim index 949733f8..f866eb09 100644 --- a/ale_linters/java/javac.vim +++ b/ale_linters/java/javac.vim @@ -6,7 +6,7 @@ let s:classpath_sep = has('unix') ? ':' : ';' call ale#Set('java_javac_executable', 'javac') call ale#Set('java_javac_options', '') call ale#Set('java_javac_classpath', '') -call ale#Set('java_javac_sourcepath', []) +call ale#Set('java_javac_sourcepath', '') function! ale_linters#java#javac#RunWithImportPaths(buffer) abort let l:command = '' diff --git a/doc/ale-java.txt b/doc/ale-java.txt index 1fcd663b..d2001ca7 100644 --- a/doc/ale-java.txt +++ b/doc/ale-java.txt @@ -70,7 +70,7 @@ g:ale_java_javac_options *g:ale_java_javac_options* g:ale_java_javac_sourcepath *g:ale_java_javac_sourcepath* *b:ale_java_javac_sourcepath* Type: |String| or |List| - Default: `[]` + Default: `''` This variable can set multiple source code paths, the source code path is a relative path (relative to the project root directory). From 7265ceb6d050d1a4642741d248f11e4f2abd37e1 Mon Sep 17 00:00:00 2001 From: Paco Date: Fri, 22 May 2020 19:09:14 +0800 Subject: [PATCH 70/70] Support revive for go files (#2933) Signed-off-by: Penghui Liao --- ale_linters/go/revive.vim | 21 +++++++++++++ doc/ale-go.txt | 19 ++++++++++++ doc/ale-supported-languages-and-tools.txt | 1 + doc/ale.txt | 1 + supported-tools.md | 1 + .../test_revive_command_callbacks.vader | 30 +++++++++++++++++++ 6 files changed, 73 insertions(+) create mode 100644 ale_linters/go/revive.vim create mode 100644 test/command_callback/test_revive_command_callbacks.vader diff --git a/ale_linters/go/revive.vim b/ale_linters/go/revive.vim new file mode 100644 index 00000000..b14b5ab9 --- /dev/null +++ b/ale_linters/go/revive.vim @@ -0,0 +1,21 @@ +" Author: Penghui Liao +" Description: Adds support for revive + +call ale#Set('go_revive_executable', 'revive') +call ale#Set('go_revive_options', '') + +function! ale_linters#go#revive#GetCommand(buffer) abort + let l:options = ale#Var(a:buffer, 'go_revive_options') + + return ale#go#EnvString(a:buffer) . '%e' + \ . (!empty(l:options) ? ' ' . l:options : '') + \ . ' %t' +endfunction + +call ale#linter#Define('go', { +\ 'name': 'revive', +\ 'output_stream': 'both', +\ 'executable': {b -> ale#Var(b, 'go_revive_executable')}, +\ 'command': function('ale_linters#go#revive#GetCommand'), +\ 'callback': 'ale#handlers#unix#HandleAsWarning', +\}) diff --git a/doc/ale-go.txt b/doc/ale-go.txt index be53783e..5c0791bc 100644 --- a/doc/ale-go.txt +++ b/doc/ale-go.txt @@ -219,6 +219,25 @@ g:ale_go_govet_options *g:ale_go_govet_options* This variable can be set to pass additional options to the go vet linter. +=============================================================================== +revive *ale-go-revive* + +g:ale_go_revive_executable *g:ale_go_revive_executable* + *b:ale_go_revive_executable* + Type: |String| + Default: `'revive'` + + This variable can be set to change the revive executable path. + + +g:ale_go_revive_options *g:ale_go_revive_options* + *b:ale_go_revive_options* + Type: |String| + Default: `''` + + This variable can be set to pass additional options to the revive + + =============================================================================== staticcheck *ale-go-staticcheck* diff --git a/doc/ale-supported-languages-and-tools.txt b/doc/ale-supported-languages-and-tools.txt index bd2d5b4a..45252294 100644 --- a/doc/ale-supported-languages-and-tools.txt +++ b/doc/ale-supported-languages-and-tools.txt @@ -164,6 +164,7 @@ Notes: * `gosimple`!! * `gotype`!! * `go vet`!! + * `revive`!! * `staticcheck`!! * GraphQL * `eslint` diff --git a/doc/ale.txt b/doc/ale.txt index 8d5b8820..724da57e 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -2379,6 +2379,7 @@ documented in additional help files. gometalinter..........................|ale-go-gometalinter| gopls.................................|ale-go-gopls| govet.................................|ale-go-govet| + revive................................|ale-go-revive| staticcheck...........................|ale-go-staticcheck| graphql.................................|ale-graphql-options| eslint................................|ale-graphql-eslint| diff --git a/supported-tools.md b/supported-tools.md index f6b26458..7d2f5287 100644 --- a/supported-tools.md +++ b/supported-tools.md @@ -173,6 +173,7 @@ formatting. * [gosimple](https://github.com/dominikh/go-tools/tree/master/cmd/gosimple) :warning: :floppy_disk: * [gotype](https://godoc.org/golang.org/x/tools/cmd/gotype) :warning: :floppy_disk: * [go vet](https://golang.org/cmd/vet/) :floppy_disk: + * [revive](https://github.com/mgechev/revive) :warning: :floppy_disk: * [staticcheck](https://github.com/dominikh/go-tools/tree/master/cmd/staticcheck) :warning: :floppy_disk: * GraphQL * [eslint](http://eslint.org/) diff --git a/test/command_callback/test_revive_command_callbacks.vader b/test/command_callback/test_revive_command_callbacks.vader new file mode 100644 index 00000000..172294f3 --- /dev/null +++ b/test/command_callback/test_revive_command_callbacks.vader @@ -0,0 +1,30 @@ +Before: + Save g:ale_go_go111module + + call ale#assert#SetUpLinterTest('go', 'revive') + +After: + Restore + + unlet! b:ale_go_go111module + + call ale#assert#TearDownLinterTest() + +Execute(The default revive command should be correct): + AssertLinter 'revive', ale#Escape('revive') . ' %t' + +Execute(The revive executable should be configurable): + let b:ale_go_revive_executable = 'foobar' + + AssertLinter 'foobar', ale#Escape('foobar') . ' %t' + +Execute(The revive options should be configurable): + let b:ale_go_revive_options = '--foo' + + AssertLinter 'revive', ale#Escape('revive') . ' --foo %t' + +Execute(The revive command should support Go environment variables): + let b:ale_go_go111module = 'on' + + AssertLinter 'revive', + \ ale#Env('GO111MODULE', 'on') . ale#Escape('revive') . ' %t'