Skip to content

Commit 3442006

Browse files
authored
feat: run/debug profiles (nvim-java#110, nvim-java#131) (nvim-java#146)
1 parent e7692a2 commit 3442006

File tree

13 files changed

+1998
-538
lines changed

13 files changed

+1998
-538
lines changed

lua/java.lua

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ local setup_wrap = require('java.startup.lspconfig-setup-wrap')
66
local test = require('java.api.test')
77
local dap = require('java.api.dap')
88
local runner = require('java.api.runner')
9+
local profile_ui = require('java.ui.profile')
910

1011
local global_config = require('java.config')
1112

@@ -62,6 +63,12 @@ M.runner.built_in.run_app = runner.built_in.run_app
6263
M.runner.built_in.toggle_logs = runner.built_in.toggle_logs
6364
M.runner.built_in.stop_app = runner.built_in.stop_app
6465

66+
----------------------------------------------------------------------
67+
-- Profile UI --
68+
----------------------------------------------------------------------
69+
M.profile = {}
70+
M.profile.ui = profile_ui.ui
71+
6572
function M.__run()
6673
test.debug_current_method()
6774
end

lua/java/api/dap.lua

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ local get_error_handler = require('java.handlers.error')
55
local jdtls = require('java.utils.jdtls')
66
local async = require('java-core.utils.async').sync
77
local notify = require('java-core.utils.notify')
8+
local project_config = require('java.api.profile_config')
89

910
local M = {}
1011

@@ -47,8 +48,8 @@ function M.on_jdtls_attach(ev)
4748
if server_name == 'jdtls' then
4849
log.info('setup java dap config & adapter')
4950

51+
project_config.setup()
5052
M.config_dap()
51-
5253
-- removing the event handler after configuring dap
5354
vim.api.nvim_del_autocmd(M.even_id)
5455
end

lua/java/api/profile_config.lua

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
local async = require('java-core.utils.async').sync
2+
local get_error_handler = require('java.handlers.error')
3+
local class = require('java-core.utils.class')
4+
5+
local config_path = vim.fn.stdpath('data') .. '/nvim-java-profiles.json'
6+
7+
--- @class Profile
8+
--- @field vm_args string
9+
--- @field prog_args string
10+
--- @field name string
11+
--- @field is_active boolean
12+
local Profile = class()
13+
14+
--- @param vm_args string
15+
--- @param prog_args string
16+
--- @param name string
17+
--- @param is_active boolean
18+
function Profile:_init(vm_args, prog_args, name, is_active)
19+
self.vm_args = vm_args
20+
self.prog_args = prog_args
21+
self.name = name
22+
self.is_active = is_active or false
23+
end
24+
25+
-- palin config structure
26+
-- {
27+
-- "roo_dir" : {
28+
-- "mod1 -> main_class" : [
29+
-- {
30+
-- "vm_args": "-Xmx1024m",
31+
-- "prog_args": "arg1 arg2",
32+
-- "name": "profile_name1",
33+
-- "is_active": true
34+
-- },
35+
-- {
36+
-- "vm_args": "-Xmx1024m",
37+
-- "prog_args": "arg1 arg2",
38+
-- "name": "profile_name2",
39+
-- "is_active": false
40+
-- }
41+
-- ],
42+
-- "mod2 -> main_class" : [
43+
-- ...
44+
-- ]
45+
-- }
46+
-- }
47+
--- @return table
48+
local function read_full_config()
49+
local file = io.open(config_path, 'r')
50+
if not file then
51+
return {}
52+
end
53+
local data = file:read('*a')
54+
file:close()
55+
local ok, config = pcall(vim.fn.json_decode, data)
56+
if not ok or not config then
57+
vim.notify('Failed to read config')
58+
return {}
59+
end
60+
return config
61+
end
62+
63+
local M = {}
64+
65+
-- loaded profiles
66+
-- {
67+
-- ['mod1 -> dap_config_name'] = {
68+
-- profile_name1 = {
69+
-- vm_args = '-Xmx1024m',
70+
-- prog_args = 'arg1 arg2',
71+
-- name = 'profile_name1',
72+
-- is_active = true,
73+
-- },
74+
-- profile_name2 = {
75+
-- vm_args = '-Xmx1024m',
76+
-- prog_args = 'arg1 arg2',
77+
-- name = 'profile_name2',
78+
-- is_active = false,
79+
-- },
80+
-- },
81+
-- ['mod2 -> dap_config_name'] = {
82+
-- ....
83+
-- },
84+
-- }
85+
--- @return table<string, table<string, Profile>>
86+
function M.load_current_project_profiles()
87+
local result = {}
88+
local current = read_full_config()[M.current_project_path] or {}
89+
for dap_config_name, dap_config_name_val in pairs(current) do
90+
result[dap_config_name] = {}
91+
for _, profile in pairs(dap_config_name_val) do
92+
result[dap_config_name][profile.name] = Profile(
93+
profile.vm_args,
94+
profile.prog_args,
95+
profile.name,
96+
profile.is_active
97+
)
98+
end
99+
end
100+
return result
101+
end
102+
103+
function M.save()
104+
return async(function()
105+
local full_config = read_full_config()
106+
local updated_profiles = {}
107+
for dap_config_name, val in pairs(M.project_profiles) do
108+
updated_profiles[dap_config_name] = {}
109+
for _, profile in pairs(val) do
110+
table.insert(updated_profiles[dap_config_name], profile)
111+
end
112+
end
113+
full_config[M.current_project_path] = updated_profiles
114+
local ok, json = pcall(vim.fn.json_encode, full_config)
115+
assert(ok, 'Failed to encode json')
116+
local file = io.open(config_path, 'w')
117+
assert(file, 'Failed to open file')
118+
file:write(json)
119+
file:close()
120+
end)
121+
.catch(get_error_handler('Failed to save profile'))
122+
.run()
123+
end
124+
--- @param dap_config_name string
125+
--- @return Profile|nil
126+
function M.get_active_profile(dap_config_name)
127+
if M.project_profiles[dap_config_name] == nil then
128+
return nil
129+
end
130+
local number_of_profiles = 0
131+
for _, profile in pairs(M.project_profiles[dap_config_name]) do
132+
number_of_profiles = number_of_profiles + 1
133+
if profile.is_active then
134+
return profile
135+
end
136+
end
137+
if number_of_profiles > 0 then
138+
error('No active profile')
139+
end
140+
end
141+
142+
--- @param dap_config_name string
143+
--- @param profile_name string
144+
--- @return Profile|nil
145+
function M.get_profile(profile_name, dap_config_name)
146+
if M.project_profiles[dap_config_name] == nil then
147+
return nil
148+
end
149+
return M.project_profiles[dap_config_name][profile_name]
150+
end
151+
152+
--- @param dap_config_name_key string
153+
--- @return table<string, Profile>
154+
function M.get_all_profiles(dap_config_name)
155+
return M.project_profiles[dap_config_name] or {}
156+
end
157+
--- @param dap_config_name string
158+
--- @param profile_name string
159+
function M.set_active_profile(profile_name, dap_config_name)
160+
for _, profile in pairs(M.project_profiles[dap_config_name]) do
161+
if profile.is_active then
162+
profile.is_active = false
163+
break
164+
end
165+
end
166+
M.project_profiles[dap_config_name][profile_name].is_active = true
167+
M.save()
168+
end
169+
170+
--- @param dap_config_name string
171+
--- @param current_profile_name string|nil
172+
--- @param new_profile Profile
173+
function M.add_or_update_profile(
174+
new_profile,
175+
current_profile_name,
176+
dap_config_name
177+
)
178+
assert(new_profile.name, 'Profile name is required')
179+
if current_profile_name then
180+
M.project_profiles[dap_config_name][current_profile_name] = nil
181+
end
182+
assert(
183+
M.get_profile(new_profile.name, dap_config_name) == nil,
184+
"Profile with name '" .. new_profile.name .. "' already exists"
185+
)
186+
187+
if M.project_profiles[dap_config_name] == nil then
188+
M.project_profiles[dap_config_name] = {}
189+
else
190+
for _, profile in pairs(M.project_profiles[dap_config_name]) do
191+
profile.is_active = false
192+
end
193+
end
194+
195+
new_profile.is_active = true
196+
M.project_profiles[dap_config_name][new_profile.name] = new_profile
197+
M.save()
198+
end
199+
200+
--- @param dap_config_name string
201+
--- @param profile_name string
202+
function M.delete_profile(profile_name, dap_config_name)
203+
M.project_profiles[dap_config_name][profile_name] = nil
204+
M.save()
205+
end
206+
207+
--- @type Profile
208+
M.Profile = Profile
209+
210+
M.setup = function()
211+
async(function()
212+
M.current_project_path = vim.fn.getcwd()
213+
M.project_profiles = M.load_current_project_profiles()
214+
end)
215+
.catch(get_error_handler('Failed to read profile config'))
216+
.run()
217+
end
218+
219+
return M

lua/java/api/runner.lua

Lines changed: 24 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,17 @@ local log = require('java.utils.log')
22
local async = require('java-core.utils.async').sync
33
local get_error_handler = require('java.handlers.error')
44
local jdtls = require('java.utils.jdtls')
5-
local notify = require('java-core.utils.notify')
65
local DapSetup = require('java-dap.api.setup')
76
local ui = require('java.utils.ui')
7+
local profile_config = require('java.api.profile_config')
8+
local class = require('java-core.utils.class')
89

910
--- @class BuiltInMainRunner
1011
--- @field win number
1112
--- @field bufnr number
1213
--- @field job_id number
1314
--- @field is_open boolean
14-
local BuiltInMainRunner = {}
15+
local BuiltInMainRunner = class()
1516

1617
function BuiltInMainRunner:_set_up_buffer_autocmd()
1718
local group = vim.api.nvim_create_augroup('logger', { clear = true })
@@ -24,14 +25,8 @@ function BuiltInMainRunner:_set_up_buffer_autocmd()
2425
})
2526
end
2627

27-
function BuiltInMainRunner:new()
28-
local o = {
29-
is_open = false,
30-
}
31-
32-
setmetatable(o, self)
33-
self.__index = self
34-
return o
28+
function BuiltInMainRunner:_init()
29+
self.is_open = false
3530
end
3631

3732
function BuiltInMainRunner:stop()
@@ -138,45 +133,16 @@ end
138133
--- @class RunnerApi
139134
--- @field client LspClient
140135
--- @field private dap java.DapSetup
141-
local RunnerApi = {}
142-
143-
function RunnerApi:new(args)
144-
local o = {
145-
client = args.client,
146-
}
136+
local RunnerApi = class()
147137

148-
o.dap = DapSetup(args.client)
149-
setmetatable(o, self)
150-
self.__index = self
151-
return o
138+
function RunnerApi:_init(args)
139+
self.client = args.client
140+
self.dap = DapSetup(args.client)
152141
end
153142

154143
function RunnerApi:get_config()
155144
local configs = self.dap:get_dap_config()
156-
log.debug('dap configs: ', configs)
157-
158-
local config_names = {}
159-
local config_lookup = {}
160-
for _, config in ipairs(configs) do
161-
if config.projectName then
162-
table.insert(config_names, config.name)
163-
config_lookup[config.name] = config
164-
end
165-
end
166-
167-
if #config_names == 0 then
168-
notify.warn('Dap config not found')
169-
return
170-
end
171-
172-
if #config_names == 1 then
173-
return config_lookup[config_names[1]]
174-
end
175-
176-
local selected_config =
177-
ui.select('Select the main class (modul -> mainClass)', config_names)
178-
179-
return config_lookup[selected_config]
145+
return ui.select_from_dap_configs(configs)
180146
end
181147

182148
--- @param callback fun(cmd)
@@ -193,13 +159,24 @@ function RunnerApi:run_app(callback, args)
193159
local main_class = enrich_config.mainClass
194160
local java_exec = enrich_config.javaExec
195161

162+
local active_profile = profile_config.get_active_profile(enrich_config.name)
163+
164+
local vm_args = ''
165+
local prog_args = ''
166+
if active_profile then
167+
prog_args = (active_profile.prog_args or '') .. ' ' .. (args or '')
168+
vm_args = active_profile.vm_args or ''
169+
end
170+
196171
local cmd = {
197172
java_exec,
198-
args or '',
173+
vm_args,
199174
'-cp',
200175
class_paths,
201176
main_class,
177+
prog_args,
202178
}
179+
203180
log.debug('run app cmd: ', cmd)
204181
callback(cmd)
205182
end
@@ -212,7 +189,7 @@ local M = {
212189
--- @param args string
213190
function M.run_app(callback, args)
214191
return async(function()
215-
return RunnerApi:new(jdtls()):run_app(callback, args)
192+
return RunnerApi(jdtls()):run_app(callback, args)
216193
end)
217194
.catch(get_error_handler('failed to run app'))
218195
.run()
@@ -221,7 +198,7 @@ end
221198
--- @param opts {}
222199
function M.built_in.run_app(opts)
223200
if not M.BuildInRunner then
224-
M.BuildInRunner = BuiltInMainRunner:new()
201+
M.BuildInRunner = BuiltInMainRunner()
225202
end
226203
M.run_app(function(cmd)
227204
M.BuildInRunner:run_app(cmd)

0 commit comments

Comments
 (0)