nvim/pack/acp/opt/nvim-lspconfig/lua/lspconfig/server_configurations/jdtls.lua

194 lines
6.3 KiB
Lua

local util = require 'lspconfig.util'
local handlers = require 'vim.lsp.handlers'
local sysname = vim.loop.os_uname().sysname
local env = {
HOME = vim.loop.os_homedir(),
JAVA_HOME = os.getenv 'JAVA_HOME',
JDTLS_HOME = os.getenv 'JDTLS_HOME',
WORKSPACE = os.getenv 'WORKSPACE',
}
local function get_java_executable()
local executable = env.JAVA_HOME and util.path.join(env.JAVA_HOME, 'bin', 'java') or 'java'
return sysname:match 'Windows' and executable .. '.exe' or executable
end
local function get_workspace_dir()
return env.WORKSPACE and env.WORKSPACE or util.path.join(env.HOME, 'workspace')
end
local function get_jdtls_jar()
return vim.fn.expand '$JDTLS_HOME/plugins/org.eclipse.equinox.launcher_*.jar'
end
local function get_jdtls_config()
if sysname:match 'Linux' then
return util.path.join(env.JDTLS_HOME, 'config_linux')
elseif sysname:match 'Darwin' then
return util.path.join(env.JDTLS_HOME, 'config_mac')
elseif sysname:match 'Windows' then
return util.path.join(env.JDTLS_HOME, 'config_win')
else
return util.path.join(env.JDTLS_HOME, 'config_linux')
end
end
-- TextDocument version is reported as 0, override with nil so that
-- the client doesn't think the document is newer and refuses to update
-- See: https://github.com/eclipse/eclipse.jdt.ls/issues/1695
local function fix_zero_version(workspace_edit)
if workspace_edit and workspace_edit.documentChanges then
for _, change in pairs(workspace_edit.documentChanges) do
local text_document = change.textDocument
if text_document and text_document.version and text_document.version == 0 then
text_document.version = nil
end
end
end
return workspace_edit
end
local function on_textdocument_codeaction(err, actions, ctx)
for _, action in ipairs(actions) do
-- TODO: (steelsojka) Handle more than one edit?
if action.command == 'java.apply.workspaceEdit' then -- 'action' is Command in java format
action.edit = fix_zero_version(action.edit or action.arguments[1])
elseif type(action.command) == 'table' and action.command.command == 'java.apply.workspaceEdit' then -- 'action' is CodeAction in java format
action.edit = fix_zero_version(action.edit or action.command.arguments[1])
end
end
handlers[ctx.method](err, actions, ctx)
end
local function on_textdocument_rename(err, workspace_edit, ctx)
handlers[ctx.method](err, fix_zero_version(workspace_edit), ctx)
end
local function on_workspace_applyedit(err, workspace_edit, ctx)
handlers[ctx.method](err, fix_zero_version(workspace_edit), ctx)
end
-- Non-standard notification that can be used to display progress
local function on_language_status(_, result)
local command = vim.api.nvim_command
command 'echohl ModeMsg'
command(string.format('echo "%s"', result.message))
command 'echohl None'
end
local root_files = {
-- Single-module projects
{
'build.xml', -- Ant
'pom.xml', -- Maven
'settings.gradle', -- Gradle
'settings.gradle.kts', -- Gradle
},
-- Multi-module projects
{ 'build.gradle', 'build.gradle.kts' },
}
return {
default_config = {
cmd = {
get_java_executable(),
'-Declipse.application=org.eclipse.jdt.ls.core.id1',
'-Dosgi.bundles.defaultStartLevel=4',
'-Declipse.product=org.eclipse.jdt.ls.core.product',
'-Dlog.protocol=true',
'-Dlog.level=ALL',
'-Xms1g',
'-Xmx2G',
'--add-modules=ALL-SYSTEM',
'--add-opens',
'java.base/java.util=ALL-UNNAMED',
'--add-opens',
'java.base/java.lang=ALL-UNNAMED',
'-jar',
get_jdtls_jar(),
'-configuration',
get_jdtls_config(),
'-data',
get_workspace_dir(),
},
filetypes = { 'java' },
root_dir = function(fname)
for _, patterns in ipairs(root_files) do
local root = util.root_pattern(unpack(patterns))(fname)
if root then
return root
end
end
end,
single_file_support = true,
init_options = {
workspace = get_workspace_dir(),
jvm_args = {},
os_config = nil,
},
handlers = {
-- Due to an invalid protocol implementation in the jdtls we have to conform these to be spec compliant.
-- https://github.com/eclipse/eclipse.jdt.ls/issues/376
['textDocument/codeAction'] = on_textdocument_codeaction,
['textDocument/rename'] = on_textdocument_rename,
['workspace/applyEdit'] = on_workspace_applyedit,
['language/status'] = vim.schedule_wrap(on_language_status),
},
},
docs = {
package_json = 'https://raw.githubusercontent.com/redhat-developer/vscode-java/master/package.json',
description = [[
https://projects.eclipse.org/projects/eclipse.jdt.ls
Language server for Java.
IMPORTANT: If you want all the features jdtls has to offer, [nvim-jdtls](https://github.com/mfussenegger/nvim-jdtls)
is highly recommended. If all you need is diagnostics, completion, imports, gotos and formatting and some code actions
you can keep reading here.
For manual installation you can download precompiled binaries from the
[official downloads site](http://download.eclipse.org/jdtls/snapshots/?d)
Due to the nature of java, settings cannot be inferred. Please set the following
environmental variables to match your installation. If you need per-project configuration
[direnv](https://github.com/direnv/direnv) is highly recommended.
```bash
# Mandatory:
# .bashrc
export JDTLS_HOME=/path/to/jdtls_root # Directory with the plugin and configs directories
# Optional:
export JAVA_HOME=/path/to/java_home # In case you don't have java in path or want to use a version in particular
export WORKSPACE=/path/to/workspace # Defaults to $HOME/workspace
```
```lua
-- init.lua
require'lspconfig'.jdtls.setup{}
```
For automatic installation you can use the following unofficial installers/launchers under your own risk:
- [jdtls-launcher](https://github.com/eruizc-dev/jdtls-launcher) (Includes lombok support by default)
```lua
-- init.lua
require'lspconfig'.jdtls.setup{ cmd = { 'jdtls' } }
```
]],
default_config = {
root_dir = [[{
-- Single-module projects
{
'build.xml', -- Ant
'pom.xml', -- Maven
'settings.gradle', -- Gradle
'settings.gradle.kts', -- Gradle
},
-- Multi-module projects
{ 'build.gradle', 'build.gradle.kts' },
} or vim.fn.getcwd()]],
},
},
}