diff options
author | w0rp <devw0rp@gmail.com> | 2021-03-14 21:10:05 +0000 |
---|---|---|
committer | w0rp <devw0rp@gmail.com> | 2021-03-14 21:10:20 +0000 |
commit | b45ee8ec6c760089c68fb28a5436ec8275ca5381 (patch) | |
tree | b37f356b016f3c09ac7a706ed22fa0d852b32969 | |
parent | 80a48d01be663205b92902ca3fa137706e3e88c6 (diff) | |
download | ale-b45ee8ec6c760089c68fb28a5436ec8275ca5381.zip |
Close #2102 - Add support for the Angular language server
-rw-r--r-- | ale_linters/html/angular.vim | 52 | ||||
-rw-r--r-- | autoload/ale/assert.vim | 15 | ||||
-rw-r--r-- | autoload/ale/definition.vim | 14 | ||||
-rw-r--r-- | autoload/ale/lsp_linter.vim | 5 | ||||
-rw-r--r-- | autoload/ale/test.vim | 17 | ||||
-rw-r--r-- | doc/ale-html.txt | 99 | ||||
-rw-r--r-- | doc/ale-supported-languages-and-tools.txt | 3 | ||||
-rw-r--r-- | doc/ale.txt | 3 | ||||
-rw-r--r-- | supported-tools.md | 3 | ||||
-rw-r--r-- | test/command_callback/test_angular_command_callback.vader | 44 | ||||
-rw-r--r-- | test/test-projects/angular/node_modules/@angular/language-server/bin/ngserver | 0 | ||||
-rw-r--r-- | test/test-projects/angular/node_modules/@angular/language-service/dummy | 0 | ||||
-rw-r--r-- | test/test_go_to_definition.vader | 23 |
13 files changed, 230 insertions, 48 deletions
diff --git a/ale_linters/html/angular.vim b/ale_linters/html/angular.vim new file mode 100644 index 00000000..f550d665 --- /dev/null +++ b/ale_linters/html/angular.vim @@ -0,0 +1,52 @@ +" Author: w0rp <devw0rp@gmail.com> +" Description: tsserver integration for ALE + +call ale#Set('html_angular_executable', 'ngserver') +call ale#Set('html_angular_use_global', get(g:, 'ale_use_global_executables', 0)) + +function! ale_linters#html#angular#GetProjectRoot(buffer) abort + return ale#path#Dirname( + \ ale#path#FindNearestDirectory(a:buffer, 'node_modules') + \) +endfunction + +function! ale_linters#html#angular#GetExecutable(buffer) abort + return ale#node#FindExecutable(a:buffer, 'html_angular', [ + \ 'node_modules/@angular/language-server/bin/ngserver', + \ 'node_modules/@angular/language-server/index.js', + \]) +endfunction + +function! ale_linters#html#angular#GetCommand(buffer) abort + let l:language_service_dir = ale#path#Simplify( + \ ale#path#FindNearestDirectory( + \ a:buffer, + \ 'node_modules/@angular/language-service' + \ ) + \) + + if empty(l:language_service_dir) + return '' + endif + + let l:language_service_dir = fnamemodify(l:language_service_dir, ':h') + let l:typescript_dir = ale#path#Simplify( + \ fnamemodify(l:language_service_dir, ':h:h') + \ . '/typescript' + \) + let l:executable = ale_linters#html#angular#GetExecutable(a:buffer) + + return ale#node#Executable(a:buffer, l:executable) + \ . ' --ngProbeLocations ' . ale#Escape(l:language_service_dir) + \ . ' --tsProbeLocations ' . ale#Escape(l:typescript_dir) + \ . ' --stdio' +endfunction + +call ale#linter#Define('html', { +\ 'name': 'angular', +\ 'aliases': ['angular-language-server'], +\ 'lsp': 'stdio', +\ 'executable': function('ale_linters#html#angular#GetExecutable'), +\ 'command': function('ale_linters#html#angular#GetCommand'), +\ 'project_root': function('ale_linters#html#angular#GetProjectRoot'), +\}) diff --git a/autoload/ale/assert.vim b/autoload/ale/assert.vim index 8c7a5461..8200a3bf 100644 --- a/autoload/ale/assert.vim +++ b/autoload/ale/assert.vim @@ -169,8 +169,21 @@ function! ale#assert#LinterNotExecuted() abort let l:buffer = bufnr('') let l:linter = s:GetLinter() let l:executable = ale#linter#GetExecutable(l:buffer, l:linter) + let l:executed = 1 - Assert empty(l:executable), "The linter will be executed when it shouldn't be" + if !empty(l:executable) + let l:command = ale#linter#GetCommand(l:buffer, l:linter) + + if type(l:command) is v:t_list + let l:command = l:command[-1] + endif + + let l:executed = !empty(l:command) + else + let l:executed = 0 + endif + + Assert !l:executed, "The linter will be executed when it shouldn't be" endfunction function! ale#assert#LSPOptions(expected_options) abort diff --git a/autoload/ale/definition.vim b/autoload/ale/definition.vim index a5a9271e..9574017b 100644 --- a/autoload/ale/definition.vim +++ b/autoload/ale/definition.vim @@ -66,9 +66,17 @@ function! ale#definition#HandleLSPResponse(conn_id, response) abort endif for l:item in l:result - let l:filename = ale#path#FromURI(l:item.uri) - let l:line = l:item.range.start.line + 1 - let l:column = l:item.range.start.character + 1 + if has_key(l:item, 'targetUri') + " LocationLink items use targetUri + let l:filename = ale#path#FromURI(l:item.targetUri) + let l:line = l:item.targetRange.start.line + 1 + let l:column = l:item.targetRange.start.character + 1 + else + " LocationLink items use uri + let l:filename = ale#path#FromURI(l:item.uri) + let l:line = l:item.range.start.line + 1 + let l:column = l:item.range.start.character + 1 + endif call ale#definition#UpdateTagStack() call ale#util#Open(l:filename, l:line, l:column, l:options) diff --git a/autoload/ale/lsp_linter.vim b/autoload/ale/lsp_linter.vim index 0d039198..b8885f31 100644 --- a/autoload/ale/lsp_linter.vim +++ b/autoload/ale/lsp_linter.vim @@ -294,14 +294,15 @@ function! s:StartLSP(options, address, executable, command) abort call ale#lsp#MarkConnectionAsTsserver(l:conn_id) endif + let l:cwd = ale#linter#GetCwd(l:buffer, l:linter) let l:command = ale#command#FormatCommand( \ l:buffer, \ a:executable, \ a:command, \ 0, \ v:false, - \ v:null, - \ [], + \ l:cwd, + \ ale#GetFilenameMappings(l:buffer, l:linter.name), \)[1] let l:command = ale#job#PrepareCommand(l:buffer, l:command) let l:ready = ale#lsp#StartProgram(l:conn_id, a:executable, l:command) diff --git a/autoload/ale/test.vim b/autoload/ale/test.vim index 6fcbf35e..4d75d515 100644 --- a/autoload/ale/test.vim +++ b/autoload/ale/test.vim @@ -34,12 +34,11 @@ function! ale#test#RestoreDirectory() abort unlet! g:dir endfunction -" Change the filename for the current buffer using a relative path to -" the script without running autocmd commands. +" Get a filename for the current buffer using a relative path to the script. " " If a g:dir variable is set, it will be used as the path to the directory " containing the test file. -function! ale#test#SetFilename(path) abort +function! ale#test#GetFilename(path) abort let l:dir = get(g:, 'dir', '') if empty(l:dir) @@ -50,7 +49,17 @@ function! ale#test#SetFilename(path) abort \ ? a:path \ : l:dir . '/' . a:path - silent! noautocmd execute 'file ' . fnameescape(ale#path#Simplify(l:full_path)) + return ale#path#Simplify(l:full_path) +endfunction + +" Change the filename for the current buffer using a relative path to +" the script without running autocmd commands. +" +" If a g:dir variable is set, it will be used as the path to the directory +" containing the test file. +function! ale#test#SetFilename(path) abort + let l:full_path = ale#test#GetFilename(a:path) + silent! noautocmd execute 'file ' . fnameescape(l:full_path) endfunction function! s:RemoveModule(results) abort diff --git a/doc/ale-html.txt b/doc/ale-html.txt index c78dc4cd..2c048148 100644 --- a/doc/ale-html.txt +++ b/doc/ale-html.txt @@ -3,12 +3,40 @@ ALE HTML Integration *ale-html-options* =============================================================================== +angular *ale-html-angular* + +ALE supports language server features for Angular. You can install it via `npm`: > + + $ npm install --save-dev @angular/language-server +< +Angular 11 and up are supported. + + +g:ale_html_angular_executable *g:ale_html_angular_executable* + *b:ale_html_angular_executable* + Type: |String| + Default: `'ngserver'` + + See |ale-integrations-local-executables| + + +g:ale_html_angular_use_global *g:ale_html_angular_use_global* + *b:ale_html_angular_use_global* + Type: |String| + Default: `get(g:, 'ale_use_global_executables', 0)` + + See |ale-integrations-local-executables| + + +=============================================================================== fecs *ale-html-fecs* -`fecs` options for HTMl is the same as the options for JavaScript, -and both of them reads `./.fecsrc` as the default configuration file. +`fecs` options for HTML are the same as the options for JavaScript, and both +of them read `./.fecsrc` as the default configuration file. + See: |ale-javascript-fecs|. + =============================================================================== html-beautify *ale-html-beautify* @@ -47,6 +75,40 @@ g:ale_html_htmlhint_use_global *g:ale_html_htmlhint_use_global* See |ale-integrations-local-executables| + +=============================================================================== +prettier *ale-html-prettier* + +See |ale-javascript-prettier| for information about the available options. + + +=============================================================================== +stylelint *ale-html-stylelint* + +g:ale_html_stylelint_executable *g:ale_html_stylelint_executable* + *b:ale_html_stylelint_executable* + Type: |String| + Default: `'stylelint'` + + See |ale-integrations-local-executables| + + +g:ale_html_stylelint_options *g:ale_html_stylelint_options* + *b:ale_html_stylelint_options* + Type: |String| + Default: `''` + + This variable can be set to pass additional options to stylelint. + + +g:ale_html_stylelint_use_global *g:ale_html_stylelint_use_global* + *b:ale_html_stylelint_use_global* + Type: |String| + Default: `0` + + See |ale-integrations-local-executables| + + =============================================================================== tidy *ale-html-tidy* @@ -98,39 +160,6 @@ g:ale_html_tidy_use_global *g:html_tidy_use_global* =============================================================================== -prettier *ale-html-prettier* - -See |ale-javascript-prettier| for information about the available options. - - -=============================================================================== -stylelint *ale-html-stylelint* - -g:ale_html_stylelint_executable *g:ale_html_stylelint_executable* - *b:ale_html_stylelint_executable* - Type: |String| - Default: `'stylelint'` - - See |ale-integrations-local-executables| - - -g:ale_html_stylelint_options *g:ale_html_stylelint_options* - *b:ale_html_stylelint_options* - Type: |String| - Default: `''` - - This variable can be set to pass additional options to stylelint. - - -g:ale_html_stylelint_use_global *g:ale_html_stylelint_use_global* - *b:ale_html_stylelint_use_global* - Type: |String| - Default: `0` - - See |ale-integrations-local-executables| - - -=============================================================================== write-good *ale-html-write-good* See |ale-write-good-options| diff --git a/doc/ale-supported-languages-and-tools.txt b/doc/ale-supported-languages-and-tools.txt index e6764144..cc25ca95 100644 --- a/doc/ale-supported-languages-and-tools.txt +++ b/doc/ale-supported-languages-and-tools.txt @@ -216,10 +216,11 @@ Notes: * HCL * `terraform-fmt` * HTML - * `HTMLHint` * `alex`!! + * `angular` * `fecs` * `html-beautify` + * `htmlhint` * `prettier` * `proselint` * `tidy` diff --git a/doc/ale.txt b/doc/ale.txt index 0fc95ae0..66b2e4ce 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -2777,12 +2777,13 @@ documented in additional help files. hcl.....................................|ale-hcl-options| terraform-fmt.........................|ale-hcl-terraform-fmt| html....................................|ale-html-options| + angular...............................|ale-html-angular| fecs..................................|ale-html-fecs| html-beautify.........................|ale-html-beautify| htmlhint..............................|ale-html-htmlhint| - tidy..................................|ale-html-tidy| prettier..............................|ale-html-prettier| stylelint.............................|ale-html-stylelint| + tidy..................................|ale-html-tidy| write-good............................|ale-html-write-good| idris...................................|ale-idris-options| idris.................................|ale-idris-idris| diff --git a/supported-tools.md b/supported-tools.md index a522d748..616008cc 100644 --- a/supported-tools.md +++ b/supported-tools.md @@ -225,10 +225,11 @@ formatting. * HCL * [terraform-fmt](https://github.com/hashicorp/terraform) * HTML - * [HTMLHint](http://htmlhint.com/) * [alex](https://github.com/wooorm/alex) :floppy_disk: + * [angular](https://www.npmjs.com/package/@angular/language-server) * [fecs](http://fecs.baidu.com/) * [html-beautify](https://beautifier.io/) + * [htmlhint](http://htmlhint.com/) * [prettier](https://github.com/prettier/prettier) * [proselint](http://proselint.com/) * [tidy](http://www.html-tidy.org/) diff --git a/test/command_callback/test_angular_command_callback.vader b/test/command_callback/test_angular_command_callback.vader new file mode 100644 index 00000000..c5de3d87 --- /dev/null +++ b/test/command_callback/test_angular_command_callback.vader @@ -0,0 +1,44 @@ +Before: + call ale#assert#SetUpLinterTest('html', 'angular') + let g:paths = {} + +After: + call ale#assert#TearDownLinterTest() + unlet g:paths + +Execute(The Angular LSP connection shouldn't be created outside of Angular projects): + AssertLSPLanguage 'html' + AssertLSPConfig {} + AssertLSPProject '' + AssertLinterNotExecuted + +Execute(The default command for Angular should be correct): + call ale#test#SetFilename('../test-projects/angular/test.html') + let g:paths = { + \ 'ngserver': ale#test#GetFilename('../test-projects/angular/node_modules/@angular/language-server/bin/ngserver'), + \ 'service': ale#test#GetFilename('../test-projects/angular/node_modules/@angular/language-service'), + \ 'typescript': ale#test#GetFilename('../test-projects/angular/node_modules/typescript'), + \} + + AssertLSPLanguage 'html' + AssertLSPProject ale#test#GetFilename('../test-projects/angular') + AssertLinter g:paths.ngserver, ale#Escape(g:paths.ngserver) + \ . ' --ngProbeLocations ' . ale#Escape(g:paths.service) + \ . ' --tsProbeLocations ' . ale#Escape(g:paths.typescript) + \ . ' --stdio' + +Execute(It should be possible to use the global ngserver): + let b:ale_html_angular_use_global = 1 + + call ale#test#SetFilename('../test-projects/angular/test.html') + let g:paths = { + \ 'service': ale#test#GetFilename('../test-projects/angular/node_modules/@angular/language-service'), + \ 'typescript': ale#test#GetFilename('../test-projects/angular/node_modules/typescript'), + \} + + AssertLSPLanguage 'html' + AssertLSPProject ale#test#GetFilename('../test-projects/angular') + AssertLinter 'ngserver', ale#Escape('ngserver') + \ . ' --ngProbeLocations ' . ale#Escape(g:paths.service) + \ . ' --tsProbeLocations ' . ale#Escape(g:paths.typescript) + \ . ' --stdio' diff --git a/test/test-projects/angular/node_modules/@angular/language-server/bin/ngserver b/test/test-projects/angular/node_modules/@angular/language-server/bin/ngserver new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/test-projects/angular/node_modules/@angular/language-server/bin/ngserver diff --git a/test/test-projects/angular/node_modules/@angular/language-service/dummy b/test/test-projects/angular/node_modules/@angular/language-service/dummy new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/test-projects/angular/node_modules/@angular/language-service/dummy diff --git a/test/test_go_to_definition.vader b/test/test_go_to_definition.vader index c7805932..3807bb05 100644 --- a/test/test_go_to_definition.vader +++ b/test/test_go_to_definition.vader @@ -343,6 +343,29 @@ Execute(Other files should be jumped to for LSP definition responses): AssertEqual [3, 8], getpos('.')[1:2] AssertEqual {}, ale#definition#GetMap() +Execute(Newer LocationLink items should be supported): + call ale#definition#SetMap({3: {'open_in': 'current-buffer'}}) + call ale#definition#HandleLSPResponse( + \ 1, + \ { + \ 'id': 3, + \ 'result': { + \ 'targetUri': ale#path#ToURI(ale#path#Simplify(g:dir . '/completion_dummy_file')), + \ 'targetRange': { + \ 'start': {'line': 2, 'character': 7}, + \ }, + \ }, + \ } + \) + + AssertEqual + \ [ + \ 'edit +3 ' . fnameescape(ale#path#Simplify(g:dir . '/completion_dummy_file')), + \ ], + \ g:expr_list + AssertEqual [3, 8], getpos('.')[1:2] + AssertEqual {}, ale#definition#GetMap() + Execute(Locations inside the same file should be jumped to without using :edit): call ale#definition#SetMap({3: {'open_in': 'current-buffer'}}) call ale#definition#HandleLSPResponse( |