Skip to content

Commit

Permalink
feat: run/debug profiles (#110, #131) (#146)
Browse files Browse the repository at this point in the history
  • Loading branch information
atm1020 committed Apr 12, 2024
1 parent e7692a2 commit 3442006
Show file tree
Hide file tree
Showing 13 changed files with 1,998 additions and 538 deletions.
7 changes: 7 additions & 0 deletions lua/java.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ local setup_wrap = require('java.startup.lspconfig-setup-wrap')
local test = require('java.api.test')
local dap = require('java.api.dap')
local runner = require('java.api.runner')
local profile_ui = require('java.ui.profile')

local global_config = require('java.config')

Expand Down Expand Up @@ -62,6 +63,12 @@ M.runner.built_in.run_app = runner.built_in.run_app
M.runner.built_in.toggle_logs = runner.built_in.toggle_logs
M.runner.built_in.stop_app = runner.built_in.stop_app

----------------------------------------------------------------------
-- Profile UI --
----------------------------------------------------------------------
M.profile = {}
M.profile.ui = profile_ui.ui

function M.__run()
test.debug_current_method()
end
Expand Down
3 changes: 2 additions & 1 deletion lua/java/api/dap.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ local get_error_handler = require('java.handlers.error')
local jdtls = require('java.utils.jdtls')
local async = require('java-core.utils.async').sync
local notify = require('java-core.utils.notify')
local project_config = require('java.api.profile_config')

local M = {}

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

project_config.setup()
M.config_dap()

-- removing the event handler after configuring dap
vim.api.nvim_del_autocmd(M.even_id)
end
Expand Down
219 changes: 219 additions & 0 deletions lua/java/api/profile_config.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
local async = require('java-core.utils.async').sync
local get_error_handler = require('java.handlers.error')
local class = require('java-core.utils.class')

local config_path = vim.fn.stdpath('data') .. '/nvim-java-profiles.json'

--- @class Profile
--- @field vm_args string
--- @field prog_args string
--- @field name string
--- @field is_active boolean
local Profile = class()

--- @param vm_args string
--- @param prog_args string
--- @param name string
--- @param is_active boolean
function Profile:_init(vm_args, prog_args, name, is_active)
self.vm_args = vm_args
self.prog_args = prog_args
self.name = name
self.is_active = is_active or false
end

-- palin config structure
-- {
-- "roo_dir" : {
-- "mod1 -> main_class" : [
-- {
-- "vm_args": "-Xmx1024m",
-- "prog_args": "arg1 arg2",
-- "name": "profile_name1",
-- "is_active": true
-- },
-- {
-- "vm_args": "-Xmx1024m",
-- "prog_args": "arg1 arg2",
-- "name": "profile_name2",
-- "is_active": false
-- }
-- ],
-- "mod2 -> main_class" : [
-- ...
-- ]
-- }
-- }
--- @return table
local function read_full_config()
local file = io.open(config_path, 'r')
if not file then
return {}
end
local data = file:read('*a')
file:close()
local ok, config = pcall(vim.fn.json_decode, data)
if not ok or not config then
vim.notify('Failed to read config')
return {}
end
return config
end

local M = {}

-- loaded profiles
-- {
-- ['mod1 -> dap_config_name'] = {
-- profile_name1 = {
-- vm_args = '-Xmx1024m',
-- prog_args = 'arg1 arg2',
-- name = 'profile_name1',
-- is_active = true,
-- },
-- profile_name2 = {
-- vm_args = '-Xmx1024m',
-- prog_args = 'arg1 arg2',
-- name = 'profile_name2',
-- is_active = false,
-- },
-- },
-- ['mod2 -> dap_config_name'] = {
-- ....
-- },
-- }
--- @return table<string, table<string, Profile>>
function M.load_current_project_profiles()
local result = {}
local current = read_full_config()[M.current_project_path] or {}
for dap_config_name, dap_config_name_val in pairs(current) do
result[dap_config_name] = {}
for _, profile in pairs(dap_config_name_val) do
result[dap_config_name][profile.name] = Profile(
profile.vm_args,
profile.prog_args,
profile.name,
profile.is_active
)
end
end
return result
end

function M.save()
return async(function()
local full_config = read_full_config()
local updated_profiles = {}
for dap_config_name, val in pairs(M.project_profiles) do
updated_profiles[dap_config_name] = {}
for _, profile in pairs(val) do
table.insert(updated_profiles[dap_config_name], profile)
end
end
full_config[M.current_project_path] = updated_profiles
local ok, json = pcall(vim.fn.json_encode, full_config)
assert(ok, 'Failed to encode json')
local file = io.open(config_path, 'w')
assert(file, 'Failed to open file')
file:write(json)
file:close()
end)
.catch(get_error_handler('Failed to save profile'))
.run()
end
--- @param dap_config_name string
--- @return Profile|nil
function M.get_active_profile(dap_config_name)
if M.project_profiles[dap_config_name] == nil then
return nil
end
local number_of_profiles = 0
for _, profile in pairs(M.project_profiles[dap_config_name]) do
number_of_profiles = number_of_profiles + 1
if profile.is_active then
return profile
end
end
if number_of_profiles > 0 then
error('No active profile')
end
end

--- @param dap_config_name string
--- @param profile_name string
--- @return Profile|nil
function M.get_profile(profile_name, dap_config_name)
if M.project_profiles[dap_config_name] == nil then
return nil
end
return M.project_profiles[dap_config_name][profile_name]
end

--- @param dap_config_name_key string
--- @return table<string, Profile>
function M.get_all_profiles(dap_config_name)
return M.project_profiles[dap_config_name] or {}
end
--- @param dap_config_name string
--- @param profile_name string
function M.set_active_profile(profile_name, dap_config_name)
for _, profile in pairs(M.project_profiles[dap_config_name]) do
if profile.is_active then
profile.is_active = false
break
end
end
M.project_profiles[dap_config_name][profile_name].is_active = true
M.save()
end

--- @param dap_config_name string
--- @param current_profile_name string|nil
--- @param new_profile Profile
function M.add_or_update_profile(
new_profile,
current_profile_name,
dap_config_name
)
assert(new_profile.name, 'Profile name is required')
if current_profile_name then
M.project_profiles[dap_config_name][current_profile_name] = nil
end
assert(
M.get_profile(new_profile.name, dap_config_name) == nil,
"Profile with name '" .. new_profile.name .. "' already exists"
)

if M.project_profiles[dap_config_name] == nil then
M.project_profiles[dap_config_name] = {}
else
for _, profile in pairs(M.project_profiles[dap_config_name]) do
profile.is_active = false
end
end

new_profile.is_active = true
M.project_profiles[dap_config_name][new_profile.name] = new_profile
M.save()
end

--- @param dap_config_name string
--- @param profile_name string
function M.delete_profile(profile_name, dap_config_name)
M.project_profiles[dap_config_name][profile_name] = nil
M.save()
end

--- @type Profile
M.Profile = Profile

M.setup = function()
async(function()
M.current_project_path = vim.fn.getcwd()
M.project_profiles = M.load_current_project_profiles()
end)
.catch(get_error_handler('Failed to read profile config'))
.run()
end

return M
71 changes: 24 additions & 47 deletions lua/java/api/runner.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@ local log = require('java.utils.log')
local async = require('java-core.utils.async').sync
local get_error_handler = require('java.handlers.error')
local jdtls = require('java.utils.jdtls')
local notify = require('java-core.utils.notify')
local DapSetup = require('java-dap.api.setup')
local ui = require('java.utils.ui')
local profile_config = require('java.api.profile_config')
local class = require('java-core.utils.class')

--- @class BuiltInMainRunner
--- @field win number
--- @field bufnr number
--- @field job_id number
--- @field is_open boolean
local BuiltInMainRunner = {}
local BuiltInMainRunner = class()

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

function BuiltInMainRunner:new()
local o = {
is_open = false,
}

setmetatable(o, self)
self.__index = self
return o
function BuiltInMainRunner:_init()
self.is_open = false
end

function BuiltInMainRunner:stop()
Expand Down Expand Up @@ -138,45 +133,16 @@ end
--- @class RunnerApi
--- @field client LspClient
--- @field private dap java.DapSetup
local RunnerApi = {}

function RunnerApi:new(args)
local o = {
client = args.client,
}
local RunnerApi = class()

o.dap = DapSetup(args.client)
setmetatable(o, self)
self.__index = self
return o
function RunnerApi:_init(args)
self.client = args.client
self.dap = DapSetup(args.client)
end

function RunnerApi:get_config()
local configs = self.dap:get_dap_config()
log.debug('dap configs: ', configs)

local config_names = {}
local config_lookup = {}
for _, config in ipairs(configs) do
if config.projectName then
table.insert(config_names, config.name)
config_lookup[config.name] = config
end
end

if #config_names == 0 then
notify.warn('Dap config not found')
return
end

if #config_names == 1 then
return config_lookup[config_names[1]]
end

local selected_config =
ui.select('Select the main class (modul -> mainClass)', config_names)

return config_lookup[selected_config]
return ui.select_from_dap_configs(configs)
end

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

local active_profile = profile_config.get_active_profile(enrich_config.name)

local vm_args = ''
local prog_args = ''
if active_profile then
prog_args = (active_profile.prog_args or '') .. ' ' .. (args or '')
vm_args = active_profile.vm_args or ''
end

local cmd = {
java_exec,
args or '',
vm_args,
'-cp',
class_paths,
main_class,
prog_args,
}

log.debug('run app cmd: ', cmd)
callback(cmd)
end
Expand All @@ -212,7 +189,7 @@ local M = {
--- @param args string
function M.run_app(callback, args)
return async(function()
return RunnerApi:new(jdtls()):run_app(callback, args)
return RunnerApi(jdtls()):run_app(callback, args)
end)
.catch(get_error_handler('failed to run app'))
.run()
Expand All @@ -221,7 +198,7 @@ end
--- @param opts {}
function M.built_in.run_app(opts)
if not M.BuildInRunner then
M.BuildInRunner = BuiltInMainRunner:new()
M.BuildInRunner = BuiltInMainRunner()
end
M.run_app(function(cmd)
M.BuildInRunner:run_app(cmd)
Expand Down

0 comments on commit 3442006

Please sign in to comment.