summaryrefslogtreecommitdiffstats
path: root/after/ftplugin/java.lua
blob: 26e7e2ef63349aedcb810ab04d40356b582f6b4b (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
local misc = require('core.misc')
local lsp = require('core.lsp.functions')
local map, auto = misc.map, misc.auto

local jdtls = require('jdtls')
local jdtls_install = require('mason-registry').get_package('jdtls'):get_install_path()

-- make sure to check if things with 💀 need updating
local config = {
  cmd = {
    'java', -- 💀
    '-jar', vim.fn.glob(jdtls_install..'/plugins/org.eclipse.equinox.launcher_*.jar'), -- 💀
    '-configuration', jdtls_install..'/config_linux',
    '-data', vim.fn.stdpath('cache')..'/nvim-jdtls',

    '--add-modules=ALL-SYSTEM',
    '--add-opens', 'java.base/java.lang=ALL-UNNAMED',
    '--add-opens', 'java.base/java.util=ALL-UNNAMED',
    '-Declipse.application=org.eclipse.jdt.ls.core.id1',
    '-Declipse.product=org.eclipse.jdt.ls.core.product',
    '-Dlog.level=ALL',
    '-Dlog.protocol=true',
    '-Dosgi.bundles.defaultStartLevel=4',
    '-Xmx1G',
  },
  root_dir = vim.fs.dirname(vim.fs.find({
    'gradlew',
    '.git',
    'mvnw',
    'settings.gradle', -- Gradle (multi-project)
    'settings.gradle.kts', -- Gradle (multi-project)
    'build.xml', -- Ant
    'pom.xml', -- Maven
  }, { upward = true })[1]),

  -- don't print out status messages
  handlers = {
    ['language/status'] = function() end
  },

  on_attach = function(_, bufnr)
    -- add some jdtls specific mappings
    local opts = { buffer = bufnr }
    map('n', 'cri', jdtls.organize_imports, opts)
    map('n', 'crv', jdtls.extract_variable, opts)
    map('n', 'crc', jdtls.extract_constant, opts)
    map('x', 'crv', function() jdtls.extract_variable(true) end, opts)
    map('x', 'crc', function() jdtls.extract_constant(true) end, opts)
    map('x', 'crm', function() jdtls.extract_method(true) end, opts)

    pcall(vim.lsp.codelens.refresh)
    auto('BufWritePost', {
      buffer = bufnr,
      desc = 'refresh codelens',
      callback = function()
        pcall(vim.lsp.codelens.refresh)
      end
    })
  end,
  capabilities = lsp.capabilities
}

-- generate the path to the java file(s)
---@type string|nil
local cache_path = vim.fs.joinpath(vim.fn.stdpath("cache"), "/JavaVersion.class")
---@type string|nil
local src_path = vim.fs.joinpath(vim.fn.stdpath("config"), "/extras/JavaVersion.java")

-- if either path is invalid
if not cache_path or not src_path then
  return
end

--- build a cache of the JavaVersion code
local function build_cache()
  -- check if we have javac
  vim.system({ "javac" }, {}, function(out)
    if out.code == 127 then
      cache_path = nil
      return
    end

    -- compile our code
    vim.system({ 'javac', src_path, '-d', vim.fn.stdpath("cache") }, {}, function(out)
      if out.code ~= 0 then
        cache_path = nil
      end
    end)
  end)
end

-- check if we have a compiled version of JavaVersion
local f, _ = io.open(cache_path, "r")
if not f then -- if we don't have a cache
  build_cache()
else
  io.close(f)
end

-- check the java version
local buffer = {}
vim.fn.jobstart({
  config.cmd[1],
  (cache_path and "JavaVersion") or src_path
}, {
    cwd = vim.fn.stdpath("cache"),
    stdin = nil,
    on_stdout = function(_, data, _)
      table.insert(buffer, table.concat(data))
    end,
    on_exit = function(_, exit_code, _)
      local v = vim.version.parse(table.concat(buffer))

      -- if there's an error, no version info, or the java version is
      -- less than 17 stop the lsp from starting
      if exit_code ~= 0 then
        vim.notify(string.format(
          "java version check failed: exit code %s", exit_code),
          vim.log.levels.ERROR, { title = misc.appid })
        return
      elseif not v then
        vim.notify("no java version info found", vim.log.levels.ERROR,
          { title = misc.appid })
        return
      elseif v.major < 17 then
        vim.notify(string.format(
          "java version %s < 17.0.0 Cannot run jdtls, bailing out",
          v[1].."."..v[2].."."..v[3]),
          vim.log.levels.ERROR, { title = misc.appid })
        return
      end

      -- start lsp
      jdtls.start_or_attach(config)
    end
  })