aboutsummaryrefslogtreecommitdiffstats
path: root/lua/nvim_lsp/jdtls.lua
blob: ed0f022d274d2c7f57c76bf432a8015a4371d94a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
local configs = require 'nvim_lsp/configs'
local util = require 'nvim_lsp/util'
local callbacks = require 'vim.lsp.callbacks'
local path = util.path

local server_name = "jdtls"

local function make_installer()
  local install_dir = path.join { util.base_install_dir, server_name }
  local tar_name = "jdt-language-server-latest.tar.gz"
  local script = string.format([[
    curl -LO http://download.eclipse.org/jdtls/snapshots/%s > %s
    tar xf %s
  ]], tar_name, tar_name, tar_name)
  local launcher_ls = "ls " .. path.join { install_dir, "plugins", "org.eclipse.equinox.launcher_*.jar" }

  local X = {}

  function X.install()
    if not util.has_bins("curl", "tar") then
      error('Need the binaries "curl", "tar" to install this.')
      return
    end

    vim.fn.mkdir(install_dir, "p")
    util.sh(script, install_dir)
  end

  function X.info()
    return {
      is_installed = util.path.exists(install_dir, 'features') ~= false;
      install_dir = install_dir;
    }
  end

  function X.get_os_config()
    if vim.fn.has("osx") == 1 then
      return "config_mac"
    elseif vim.fn.has("unix") == 1 then
      return "config_linux"
    else
      return "config_win"
    end
  end

  function X.get_launcher()
    local file = io.popen(launcher_ls)
    local results = {}

    for line in file:lines() do
      table.insert(results, line)
    end

    if #results == 1 then
      return results[1]
    end

    error("Could not find launcher for jdtls.")
  end

  function X.configure(config)
    local install_info = X.info()
    local launcher_path = X.get_launcher()

    if install_info.is_installed then
      config.cmd = vim.list_extend(
        vim.list_extend(
          {
            "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",
          },
          config.init_options.jvm_args),
        {
          "-jar", launcher_path,
          "-configuration", path.join { install_dir, config.init_options.os_config or X.get_os_config() },
          "-data", config.init_options.workspace,
          -- TODO: Handle Java versions 8 and under. This may just work...
          "--add-modules=ALL-SYSTEM",
          "--add-opens", "java.base/java.util=ALL-UNNAMED",
          "--add-opens", "java.base/java.lang=ALL-UNNAMED"
        })
    end
  end

  return X
end

local installer = make_installer()

configs[server_name] = {
  default_config = {
    filetypes = { "java" };
    root_dir = util.root_pattern('.git');
    init_options = {
      workspace = path.join { vim.loop.os_homedir(), "workspace" };
      jvm_args = {};
      os_config = nil;
    };
    callbacks = {
      -- 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'] = function(a, b, actions)
        for _,action in ipairs(actions) do
          -- TODO: (steelsojka) Handle more than one edit?
          if action.command == 'java.apply.workspaceEdit' then
            action.edit = action.arguments[1]
          end
        end

        callbacks['textDocument/codeAction'](a, b, actions)
      end
    };
  };
  on_new_config = function(config)
    installer.configure(config)
  end;
  docs = {
    description = [[
https://projects.eclipse.org/projects/eclipse.jdt.ls

Language server can be installed with `:LspInstall jdtls`

Language server for Java.
    ]];
    default_config = {
      root_dir = [[root_pattern(".git")]];
    };
  };
}

configs[server_name].install = installer.install
configs[server_name].install_info = installer.info