lazyvim折腾日记(10)
lazyvim 折腾日记(10)
前言
接续上一章节,我们对 java 语言在 lazy(astro)vim 中的开发进行了相关的配置\
但是在实际的使用过程中仍然存在一些问题,具体体现在
- 在加载
gradle project的时候,无法识别build.gradle文件的变更, 导致依赖无法导入 - 无法自动生成模板代码,具体体现为在新建类的时候需要手动编写相关的模板语言
针对这两个问题该如何处理呢?
- 添加相关函数,使得 Nvim 能够自动识别依赖
- 配置 Cmp 插件,使得拥有自动生成代码的功能
内容
基本知识点准备
java 命令的含义
我觉得这里还有一个东西是需要阐明的,就是说,这里的 java 并不是简单的用于跑一个程序
而是用于为 eclipse 构建一个可以承载 lsp 的 jvm
所以说这里还是与一般的存在区别,针对 lsp 的启动方式
大类参数含义
| 序号 | 前缀 | 含义 |
|---|---|---|
| 1 | -X | 内存与堆栈 |
| 2 | -D | 系统参数设置 |
| 3 | -XX | JVM 垃圾回收设置 |
详细参数定义
| 序号 | 前缀 | 含义 |
|---|---|---|
| 1 | -Declipse.application | 设置eclipse.eclipse 的值,一般用于 eclipse(osgi) 应用程序 |
| 2 | -Dosgi.bundles.defaultStartLevel | 设置 osgi 模型的 log 等级 |
| 3 | -Declipse.product | 确定 eclipse.product 的产品属性 |
| 4 | -Dlog.protocol | 控制 lsp 的 logging 行为 |
| 5 | -Dlog.level | 控制 lsp 的 log 的打印等级 |
| 6 | -javaagent | 设置额外的 java 组件 |
| 7 | -Xms | 设置最小堆栈 |
| 8 | -Xmx | 设置最大堆栈 |
特殊参数定义
| 序号 | 前缀 | 含义 |
|---|---|---|
| 1 | --add-modules | 添加模块 |
| 2 | --add-opens | 打开模块(能够读取其中的方法名) |
| 3 | java.base/java.util | 包名 |
| 4 | java.base/java.lang | 包名 |
OSGI framework 参数定义
| 序号 | 前缀 | 含义 |
|---|---|---|
| 1 | -configuration | OSGI 设置,本文中需要加载 linux 的设置 |
| 2 | -data | lsp 的 index 和 log 的存储位置 |
Jdtls 初始化配置参数
由于这是一个 Gradle 项目,我们需要关注与 gradle 有关的配置选项
interface GradleOption {
annotationProcessing?: EnabledOption;
arguments?: string[];
enabled?: boolean;
home?: string;
java?: HomeOption;
jvmArguments?: string[];
offline?: EnabledOption;
user?: HomeOption;
version?: string;
wrapper?: GradleWrapperOption;
}
interface GradleWrapperOption {
enabled?: boolean;
checksums?: string[];
}
其参考文档为:
新建 vim 自定义命令
如果说自动导入不成功的话,我们需要自定义一个命令,
使得 nvim 能够接受这个命令从而手动刷新项目依赖
| 序号 | 函数 | 含义 |
|---|---|---|
| 1 | vim.api.nvim_create_autocmd | 根据事件创建一个自动执行的命令 |
| 2 | vim.api.nvim_create_user_command | 创建一个用户手动执行的命令 |
具体用法分别参考
在 lazy(astro)vim 中一般会选择放在 conifg = function 函数块中
问题分析
-
无法自动加载
build.gradle文件并更新其依赖\ 原因:
Gradle 没有进行正确配置,并且没有正确识别 gradle 项目 -
无法自动生成模板语法\ 原因:
没有对 Jdtls Initoption 进行相关配置
针对以上两点问题,结合上述方法,我们可以做出如下判断
-
正确配置 jdtls , 从而能够正确加载 gradle 项目
配置更大的构建内存,加快项目的编译
配置 jdtls , 使得其能识别 gradle 项目 -
添加手动以及自动命令,使得 nvim 能够加载识别项目
在 config 中添加命令
解决方案(具体的配置方法)
结合上一章节的知识点,下面放出具体的配置代码
{
"mfussenegger/nvim-jdtls",
lazy = true,
ft = { "java" },
dependencies = {
"williamboman/mason.nvim",
"neovim/nvim-lspconfig",
"williamboman/mason-lspconfig.nvim",
{
"AstroNvim/astrolsp",
optional = true,
---@type AstroLSPOpts
opts = {
setup_handlers = {
---@diagnostic disable:missing-fields
jdtls = false,
},
},
},
},
opts = function(_, opts)
local utils = require "astrocore"
local project_name = vim.fn.fnamemodify(vim.fn.getcwd(), ":p:h:t")
local workspace_dir = vim.fn.stdpath "data" .. "/jdtls/workspace/" .. project_name
vim.fn.mkdir(workspace_dir, "p")
local jdtls_path = "${the path of jdtls}"
return utils.extend_tbl(opts, {
cmd = {
"java",
-- 设置 eclipse.application , 告诉 java 现在启动的是命令行 lsp
"-Declipse.application=org.eclipse.jdt.ls.core.id1",
-- 设置 osgi 模型的 log 等级
"-Dosgi.bundles.defaultStartLevel=4",
-- 使用 org.eclipse.jdt.ls.core.product 定义 eclipse.product 的产品属性
"-Declipse.product=org.eclipse.jdt.ls.core.product",
-- 打印 lsp 的 log
"-Dlog.protocol=true",
"-Dlog.level=ALL",
"-javaagent:${the path of lombok}",
-- 设置堆栈大小
"-Xms1g",
"-Xmx2g",
-- 加载所有系统 model
"--add-modules=ALL-SYSTEM",
"--add-opens",
-- 前面一个 --add-modules 是让 java 能够加载所有包,
-- 这个 --add-opens 是让 lsp 能够解析这些包
-- 打开 java.base/java.util 能够加载未命名包,
"java.base/java.util=ALL-UNNAMED",
"--add-opens",
"java.base/java.lang=ALL-UNNAMED",
"-jar",
-- 这个 jar 包是 lsp 的启动器, jvm 首先启动这个 jar 包, 再通过这个 jar 包启动 jdtls
vim.fn.glob(jdtls_path .. "/plugins/org.eclipse.equinox.launcher_*.jar"),
"-configuration",
jdtls_path .. "/config_linux",
"-data",
workspace_dir,
},
-- 寻找项目的根目录
root_dir = require("jdtls.setup").find_root {
".git",
"mvnw",
"gradlew",
"pom.xml",
"build.gradle",
"settings.gradle",
},
settings = {
java = {
configuration = {
updateBuildConfiguration = "automatic",
runtimes = {
{
name = "JavaSE-21",
path = "${the path of java21}",
default = true,
},
{
name = "JavaSE-17",
path = "${the path of java17}",
},
{
name = "JavaSE-11",
path = "${the path of java11}",
},
},
},
implementationsCodeLens = {
enabled = true,
},
referencesCodeLens = {
enabled = true,
},
references = {
includeDecompiledSources = true,
},
format = {
enabled = true,
},
-- 参考前面的资料
import = {
gradle = {
enabled = true,
wrapper = {
enabled = true,
},
version = nil,
home = nil,
offline = {
enabled = false,
},
arguments = nil,
jvmArguments = nil,
user = {
home = nil,
},
},
maven = {
enabled = true,
},
exclusions = {
"**/node_modules/**",
"**/.metadata/**",
"**/archetype-resources/**",
"**/META-INF/maven/**",
},
},
},
signatureHelp = { enabled = true },
completion = {
-- 优先注入这些静态成员
favoriteStaticMembers = {
"org.junit.Assert.*",
"org.junit.Assume.*",
"org.junit.jupiter.api.Assertions.*",
"org.junit.jupiter.api.Assumptions.*",
"org.junit.jupiter.api.DynamicContainer.*",
"org.junit.jupiter.api.DynamicTest.*",
},
},
sources = {
organizeImports = {
starThreshold = 9999,
staticStarThreshold = 9999,
},
},
codeGeneration = {
-- 定义 lsp 的 tostring 方法
toString = {
template = "${object.className}{${member.name()}=${member.value}, ${otherMembers}}",
},
useBlocks = true,
},
},
init_options = {
bundles = {
vim.fn.glob "${the path of debug jar}",
},
},
})
end,
config = function(_, opts)
vim.api.nvim_create_autocmd("Filetype", {
pattern = "java",
callback = function()
if opts.root_dir and opts.root_dir ~= "" then
require("jdtls").start_or_attach(opts)
-- 等待 LSP 启动后自动触发项目导入
vim.defer_fn(function()
local clients = vim.lsp.get_active_clients({ name = "jdtls" })
if #clients > 0 then vim.notify("jdtls started, importing Gradle project...", vim.log.levels.INFO) end
end, 3000)
else
require("astrocore").notify("jdtls: root_dir not found, not starting jdtls", vim.log.levels.ERROR)
end
end,
})
-- 添加用户命令来手动刷新项目
vim.api.nvim_create_user_command("JdtlsUpdateProject", function()
local bufnr = vim.api.nvim_get_current_buf()
local params = {
command = "java.projectConfiguration.update",
arguments = { vim.uri_from_bufnr(bufnr) },
}
vim.lsp.buf_request(bufnr, "workspace/executeCommand", params, function(err)
if err then
vim.notify("Failed to update project: " .. vim.inspect(err), vim.log.levels.ERROR)
else
vim.notify("Java project configuration updated", vim.log.levels.INFO)
end
end)
end, { desc = "Update Java project configuration" })
-- 添加用户命令来重新导入项目
vim.api.nvim_create_user_command("JdtlsReimport", function()
local bufnr = vim.api.nvim_get_current_buf()
-- 定义 lsp 命令,使得 lsp 执行'java.project.import' 命令
local params = {
command = "java.project.import",
}
vim.lsp.buf_request(bufnr, "workspace/executeCommand", params, function(err)
if err then
vim.notify("Failed to reimport project: " .. vim.inspect(err), vim.log.levels.ERROR)
else
vim.notify("Java project reimported", vim.log.levels.INFO)
end
end)
end, { desc = "Reimport Java project" })
vim.api.nvim_create_user_command("JdtClearWorkspace", function()
local project_name = vim.fn.fnamemodify(vim.fn.getcwd(), ":p:h:t")
local workspace_dir = vim.fn.stdpath "data" .. "/jdtls/workspace/" .. project_name
-- 停止 jdtls
local clients = vim.lsp.get_active_clients({ name = "jdtls" })
for _, client in ipairs(clients) do
client.stop()
end
-- 删除工作空间
vim.fn.delete(workspace_dir, "rf")
vim.notify("Workspace cleared. Please restart Neovim.", vim.log.levels.INFO)
end, { desc = "Clear jdtls workspace" })
end,
}
总结
讲述了 java 命令的具体意思以及对 jdtls 的具体配置
根据以上的调整,我的项目能够成功加载 gradle 项目

浙公网安备 33010602011771号