forked from github-mirrors/ale
Close #2102 - Add support for the Angular language server
This commit is contained in:
parent
80a48d01be
commit
b45ee8ec6c
|
@ -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'),
|
||||
\})
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -2,13 +2,41 @@
|
|||
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*
|
||||
|
||||
|
@ -97,39 +159,6 @@ g:ale_html_tidy_use_global *g:html_tidy_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|
|
||||
|
||||
|
||||
===============================================================================
|
||||
write-good *ale-html-write-good*
|
||||
|
||||
|
|
|
@ -216,10 +216,11 @@ Notes:
|
|||
* HCL
|
||||
* `terraform-fmt`
|
||||
* HTML
|
||||
* `HTMLHint`
|
||||
* `alex`!!
|
||||
* `angular`
|
||||
* `fecs`
|
||||
* `html-beautify`
|
||||
* `htmlhint`
|
||||
* `prettier`
|
||||
* `proselint`
|
||||
* `tidy`
|
||||
|
|
|
@ -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|
|
||||
|
|
|
@ -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/)
|
||||
|
|
|
@ -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'
|
0
test/test-projects/angular/node_modules/@angular/language-server/bin/ngserver
generated
vendored
Normal file
0
test/test-projects/angular/node_modules/@angular/language-server/bin/ngserver
generated
vendored
Normal file
0
test/test-projects/angular/node_modules/@angular/language-service/dummy
generated
vendored
Normal file
0
test/test-projects/angular/node_modules/@angular/language-service/dummy
generated
vendored
Normal file
|
@ -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(
|
||||
|
|
Loading…
Reference in New Issue