Skip to content
This repository was archived by the owner on Nov 30, 2025. It is now read-only.

Commit d3bcc87

Browse files
authored
feat: API for generating jdtls config (#2)
fixes: s1n7ax/nvim-java#1
1 parent 27b417b commit d3bcc87

31 files changed

+1504
-102
lines changed

.devcontainer/devcontainer.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"name": "Container",
3+
"image": "ubuntu:latest",
4+
"features": {
5+
"ghcr.io/s1n7ax/devcontainer-features/neovim-essentials:0": {},
6+
"ghcr.io/s1n7ax/devcontainer-features/neovim:0": {},
7+
"ghcr.io/s1n7ax/devcontainer-features/astronvim:0": {}
8+
}
9+
}

.stylua.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
column_width = 120
1+
column_width = 80
22
line_endings = "Unix"
3-
indent_type = "Spaces"
3+
indent_type = "Tabs"
44
indent_width = 2
5-
quote_style = "AutoPreferDouble"
5+
quote_style = "AutoPreferSingle"
66
no_call_parentheses = false

Makefile

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
TESTS_INIT=tests/minimal_init.lua
1+
PREPARE_CONFIG=tests/prepare_config.lua
2+
TEST_CONFIG=tests/test_config.lua
23
TESTS_DIR=tests/
34

45
.PHONY: test
56

67
test:
78
@nvim \
89
--headless \
9-
--noplugin \
10-
-u ${TESTS_INIT} \
11-
-c "PlenaryBustedDirectory ${TESTS_DIR} { minimal_init = '${TESTS_INIT}' }"
10+
-u ${PREPARE_CONFIG} \
11+
"+PlenaryBustedDirectory ${TESTS_DIR} { minimal_init = '${TEST_CONFIG}' }"

README.md

Lines changed: 28 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,40 @@
1-
# A Neovim Plugin Template
1+
# :construction: nvim-java (WIP)
22

3-
![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/ellisonleao/nvim-plugin-template/lint-test.yml?branch=main&style=for-the-badge)
4-
![Lua](https://img.shields.io/badge/Made%20with%20Lua-blueviolet.svg?style=for-the-badge&logo=lua)
3+
No need to put up with [jdtls](https://github.com/eclipse-jdtls/eclipse.jdt.ls) nonsense anymore.
4+
Just install and start writing `public static void main(String[] args)`.
55

6-
A template repository for Neovim plugins.
6+
## Features
77

8-
## Using it
8+
:white_check_mark: are supported features. :x: are pending features.
99

10-
Via `gh`:
10+
- :white_check_mark: Diagnostics & Auto Completion
11+
- :x: Automatic [DAP](https://github.com/mfussenegger/nvim-dap) debug configuration
12+
- :x: Running tests
1113

12-
```
13-
$ gh repo create my-plugin -p ellisonleao/nvim-plugin-template
14-
```
14+
## Why
1515

16-
Via github web page:
16+
- Uses [nvim-lspconfig]() to setup `jdtls`
17+
- Uses `jdtls` and auto loads `jdtls` plugins from [mason.nvim](https://github.com/williamboman/mason.nvim) (If they are installed)
18+
- Supported plugins are,
19+
- `lombok` (mason `jdtls` package contains the lombok jar. So no need to installed it separately)
20+
- `java-test`
21+
- `java-debug-adapter`
22+
- Typed & documented APIs
23+
- No callback hells I [promise](https://github.com/pyericz/promise-lua)
1724

18-
Click on `Use this template`
25+
## How to Use
1926

20-
![](https://docs.github.com/assets/cb-36544/images/help/repository/use-this-template-button.png)
27+
```lua
28+
local java = require('java')
2129

22-
## Features and structure
30+
require('lspconfig').jdtls.setup(java.get_config())
2331

24-
- 100% Lua
25-
- Github actions for:
26-
- running tests using [plenary.nvim](https://github.com/nvim-lua/plenary.nvim) and [busted](https://olivinelabs.com/busted/)
27-
- check for formatting errors (Stylua)
28-
- vimdocs autogeneration from README.md file
29-
- luarocks release (LUAROCKS_API_KEY secret configuration required)
32+
vim.api.nvim_create_autocmd('LspAttach', {
33+
callback = function(args)
34+
local buffer = args.buf
3035

31-
### Plugin structure
32-
33-
```
34-
.
35-
├── lua
36-
│   ├── plugin_name
37-
│   │   └── module.lua
38-
│   └── plugin_name.lua
39-
├── Makefile
40-
├── plugin
41-
│   └── plugin_name.lua
42-
├── README.md
43-
├── tests
44-
│   ├── minimal_init.lua
45-
│   └── plugin_name
46-
│   └── plugin_name_spec.lua
36+
-- add your language server keymaps here
37+
end,
38+
group = vim.api.nvim_create_augroup('LSP Keymaps', {}),
39+
})
4740
```

dev/gen_jdtls_types.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import re
2+
import urllib.request
3+
4+
things_to_export = []
5+
6+
def _iface(text):
7+
lines = text.split('\n')
8+
lua_lines = []
9+
10+
for line in lines:
11+
line = line.strip()
12+
if line.startswith("interface"):
13+
interface_name = line.split(" ")[1]
14+
lua_lines.append(f'---@class {interface_name}')
15+
elif line.startswith("{") or line.startswith("}"):
16+
continue
17+
elif line.startswith("/") or line.startswith("*"):
18+
continue
19+
elif line:
20+
properties = re.findall('\s*(\w*\?*):(\?*) *(\w*)', line)
21+
lua_lines.append(f'---@field {properties[0][0]} {properties[0][2]}')
22+
23+
lua_lines.append('\n')
24+
lua_annotation = "\n".join(lua_lines)
25+
26+
return lua_annotation
27+
28+
def _enum(text):
29+
lines = text.split('\n')
30+
lua_lines = []
31+
32+
for line in lines:
33+
line = line.strip()
34+
if line.startswith("enum"):
35+
interface_name = line.split(" ")[1]
36+
lua_lines.append(f'---@enum {interface_name}')
37+
lua_lines.append(f'M.{interface_name} = {{')
38+
things_to_export.append(interface_name)
39+
elif line.startswith("{") or line.startswith("}"):
40+
continue
41+
elif line.startswith("/") or line.startswith("*"):
42+
continue
43+
elif line:
44+
suffix = ''
45+
if line.endswith(',') != True:
46+
suffix = ','
47+
lua_lines.append('\t' + line + suffix)
48+
49+
lua_lines.append('}')
50+
lua_lines.append('\n')
51+
lua_annotation = "\n".join(lua_lines)
52+
53+
return lua_annotation
54+
55+
lua_doc = ''
56+
57+
lua_doc = lua_doc + 'local M = {}\n'
58+
59+
content = urllib.request.urlopen("https://raw.githubusercontent.com/wiki/eclipse-jdtls/eclipse.jdt.ls/Running-the-JAVA-LS-server-from-the-command-line.md").read().decode('utf-8')
60+
61+
code_block_pattern = r'```typescript[a-zA-Z]*\n(.*?)```'
62+
code_blocks = re.findall(code_block_pattern, content, re.DOTALL)
63+
64+
65+
for code_block in code_blocks:
66+
text = code_block.strip()
67+
if re.match('^interface', text):
68+
lua_doc = lua_doc + _iface(text)
69+
elif re.match('^enum', text):
70+
lua_doc = lua_doc + _enum(text)
71+
72+
lua_doc = lua_doc + 'return M\n'
73+
74+
with open("./lua/java/jdtls-types.lua", "w") as f:
75+
f.write(lua_doc)

dev/init.lua

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
local cwd = vim.fn.getcwd()
2+
vim.opt.runtimepath:prepend(cwd)
3+
4+
--[[
5+
-- plugin name will be used to reload the loaded modules
6+
--]]
7+
local package_name = 'java'
8+
9+
-- add the escape character to special characters
10+
local escape_pattern = function(text)
11+
return text:gsub('([^%w])', '%%%1')
12+
end
13+
14+
-- unload loaded modules by the matching text
15+
local unload_packages = function()
16+
local esc_package_name = escape_pattern(package_name)
17+
18+
for module_name, _ in pairs(package.loaded) do
19+
if string.find(module_name, esc_package_name) then
20+
package.loaded[module_name] = nil
21+
end
22+
end
23+
end
24+
25+
-- executes the run method in the package
26+
local run_action = function()
27+
vim.cmd.messages('clear')
28+
29+
require(package_name).__run()
30+
end
31+
32+
-- unload and run the function from the package
33+
function _G.Reload_and_run()
34+
unload_packages()
35+
run_action()
36+
end
37+
38+
---@diagnostic disable-next-line: undefined-global
39+
local set_keymap = vim.api.nvim_set_keymap
40+
41+
set_keymap('n', '<leader><leader>r', '<cmd>luafile dev/init.lua<cr>', {})
42+
set_keymap('n', '<leader><leader>w', '<cmd>lua Reload_and_run()<cr>', {})

lua/java.lua

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
local server = require('java.server')
2+
local config = require('java.config')
3+
local settings = require('java.settings')
4+
5+
---@class Java
6+
---@field config JavaConfig
7+
local M = {}
8+
9+
---Setup the plugin
10+
---@param args JavaConfig
11+
M.setup = function(args)
12+
config = vim.tbl_deep_extend('force', config, args or {})
13+
end
14+
15+
---Returns the jdtls config
16+
---@param root_markers? string[] list of files to find the root dir of a project
17+
---@return LSPSetupConfig
18+
function M.get_config(root_markers)
19+
return server.get_config({
20+
root_markers = root_markers or config.root_markers,
21+
})
22+
end
23+
24+
M.__run = function()
25+
settings.change_settings({})
26+
end
27+
28+
return M

lua/java/config.lua

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---@class JavaConfig
2+
---@field workspace_root string path to the root of workspaces
3+
---@field root_markers string[] list of files that indicates the project root
4+
local config = {
5+
workspace_root = vim.fn.stdpath('data') .. '/nvim-java/workspaces',
6+
7+
root_markers = {
8+
'settings.gradle',
9+
'settings.gradle.kts',
10+
'pom.xml',
11+
'build.gradle',
12+
'mvnw',
13+
'gradlew',
14+
'build.gradle',
15+
'build.gradle.kts',
16+
'.git',
17+
},
18+
}
19+
20+
return config

0 commit comments

Comments
 (0)