forked from rcasia/neotest-java
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement more robust runtime collection and compilation
On top of the existing runtime this improvement also tries to check the maven or gradle (todo) to collect as much information about the runtime of the project, if that is not possible, the user might be prompted to enter the home directory of the runtime, the user might also configure the runtimes statically in the plugin's configuration. Furthermore dependencies on other plugins such as nvim-jdtls is removed, and the changes rely only on native the nvim lsp or coc.nvim.
- Loading branch information
1 parent
8003930
commit 84c5342
Showing
8 changed files
with
312 additions
and
85 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
local lsp = require("neotest-java.lsp") | ||
local log = require("neotest-java.logger") | ||
|
||
---@param additional_classpath_entries string[] | ||
---@return string[] | ||
local function get_classpaths(additional_classpath_entries) | ||
additional_classpath_entries = additional_classpath_entries or {} | ||
|
||
-- this is not good ???? | ||
local bufnr = vim.api.nvim_get_current_buf() | ||
local uri = vim.uri_from_bufnr(bufnr) | ||
local result_classpaths = {} | ||
|
||
for _, v in ipairs(additional_classpath_entries) do | ||
table.insert(result_classpaths, v) | ||
end | ||
|
||
for _, scope in ipairs({ "runtime", "test" }) do | ||
local options = vim.json.encode({ scope = scope }) | ||
local err, result, client = lsp.execute_command("workspace/executeCommand", { | ||
command = "java.project.getClasspaths", | ||
arguments = { uri, options }, | ||
}, bufnr) | ||
if result == nil or err ~= nil or client == nil then | ||
log.warn(string.format("Unable to resolve [%s] classpahts", scope)) | ||
else | ||
for _, v in ipairs(result.classpaths or {}) do | ||
table.insert(result_classpaths, v) | ||
end | ||
end | ||
end | ||
|
||
return result_classpaths | ||
end | ||
|
||
return get_classpaths |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
local log = require("neotest-java.logger") | ||
local lsp = require("neotest-java.lsp") | ||
local nio = require("nio") | ||
|
||
---@param compilation_type string | ||
local function run_compile(compilation_type) | ||
local bufnr = nio.api.nvim_get_current_buf() | ||
lsp.execute_command("java/buildWorkspace", compilation_type == "full", bufnr) | ||
log.info("Triggered build for the current workspace") | ||
end | ||
|
||
return run_compile |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
local File = require("neotest.lib.file") | ||
|
||
local read_xml_tag = require("neotest-java.util.read_xml_tag") | ||
local ch = require("neotest-java.context_holder") | ||
local log = require("neotest-java.logger") | ||
local lsp = require("neotest-java.lsp") | ||
local nio = require("nio") | ||
|
||
local COMPILER = "org.eclipse.jdt.core.compiler.source" | ||
local LOCATION = "org.eclipse.jdt.ls.core.vm.location" | ||
local RUNTIMES = {} | ||
|
||
local function get_env(var) | ||
return nio.fn.getenv(var) | ||
end | ||
|
||
local function get_java_home() | ||
return get_env("JAVA_HOME") | ||
end | ||
|
||
local function has_env(var) | ||
return nio.fn.getenv(var) ~= vim.NIL | ||
end | ||
|
||
local function input_runtime(actual_version) | ||
local message = | ||
string.format("Enter runtime directory for JDK-%s (defaults to JAVA_HOME if empty): ", actual_version) | ||
local runtime_path = nio.fn.input({ | ||
default = "", | ||
prompt = message, | ||
completion = "dir", | ||
cancelreturn = "__INPUT_CANCELLED__", | ||
}) | ||
if runtime_path == "__INPUT_CANCELLED__" then | ||
log.info(string.format("Defaulting to JAVA_HOME due to empty user input for %s", actual_version)) | ||
return get_java_home() | ||
elseif | ||
not runtime_path | ||
or #runtime_path == 0 | ||
or nio.fn.isdirectory(runtime_path) == 0 | ||
or nio.fn.isdirectory(string.format("%s/bin", runtime_path)) == 0 | ||
then | ||
log.warn(string.format("Invalid runtime home directory %s was specified, please try again", runtime_path)) | ||
return input_runtime(actual_version) | ||
else | ||
log.info(string.format("Using user input %s for runtime version %s", runtime_path, actual_version)) | ||
return runtime_path | ||
end | ||
end | ||
|
||
local function maven_runtime() | ||
local context = ch.get_context() | ||
local plugins = read_xml_tag("pom.xml", "project.build.plugins.plugin") | ||
|
||
for _, plugin in ipairs(plugins or {}) do | ||
if plugin.artifactId == "maven-compiler-plugin" and plugin.configuration then | ||
if plugin.configuration.target ~= plugin.configuration.source then | ||
error("Target and source mismatch detected in maven-compiler-plugin") | ||
end | ||
local target_version = vim.split(plugin.configuration.target, "%.") | ||
local actual_version = target_version[#target_version] | ||
if RUNTIMES[actual_version] then | ||
return RUNTIMES[actual_version] | ||
end | ||
|
||
local runtime_name = string.format("JAVA_HOME_%d", actual_version) | ||
if context and context.config.java_runtimes[runtime_name] then | ||
return ch.get_context().config.java_runtimes[runtime_name] | ||
elseif has_env(runtime_name) then | ||
return get_env(runtime_name) | ||
else | ||
local runtime_path = input_runtime(actual_version) | ||
RUNTIMES[actual_version] = runtime_path | ||
return runtime_path | ||
end | ||
end | ||
end | ||
log.warn("Unable to resolve the runtime from maven-compiler-plugin, defaulting to JAVA_HOME") | ||
return get_java_home() | ||
end | ||
|
||
local function gradle_runtime() | ||
-- fix: the build.gradle has to be read to obtain information about the project's configured runtime | ||
log.warn("Unable to resolve the runtime from build.gradle, defaulting to JAVA_HOME") | ||
return get_java_home() | ||
end | ||
|
||
local function extract_runtime(bufnr) | ||
local uri = vim.uri_from_bufnr(bufnr) | ||
local err, settings, client = lsp.execute_command("workspace/executeCommand", { | ||
command = "java.project.getSettings", | ||
arguments = { uri, { COMPILER, LOCATION } }, | ||
}, bufnr) | ||
|
||
if err ~= nil or client == nil or settings == nil then | ||
log.info("Unable to extract runtime from an active lsp client") | ||
return | ||
end | ||
|
||
local config = client.config.settings.java or {} | ||
config = config.configuration or {} | ||
|
||
-- location starts off being nil, we require strict matching, otherwise the | ||
-- runtime resolve will fallback to maven or gradle, we do not want to | ||
-- resolve to JAVA_HOME immediately here, it is too early. | ||
local location = nil | ||
local runtimes = config.runtimes | ||
local compiler = settings[COMPILER] | ||
|
||
-- we can early exit with location here | ||
if settings[LOCATION] then | ||
location = settings[LOCATION] | ||
else | ||
-- go over available runtimes and resolve it | ||
for _, runtime in ipairs(runtimes or {}) do | ||
-- default runtimes get priority | ||
if runtime.default == true then | ||
location = runtime.path | ||
break | ||
end | ||
-- match runtime against compliance version | ||
local match = runtime.name:match(".*-(.*)") | ||
if match and match == compiler then | ||
location = runtime.path | ||
break | ||
end | ||
end | ||
end | ||
|
||
-- location has to be strictly resolved from the project `settings` or from | ||
-- the runtimes in client's settings, otherwise we return `nil` for runtime | ||
if not location or #location == 0 or nio.fn.isdirectory(location) == 0 then | ||
return nil | ||
end | ||
return location | ||
end | ||
|
||
---@return string | nil | ||
local function get_runtime() | ||
local bufnr = nio.api.nvim_get_current_buf() | ||
local runtime = extract_runtime(bufnr) | ||
|
||
-- in case the runtime was not found, try to fetch one from the build | ||
-- system which the current project is using, match against maven or gradle | ||
-- and try to find the configured runtime, or fallback to JAVA_HOME | ||
if not runtime or #runtime == 0 then | ||
if File.exists("pom.xml") then | ||
runtime = maven_runtime() | ||
elseif File.exists("build.gradle") then | ||
runtime = gradle_runtime() | ||
end | ||
end | ||
|
||
if runtime and #runtime > 0 then | ||
log.info(string.format("Resolved project runtime %s", runtime)) | ||
return runtime | ||
else | ||
log.warn("Unable to resolve the project's runtime") | ||
return nil | ||
end | ||
end | ||
|
||
return get_runtime |
Oops, something went wrong.