diff --git a/ale_linters/java/eclipselsp.vim b/ale_linters/java/eclipselsp.vim new file mode 100644 index 00000000..af9a325e --- /dev/null +++ b/ale_linters/java/eclipselsp.vim @@ -0,0 +1,130 @@ +" Author: Horacio Sanson +" Description: Support for the Eclipse language server https://github.com/eclipse/eclipse.jdt.ls + +let s:version_cache = {} + +call ale#Set('java_eclipselsp_path', 'eclipse.jdt.ls') +call ale#Set('java_eclipselsp_executable', 'java') + +function! ale_linters#java#eclipselsp#Executable(buffer) abort + return ale#Var(a:buffer, 'java_eclipselsp_executable') +endfunction + +function! ale_linters#java#eclipselsp#TargetPath(buffer) abort + return ale#Var(a:buffer, 'java_eclipselsp_path') +endfunction + +function! ale_linters#java#eclipselsp#JarPath(buffer) abort + let l:path = ale_linters#java#eclipselsp#TargetPath(a:buffer) + let l:path = l:path . '/org.eclipse.jdt.ls.product/target/repository/plugins' + + let l:files = globpath(l:path, 'org.eclipse.equinox.launcher_*.jar', 1, 1) + + if empty(l:files) + return '' + endif + + return l:files[0] +endfunction + +function! ale_linters#java#eclipselsp#ConfigurationPath(buffer) abort + let l:path = ale_linters#java#eclipselsp#TargetPath(a:buffer) + let l:path = l:path . '/org.eclipse.jdt.ls.product/target/repository' + + if has('win32') + let l:path = l:path . '/config_win' + elseif has('macunix') + let l:path = l:path . '/config_mac' + else + let l:path = l:path . '/config_linux' + endif + + return ale#path#Simplify(l:path) +endfunction + +function! ale_linters#java#eclipselsp#VersionCheck(version_lines) abort + return s:GetVersion('', a:version_lines) +endfunction + +function! s:GetVersion(executable, version_lines) abort + let l:version = [] + + for l:line in a:version_lines + let l:match = matchlist(l:line, '\(\d\+\)\.\(\d\+\)\.\(\d\+\)') + + if !empty(l:match) + let l:version = [l:match[1] + 0, l:match[2] + 0, l:match[3] + 0] + let s:version_cache[a:executable] = l:version + break + endif + endfor + + return l:version +endfunction + +function! ale_linters#java#eclipselsp#CommandWithVersion(buffer, version_lines, meta) abort + let l:executable = ale_linters#java#eclipselsp#Executable(a:buffer) + let l:version = s:GetVersion(l:executable, a:version_lines) + + return ale_linters#java#eclipselsp#Command(a:buffer, l:version) +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), + \ '-Declipse.application=org.eclipse.jdt.ls.core.id1', + \ '-Dosgi.bundles.defaultStartLevel=4', + \ '-Declipse.product=org.eclipse.jdt.ls.core.product', + \ '-Dlog.level=ALL', + \ '-noverify', + \ '-Xmx1G', + \ '-jar', + \ ale_linters#java#eclipselsp#JarPath(a:buffer), + \ '-configuration', + \ ale_linters#java#eclipselsp#ConfigurationPath(a:buffer), + \ '-data', + \ ale#java#FindProjectRoot(a:buffer) + \ ] + + if ale#semver#GTE(a:version, [1, 9]) + call add(l:cmd, '--add-modules=ALL-SYSTEM') + call add(l:cmd, '--add-opens java.base/java.util=ALL-UNNAMED') + call add(l:cmd, '--add-opens java.base/java.lang=ALL-UNNAMED') + endif + + return join(l:cmd, ' ') +endfunction + +function! ale_linters#java#eclipselsp#RunWithVersionCheck(buffer) abort + let l:executable = ale_linters#java#eclipselsp#Executable(a:buffer) + + if empty(l:executable) + return '' + endif + + let l:cache = s:version_cache + + if has_key(s:version_cache, l:executable) + return ale_linters#java#eclipselsp#Command(a:buffer, s:version_cache[l:executable]) + endif + + let l:command = ale#Escape(l:executable) . ' -version' + + return ale#command#Run( + \ a:buffer, + \ l:command, + \ function('ale_linters#java#eclipselsp#CommandWithVersion') + \) +endfunction + +call ale#linter#Define('java', { +\ 'name': 'eclipselsp', +\ 'lsp': 'stdio', +\ 'executable': function('ale_linters#java#eclipselsp#Executable'), +\ 'command': function('ale_linters#java#eclipselsp#RunWithVersionCheck'), +\ 'language': 'java', +\ 'project_root': function('ale#java#FindProjectRoot'), +\}) diff --git a/doc/ale-java.txt b/doc/ale-java.txt index aa226305..35967f03 100644 --- a/doc/ale-java.txt +++ b/doc/ale-java.txt @@ -101,6 +101,39 @@ g:ale_java_javalsp_executable *g:ale_java_javalsp_executable* This variable can be changed to use a different executable for java. +=============================================================================== +eclipselsp *ale-java-eclipselsp* + +To enable Java LSP linter you need to clone and build the eclipse.jdt.ls +language server from https://github.com/eclipse/eclipse.jdt.ls. Simply +clone the source code repo and then build the plugin: + + ./mvnw clean verify + +Note: currently, the build can only run when launched with JDK 8. JDK 9 or more +recent versions can be used to run the server though. + +After build completes the files required to run the language server will be +located inside the folder |org.eclipse.jdt.ls.product/target/repository|. +Ensure to set |g:ale_java_eclipselsp_path| to the absolute path of that folder. + +g:ale_java_eclipselsp_path *g:ale_java_eclipselsp_path* + *b:ale_java_eclipselsp_path* + + Type: |String| + Default: `'eclipse.jdt.ls/org.eclipse.jdt.ls.product/target/repository'` + + Path to the location of the eclipse.jdt.ls product repository. + + +g:ale_java_eclipselsp_executable *g:ale_java_eclipse_executable* + *b:ale_java_eclipse_executable* + Type: |String| + Default: `'java'` + + This variable can be set to change the executable path used for java. + + =============================================================================== uncrustify *ale-java-uncrustify* diff --git a/doc/ale-supported-languages-and-tools.txt b/doc/ale-supported-languages-and-tools.txt index 3f329ba2..066ca60d 100644 --- a/doc/ale-supported-languages-and-tools.txt +++ b/doc/ale-supported-languages-and-tools.txt @@ -195,6 +195,7 @@ Notes: * `ispc`!! * Java * `checkstyle` + * `eclipselsp` * `google-java-format` * `javac` * `javalsp` diff --git a/doc/ale.txt b/doc/ale.txt index 6155dc37..c9654c49 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -1982,6 +1982,7 @@ documented in additional help files. google-java-format....................|ale-java-google-java-format| pmd...................................|ale-java-pmd| javalsp...............................|ale-java-javalsp| + eclipselsp............................|ale-java-eclipselsp| uncrustify............................|ale-java-uncrustify| javascript..............................|ale-javascript-options| eslint................................|ale-javascript-eslint| diff --git a/supported-tools.md b/supported-tools.md index 532fc1f8..e104c115 100644 --- a/supported-tools.md +++ b/supported-tools.md @@ -204,6 +204,7 @@ formatting. * [ispc](https://ispc.github.io/) :floppy_disk: * Java * [checkstyle](http://checkstyle.sourceforge.net) + * [eclipselsp](https://github.com/eclipse/eclipse.jdt.ls) * [google-java-format](https://github.com/google/google-java-format) * [javac](http://www.oracle.com/technetwork/java/javase/downloads/index.html) * [javalsp](https://github.com/georgewfraser/vscode-javac) diff --git a/test/command_callback/test_eclipselsp_command_callback.vader b/test/command_callback/test_eclipselsp_command_callback.vader new file mode 100644 index 00000000..f6f587da --- /dev/null +++ b/test/command_callback/test_eclipselsp_command_callback.vader @@ -0,0 +1,87 @@ +Before: + call ale#assert#SetUpLinterTest('java', 'eclipselsp') + let b:ale_java_eclipselsp_path = '/home/user/eclipse.dst.ls' + call ale#test#SetFilename('dummy.java') + + let b:cfg = '/home/user/eclipse.dst.ls/org.eclipse.jdt.ls.product/target/repository/config_linux' + + if has('win32') + let b:cfg = '\home\user\eclipse.dst.ls\org.eclipse.jdt.ls.product\target\repository\config_win' + elseif has('macunix') + let b:cfg = '/home/user/eclipse.dst.ls/org.eclipse.jdt.ls.product/target/repository/config_mac' + endif + + +After: + unlet b:ale_java_eclipselsp_path + call ale#assert#TearDownLinterTest() + +Execute(VersionCheck should return correct version): + + " OpenJDK Java 1.8 + AssertEqual [1, 8, 0], ale_linters#java#eclipselsp#VersionCheck([ + \ 'openjdk version "1.8.0_191"', + \ 'OpenJDK Runtime Environment (build 1.8.0_191-8u191-b12-0ubuntu0.18.04.1-b12)', + \ 'OpenJDK 64-Bit Server VM (build 25.191-b12, mixed mode)' + \]) + + " OpenJDK Java 10 + AssertEqual [10, 0, 2], ale_linters#java#eclipselsp#VersionCheck([ + \ 'openjdk version "10.0.2" 2018-07-17', + \ 'OpenJDK Runtime Environment (build 10.0.2+13-Ubuntu-1ubuntu0.18.04.4)', + \ 'OpenJDK 64-Bit Server VM (build 10.0.2+13-Ubuntu-1ubuntu0.18.04.4, mixed mode)' + \]) + + " Oracle Java 1.8 + AssertEqual [1, 8, 0], ale_linters#java#eclipselsp#VersionCheck([ + \ 'java version "1.8.0_161"', + \ 'Java(TM) SE Runtime Environment (build 1.8.0_161-b12)', + \ 'Java HotSpot(TM) 64-Bit Server VM (build 25.161-b12, mixed mode)' + \]) + + " Oracle Java 10 + AssertEqual [10, 0, 1], ale_linters#java#eclipselsp#VersionCheck([ + \ 'java version "10.0.1" 2018-04-17', + \ 'Java(TM) SE Runtime Environment 18.3 (build 10.0.1+10)', + \ 'Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10.0.1+10, mixed mode)' + \]) + + AssertEqual [], ale_linters#java#eclipselsp#VersionCheck(['x']) + + AssertEqual [], ale_linters#java#eclipselsp#VersionCheck([]) + +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', + \ '-Dlog.level=ALL', + \ '-noverify', + \ '-Xmx1G', + \ '-jar', + \ '', + \ '-configuration', + \ b:cfg, + \ '-data', + \ '' + \] + AssertLinter 'java', join(cmd, ' ') + +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', + \ '-Dlog.level=ALL', + \ '-noverify', + \ '-Xmx1G', + \ '-jar', + \ '', + \ '-configuration', + \ b:cfg, + \ '-data', + \ '' + \] + AssertLinter '/bin/foobar', join(cmd, ' ') +