Skip to content

Commit 08b5579

Browse files
authored
feat(neovim): Add java ☕ debugging support (#43)
Adds Java debugging capabilities to the Neovim configuration. deliver #41 related to #38, #17 ## Key changes - Installs and configures the Java debug adapter (`vscode-java-debug`). - Sets up DAP configurations for launching and attaching to Java processes. - Improves Java project root detection for the JDTLS language server. - Adds a `.editorconfig` file to ensure consistent coding styles across different editors. ``` ┌────────────┐ ┌────────────────┐ │ nvim-jdtls │ │ nvim-lspconfig │ └────────────┘ └────────────────┘ | | start_or_attach nvim_lsp.jdtls.setup │ | │ setup java filetype hook │ ┌─────────┐ │ └───►│ vim.lsp │◄─────────────────┘ └─────────┘ ``` Diagram 1: The diagram, from the nvim-jdtls documentation, shows how it differs from nvim-lspconfig ``` DAP-Client ----- Debug Adapter ------- Debugger ------ Debugee (nvim-dap) | (per language) | (per language) (your app) | | | Implementation specific communication | Debug adapter and debugger could be the same process | Communication via the Debug Adapter Protocol ``` Diagram 2: The diagram, from the nvim-dap documentation, shows how these pieces interact. <img width="3840" height="2110" alt="image" src="https://sookocheff.com/post/vim/neovim-java-ide/assets/jdtls.gif" /> Image 1: Animation with Extracting a Method Using JDTLS ### 📚 Documentation - [Using Neovim as a Java IDE](https://sookocheff.com/post/vim/neovim-java-ide/) - [WIKI: Debug Adapter installation - Java](https://codeberg.org/mfussenegger/nvim-dap/wiki/Java) - [VSCode Debugger for Java - Options](https://github.com/microsoft/vscode-java-debug#options)
1 parent 0efbebc commit 08b5579

18 files changed

+561
-264
lines changed

.editorconfig

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# EditorConfig helps maintain consistent coding styles for multiple developers
2+
# working on the same project across various editors and IDEs
3+
# http://editorconfig.org
4+
5+
# top-most EditorConfig file
6+
root = true
7+
8+
# All files
9+
[*]
10+
charset = utf-8
11+
end_of_line = lf
12+
indent_style = space
13+
indent_size = 2
14+
insert_final_newline = true
15+
trim_trailing_whitespace = true
16+
17+
# Markdown files
18+
[*.md]
19+
trim_trailing_whitespace = false
20+
21+

docs/nvim/Neovim-Java-Support.md

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
# Suporte a Java no Neovim
2+
3+
Este projeto oferece suporte completo ao desenvolvimento em Java através da integração com o **Eclipse JDT Language Server (jdtls)**, proporcionando uma experiência de desenvolvimento moderna com recursos como autocompletar, navegação de código, refatoração e depuração.
4+
5+
## O que é o JDTLS?
6+
7+
O **Eclipse JDT Language Server** é um servidor de linguagem que implementa o protocolo LSP (Language Server Protocol) para Java. Ele foi desenvolvido pela Eclipse Foundation e oferece:
8+
9+
- **IntelliSense avançado**: Autocompletar, verificação de sintaxe e análise de código em tempo real
10+
- **Navegação de código**: Go-to-definition, find references, outline e hierarchy
11+
- **Refatoração**: Rename, extract method, organize imports e muito mais
12+
- **Depuração**: Integração completa com debugger através do DAP (Debug Adapter Protocol)
13+
- **Gerenciamento de projetos**: Suporte a Maven, Gradle e projetos Eclipse
14+
- **Formatação e organização**: Code formatting e import organization
15+
16+
## Integração com Neovim
17+
18+
### nvim-jdtls
19+
20+
O plugin `mfussenegger/nvim-jdtls` é uma extensão especializada do cliente LSP nativo do Neovim, oferecendo funcionalidades específicas do Java:
21+
22+
```lua
23+
-- Exemplo de configuração básica
24+
local config = {
25+
cmd = {'/path/to/jdtls'},
26+
root_dir = vim.fs.dirname(vim.fs.find({'gradlew', '.git', 'mvnw'}, { upward = true })[1]),
27+
28+
-- Configurações específicas do jdtls
29+
settings = {
30+
java = {
31+
eclipse = { downloadSources = true },
32+
configuration = { updateBuildConfiguration = "interactive" },
33+
maven = { downloadSources = true },
34+
implementationsCodeLens = { enabled = true },
35+
referencesCodeLens = { enabled = true },
36+
references = { includeDecompiledSources = true },
37+
format = { enabled = true },
38+
}
39+
},
40+
41+
-- Inicialização de funcionalidades específicas
42+
init_options = {
43+
bundles = {}
44+
}
45+
}
46+
47+
require('jdtls').start_or_attach(config)
48+
```
49+
50+
**Funcionalidades exclusivas do nvim-jdtls:**
51+
52+
- **Organize imports**: `:lua require'jdtls'.organize_imports()`
53+
- **Extract variable/method**: `:lua require'jdtls'.extract_variable()`
54+
- **Generate constructors/getters/setters**: `:lua require'jdtls'.code_action()`
55+
- **Test integration**: Execução de testes JUnit diretamente no Neovim
56+
57+
### nvim-dap (Depuração)
58+
59+
O `mfussenegger/nvim-dap` trabalha em conjunto com o jdtls para fornecer capacidades de depuração:
60+
61+
```lua
62+
-- Configuração do DAP para Java
63+
local dap = require('dap')
64+
65+
dap.configurations.java = {
66+
{
67+
type = 'java',
68+
request = 'attach',
69+
name = "Debug (Attach) - Remote",
70+
hostName = "127.0.0.1",
71+
port = 5005,
72+
},
73+
}
74+
75+
-- Integração com jdtls
76+
require('jdtls').setup_dap({ hotcodereplace = 'auto' })
77+
```
78+
79+
**Recursos de depuração:**
80+
81+
- Breakpoints condicionais
82+
- Variáveis watch
83+
- Call stack navigation
84+
- Hot code replacement
85+
- Remote debugging
86+
87+
## Instalação do JDTLS
88+
89+
### Pré-requisitos
90+
91+
O JDTLS requer **Java 17 ou superior**:
92+
93+
```bash
94+
# Verificar versão do Java
95+
java -version
96+
97+
# Se necessário, instalar Java 17+
98+
```
99+
100+
### macOS
101+
102+
**Via Homebrew (recomendado):**
103+
104+
```bash
105+
# Instalar Java se necessário
106+
brew install openjdk@17
107+
108+
# Instalar jdtls
109+
brew install jdtls
110+
```
111+
112+
O executável ficará disponível em `/opt/homebrew/bin/jdtls`.
113+
114+
### Ubuntu
115+
116+
**Via APT (recomendado):**
117+
118+
```bash
119+
# Instalar Java se necessário
120+
sudo apt update
121+
sudo apt install openjdk-17-jdk
122+
123+
# Instalar jdtls
124+
sudo apt install eclipse-jdt-language-server
125+
```
126+
127+
O servidor ficará disponível em `/usr/share/java/jdtls/`.
128+
129+
### Fedora
130+
131+
**Via DNF (recomendado):**
132+
133+
```bash
134+
# Instalar Java se necessário
135+
sudo dnf install java-17-openjdk-devel
136+
137+
# Instalar jdtls
138+
sudo dnf install eclipse-jdt-language-server
139+
```
140+
141+
### Instalação Manual
142+
143+
Para todas as plataformas, você pode baixar e instalar manualmente:
144+
145+
```bash
146+
# 1. Criar diretório de instalação
147+
sudo mkdir -p /opt/jdtls
148+
149+
# 2. Baixar a versão mais recente
150+
JDTLS_VERSION="1.38.0" # Verificar versão atual no site
151+
curl -LO "http://download.eclipse.org/jdtls/milestones/${JDTLS_VERSION}/jdt-language-server-${JDTLS_VERSION}-202406271335.tar.gz"
152+
153+
# 3. Extrair arquivos
154+
sudo tar -xzf jdt-language-server-*.tar.gz -C /opt/jdtls
155+
156+
# 4. Verificar instalação
157+
ls /opt/jdtls/plugins/org.eclipse.equinox.launcher_*.jar
158+
```
159+
160+
**Script de inicialização** (`/usr/local/bin/jdtls`):
161+
162+
```bash
163+
#!/usr/bin/env bash
164+
165+
JAR="/opt/jdtls/plugins/org.eclipse.equinox.launcher_*.jar"
166+
GRADLE_HOME=$HOME/gradle java \
167+
-Declipse.application=org.eclipse.jdt.ls.core.id1 \
168+
-Dosgi.bundles.defaultStartLevel=4 \
169+
-Declipse.product=org.eclipse.jdt.ls.core.product \
170+
-Dlog.protocol=true \
171+
-Dlog.level=ALL \
172+
-Xms1g \
173+
-Xmx2G \
174+
--add-modules=ALL-SYSTEM \
175+
--add-opens java.base/java.util=ALL-UNNAMED \
176+
--add-opens java.base/java.lang=ALL-UNNAMED \
177+
-jar $(echo $JAR) \
178+
-configuration /opt/jdtls/config_linux \
179+
-data "${1:-$HOME/workspace}" \
180+
--add-modules=ALL-SYSTEM \
181+
--add-opens java.base/java.util=ALL-UNNAMED \
182+
--add-opens java.base/java.lang=ALL-UNNAMED
183+
```
184+
185+
Torne o script executável:
186+
187+
```bash
188+
sudo chmod +x /usr/local/bin/jdtls
189+
```
190+
191+
## Verificação da Instalação
192+
193+
Para verificar se o jdtls está funcionando corretamente:
194+
195+
```bash
196+
# Testar execução do servidor
197+
jdtls --help
198+
199+
# Ou verificar se o jar está no local correto
200+
java -jar /opt/jdtls/plugins/org.eclipse.equinox.launcher_*.jar --help
201+
```
202+
203+
## Configuração no Projeto
204+
205+
Após a instalação, configure o nvim-jdtls apontando para o executável correto:
206+
207+
```lua
208+
local config = {
209+
cmd = {
210+
'jdtls', -- ou caminho completo: '/opt/homebrew/bin/jdtls'
211+
-- Adicione configurações específicas do seu ambiente
212+
},
213+
-- ... resto da configuração
214+
}
215+
```
216+
217+
## Troubleshooting
218+
219+
**Problemas comuns:**
220+
221+
1. **Java não encontrado**: Verifique se o `JAVA_HOME` está configurado corretamente
222+
2. **Permissões**: Certifique-se de que o script jdtls tem permissões de execução
223+
3. **Workspace**: Configure um diretório de workspace adequado para seus projetos
224+
4. **Memory**: Ajuste os parâmetros `-Xms` e `-Xmx` conforme necessário para projetos grandes
225+
226+
Para mais detalhes sobre configuração avançada, consulte a [documentação oficial do nvim-jdtls](https://github.com/mfussenegger/nvim-jdtls).
227+

nvim/lua/plugins/DAP.lua

Lines changed: 20 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,5 @@
1-
local js_based_languages = {
2-
"typescript",
3-
"javascript",
4-
"typescriptreact",
5-
"javascriptreact",
6-
"vue",
7-
}
8-
91
return {
102
{ "nvim-neotest/nvim-nio" },
11-
{
12-
"jay-babu/mason-nvim-dap.nvim",
13-
config = function ()
14-
require("mason-nvim-dap").setup({
15-
automatic_installation = true,
16-
})
17-
end
18-
},
193
{
204
"mfussenegger/nvim-dap",
215
dependencies = {
@@ -36,99 +20,30 @@ return {
3620
vim.keymap.set("n", "<Leader>di", dap.step_into, {})
3721
-- debug repl: Inspecting the state via the built-in REPL
3822
vim.keymap.set("n", "<Leader>dr", dap.repl.open, {})
39-
end,
40-
},
41-
{
42-
"mfussenegger/nvim-dap-python",
43-
ft = "python",
44-
dependecies = {
45-
"mfussenegger/nvim-dap",
46-
"rcarriga/nvim-dap-ui",
47-
},
48-
config = function(_, opts)
49-
--[[ local path = "~/.local/share/nvim/mason/packages/debugpy/venv/bin/python"
50-
require("dap-python").setup(path) ]]
51-
local dap = require("dap-python")
5223

53-
-- calls dap python run file
54-
vim.keymap.set("n", "<leader>dpr", dap.test_method, {})
55-
end,
56-
},
57-
{
58-
"rcarriga/nvim-dap-ui",
59-
dependencies = {
60-
"mfussenegger/nvim-dap",
61-
"nvim-neotest/nvim-nio",
62-
},
63-
config = function()
64-
local dap = require("dap")
65-
local dapui = require("dapui")
66-
67-
dap.listeners.before.attach.dapui_config = function()
68-
dapui.open()
69-
end
70-
dap.listeners.before.launch.dapui_config = function()
71-
dapui.open()
72-
end
73-
dap.listeners.before.event_terminated.dapui_config = function()
74-
dapui.close()
75-
end
76-
dap.listeners.before.event_exited.dapui_config = function()
77-
dapui.close()
78-
end
79-
end,
80-
},
81-
{
82-
"theHamsta/nvim-dap-virtual-text",
83-
config = function()
84-
local dap_virtual_text = require("nvim-dap-virtual-text")
85-
86-
dap_virtual_text.setup({
87-
enabled = true, -- enable this plugin (the default)
88-
enabled_commands = true, -- create commands
89-
-- * DapVirtualTextEnable
90-
-- * DapVirtualTextDisable
91-
-- * DapVirtualTextToggle
92-
highlight_changed_variables = true, -- highlight changed values with NvimDapVirtualTextChanged, else always NvimDapVirtualText
93-
highlight_new_as_changed = false, -- highlight new variables in the same way as changed variables
94-
show_stop_reason = true, -- show stop reason when stopped for exceptions
95-
commented = false, -- prefix virtual text with comment string
96-
only_first_definition = true, -- only show virtual text at first definition (if there are multiple)
97-
all_references = false, -- show virtual text on all all references of the variable (not only definitions)
98-
clear_on_continue = false, -- clear virtual text on "continue" (might cause flickering when stepping)
99-
virt_text_pos = vim.fn.has("nvim-0.10") == 1 and "inline" or "eol", -- position of virtual text, see `:h nvim_buf_set_extmark()`
100-
})
101-
end,
102-
},
103-
{
104-
"jay-babu/mason-nvim-dap.nvim",
105-
opts = {
106-
-- This line is essential to making automatic installation work
107-
-- :exploding-brain
108-
-- https://www.johntobin.ie/blog/debugging_in_neovim_with_nvim-dap/
109-
handlers = {},
110-
automatic_installation = {
111-
exclude = {
112-
"python",
24+
dap.adapters.java = {
25+
type = "executable",
26+
command = "$HOME/.local/share/nvim/mason/bin/vscode-java-debug",
27+
options = {
28+
cwd = vim.fn.getcwd(),
11329
},
114-
ensure_installed = {
115-
"python",
116-
"debugpy",
30+
}
31+
32+
dap.configurations.java = {
33+
{
34+
name = "Launch Current File",
35+
type = "java",
36+
request = "launch",
37+
mainClass = "${file}",
11738
},
118-
},
119-
},
120-
dependencies = {
121-
"mfussenegger/nvim-dap",
122-
"williamboman/mason.nvim",
123-
},
124-
config = function()
125-
require("mason-nvim-dap").setup({
126-
automatic_installation = true,
127-
ensure_installed = {
128-
"python",
129-
"debugpy",
39+
{
40+
name = "Attach to Remote JVM",
41+
type = "java",
42+
request = "attach",
43+
hostName = "127.0.0.1", -- Or localhost
44+
port = 5005,
13045
},
131-
})
46+
}
13247
end,
13348
},
13449
}

0 commit comments

Comments
 (0)