From 30a1d3648f4b527f7d26ed36f1042cf28c566e0d Mon Sep 17 00:00:00 2001 From: Srinesh Nisala Date: Thu, 30 May 2024 00:04:58 +0530 Subject: [PATCH 1/5] chore(doc): add Q&A link to readme (#199) --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index c45f26c..b6e04a8 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ https://github.com/nvim-java/nvim-java/assets/18459807/047c8c46-9a0a-4869-b342-d - :white_check_mark: Automatic [DAP](https://github.com/mfussenegger/nvim-dap) debug configuration - :white_check_mark: Running tests +- :white_check_mark: Run & Debug profiles ## :bulb: Why @@ -36,6 +37,10 @@ https://github.com/nvim-java/nvim-java/assets/18459807/047c8c46-9a0a-4869-b342-d :small_orange_diamond:details +### Q & A + +If you face any issues, check our [Q & A](https://github.com/nvim-java/nvim-java/wiki/Q-&-A) wiki to see if that helps + ### Distributions - [Lazyvim](https://github.com/nvim-java/nvim-java/wiki/Lazyvim) From ca5cfdba0d0629a829d16fa838808be0d5db8baa Mon Sep 17 00:00:00 2001 From: atm1020 <30997516+atm1020@users.noreply.github.com> Date: Wed, 5 Jun 2024 06:15:36 +0200 Subject: [PATCH 2/5] feat: handle multipel running app (#182) (#191) Co-authored-by: Srinesh Nisala --- lua/java.lua | 1 + lua/java/api/runner.lua | 400 +++++++---- lua/java/utils/ui.lua | 8 +- plugin/java.lua | 1 + tests/java/api/runner_spec.lua | 1214 +++++++++++++++++++------------- 5 files changed, 991 insertions(+), 633 deletions(-) diff --git a/lua/java.lua b/lua/java.lua index eb29279..6925e81 100644 --- a/lua/java.lua +++ b/lua/java.lua @@ -70,6 +70,7 @@ M.runner.built_in = {} 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 +M.runner.built_in.switch_app = runner.built_in.switch_app ---------------------------------------------------------------------- -- Profile UI -- diff --git a/lua/java/api/runner.lua b/lua/java/api/runner.lua index 7c1909f..84a909e 100644 --- a/lua/java/api/runner.lua +++ b/lua/java/api/runner.lua @@ -7,185 +7,310 @@ local ui = require('java.utils.ui') local profile_config = require('java.api.profile_config') local class = require('java-core.utils.class') ---- @class BuiltInMainRunner +local group = vim.api.nvim_create_augroup('logger', { clear = true }) + +--- @class RunnerApi +--- @field client LspClient +--- @field private dap java.DapSetup +local RunnerApi = class() + +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() + return ui.select_from_dap_configs(configs) +end + +--- @param callback fun(cmd, config) +--- @param args string +function RunnerApi:run_app(callback, args) + local config = self:get_config() + if not config then + return + end + + config.request = 'launch' + local enrich_config = self.dap:enrich_config(config) + local class_paths = table.concat(enrich_config.classPaths, ':') + local main_class = enrich_config.mainClass + local java_exec = enrich_config.javaExec + + local active_profile = + profile_config.get_active_profile(enrich_config.mainClass) + + 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, + vm_args, + '-cp', + class_paths, + main_class, + prog_args, + } + log.debug('run app cmd: ', cmd) + callback(cmd, config) +end + +--- @class RunningApp --- @field win number --- @field bufnr number --- @field job_id number +--- @field chan number +--- @field dap_config table --- @field is_open boolean +--- @field running_status string +local RunningApp = class() + +--- @param dap_config table +function RunningApp:_init(dap_config) + self.is_open = false + self.dap_config = dap_config + self.bufnr = vim.api.nvim_create_buf(false, true) +end + +--- @class BuiltInMainRunner +--- @field running_apps table +--- @field current_app RunningApp local BuiltInMainRunner = class() -function BuiltInMainRunner:_set_up_buffer_autocmd() - local group = vim.api.nvim_create_augroup('logger', { clear = true }) +function BuiltInMainRunner:_init() + self.running_apps = {} + self.current_app = nil +end + +--- @param running_app RunningApp +function BuiltInMainRunner.set_up_buffer_autocmd(running_app) vim.api.nvim_create_autocmd({ 'BufHidden' }, { group = group, - buffer = self.bufnr, + buffer = running_app.bufnr, callback = function(_) - self.is_open = true + running_app.is_open = false end, }) end -function BuiltInMainRunner:_init() - self.is_open = false +--- @param running_app RunningApp +function BuiltInMainRunner.stop(running_app) + if running_app.job_id ~= nil then + vim.fn.jobstop(running_app.job_id) + vim.fn.jobwait({ running_app.job_id }, 1000) + running_app.job_id = nil + end end -function BuiltInMainRunner:stop() - if self.job_id ~= nil then - vim.fn.jobstop(self.job_id) - vim.fn.jobwait({ self.job_id }, 1000) - self.job_id = nil - end +--- @param running_app RunningApp +function BuiltInMainRunner.set_up_buffer(running_app) + vim.cmd('sp | winc J | res 15 | buffer ' .. running_app.bufnr) + running_app.win = vim.api.nvim_get_current_win() + + vim.wo[running_app.win].number = false + vim.wo[running_app.win].relativenumber = false + vim.wo[running_app.win].signcolumn = 'no' + + BuiltInMainRunner.set_up_buffer_autocmd(running_app) + running_app.is_open = true end ---- @param cmd string[] -function BuiltInMainRunner:run_app(cmd) - self:stop() - if not self.bufnr then - self.bufnr = vim.api.nvim_create_buf(false, true) - vim.api.nvim_buf_call(self.bufnr, function() - self:_set_up_buffer() - end) +--- @param exit_code number +--- @param running_app RunningApp +function BuiltInMainRunner.on_exit(exit_code, running_app) + local exit_message = 'Process finished with exit code ' .. exit_code + vim.fn.chansend(running_app.chan, '\n' .. exit_message .. '\n') + local current_buf = vim.api.nvim_get_current_buf() + if current_buf == running_app.bufnr then + vim.cmd('stopinsert') end + vim.notify(running_app.dap_config.name .. ' ' .. exit_message) + running_app.running_status = exit_message +end - self.chan = vim.api.nvim_open_term(self.bufnr, { - on_input = function(_, _, _, data) - if self.job_id then - vim.fn.chansend(self.job_id, data) - end - end, - }) - - local command = table.concat(cmd, ' ') - vim.fn.chansend(self.chan, command) - self.job_id = vim.fn.jobstart(command, { - pty = true, - on_stdout = function(_, data) - self:_on_stdout(data) - end, - on_exit = function(_, exit_code) - self:_on_exit(exit_code) - end, - }) +--- @param running_app RunningApp +function BuiltInMainRunner.scroll_down(running_app) + local last_line = vim.api.nvim_buf_line_count(running_app.bufnr) + vim.api.nvim_win_set_cursor(running_app.win, { last_line, 0 }) end -function BuiltInMainRunner:hide_logs() - if self.bufnr then - self.is_open = true - vim.api.nvim_buf_call(self.bufnr, function() +--- @param running_app RunningApp +function BuiltInMainRunner.hide_logs(running_app) + if not running_app or not running_app.is_open then + return + end + if running_app.bufnr then + vim.api.nvim_buf_call(running_app.bufnr, function() vim.cmd('hide') end) end end -function BuiltInMainRunner:toggle_logs() - if self.is_open then - vim.api.nvim_buf_call(self.bufnr, function() - self:_set_up_buffer() - self:_scroll_down() +--- @param running_app RunningApp +function BuiltInMainRunner.toggle_logs(running_app) + if running_app and not running_app.is_open then + vim.api.nvim_buf_call(running_app.bufnr, function() + BuiltInMainRunner.set_up_buffer(running_app) + BuiltInMainRunner.scroll_down(running_app) end) else - self:hide_logs() + BuiltInMainRunner.hide_logs(running_app) end end -function BuiltInMainRunner:_set_up_buffer() - vim.cmd('sp | winc J | res 15 | buffer ' .. self.bufnr) - self.win = vim.api.nvim_get_current_win() - - vim.wo[self.win].number = false - vim.wo[self.win].relativenumber = false - vim.wo[self.win].signcolumn = 'no' - - self:_set_up_buffer_autocmd() - self.is_open = false +function BuiltInMainRunner:toggle_current_app_logs() + local running_app = self.current_app + if not running_app then + return + end + BuiltInMainRunner.toggle_logs(running_app) end --- @param data string[] -function BuiltInMainRunner:_on_stdout(data) - vim.fn.chansend(self.chan, data) - vim.api.nvim_buf_call(self.bufnr, function() +--- @param running_app RunningApp +function BuiltInMainRunner.on_stdout(data, running_app) + vim.fn.chansend(running_app.chan, data) + if not running_app.is_open then + return + end + vim.api.nvim_buf_call(running_app.bufnr, function() local current_buf = vim.api.nvim_get_current_buf() local mode = vim.api.nvim_get_mode().mode - if current_buf ~= self.bufnr or mode ~= 'i' then - self:_scroll_down() + if current_buf ~= running_app.bufnr or mode ~= 'i' then + BuiltInMainRunner.scroll_down(running_app) end end) end ---- @param exit_code number -function BuiltInMainRunner:_on_exit(exit_code) - vim.fn.chansend( - self.chan, - '\nProcess finished with exit code ' .. exit_code .. '\n' - ) - self.job_id = nil - local current_buf = vim.api.nvim_get_current_buf() - if current_buf == self.bufnr then - vim.cmd('stopinsert') +--- @param cmd string[] +--- @param config table +function BuiltInMainRunner:run_app(cmd, config) + local selected_app = self:select_app_with_dap_config(config) + if self.current_app then + if self.current_app.job_id == selected_app.job_id then + BuiltInMainRunner.stop(selected_app) + end + end + self:change_current_app(selected_app) + if not selected_app.is_open or not selected_app.chan then + vim.api.nvim_buf_call(selected_app.bufnr, function() + BuiltInMainRunner.set_up_buffer(selected_app) + BuiltInMainRunner.scroll_down(selected_app) + end) + vim.api.nvim_buf_set_name(selected_app.bufnr, selected_app.dap_config.name) end -end -function BuiltInMainRunner:_scroll_down() - local last_line = vim.api.nvim_buf_line_count(self.bufnr) - vim.api.nvim_win_set_cursor(self.win, { last_line, 0 }) + selected_app.chan = vim.api.nvim_open_term(selected_app.bufnr, { + on_input = function(_, _, _, data) + if selected_app.job_id then + vim.fn.chansend(selected_app.job_id, data) + end + end, + }) + + selected_app.running_status = '(running)' + local command = table.concat(cmd, ' ') + vim.fn.chansend(selected_app.chan, command) + selected_app.job_id = vim.fn.jobstart(command, { + pty = true, + on_stdout = function(_, data) + BuiltInMainRunner.on_stdout(data, selected_app) + end, + on_exit = function(_, exit_code) + BuiltInMainRunner.on_exit(exit_code, selected_app) + end, + }) end ---- @class RunnerApi ---- @field client LspClient ---- @field private dap java.DapSetup -local RunnerApi = class() +--- @return RunningApp|nil +function BuiltInMainRunner:select_app_with_ui() + --- @type RunningApp + local app = nil + local count = 0 + for _ in pairs(self.running_apps) do + count = count + 1 + end + if count == 0 then + error('No running apps') + elseif count == 1 then + for _, _app in pairs(self.running_apps) do + app = _app + end + else + local configs = {} + for _, _app in pairs(self.running_apps) do + _app.dap_config.extra_args = _app.running_status + table.insert(configs, _app.dap_config) + end -function RunnerApi:_init(args) - self.client = args.client - self.dap = DapSetup(args.client) + local selected = ui.select_from_dap_configs(configs) + if not selected then + return nil + end + app = self.running_apps[selected.mainClass] + end + self:change_current_app(app) + return app end -function RunnerApi:get_config() - local configs = self.dap:get_dap_config() - return ui.select_from_dap_configs(configs) +--- @param app RunningApp +function BuiltInMainRunner:change_current_app(app) + if + self.current_app + and self.current_app.dap_config.name ~= app.dap_config.name + then + BuiltInMainRunner.hide_logs(self.current_app) + end + self.current_app = app end ---- @param callback fun(cmd) ---- @param args string -function RunnerApi:run_app(callback, args) - local config = self:get_config() +--- @param config table|nil +--- @return RunningApp +function BuiltInMainRunner:select_app_with_dap_config(config) + --- @type RunningApp if not config then - return + error('No config') end - config.request = 'launch' - local enrich_config = self.dap:enrich_config(config) - local class_paths = table.concat(enrich_config.classPaths, ':') - 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 '' + if self.running_apps and self.running_apps[config.mainClass] then + return self.running_apps[config.mainClass] end + local running_app = RunningApp(config) + self.running_apps[running_app.dap_config.mainClass] = running_app + return running_app +end - local cmd = { - java_exec, - vm_args, - '-cp', - class_paths, - main_class, - prog_args, - } +function BuiltInMainRunner:switch_app() + local selected_app = self:select_app_with_ui() + if not selected_app then + return + end + if not selected_app.is_open then + BuiltInMainRunner.toggle_logs(selected_app) + end +end - log.debug('run app cmd: ', cmd) - callback(cmd) +function BuiltInMainRunner:stop_app() + local selected_app = self:select_app_with_ui() + if not selected_app then + return + end + BuiltInMainRunner.stop(selected_app) + BuiltInMainRunner.toggle_logs(selected_app) end local M = { built_in = {}, + --- @type BuiltInMainRunner + runner = BuiltInMainRunner(), } ---- @param callback fun(cmd) +--- @param callback fun(cmd, config) --- @param args string function M.run_app(callback, args) return async(function() @@ -197,26 +322,41 @@ end --- @param opts {} function M.built_in.run_app(opts) - if not M.BuildInRunner then - M.BuildInRunner = BuiltInMainRunner() - end - M.run_app(function(cmd) - M.BuildInRunner:run_app(cmd) - end, opts.args) + async(function() + M.run_app(function(cmd, config) + M.runner:run_app(cmd, config) + end, opts.args) + end) + .catch(get_error_handler('failed to run app')) + .run() end function M.built_in.toggle_logs() - if M.BuildInRunner then - M.BuildInRunner:toggle_logs() - end + async(function() + M.runner:toggle_current_app_logs() + end) + .catch(get_error_handler('failed to toggle logs')) + .run() +end + +function M.built_in.switch_app() + async(function() + M.runner:switch_app() + end) + .catch(get_error_handler('failed to switch app')) + .run() end function M.built_in.stop_app() - if M.BuildInRunner then - M.BuildInRunner:stop(false) - end + async(function() + M.runner:stop_app() + end) + .catch(get_error_handler('failed to stop app')) + .run() end M.RunnerApi = RunnerApi M.BuiltInMainRunner = BuiltInMainRunner +M.RunningApp = RunningApp + return M diff --git a/lua/java/utils/ui.lua b/lua/java/utils/ui.lua index 7c06439..214112d 100644 --- a/lua/java/utils/ui.lua +++ b/lua/java/utils/ui.lua @@ -26,8 +26,12 @@ function M.select_from_dap_configs(configs) local config_lookup = {} for _, config in ipairs(configs) do if config.projectName then - table.insert(config_names, config.name) - config_lookup[config.name] = config + local key = config.name + if config.extra_args then + key = key .. ' | ' .. config.extra_args + end + table.insert(config_names, key) + config_lookup[key] = config end end diff --git a/plugin/java.lua b/plugin/java.lua index 3e43e25..9c28519 100644 --- a/plugin/java.lua +++ b/plugin/java.lua @@ -18,6 +18,7 @@ local cmd_map = { JavaRunnerRunMain = { java.runner.built_in.run_app, { nargs = '?' } }, JavaRunnerStopMain = { java.runner.built_in.stop_app }, JavaRunnerToggleLogs = { java.runner.built_in.toggle_logs }, + JavaRunnerSwitchLogs = { java.runner.built_in.switch_app }, JavaProfile = { java.profile.ui }, diff --git a/tests/java/api/runner_spec.lua b/tests/java/api/runner_spec.lua index c78086d..3707e8f 100644 --- a/tests/java/api/runner_spec.lua +++ b/tests/java/api/runner_spec.lua @@ -1,501 +1,713 @@ --- local spy = require('luassert.spy') --- local mock = require('luassert.mock') --- local notify = require('java-core.utils.notify') --- local DapSetup = require('java-dap.api.setup') --- local mock_client = { jdtls_args = {} } --- local runner = require('java.api.runner') --- local async = require('java-core.utils.async').sync --- local profile_config = require('java.api.profile_config') --- --- local RunnerApi = runner.RunnerApi({ client = mock_client }) --- --- describe('java-core.api.runner', function() --- it('RunnerApi()', function() --- local mock_dap = DapSetup(mock_client) --- assert.same(RunnerApi.client, mock_client) --- assert.same(RunnerApi.dap, mock_dap) --- end) --- --- it('RunnerApi:get_config when no config found', function() --- local dap_mock = mock(DapSetup, true) --- dap_mock.get_dap_config.returns({}) --- --- local notify_spy = spy.on(notify, 'warn') --- local config = RunnerApi:get_config() --- --- assert.equals(config, nil) --- assert.spy(notify_spy).was_called_with('Config not found') --- mock.revert() --- end) --- --- it('RunnerApi:get_config when only one config found', function() --- local dap_mock = mock(DapSetup, true) --- dap_mock.get_dap_config.returns({ --- { name = 'config1', projectName = 'projectName' }, --- }) --- --- local config = RunnerApi:get_config() --- assert.same(config, { name = 'config1', projectName = 'projectName' }) --- mock.revert() --- end) --- --- it('RunnerApi:get_config when multiple config found', function() --- RunnerApi.dap.get_dap_config = function() --- return { --- { name = 'config1' }, --- { name = 'config2', projectName = 'project2' }, --- { name = 'config3', projectName = 'project3' }, --- } --- end --- --- local ui = mock(vim.ui, true) --- local mock_select = function(main_class_choices, opts, callback) --- assert.same(main_class_choices, { 'config2', 'config3' }) --- assert.same(opts, { --- prompt = 'Select the main class (modul -> mainClass)', --- }) --- callback('config2', 2) --- end --- --- ui.select = mock_select --- --- return async(function() --- local config = RunnerApi:get_config() --- --- assert.same({ name = 'config2', projectName = 'project2' }, config) --- mock.revert(ui) --- end).run() --- end) --- --- it('RunnerApi:run_app when no config found', function() --- RunnerApi.get_config = function() --- return nil --- end --- --- local callback_mock = function(_) end --- local callback_spy = spy.new(callback_mock) --- --- RunnerApi:run_app(callback_spy) --- assert.spy(callback_spy).was_not_called() --- end) --- --- it('RunnerApi:run_app without active profile', function() --- RunnerApi.get_config = function() --- return { name = 'config1' } --- end --- --- RunnerApi.dap.enrich_config = function() --- return { --- classPaths = { 'path1', 'path2' }, --- mainClass = 'mainClass', --- javaExec = 'javaExec', --- } --- end --- --- RunnerApi.profile_config = profile_config --- RunnerApi.profile_config.get_active_profile = function(main_class) --- assert.equals(main_class, 'mainClass') --- return nil --- end --- --- local callback_mock = function(_, _) end --- local callback_spy = spy.new(callback_mock) --- --- RunnerApi:run_app(callback_spy) --- assert.spy(callback_spy).was_called_with({ --- 'javaExec', --- '', -- vm_args --- '-cp', --- 'path1:path2', --- 'mainClass', --- '', -- prog_args --- }) --- end) --- --- it('RunnerApi:run_app with active profile', function() --- RunnerApi.get_config = function() --- return { name = 'config1' } --- end --- --- RunnerApi.dap.enrich_config = function() --- return { --- classPaths = { 'path1', 'path2' }, --- mainClass = 'mainClass', --- javaExec = 'javaExec', --- } --- end --- --- RunnerApi.profile_config = profile_config --- RunnerApi.profile_config.get_active_profile = function(main_class) --- assert.equals(main_class, 'mainClass') --- return { --- prog_args = 'profile_prog_args', --- vm_args = 'vm_args', --- } --- end --- --- local callback_mock = function(_, _) end --- local callback_spy = spy.new(callback_mock) --- --- RunnerApi:run_app(callback_spy, 'input_prog_args') --- assert.spy(callback_spy).was_called_with({ --- 'javaExec', --- 'vm_args', --- '-cp', --- 'path1:path2', --- 'mainClass', --- 'profile_prog_args input_prog_args', --- }) --- end) --- --- it('BuildInRunner:new', function() --- local built_in_main_runner = runner.BuiltInMainRunner() --- assert.equals(built_in_main_runner.is_open, false) --- end) --- --- it('BuildInRunner:_set_up_buffer', function() --- local vim = mock(vim, true) --- vim.wo = {} --- vim.wo[1] = {} --- local spy_cmd = spy.on(vim, 'cmd') --- --- local api = mock(vim.api, true) --- api.nvim_get_current_win.returns(1) --- --- local built_in_main_runner = runner.BuiltInMainRunner() --- built_in_main_runner.bufnr = 1 --- built_in_main_runner.is_open = true --- spy.on(built_in_main_runner, '_set_up_buffer_autocmd') --- built_in_main_runner:_set_up_buffer() --- --- assert.equals(built_in_main_runner.is_open, false) --- assert.spy(spy_cmd).was_called_with('sp | winc J | res 15 | buffer 1') --- assert.spy(built_in_main_runner._set_up_buffer_autocmd).was_called() --- --- mock.revert(vim) --- mock.revert(api) --- end) --- --- it('BuildInRunner:_set_up_buffer_autocmd', function() --- local api = mock(vim.api, true) --- --- local built_in_main_runner = runner.BuiltInMainRunner() --- built_in_main_runner.bufnr = 1 --- built_in_main_runner.is_open = false --- built_in_main_runner:_set_up_buffer_autocmd() --- --- local call_info = api.nvim_create_autocmd.calls[1] --- assert.same(call_info.vals[1], { 'BufHidden' }) --- assert.equals(call_info.vals[2].buffer, 1) --- --- call_info.vals[2].callback() --- assert.is_true(built_in_main_runner.is_open) --- --- mock.revert(api) --- end) --- --- it( --- 'BuiltInMainRunner:_on_stdout when bufnr is equal to current bufnr and mode is "i" (skip scroll)', --- function() --- local mock_current_bufnr = 1 --- local vim = mock(vim, true) --- local api = mock(vim.api, true) --- local spy_chensend = spy.on(vim.fn, 'chansend') --- --- api.nvim_get_current_buf.returns(mock_current_bufnr) --- api.nvim_get_mode.returns({ mode = 'i' }) --- --- local built_in_main_runner = runner.BuiltInMainRunner() --- built_in_main_runner.chan = 2 --- built_in_main_runner.bufnr = mock_current_bufnr --- spy.on(built_in_main_runner, '_scroll_down') --- --- built_in_main_runner:_on_stdout({ 'data1', 'data2' }) --- --- assert.spy(spy_chensend).was_called_with(2, { 'data1', 'data2' }) --- -- call nvim_create_buf --- local call_info = api.nvim_buf_call.calls[1] --- call_info.vals[2]() --- assert.spy(built_in_main_runner._scroll_down).was_not_called() --- -- --- mock.revert(vim) --- mock.revert(api) --- end --- ) --- --- it( --- 'BuiltInMainRunner:_on_stdout when bufnr is not equal to current bufnr and mode is "i" (scroll)', --- function() --- local api = mock(vim.api, true) --- local spy_chensend = spy.on(vim.fn, 'chansend') --- --- api.nvim_get_current_buf.returns(2) --- api.nvim_get_mode.returns({ mode = 'i' }) --- --- local built_in_main_runner = runner.BuiltInMainRunner() --- built_in_main_runner.bufnr = 1 --- built_in_main_runner.chan = 2 --- spy.on(built_in_main_runner, '_scroll_down') --- built_in_main_runner:_on_stdout({ 'data1', 'data2', 'data3' }) --- --- assert.spy(spy_chensend).was_called_with(2, { 'data1', 'data2', 'data3' }) --- local call_info = api.nvim_buf_call.calls[1] --- assert.equals(call_info.vals[1], 1) --- --- call_info.vals[2]() --- assert.spy(built_in_main_runner._scroll_down).was_called() --- --- mock.revert(api) --- end --- ) --- --- it( --- 'BuiltInMainRunner:_on_stdout when bufnr is equal to current bufnr and mode is not "i" (scroll)', --- function() --- local mock_current_bufnr = 1 --- local api = mock(vim.api, true) --- local spy_chensend = spy.on(vim.fn, 'chansend') --- --- api.nvim_get_current_buf.returns(mock_current_bufnr) --- api.nvim_get_mode.returns({ mode = 'n' }) --- api.nvim_buf_line_count.returns(3) --- --- local built_in_main_runner = runner.BuiltInMainRunner() --- built_in_main_runner.bufnr = mock_current_bufnr --- built_in_main_runner.chan = 2 --- spy.on(built_in_main_runner, '_scroll_down') --- built_in_main_runner:_on_stdout({ 'data1', 'data2' }) --- --- assert.spy(spy_chensend).was_called_with(2, { 'data1', 'data2' }) --- local call_info = api.nvim_buf_call.calls[1] --- assert.equals(call_info.vals[1], 1) --- --- call_info.vals[2]() --- assert.spy(built_in_main_runner._scroll_down).was_called() --- --- mock.revert(api) --- end --- ) --- --- it( --- 'BuiltInMainRunner:_on_exit when bufnr is equal to current bufnr (scroll)', --- function() --- local mock_current_bufnr = 1 --- local api = mock(vim.api, true) --- local spy_chensend = spy.on(vim.fn, 'chansend') --- local spy_cmd = spy.on(vim, 'cmd') --- --- api.nvim_get_current_buf.returns(mock_current_bufnr) --- --- local built_in_main_runner = runner.BuiltInMainRunner() --- built_in_main_runner.bufnr = mock_current_bufnr --- built_in_main_runner.chan = 2 --- built_in_main_runner:_on_exit(0) --- --- assert --- .spy(spy_chensend) --- .was_called_with(2, '\nProcess finished with exit code 0\n') --- assert.spy(spy_cmd).was_called_with('stopinsert') --- assert.equals(built_in_main_runner.job_id, nil) --- --- mock.revert(api) --- end --- ) --- --- it( --- 'BuiltInMainRunner:_on_exit when bufnr is not equal to current bufnr (skip scroll)', --- function() --- local mock_current_bufnr = 1 --- local api = mock(vim.api, true) --- local spy_chensend = spy.on(vim.fn, 'chansend') --- local spy_cmd = spy.on(vim, 'cmd') --- --- api.nvim_get_current_buf.returns(mock_current_bufnr) --- --- local built_in_main_runner = runner.BuiltInMainRunner() --- built_in_main_runner.bufnr = mock_current_bufnr + 1 --- built_in_main_runner.chan = 2 --- built_in_main_runner:_on_exit(0) --- --- assert --- .spy(spy_chensend) --- .was_called_with(2, '\nProcess finished with exit code 0\n') --- assert.spy(spy_cmd).was_not_called() --- assert.equals(built_in_main_runner.job_id, nil) --- --- mock.revert(api) --- end --- ) --- --- it('BuiltInMainRunner:run_app when there is no running job', function() --- local fn = mock(vim.fn, true) --- local spy_jobstart = spy.on(fn, 'jobstart') --- local spy_chansend = spy.on(fn, 'chansend') --- local spy_stop = spy.on(fn, 'jobstop') --- local api = mock(vim.api, true) --- --- api.nvim_create_buf.returns(1) --- api.nvim_open_term.returns(2) --- --- local built_in_main_runner = runner.BuiltInMainRunner() --- built_in_main_runner:run_app({ 'java', '-cp', 'path1:path2', 'mainClass' }) --- --- assert --- .spy(spy_chansend) --- .was_called_with(2, 'java -cp path1:path2 mainClass') --- assert.stub(api.nvim_buf_call).was_called() --- assert.spy(spy_jobstart).was_called() --- assert.not_nil(built_in_main_runner.job_id) --- --- local call_info = fn.jobstart.calls[1] --- assert.equals(call_info.vals[1], 'java -cp path1:path2 mainClass') --- assert.not_nil(call_info.vals[2].on_exit) --- assert.not_nil(call_info.vals[2].on_stdout) --- assert.spy(spy_stop).was_not_called() --- --- mock.revert(api) --- mock.revert(fn) --- end) --- --- it('BuiltInMainRunner:run_app when there is a running job', function() --- local fn = mock(vim.fn, true) --- local spy_chensend = spy.on(fn, 'chansend') --- local spy_jobstart = spy.on(fn, 'jobstart') --- local spy_jobwait = spy.on(fn, 'jobwait') --- local spy_stop = spy.on(fn, 'jobstop') --- local api = mock(vim.api, true) --- --- api.nvim_create_buf.returns(1) --- api.nvim_open_term.returns(2) --- --- local built_in_main_runner = runner.BuiltInMainRunner() --- built_in_main_runner.bufnr = 11 --- built_in_main_runner.job_id = 1 --- built_in_main_runner:run_app({ 'java', '-cp', 'path1:path2', 'mainClass' }) --- --- assert --- .spy(spy_chensend) --- .was_called_with(2, 'java -cp path1:path2 mainClass') --- assert.spy(spy_stop).was_called_with(1) --- assert.spy(spy_jobstart).was_called() --- assert.spy(spy_jobwait).was_called_with({ 1 }, 1000) --- --- mock.revert(api) --- mock.revert(fn) --- end) --- --- it('BuiltInMainRunner:toggle_logs when is_open=true', function() --- local api = mock(vim.api, true) --- --- api.nvim_buf_line_count.returns(3) --- --- local built_in_main_runner = runner.BuiltInMainRunner() --- -- mock private functions --- built_in_main_runner._set_up_buffer = function() end --- built_in_main_runner.hide_logs = function() end --- --- built_in_main_runner.is_open = true --- built_in_main_runner.bufnr = 11 --- spy.on(built_in_main_runner, '_set_up_buffer') --- spy.on(built_in_main_runner, 'hide_logs') --- --- built_in_main_runner:toggle_logs() --- --- local call_info = api.nvim_buf_call.calls[1] --- assert.equals(call_info.vals[1], 11) --- --- -- verify that private functions were called --- call_info.vals[2]() --- assert.spy(built_in_main_runner._set_up_buffer).was_called() --- assert.spy(built_in_main_runner.hide_logs).was_not_called() --- --- mock.revert(api) --- end) --- --- it('BuiltInMainRunner:toggle_logs when is_open=false', function() --- local api = mock(vim.api, true) --- --- local built_in_main_runner = runner.BuiltInMainRunner() --- built_in_main_runner.is_open = false --- spy.on(built_in_main_runner, 'hide_logs') --- --- built_in_main_runner:toggle_logs() --- --- assert.stub(api.nvim_buf_call).was_not_called() --- assert.spy(built_in_main_runner.hide_logs).was_called() --- --- mock.revert(api) --- end) --- --- it('BuiltInMainRunner:stop when job_id is nil', function() --- local fn = mock(vim.fn, true) --- local spy_jobstop = spy.on(fn, 'jobstop') --- --- local built_in_main_runner = runner.BuiltInMainRunner() --- built_in_main_runner:stop() --- --- assert.spy(spy_jobstop).was_not_called() --- --- mock.revert(fn) --- end) --- --- it('BuiltInMainRunner:hide_logs', function() --- local vim = mock(vim, true) --- local spy_cmd = spy.on(vim, 'cmd') --- local api = mock(vim.api, true) --- --- local built_in_main_runner = runner.BuiltInMainRunner() --- built_in_main_runner.bufnr = 1 --- built_in_main_runner:hide_logs() --- --- local call_info = api.nvim_buf_call.calls[1] --- assert.equals(call_info.vals[1], 1) --- assert.is_function(call_info.vals[2]) --- --- call_info.vals[2]() --- assert.spy(spy_cmd).was_called_with('hide') --- --- mock.revert(vim) --- mock.revert(api) --- end) --- --- it('built_in.run_app', function() --- local built_in_main_runner_mock = mock(runner.BuiltInMainRunner, true) --- built_in_main_runner_mock._init.returns(built_in_main_runner_mock) --- spy.on(built_in_main_runner_mock, 'run_app') --- spy.on(built_in_main_runner_mock, '_init') --- --- runner.run_app = function(callback, args) --- assert.equals(args, 'args') --- callback() --- end --- --- runner.built_in.run_app({ args = 'args' }) --- --- assert.not_nil(runner.BuiltInMainRunner) --- assert.spy(built_in_main_runner_mock._init).was_called() --- assert.spy(built_in_main_runner_mock.run_app).was_called() --- end) --- --- it('built_in.toggle_logs', function() --- local built_in_main_runner_mock = mock(runner.BuiltInMainRunner, true) --- spy.on(built_in_main_runner_mock, 'toggle_logs') --- runner.BuildInRunner = built_in_main_runner_mock --- --- runner.built_in.toggle_logs() --- assert.spy(built_in_main_runner_mock.toggle_logs).was_called() --- --- runner.BuildInRunner = nil --- end) --- --- it('built_in.stop_app', function() --- local built_in_main_runner_mock = mock(runner.BuiltInMainRunner, true) --- spy.on(built_in_main_runner_mock, 'stop') --- --- runner.BuildInRunner = built_in_main_runner_mock --- --- runner.built_in.stop_app() --- assert.spy(built_in_main_runner_mock.stop).was_called() --- runner.BuildInRunner = nil --- end) --- end) +local spy = require('luassert.spy') +local mock = require('luassert.mock') +local notify = require('java-core.utils.notify') +local DapSetup = require('java-dap.api.setup') +local mock_client = { jdtls_args = {} } +local runner = require('java.api.runner') +local async = require('java-core.utils.async').sync +local profile_config = require('java.api.profile_config') +local ui = require('java.utils.ui') + +local RunnerApi = runner.RunnerApi({ client = mock_client }) + +describe('java-core.api.runner', function() + before_each(function() + package.loaded['java.api.runner'] = nil + package.loaded['java.utils.ui'] = nil + end) + + it('RunnerApi()', function() + local mock_dap = DapSetup(mock_client) + assert.same(RunnerApi.client, mock_client) + assert.same(RunnerApi.dap, mock_dap) + end) + + it('RunnerApi:get_config when no config found', function() + local dap_mock = mock(DapSetup, true) + dap_mock.get_dap_config.returns({}) + + local notify_spy = spy.on(notify, 'warn') + local config = RunnerApi:get_config() + + assert.equals(config, nil) + assert.spy(notify_spy).was_called_with('Config not found') + mock.revert() + end) + + it('RunnerApi:get_config when only one config found', function() + local dap_mock = mock(DapSetup, true) + dap_mock.get_dap_config.returns({ + { name = 'config1', projectName = 'projectName' }, + }) + + local config = RunnerApi:get_config() + assert.same(config, { name = 'config1', projectName = 'projectName' }) + mock.revert() + end) + + it('RunnerApi:get_config when multiple config found', function() + RunnerApi.dap.get_dap_config = function() + return { + { name = 'config1' }, + { name = 'config2', projectName = 'project2' }, + { name = 'config3', projectName = 'project3' }, + } + end + + local mock_ui = mock(vim.ui, true) + mock_ui.select.returns() + + local select_spy = spy.on(vim.ui, 'select') + + async(function() + local config = RunnerApi:get_config() + assert.same({ name = 'config2', projectName = 'project2' }, config) + mock.revert(mock_ui) + end).run() + + assert.same(select_spy.calls[1].vals[1], { 'config2', 'config3' }) + + assert.same( + select_spy.calls[1].vals[2], + { prompt = 'Select the main class (modul -> mainClass)' } + ) + + mock.revert(mock_ui) + end) + + it('RunnerApi:run_app when no config found', function() + RunnerApi.get_config = function() + return nil + end + + local callback_mock = function(_) end + local callback_spy = spy.new(callback_mock) + + RunnerApi:run_app(callback_spy) + assert.spy(callback_spy).was_not_called() + end) + + it('RunnerApi:run_app without active profile', function() + RunnerApi.get_config = function() + return { name = 'config1' } + end + + RunnerApi.dap.enrich_config = function() + return { + classPaths = { 'path1', 'path2' }, + mainClass = 'mainClass', + javaExec = 'javaExec', + } + end + + RunnerApi.profile_config = profile_config + RunnerApi.profile_config.get_active_profile = function(main_class) + assert.equals(main_class, 'mainClass') + return nil + end + + local callback_mock = function(_, _) end + local callback_spy = spy.new(callback_mock) + + RunnerApi:run_app(callback_spy) + assert.spy(callback_spy).was_called_with({ + 'javaExec', + '', -- vm_args + '-cp', + 'path1:path2', + 'mainClass', + '', -- prog_args + }, { name = 'config1', request = 'launch' }) + end) + + it('RunnerApi:run_app with active profile', function() + RunnerApi.get_config = function() + return { name = 'config1' } + end + + RunnerApi.dap.enrich_config = function() + return { + classPaths = { 'path1', 'path2' }, + mainClass = 'mainClass', + javaExec = 'javaExec', + } + end + + RunnerApi.profile_config = profile_config + RunnerApi.profile_config.get_active_profile = function(main_class) + assert.equals(main_class, 'mainClass') + return { + prog_args = 'profile_prog_args', + vm_args = 'vm_args', + } + end + + local callback_mock = function(_, _) end + local callback_spy = spy.new(callback_mock) + + RunnerApi:run_app(callback_spy, 'input_prog_args') + assert.spy(callback_spy).was_called_with({ + 'javaExec', + 'vm_args', + '-cp', + 'path1:path2', + 'mainClass', + 'profile_prog_args input_prog_args', + }, { name = 'config1', request = 'launch' }) + end) + + it('RunningApp:new', function() + local api = mock(vim.api, true) + api.nvim_create_buf.returns(1) + local running_app = runner.RunningApp({ projectName = 'projectName' }) + assert.equals(running_app.win, nil) + assert.equals(running_app.bufnr, 1) + assert.equals(running_app.job_id, nil) + assert.equals(running_app.chan, nil) + assert.same(running_app.dap_config, { projectName = 'projectName' }) + assert.equals(running_app.is_open, false) + assert.equals(running_app.running_status, nil) + mock.revert(api) + end) + + it('BuildInRunner:new', function() + local built_in_main_runner = runner.BuiltInMainRunner() + assert.equals(built_in_main_runner.current_app, nil) + assert.same(built_in_main_runner.running_apps, {}) + end) + + it('BuildInRunner:_set_up_buffer', function() + local vim = mock(vim, true) + vim.wo = {} + vim.wo[1] = {} + local api = mock(vim.api, true) + api.nvim_get_current_win.returns(1) + api.nvim_create_buf.returns(2) + local spy_cmd = spy.on(vim, 'cmd') + + local running_app = runner.RunningApp({ projectName = 'projectName' }) + + spy.on(runner.BuiltInMainRunner, 'set_up_buffer_autocmd') + runner.BuiltInMainRunner.set_up_buffer(running_app) + + assert.equals(running_app.is_open, true) + assert.equals(running_app.win, 1) + assert.spy(spy_cmd).was_called_with('sp | winc J | res 15 | buffer 2') + assert.spy(runner.BuiltInMainRunner.set_up_buffer_autocmd).was_called() + + mock.revert(api) + mock.revert(vim) + end) + + it('BuildInRunner:_set_up_buffer_autocmd', function() + local api = mock(vim.api, true) + api.nvim_create_buf.returns(1) + + local running_app = runner.RunningApp({ projectName = 'projectName' }) + running_app.is_open = true + runner.BuiltInMainRunner.set_up_buffer_autocmd(running_app) + + local call_info = api.nvim_create_autocmd.calls[1] + assert.same(call_info.vals[1], { 'BufHidden' }) + assert.equals(call_info.vals[2].buffer, 1) + + call_info.vals[2].callback() + assert.is_false(running_app.is_open) + + mock.revert(api) + end) + + it('BuiltInMainRunner.on_stdout when is_open=true', function() + local api = mock(vim.api, true) + local spy_chensend = spy.on(vim.fn, 'chansend') + + local running_app = runner.RunningApp({ projectName = 'projectName' }) + running_app.chan = 2 + + spy.on(vim.api, 'nvim_buf_call') + runner.BuiltInMainRunner.on_stdout({ 'data1', 'data2' }, running_app) + assert.spy(spy_chensend).was_called_with(2, { 'data1', 'data2' }) + + assert.spy(api.nvim_buf_call).was_not_called() + + mock.revert(api) + end) + + it( + 'BuiltInMainRunner.on_stdout when bufnr is equal to current bufnr and mode is "i" (skip scroll)', + function() + local mock_current_bufnr = 1 + local vim = mock(vim, true) + local api = mock(vim.api, true) + local spy_chensend = spy.on(vim.fn, 'chansend') + + api.nvim_get_current_buf.returns(mock_current_bufnr) + api.nvim_create_buf.returns(mock_current_bufnr) + api.nvim_get_mode.returns({ mode = 'i' }) + + local running_app = runner.RunningApp({ projectName = 'projectName' }) + running_app.chan = 2 + running_app.is_open = true + -- running_app.bufnr = mock_current_bufnr + spy.on(runner.BuiltInMainRunner, 'scroll_down') + + runner.BuiltInMainRunner.on_stdout({ 'data1', 'data2' }, running_app) + + assert.spy(spy_chensend).was_called_with(2, { 'data1', 'data2' }) + -- -- call nvim_create_buf + local call_info = api.nvim_buf_call.calls[1] + call_info.vals[2]() + + assert.spy(runner.BuiltInMainRunner.scroll_down).was_not_called() + -- + mock.revert(vim) + mock.revert(api) + end + ) + + it( + 'BuiltInMainRunner:_on_stdout when bufnr is not equal to current bufnr and mode is "i" (scroll)', + function() + local vim = mock(vim, true) + local api = mock(vim.api, true) + local spy_chensend = spy.on(vim.fn, 'chansend') + + api.nvim_get_current_buf.returns(1) + api.nvim_create_buf.returns(3) + api.nvim_get_mode.returns({ mode = 'i' }) + + local running_app = runner.RunningApp({ projectName = 'projectName' }) + running_app.chan = 2 + running_app.is_open = true + -- running_app.bufnr = mock_current_bufnr + spy.on(runner.BuiltInMainRunner, 'scroll_down') + + runner.BuiltInMainRunner.on_stdout({ 'data1', 'data2' }, running_app) + + assert.spy(spy_chensend).was_called_with(2, { 'data1', 'data2' }) + -- -- call nvim_create_buf + local call_info = api.nvim_buf_call.calls[1] + call_info.vals[2]() + + assert + .spy(runner.BuiltInMainRunner.scroll_down) + .was_called_with(running_app) + -- + mock.revert(vim) + mock.revert(api) + end + ) + + it( + 'BuiltInMainRunner:_on_stdout when bufnr is equal to current bufnr and mode is not "i" (scroll)', + function() + local vim = mock(vim, true) + local api = mock(vim.api, true) + local spy_chensend = spy.on(vim.fn, 'chansend') + + api.nvim_get_current_buf.returns(1) + api.nvim_create_buf.returns(1) + api.nvim_get_mode.returns({ mode = 'n' }) + + local running_app = runner.RunningApp({ projectName = 'projectName' }) + running_app.chan = 2 + running_app.is_open = true + -- running_app.bufnr = mock_current_bufnr + spy.on(runner.BuiltInMainRunner, 'scroll_down') + + runner.BuiltInMainRunner.on_stdout({ 'data1', 'data2' }, running_app) + + assert.spy(spy_chensend).was_called_with(2, { 'data1', 'data2' }) + -- -- call nvim_create_buf + local call_info = api.nvim_buf_call.calls[1] + call_info.vals[2]() + + assert + .spy(runner.BuiltInMainRunner.scroll_down) + .was_called_with(running_app) + -- + mock.revert(vim) + mock.revert(api) + end + ) + + it( + 'BuiltInMainRunner:_on_exit when bufnr is equal to current bufnr (stopinsert)', + function() + local mock_current_bufnr = 1 + local api = mock(vim.api, true) + local spy_chensend = spy.on(vim.fn, 'chansend') + local spy_cmd = spy.on(vim, 'cmd') + + api.nvim_get_current_buf.returns(mock_current_bufnr) + api.nvim_create_buf.returns(mock_current_bufnr) + + local running_app = + runner.RunningApp({ projectName = 'projectName', name = 'config1' }) + running_app.chan = 2 + running_app.is_open = true + running_app.job_id = 1 + + runner.BuiltInMainRunner.on_exit(0, running_app) + assert + .spy(spy_chensend) + .was_called_with(2, '\nProcess finished with exit code 0\n') + assert.spy(spy_cmd).was_called_with('stopinsert') + assert.equals( + running_app.running_status, + 'Process finished with exit code 0' + ) + + mock.revert(api) + end + ) + + it( + 'BuiltInMainRunner:_on_exit when bufnr is not equal to current bufnr (skip stopinsert)', + function() + local api = mock(vim.api, true) + local spy_chensend = spy.on(vim.fn, 'chansend') + local spy_cmd = spy.on(vim, 'cmd') + + api.nvim_get_current_buf.returns(3) + api.nvim_create_buf.returns(4) + + local running_app = + runner.RunningApp({ projectName = 'projectName', name = 'config1' }) + running_app.chan = 2 + running_app.is_open = true + running_app.job_id = 1 + + runner.BuiltInMainRunner.on_exit(0, running_app) + assert + .spy(spy_chensend) + .was_called_with(2, '\nProcess finished with exit code 0\n') + assert.spy(spy_cmd).was_not_called() + assert.equals( + running_app.running_status, + 'Process finished with exit code 0' + ) + + mock.revert(api) + end + ) + + it('BuiltInMainRunner:run_app when there is no running job', function() + local fn = mock(vim.fn, true) + local spy_jobstart = spy.on(fn, 'jobstart') + local spy_chansend = spy.on(fn, 'chansend') + local api = mock(vim.api, true) + + api.nvim_create_buf.returns(1) + api.nvim_open_term.returns(2) + + local running_app = runner.RunningApp() + running_app.is_open = false + running_app.dap_config = { name = 'config1' } + + local built_in_main_runner = runner.BuiltInMainRunner() + + runner.BuiltInMainRunner.set_up_buffer = function(selected_app) + assert.equals(selected_app, running_app) + end + runner.BuiltInMainRunner.scroll_down = function(selected_app) + assert.equals(selected_app, running_app) + end + + local spy_stop = spy.on(runner.BuiltInMainRunner, 'stop') + + built_in_main_runner.select_app_with_dap_config = function() + return running_app + end + + built_in_main_runner:run_app( + { 'java', '-cp', 'path1:path2', 'mainClass' }, + { name = 'config1' } + ) + + assert.equals(running_app.chan, 2) + assert.equals(running_app.running_status, '(running)') + + assert + .spy(spy_chansend) + .was_called_with(2, 'java -cp path1:path2 mainClass') + assert.stub(api.nvim_buf_call).was_called() + assert.spy(spy_jobstart).was_called() + + local call_info = fn.jobstart.calls[1] + assert.equals(call_info.vals[1], 'java -cp path1:path2 mainClass') + assert.not_nil(call_info.vals[2].on_exit) + assert.not_nil(call_info.vals[2].on_stdout) + assert.spy(spy_stop).was_not_called() + assert.spy(api.nvim_buf_set_name).was_called_with(1, 'config1') + + mock.revert(api) + mock.revert(fn) + end) + + it('BuiltInMainRunner:run_app when there is a running job', function() + local fn = mock(vim.fn, true) + local spy_chensend = spy.on(fn, 'chansend') + local spy_jobstart = spy.on(fn, 'jobstart') + local spy_jobwait = spy.on(fn, 'jobwait') + local spy_stop = spy.on(fn, 'jobstop') + local api = mock(vim.api, true) + + api.nvim_create_buf.returns(1) + api.nvim_open_term.returns(2) + + local running_app = runner.RunningApp() + running_app.is_open = false + running_app.job_id = 1 + running_app.dap_config = { name = 'config1' } + + local built_in_main_runner = runner.BuiltInMainRunner() + built_in_main_runner.current_app = running_app + + runner.BuiltInMainRunner.set_up_buffer = function(selected_app) + assert.equals(selected_app, running_app) + end + runner.BuiltInMainRunner.scroll_down = function(selected_app) + assert.equals(selected_app, running_app) + end + runner.BuiltInMainRunner.change_current_app = function(app) + assert.equals(app.job_id, nil) -- check if job_id is nil + end + + built_in_main_runner.select_app_with_dap_config = function() + return running_app + end + + built_in_main_runner:run_app( + { 'java', '-cp', 'path1:path2', 'mainClass' }, + { name = 'config1' } + ) + + assert.equals(running_app.running_status, '(running)') + assert.is_nil(running_app.job_id) + assert + .spy(spy_chensend) + .was_called_with(2, 'java -cp path1:path2 mainClass') + assert.spy(spy_stop).was_called_with(1) + assert.spy(spy_jobstart).was_called() + assert.spy(spy_jobwait).was_called_with({ 1 }, 1000) + assert.spy(api.nvim_buf_set_name).was_called_with(1, 'config1') + + mock.revert(api) + mock.revert(fn) + end) + + it('BuiltInMainRunner:toggle_logs when is_open=true', function() + local api = mock(vim.api, true) + api.nvim_create_buf.returns(11) + + local running_app = runner.RunningApp() + running_app.is_open = true + + runner.BuiltInMainRunner.hide_logs = function(selected_app) + assert.equals(selected_app, running_app) + end + + local spy_set_up_buffer = spy.on(runner.BuiltInMainRunner, 'set_up_buffer') + local spy_hide_logs = spy.on(runner.BuiltInMainRunner, 'hide_logs') + + runner.BuiltInMainRunner.toggle_logs(running_app) + + assert.spy(spy_hide_logs).was_called() + assert.spy(spy_set_up_buffer).was_not_called() + + mock.revert(api) + end) + + it('BuiltInMainRunner:toggle_logs when is_open=false', function() + local api = mock(vim.api, true) + api.nvim_create_buf.returns(1) + + local running_app = runner.RunningApp() + running_app.is_open = false + + runner.BuiltInMainRunner.set_up_buffer = function(selected_app) + assert.equals(selected_app, running_app) + end + + runner.BuiltInMainRunner.scroll_down = function(selected_app) + assert.equals(selected_app, running_app) + end + + local spy_set_up_buffer = spy.on(runner.BuiltInMainRunner, 'set_up_buffer') + local spy_hide_logs = spy.on(runner.BuiltInMainRunner, 'hide_logs') + + runner.BuiltInMainRunner.toggle_logs(running_app) + + local call_info = api.nvim_buf_call.calls[1] + assert.equals(call_info.vals[1], 1) + call_info.vals[2]() + + assert.spy(spy_hide_logs).was_not_called() + assert.spy(spy_set_up_buffer).was_called() + + mock.revert(api) + end) + + it('BuiltInMainRunner:stop when job_id is nil', function() + local running_app = runner.RunningApp() + running_app.job_id = nil + + local fn_job_stop_spy = spy.on(vim.fn, 'jobstop') + local fn_job_wait_spy = spy.on(vim.fn, 'jobwait') + runner.BuiltInMainRunner.stop(running_app) + + assert.spy(fn_job_stop_spy).was_not_called() + assert.spy(fn_job_wait_spy).was_not_called() + end) + + it('BuiltInMainRunner:stop when job_id is not nil', function() + local running_app = runner.RunningApp() + running_app.job_id = 1 + + local fn_job_stop_spy = spy.on(vim.fn, 'jobstop') + local fn_job_wait_spy = spy.on(vim.fn, 'jobwait') + + runner.BuiltInMainRunner.stop(running_app) + + assert.spy(fn_job_stop_spy).was_called_with(1) + assert.spy(fn_job_wait_spy).was_called_with({ 1 }, 1000) + end) + + it( + 'BuiltInMainRunner:select_from_avaible_apps when no running apps', + function() + local build_in_main_runner = runner.BuiltInMainRunner() + build_in_main_runner.running_apps = {} + + assert.error(function() + build_in_main_runner:select_app_with_ui() + end) + end + ) + + it( + 'BuildInRunner:select_from_running_apps when only one running app', + function() + local build_in_main_runner = runner.BuiltInMainRunner() + local running_app = runner.RunningApp({ projectName = 'projectName' }) + build_in_main_runner.running_apps = { running_app } + + local selected_app = build_in_main_runner:select_app_with_ui() + assert.equals(selected_app, running_app) + end + ) + + it( + 'BuildInRunner:select_from_running_apps when multiple running apps', + function() + local running_app1 = runner.RunningApp({ + projectName = 'projectName1', + mainClass = 'mainClass1', + }) + local running_app2 = runner.RunningApp({ + projectName = 'projectName2', + mainClass = 'mainClass2', + }) + + local build_in_main_runner = runner.BuiltInMainRunner() + build_in_main_runner.running_apps[running_app1.dap_config.mainClass] = + running_app1 + build_in_main_runner.running_apps[running_app2.dap_config.mainClass] = + running_app2 + + build_in_main_runner.change_current_app = function(_) end + + local spy_change_current_app = + spy.on(build_in_main_runner, 'change_current_app') + + ui.select_from_dap_configs = function(configs) + assert(#configs == 2) + return running_app2.dap_config + end + + local result = build_in_main_runner:select_app_with_ui() + assert.equals(result, running_app2) + + assert.spy(spy_change_current_app).was_called() + end + ) + + it('BuildInRunner:select_app_with_dap_config when no config', function() + local build_in_main_runner = runner.BuiltInMainRunner() + assert.error(function() + build_in_main_runner:select_app_with_dap_config() + end) + end) + + it( + 'BuildInRunner:select_app_with_dap_config when config is not found', + function() + local build_in_main_runner = runner.BuiltInMainRunner() + build_in_main_runner.running_apps = {} + + local config = { projectName = 'projectName', mainClass = 'mainClass' } + local selected_app = + build_in_main_runner:select_app_with_dap_config(config) + + assert.equals(selected_app.dap_config, config) + end + ) + + it('BuildInRunner:select_app_with_dap_config when config is found', function() + local build_in_main_runner = runner.BuiltInMainRunner() + build_in_main_runner.running_apps = {} + + local config1 = { projectName = 'projectName1', mainClass = 'mainClass1' } + local config2 = { projectName = 'projectName2', mainClass = 'mainClass2' } + + build_in_main_runner.running_apps[config1.mainClass] = + runner.RunningApp(config1) + build_in_main_runner.running_apps[config2.mainClass] = + runner.RunningApp(config2) + + local selected_app = + build_in_main_runner:select_app_with_dap_config(config2) + assert.equals(selected_app.dap_config, config2) + end) + + it('BuildInRunner:change_current_app', function() + local build_in_main_runner = runner.BuiltInMainRunner() + local running_app1 = runner.RunningApp({ projectName = 'projectName1' }) + local running_app2 = runner.RunningApp({ projectName = 'projectName2' }) + + runner.BuiltInMainRunner.hide_logs = function(selected_app) + assert.equals(selected_app, running_app2) + end + + local spy_hide_logs = spy.on(runner.BuiltInMainRunner, 'hide_logs') + + build_in_main_runner.current_app = running_app1 + + build_in_main_runner.hide_logs = function(selected_app) + assert.equals(selected_app, running_app1) + end + + assert.spy(spy_hide_logs).was_not_called() + build_in_main_runner.current_app = running_app2 + build_in_main_runner:change_current_app(running_app1) + end) + + it('BuildInRunner:change_current_app when dap config is equal', function() + local build_in_main_runner = runner.BuiltInMainRunner() + local running_app1 = runner.RunningApp({ projectName = 'projectName1' }) + + local spy_hide_logs = spy.on(runner.BuiltInMainRunner, 'hide_logs') + + build_in_main_runner.current_app = running_app1 + + build_in_main_runner.hide_logs = function(selected_app) + assert.equals(selected_app, running_app1) + end + + build_in_main_runner:change_current_app(running_app1) + + assert.spy(spy_hide_logs).was_not_called() + build_in_main_runner.current_app = running_app1 + end) +end) From 9e19b5ed056062d59fa18d1722c901c3dec44347 Mon Sep 17 00:00:00 2001 From: Srinesh Nisala Date: Wed, 5 Jun 2024 10:06:41 +0530 Subject: [PATCH 3/5] chore(doc): add no nvim-jdlts install warning (#202) --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index b6e04a8..c94b909 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,9 @@ Just install and start writing `public static void main(String[] args)`. +> [!WARNING] +> You cannot use `nvim-java` alongside `nvim-jdtls`. So remove `nvim-jdtls` before installing this + ## :loudspeaker: Demo https://github.com/nvim-java/nvim-java/assets/18459807/047c8c46-9a0a-4869-b342-d5c2e15647bc From fd5aad9663b3137f6c178dcd4f4fda43d83a33a0 Mon Sep 17 00:00:00 2001 From: Srinesh Nisala Date: Tue, 25 Jun 2024 23:20:10 +0530 Subject: [PATCH 4/5] chore: code clean up related to runner (#208) --- lua/java.lua | 2 - lua/java/api/runner.lua | 341 +--------------- lua/java/runner/run-logger.lua | 57 +++ lua/java/runner/run.lua | 88 ++++ lua/java/runner/runner.lua | 138 +++++++ tests/java/api/runner_spec.lua | 713 --------------------------------- tests/java/java_spec.lua | 18 - 7 files changed, 295 insertions(+), 1062 deletions(-) create mode 100644 lua/java/runner/run-logger.lua create mode 100644 lua/java/runner/run.lua create mode 100644 lua/java/runner/runner.lua delete mode 100644 tests/java/api/runner_spec.lua delete mode 100644 tests/java/java_spec.lua diff --git a/lua/java.lua b/lua/java.lua index 6925e81..e378f87 100644 --- a/lua/java.lua +++ b/lua/java.lua @@ -64,8 +64,6 @@ M.refactor.extract_variable = refactor.extract_variable -- Runner APIs -- ---------------------------------------------------------------------- M.runner = {} -M.runner.run_app = runner.run_app - M.runner.built_in = {} M.runner.built_in.run_app = runner.built_in.run_app M.runner.built_in.toggle_logs = runner.built_in.toggle_logs diff --git a/lua/java/api/runner.lua b/lua/java/api/runner.lua index 84a909e..b060062 100644 --- a/lua/java/api/runner.lua +++ b/lua/java/api/runner.lua @@ -1,362 +1,45 @@ -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 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') - -local group = vim.api.nvim_create_augroup('logger', { clear = true }) - ---- @class RunnerApi ---- @field client LspClient ---- @field private dap java.DapSetup -local RunnerApi = class() - -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() - return ui.select_from_dap_configs(configs) -end - ---- @param callback fun(cmd, config) ---- @param args string -function RunnerApi:run_app(callback, args) - local config = self:get_config() - if not config then - return - end - - config.request = 'launch' - local enrich_config = self.dap:enrich_config(config) - local class_paths = table.concat(enrich_config.classPaths, ':') - local main_class = enrich_config.mainClass - local java_exec = enrich_config.javaExec - - local active_profile = - profile_config.get_active_profile(enrich_config.mainClass) - - 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, - vm_args, - '-cp', - class_paths, - main_class, - prog_args, - } - log.debug('run app cmd: ', cmd) - callback(cmd, config) -end - ---- @class RunningApp ---- @field win number ---- @field bufnr number ---- @field job_id number ---- @field chan number ---- @field dap_config table ---- @field is_open boolean ---- @field running_status string -local RunningApp = class() - ---- @param dap_config table -function RunningApp:_init(dap_config) - self.is_open = false - self.dap_config = dap_config - self.bufnr = vim.api.nvim_create_buf(false, true) -end - ---- @class BuiltInMainRunner ---- @field running_apps table ---- @field current_app RunningApp -local BuiltInMainRunner = class() - -function BuiltInMainRunner:_init() - self.running_apps = {} - self.current_app = nil -end - ---- @param running_app RunningApp -function BuiltInMainRunner.set_up_buffer_autocmd(running_app) - vim.api.nvim_create_autocmd({ 'BufHidden' }, { - group = group, - buffer = running_app.bufnr, - callback = function(_) - running_app.is_open = false - end, - }) -end - ---- @param running_app RunningApp -function BuiltInMainRunner.stop(running_app) - if running_app.job_id ~= nil then - vim.fn.jobstop(running_app.job_id) - vim.fn.jobwait({ running_app.job_id }, 1000) - running_app.job_id = nil - end -end - ---- @param running_app RunningApp -function BuiltInMainRunner.set_up_buffer(running_app) - vim.cmd('sp | winc J | res 15 | buffer ' .. running_app.bufnr) - running_app.win = vim.api.nvim_get_current_win() - - vim.wo[running_app.win].number = false - vim.wo[running_app.win].relativenumber = false - vim.wo[running_app.win].signcolumn = 'no' - - BuiltInMainRunner.set_up_buffer_autocmd(running_app) - running_app.is_open = true -end - ---- @param exit_code number ---- @param running_app RunningApp -function BuiltInMainRunner.on_exit(exit_code, running_app) - local exit_message = 'Process finished with exit code ' .. exit_code - vim.fn.chansend(running_app.chan, '\n' .. exit_message .. '\n') - local current_buf = vim.api.nvim_get_current_buf() - if current_buf == running_app.bufnr then - vim.cmd('stopinsert') - end - vim.notify(running_app.dap_config.name .. ' ' .. exit_message) - running_app.running_status = exit_message -end - ---- @param running_app RunningApp -function BuiltInMainRunner.scroll_down(running_app) - local last_line = vim.api.nvim_buf_line_count(running_app.bufnr) - vim.api.nvim_win_set_cursor(running_app.win, { last_line, 0 }) -end - ---- @param running_app RunningApp -function BuiltInMainRunner.hide_logs(running_app) - if not running_app or not running_app.is_open then - return - end - if running_app.bufnr then - vim.api.nvim_buf_call(running_app.bufnr, function() - vim.cmd('hide') - end) - end -end - ---- @param running_app RunningApp -function BuiltInMainRunner.toggle_logs(running_app) - if running_app and not running_app.is_open then - vim.api.nvim_buf_call(running_app.bufnr, function() - BuiltInMainRunner.set_up_buffer(running_app) - BuiltInMainRunner.scroll_down(running_app) - end) - else - BuiltInMainRunner.hide_logs(running_app) - end -end - -function BuiltInMainRunner:toggle_current_app_logs() - local running_app = self.current_app - if not running_app then - return - end - BuiltInMainRunner.toggle_logs(running_app) -end - ---- @param data string[] ---- @param running_app RunningApp -function BuiltInMainRunner.on_stdout(data, running_app) - vim.fn.chansend(running_app.chan, data) - if not running_app.is_open then - return - end - vim.api.nvim_buf_call(running_app.bufnr, function() - local current_buf = vim.api.nvim_get_current_buf() - local mode = vim.api.nvim_get_mode().mode - if current_buf ~= running_app.bufnr or mode ~= 'i' then - BuiltInMainRunner.scroll_down(running_app) - end - end) -end - ---- @param cmd string[] ---- @param config table -function BuiltInMainRunner:run_app(cmd, config) - local selected_app = self:select_app_with_dap_config(config) - if self.current_app then - if self.current_app.job_id == selected_app.job_id then - BuiltInMainRunner.stop(selected_app) - end - end - self:change_current_app(selected_app) - if not selected_app.is_open or not selected_app.chan then - vim.api.nvim_buf_call(selected_app.bufnr, function() - BuiltInMainRunner.set_up_buffer(selected_app) - BuiltInMainRunner.scroll_down(selected_app) - end) - vim.api.nvim_buf_set_name(selected_app.bufnr, selected_app.dap_config.name) - end - - selected_app.chan = vim.api.nvim_open_term(selected_app.bufnr, { - on_input = function(_, _, _, data) - if selected_app.job_id then - vim.fn.chansend(selected_app.job_id, data) - end - end, - }) - - selected_app.running_status = '(running)' - local command = table.concat(cmd, ' ') - vim.fn.chansend(selected_app.chan, command) - selected_app.job_id = vim.fn.jobstart(command, { - pty = true, - on_stdout = function(_, data) - BuiltInMainRunner.on_stdout(data, selected_app) - end, - on_exit = function(_, exit_code) - BuiltInMainRunner.on_exit(exit_code, selected_app) - end, - }) -end - ---- @return RunningApp|nil -function BuiltInMainRunner:select_app_with_ui() - --- @type RunningApp - local app = nil - local count = 0 - for _ in pairs(self.running_apps) do - count = count + 1 - end - if count == 0 then - error('No running apps') - elseif count == 1 then - for _, _app in pairs(self.running_apps) do - app = _app - end - else - local configs = {} - for _, _app in pairs(self.running_apps) do - _app.dap_config.extra_args = _app.running_status - table.insert(configs, _app.dap_config) - end - - local selected = ui.select_from_dap_configs(configs) - if not selected then - return nil - end - app = self.running_apps[selected.mainClass] - end - self:change_current_app(app) - return app -end - ---- @param app RunningApp -function BuiltInMainRunner:change_current_app(app) - if - self.current_app - and self.current_app.dap_config.name ~= app.dap_config.name - then - BuiltInMainRunner.hide_logs(self.current_app) - end - self.current_app = app -end - ---- @param config table|nil ---- @return RunningApp -function BuiltInMainRunner:select_app_with_dap_config(config) - --- @type RunningApp - if not config then - error('No config') - end - - if self.running_apps and self.running_apps[config.mainClass] then - return self.running_apps[config.mainClass] - end - local running_app = RunningApp(config) - self.running_apps[running_app.dap_config.mainClass] = running_app - return running_app -end - -function BuiltInMainRunner:switch_app() - local selected_app = self:select_app_with_ui() - if not selected_app then - return - end - if not selected_app.is_open then - BuiltInMainRunner.toggle_logs(selected_app) - end -end - -function BuiltInMainRunner:stop_app() - local selected_app = self:select_app_with_ui() - if not selected_app then - return - end - BuiltInMainRunner.stop(selected_app) - BuiltInMainRunner.toggle_logs(selected_app) -end +local Runner = require('java.runner.runner') local M = { built_in = {}, - --- @type BuiltInMainRunner - runner = BuiltInMainRunner(), -} ---- @param callback fun(cmd, config) ---- @param args string -function M.run_app(callback, args) - return async(function() - return RunnerApi(jdtls()):run_app(callback, args) - end) - .catch(get_error_handler('failed to run app')) - .run() -end + ---@type java.Runner + runner = Runner(), +} --- @param opts {} function M.built_in.run_app(opts) async(function() - M.run_app(function(cmd, config) - M.runner:run_app(cmd, config) - end, opts.args) + M.runner:start_run(opts.args) end) - .catch(get_error_handler('failed to run app')) + .catch(get_error_handler('Failed to run app')) .run() end function M.built_in.toggle_logs() async(function() - M.runner:toggle_current_app_logs() + M.runner:toggle_open_log() end) - .catch(get_error_handler('failed to toggle logs')) + .catch(get_error_handler('Failed to run app')) .run() end function M.built_in.switch_app() async(function() - M.runner:switch_app() + M.runner:switch_log() end) - .catch(get_error_handler('failed to switch app')) + .catch(get_error_handler('Failed to switch run')) .run() end function M.built_in.stop_app() async(function() - M.runner:stop_app() + M.runner:stop_run() end) - .catch(get_error_handler('failed to stop app')) + .catch(get_error_handler('Failed to switch run')) .run() end -M.RunnerApi = RunnerApi -M.BuiltInMainRunner = BuiltInMainRunner -M.RunningApp = RunningApp - return M diff --git a/lua/java/runner/run-logger.lua b/lua/java/runner/run-logger.lua new file mode 100644 index 0000000..96ed4cc --- /dev/null +++ b/lua/java/runner/run-logger.lua @@ -0,0 +1,57 @@ +local class = require('java-core.utils.class') + +---@class java.RunLogger +---@field window number +local RunLogger = class() + +function RunLogger:_init() + self.window = -1 +end + +---Opens the log window with the given run buffer +---@param buffer number +function RunLogger:create(buffer) + vim.cmd('sp | winc J | res 15 | buffer ' .. buffer) + self.window = vim.api.nvim_get_current_win() + + vim.wo[self.window].number = false + vim.wo[self.window].relativenumber = false + vim.wo[self.window].signcolumn = 'no' + + self:scroll_to_bottom() +end + +function RunLogger:set_buffer(buffer) + if self:is_opened() then + vim.api.nvim_win_set_buf(self.window, buffer) + else + self:create(buffer) + end + + self:scroll_to_bottom() +end + +function RunLogger:scroll_to_bottom() + local buffer = vim.api.nvim_win_get_buf(self.window) + local line_count = vim.api.nvim_buf_line_count(buffer) + vim.api.nvim_win_set_cursor(self.window, { line_count, 0 }) +end + +---Returns true if the log window is opened +---@return boolean +function RunLogger:is_opened() + if not self.window then + return false + end + + return vim.api.nvim_win_is_valid(self.window) +end + +---Closes the log window if opened +function RunLogger:close() + if self.window and vim.api.nvim_win_is_valid(self.window) then + vim.api.nvim_win_hide(self.window) + end +end + +return RunLogger diff --git a/lua/java/runner/run.lua b/lua/java/runner/run.lua new file mode 100644 index 0000000..4e677f6 --- /dev/null +++ b/lua/java/runner/run.lua @@ -0,0 +1,88 @@ +local class = require('java-core.utils.class') +local notify = require('java-core.utils.notify') + +---@class java.Run +---@field name string +---@field main_class string +---@field buffer number +---@field private cmd string +---@field private term_chan_id number +---@field private job_chan_id number | nil +---@field private is_running boolean +---@field private is_failure boolean +local Run = class() + +---@param dap_config java-dap.DapLauncherConfig +---@param cmd string[] +function Run:_init(dap_config, cmd) + self.name = dap_config.name + self.main_class = dap_config.mainClass + self.cmd = table.concat(cmd, ' ') + self.buffer = vim.api.nvim_create_buf(false, true) + self.term_chan_id = vim.api.nvim_open_term(self.buffer, { + on_input = function(_, _, _, data) + self:send_job(data) + end, + }) +end + +function Run:start() + self.is_running = true + self:send_term(self.cmd) + + self.job_chan_id = vim.fn.jobstart(self.cmd, { + pty = true, + on_stdout = function(_, data) + self:send_term(data) + end, + on_exit = function(_, exit_code) + self:on_job_exit(exit_code) + end, + }) +end + +function Run:stop() + if not self.job_chan_id then + return + end + + vim.fn.jobstop(self.job_chan_id) + vim.fn.jobwait({ self.job_chan_id }, 1000) + self.job_chan_id = nil +end + +---Send data to execution job channel +---@private +---@param data string +function Run:send_job(data) + if self.job_chan_id then + vim.fn.chansend(self.job_chan_id, data) + end +end + +---Send message to terminal channel +---@private +---@param data string +function Run:send_term(data) + vim.fn.chansend(self.term_chan_id, data) +end + +---Runs when the current job exists +---@private +---@param exit_code number +function Run:on_job_exit(exit_code) + local message = + string.format('Process finished with exit code::%s', exit_code) + self:send_term(message) + + self.is_running = false + + if exit_code == 0 then + self.is_failure = false + else + self.is_failure = true + notify.error(string.format('%s %s', self.name, message)) + end +end + +return Run diff --git a/lua/java/runner/runner.lua b/lua/java/runner/runner.lua new file mode 100644 index 0000000..3f7c2f3 --- /dev/null +++ b/lua/java/runner/runner.lua @@ -0,0 +1,138 @@ +local ui = require('java.utils.ui') +local class = require('java-core.utils.class') +local jdtls = require('java.utils.jdtls2') +local profile_config = require('java.api.profile_config') +local Run = require('java.runner.run') +local RunLogger = require('java.runner.run-logger') +local DapSetup = require('java-dap.api.setup') + +---@class java.Runner +---@field runs table +---@field logger java.RunLogger +local Runner = class() + +function Runner:_init() + self.runs = {} + self.curr_run = nil + self.logger = RunLogger() +end + +---Starts a new run +---@param args string +function Runner:start_run(args) + local cmd, dap_config = Runner.select_dap_config(args) + + if not cmd or not dap_config then + return + end + + local run ---@as java.Run + + -- get the default run if exist or create new run + if self.runs[dap_config.mainClass] then + run = self.runs[dap_config.mainClass] + else + run = Run(dap_config, cmd) + self.runs[dap_config.mainClass] = run + end + + self.curr_run = run + self.logger:set_buffer(run.buffer) + + run:start() +end + +---Stops the user selected run +function Runner:stop_run() + local run = self:select_run() + + if not run then + return + end + + run:stop() +end + +function Runner:toggle_open_log() + if self.logger:is_opened() then + self.logger:close() + else + if self.curr_run then + self.logger:create(self.curr_run.buffer) + end + end +end + +---Switches the log to selected run +function Runner:switch_log() + local selected_run = self:select_run() + + if not selected_run then + return + end + + self.curr_run = selected_run + self.logger:set_buffer(selected_run.buffer) +end + +---Prompt the user to select an active run and returns the selected run +---@private +---@return java.Run | nil +function Runner:select_run() + local active_main_classes = {} ---@type string[] + + for _, run in pairs(self.runs) do + table.insert(active_main_classes, run.main_class) + end + + local selected_main = ui.select('Select main class', active_main_classes) + + if not selected_main then + return + end + + return self.runs[selected_main] +end + +---Returns the dap config for user selected main +---@param args string additional program arguments to pass +---@return string[] | nil +---@return java-dap.DapLauncherConfig | nil +function Runner.select_dap_config(args) + local dap = DapSetup(jdtls()) + local dap_config_list = dap:get_dap_config() + local selected_dap_config = ui.select_from_dap_configs(dap_config_list) + + if not selected_dap_config then + return nil, nil + end + + local enriched_config = dap:enrich_config(selected_dap_config) + + local class_paths = table.concat(enriched_config.classPaths, ':') + local main_class = enriched_config.mainClass + local java_exec = enriched_config.javaExec + + local active_profile = profile_config.get_active_profile(enriched_config.name) + + local vm_args = '' + local prog_args = 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, + vm_args, + '-cp', + class_paths, + main_class, + prog_args, + } + + return cmd, selected_dap_config +end + +return Runner diff --git a/tests/java/api/runner_spec.lua b/tests/java/api/runner_spec.lua deleted file mode 100644 index 3707e8f..0000000 --- a/tests/java/api/runner_spec.lua +++ /dev/null @@ -1,713 +0,0 @@ -local spy = require('luassert.spy') -local mock = require('luassert.mock') -local notify = require('java-core.utils.notify') -local DapSetup = require('java-dap.api.setup') -local mock_client = { jdtls_args = {} } -local runner = require('java.api.runner') -local async = require('java-core.utils.async').sync -local profile_config = require('java.api.profile_config') -local ui = require('java.utils.ui') - -local RunnerApi = runner.RunnerApi({ client = mock_client }) - -describe('java-core.api.runner', function() - before_each(function() - package.loaded['java.api.runner'] = nil - package.loaded['java.utils.ui'] = nil - end) - - it('RunnerApi()', function() - local mock_dap = DapSetup(mock_client) - assert.same(RunnerApi.client, mock_client) - assert.same(RunnerApi.dap, mock_dap) - end) - - it('RunnerApi:get_config when no config found', function() - local dap_mock = mock(DapSetup, true) - dap_mock.get_dap_config.returns({}) - - local notify_spy = spy.on(notify, 'warn') - local config = RunnerApi:get_config() - - assert.equals(config, nil) - assert.spy(notify_spy).was_called_with('Config not found') - mock.revert() - end) - - it('RunnerApi:get_config when only one config found', function() - local dap_mock = mock(DapSetup, true) - dap_mock.get_dap_config.returns({ - { name = 'config1', projectName = 'projectName' }, - }) - - local config = RunnerApi:get_config() - assert.same(config, { name = 'config1', projectName = 'projectName' }) - mock.revert() - end) - - it('RunnerApi:get_config when multiple config found', function() - RunnerApi.dap.get_dap_config = function() - return { - { name = 'config1' }, - { name = 'config2', projectName = 'project2' }, - { name = 'config3', projectName = 'project3' }, - } - end - - local mock_ui = mock(vim.ui, true) - mock_ui.select.returns() - - local select_spy = spy.on(vim.ui, 'select') - - async(function() - local config = RunnerApi:get_config() - assert.same({ name = 'config2', projectName = 'project2' }, config) - mock.revert(mock_ui) - end).run() - - assert.same(select_spy.calls[1].vals[1], { 'config2', 'config3' }) - - assert.same( - select_spy.calls[1].vals[2], - { prompt = 'Select the main class (modul -> mainClass)' } - ) - - mock.revert(mock_ui) - end) - - it('RunnerApi:run_app when no config found', function() - RunnerApi.get_config = function() - return nil - end - - local callback_mock = function(_) end - local callback_spy = spy.new(callback_mock) - - RunnerApi:run_app(callback_spy) - assert.spy(callback_spy).was_not_called() - end) - - it('RunnerApi:run_app without active profile', function() - RunnerApi.get_config = function() - return { name = 'config1' } - end - - RunnerApi.dap.enrich_config = function() - return { - classPaths = { 'path1', 'path2' }, - mainClass = 'mainClass', - javaExec = 'javaExec', - } - end - - RunnerApi.profile_config = profile_config - RunnerApi.profile_config.get_active_profile = function(main_class) - assert.equals(main_class, 'mainClass') - return nil - end - - local callback_mock = function(_, _) end - local callback_spy = spy.new(callback_mock) - - RunnerApi:run_app(callback_spy) - assert.spy(callback_spy).was_called_with({ - 'javaExec', - '', -- vm_args - '-cp', - 'path1:path2', - 'mainClass', - '', -- prog_args - }, { name = 'config1', request = 'launch' }) - end) - - it('RunnerApi:run_app with active profile', function() - RunnerApi.get_config = function() - return { name = 'config1' } - end - - RunnerApi.dap.enrich_config = function() - return { - classPaths = { 'path1', 'path2' }, - mainClass = 'mainClass', - javaExec = 'javaExec', - } - end - - RunnerApi.profile_config = profile_config - RunnerApi.profile_config.get_active_profile = function(main_class) - assert.equals(main_class, 'mainClass') - return { - prog_args = 'profile_prog_args', - vm_args = 'vm_args', - } - end - - local callback_mock = function(_, _) end - local callback_spy = spy.new(callback_mock) - - RunnerApi:run_app(callback_spy, 'input_prog_args') - assert.spy(callback_spy).was_called_with({ - 'javaExec', - 'vm_args', - '-cp', - 'path1:path2', - 'mainClass', - 'profile_prog_args input_prog_args', - }, { name = 'config1', request = 'launch' }) - end) - - it('RunningApp:new', function() - local api = mock(vim.api, true) - api.nvim_create_buf.returns(1) - local running_app = runner.RunningApp({ projectName = 'projectName' }) - assert.equals(running_app.win, nil) - assert.equals(running_app.bufnr, 1) - assert.equals(running_app.job_id, nil) - assert.equals(running_app.chan, nil) - assert.same(running_app.dap_config, { projectName = 'projectName' }) - assert.equals(running_app.is_open, false) - assert.equals(running_app.running_status, nil) - mock.revert(api) - end) - - it('BuildInRunner:new', function() - local built_in_main_runner = runner.BuiltInMainRunner() - assert.equals(built_in_main_runner.current_app, nil) - assert.same(built_in_main_runner.running_apps, {}) - end) - - it('BuildInRunner:_set_up_buffer', function() - local vim = mock(vim, true) - vim.wo = {} - vim.wo[1] = {} - local api = mock(vim.api, true) - api.nvim_get_current_win.returns(1) - api.nvim_create_buf.returns(2) - local spy_cmd = spy.on(vim, 'cmd') - - local running_app = runner.RunningApp({ projectName = 'projectName' }) - - spy.on(runner.BuiltInMainRunner, 'set_up_buffer_autocmd') - runner.BuiltInMainRunner.set_up_buffer(running_app) - - assert.equals(running_app.is_open, true) - assert.equals(running_app.win, 1) - assert.spy(spy_cmd).was_called_with('sp | winc J | res 15 | buffer 2') - assert.spy(runner.BuiltInMainRunner.set_up_buffer_autocmd).was_called() - - mock.revert(api) - mock.revert(vim) - end) - - it('BuildInRunner:_set_up_buffer_autocmd', function() - local api = mock(vim.api, true) - api.nvim_create_buf.returns(1) - - local running_app = runner.RunningApp({ projectName = 'projectName' }) - running_app.is_open = true - runner.BuiltInMainRunner.set_up_buffer_autocmd(running_app) - - local call_info = api.nvim_create_autocmd.calls[1] - assert.same(call_info.vals[1], { 'BufHidden' }) - assert.equals(call_info.vals[2].buffer, 1) - - call_info.vals[2].callback() - assert.is_false(running_app.is_open) - - mock.revert(api) - end) - - it('BuiltInMainRunner.on_stdout when is_open=true', function() - local api = mock(vim.api, true) - local spy_chensend = spy.on(vim.fn, 'chansend') - - local running_app = runner.RunningApp({ projectName = 'projectName' }) - running_app.chan = 2 - - spy.on(vim.api, 'nvim_buf_call') - runner.BuiltInMainRunner.on_stdout({ 'data1', 'data2' }, running_app) - assert.spy(spy_chensend).was_called_with(2, { 'data1', 'data2' }) - - assert.spy(api.nvim_buf_call).was_not_called() - - mock.revert(api) - end) - - it( - 'BuiltInMainRunner.on_stdout when bufnr is equal to current bufnr and mode is "i" (skip scroll)', - function() - local mock_current_bufnr = 1 - local vim = mock(vim, true) - local api = mock(vim.api, true) - local spy_chensend = spy.on(vim.fn, 'chansend') - - api.nvim_get_current_buf.returns(mock_current_bufnr) - api.nvim_create_buf.returns(mock_current_bufnr) - api.nvim_get_mode.returns({ mode = 'i' }) - - local running_app = runner.RunningApp({ projectName = 'projectName' }) - running_app.chan = 2 - running_app.is_open = true - -- running_app.bufnr = mock_current_bufnr - spy.on(runner.BuiltInMainRunner, 'scroll_down') - - runner.BuiltInMainRunner.on_stdout({ 'data1', 'data2' }, running_app) - - assert.spy(spy_chensend).was_called_with(2, { 'data1', 'data2' }) - -- -- call nvim_create_buf - local call_info = api.nvim_buf_call.calls[1] - call_info.vals[2]() - - assert.spy(runner.BuiltInMainRunner.scroll_down).was_not_called() - -- - mock.revert(vim) - mock.revert(api) - end - ) - - it( - 'BuiltInMainRunner:_on_stdout when bufnr is not equal to current bufnr and mode is "i" (scroll)', - function() - local vim = mock(vim, true) - local api = mock(vim.api, true) - local spy_chensend = spy.on(vim.fn, 'chansend') - - api.nvim_get_current_buf.returns(1) - api.nvim_create_buf.returns(3) - api.nvim_get_mode.returns({ mode = 'i' }) - - local running_app = runner.RunningApp({ projectName = 'projectName' }) - running_app.chan = 2 - running_app.is_open = true - -- running_app.bufnr = mock_current_bufnr - spy.on(runner.BuiltInMainRunner, 'scroll_down') - - runner.BuiltInMainRunner.on_stdout({ 'data1', 'data2' }, running_app) - - assert.spy(spy_chensend).was_called_with(2, { 'data1', 'data2' }) - -- -- call nvim_create_buf - local call_info = api.nvim_buf_call.calls[1] - call_info.vals[2]() - - assert - .spy(runner.BuiltInMainRunner.scroll_down) - .was_called_with(running_app) - -- - mock.revert(vim) - mock.revert(api) - end - ) - - it( - 'BuiltInMainRunner:_on_stdout when bufnr is equal to current bufnr and mode is not "i" (scroll)', - function() - local vim = mock(vim, true) - local api = mock(vim.api, true) - local spy_chensend = spy.on(vim.fn, 'chansend') - - api.nvim_get_current_buf.returns(1) - api.nvim_create_buf.returns(1) - api.nvim_get_mode.returns({ mode = 'n' }) - - local running_app = runner.RunningApp({ projectName = 'projectName' }) - running_app.chan = 2 - running_app.is_open = true - -- running_app.bufnr = mock_current_bufnr - spy.on(runner.BuiltInMainRunner, 'scroll_down') - - runner.BuiltInMainRunner.on_stdout({ 'data1', 'data2' }, running_app) - - assert.spy(spy_chensend).was_called_with(2, { 'data1', 'data2' }) - -- -- call nvim_create_buf - local call_info = api.nvim_buf_call.calls[1] - call_info.vals[2]() - - assert - .spy(runner.BuiltInMainRunner.scroll_down) - .was_called_with(running_app) - -- - mock.revert(vim) - mock.revert(api) - end - ) - - it( - 'BuiltInMainRunner:_on_exit when bufnr is equal to current bufnr (stopinsert)', - function() - local mock_current_bufnr = 1 - local api = mock(vim.api, true) - local spy_chensend = spy.on(vim.fn, 'chansend') - local spy_cmd = spy.on(vim, 'cmd') - - api.nvim_get_current_buf.returns(mock_current_bufnr) - api.nvim_create_buf.returns(mock_current_bufnr) - - local running_app = - runner.RunningApp({ projectName = 'projectName', name = 'config1' }) - running_app.chan = 2 - running_app.is_open = true - running_app.job_id = 1 - - runner.BuiltInMainRunner.on_exit(0, running_app) - assert - .spy(spy_chensend) - .was_called_with(2, '\nProcess finished with exit code 0\n') - assert.spy(spy_cmd).was_called_with('stopinsert') - assert.equals( - running_app.running_status, - 'Process finished with exit code 0' - ) - - mock.revert(api) - end - ) - - it( - 'BuiltInMainRunner:_on_exit when bufnr is not equal to current bufnr (skip stopinsert)', - function() - local api = mock(vim.api, true) - local spy_chensend = spy.on(vim.fn, 'chansend') - local spy_cmd = spy.on(vim, 'cmd') - - api.nvim_get_current_buf.returns(3) - api.nvim_create_buf.returns(4) - - local running_app = - runner.RunningApp({ projectName = 'projectName', name = 'config1' }) - running_app.chan = 2 - running_app.is_open = true - running_app.job_id = 1 - - runner.BuiltInMainRunner.on_exit(0, running_app) - assert - .spy(spy_chensend) - .was_called_with(2, '\nProcess finished with exit code 0\n') - assert.spy(spy_cmd).was_not_called() - assert.equals( - running_app.running_status, - 'Process finished with exit code 0' - ) - - mock.revert(api) - end - ) - - it('BuiltInMainRunner:run_app when there is no running job', function() - local fn = mock(vim.fn, true) - local spy_jobstart = spy.on(fn, 'jobstart') - local spy_chansend = spy.on(fn, 'chansend') - local api = mock(vim.api, true) - - api.nvim_create_buf.returns(1) - api.nvim_open_term.returns(2) - - local running_app = runner.RunningApp() - running_app.is_open = false - running_app.dap_config = { name = 'config1' } - - local built_in_main_runner = runner.BuiltInMainRunner() - - runner.BuiltInMainRunner.set_up_buffer = function(selected_app) - assert.equals(selected_app, running_app) - end - runner.BuiltInMainRunner.scroll_down = function(selected_app) - assert.equals(selected_app, running_app) - end - - local spy_stop = spy.on(runner.BuiltInMainRunner, 'stop') - - built_in_main_runner.select_app_with_dap_config = function() - return running_app - end - - built_in_main_runner:run_app( - { 'java', '-cp', 'path1:path2', 'mainClass' }, - { name = 'config1' } - ) - - assert.equals(running_app.chan, 2) - assert.equals(running_app.running_status, '(running)') - - assert - .spy(spy_chansend) - .was_called_with(2, 'java -cp path1:path2 mainClass') - assert.stub(api.nvim_buf_call).was_called() - assert.spy(spy_jobstart).was_called() - - local call_info = fn.jobstart.calls[1] - assert.equals(call_info.vals[1], 'java -cp path1:path2 mainClass') - assert.not_nil(call_info.vals[2].on_exit) - assert.not_nil(call_info.vals[2].on_stdout) - assert.spy(spy_stop).was_not_called() - assert.spy(api.nvim_buf_set_name).was_called_with(1, 'config1') - - mock.revert(api) - mock.revert(fn) - end) - - it('BuiltInMainRunner:run_app when there is a running job', function() - local fn = mock(vim.fn, true) - local spy_chensend = spy.on(fn, 'chansend') - local spy_jobstart = spy.on(fn, 'jobstart') - local spy_jobwait = spy.on(fn, 'jobwait') - local spy_stop = spy.on(fn, 'jobstop') - local api = mock(vim.api, true) - - api.nvim_create_buf.returns(1) - api.nvim_open_term.returns(2) - - local running_app = runner.RunningApp() - running_app.is_open = false - running_app.job_id = 1 - running_app.dap_config = { name = 'config1' } - - local built_in_main_runner = runner.BuiltInMainRunner() - built_in_main_runner.current_app = running_app - - runner.BuiltInMainRunner.set_up_buffer = function(selected_app) - assert.equals(selected_app, running_app) - end - runner.BuiltInMainRunner.scroll_down = function(selected_app) - assert.equals(selected_app, running_app) - end - runner.BuiltInMainRunner.change_current_app = function(app) - assert.equals(app.job_id, nil) -- check if job_id is nil - end - - built_in_main_runner.select_app_with_dap_config = function() - return running_app - end - - built_in_main_runner:run_app( - { 'java', '-cp', 'path1:path2', 'mainClass' }, - { name = 'config1' } - ) - - assert.equals(running_app.running_status, '(running)') - assert.is_nil(running_app.job_id) - assert - .spy(spy_chensend) - .was_called_with(2, 'java -cp path1:path2 mainClass') - assert.spy(spy_stop).was_called_with(1) - assert.spy(spy_jobstart).was_called() - assert.spy(spy_jobwait).was_called_with({ 1 }, 1000) - assert.spy(api.nvim_buf_set_name).was_called_with(1, 'config1') - - mock.revert(api) - mock.revert(fn) - end) - - it('BuiltInMainRunner:toggle_logs when is_open=true', function() - local api = mock(vim.api, true) - api.nvim_create_buf.returns(11) - - local running_app = runner.RunningApp() - running_app.is_open = true - - runner.BuiltInMainRunner.hide_logs = function(selected_app) - assert.equals(selected_app, running_app) - end - - local spy_set_up_buffer = spy.on(runner.BuiltInMainRunner, 'set_up_buffer') - local spy_hide_logs = spy.on(runner.BuiltInMainRunner, 'hide_logs') - - runner.BuiltInMainRunner.toggle_logs(running_app) - - assert.spy(spy_hide_logs).was_called() - assert.spy(spy_set_up_buffer).was_not_called() - - mock.revert(api) - end) - - it('BuiltInMainRunner:toggle_logs when is_open=false', function() - local api = mock(vim.api, true) - api.nvim_create_buf.returns(1) - - local running_app = runner.RunningApp() - running_app.is_open = false - - runner.BuiltInMainRunner.set_up_buffer = function(selected_app) - assert.equals(selected_app, running_app) - end - - runner.BuiltInMainRunner.scroll_down = function(selected_app) - assert.equals(selected_app, running_app) - end - - local spy_set_up_buffer = spy.on(runner.BuiltInMainRunner, 'set_up_buffer') - local spy_hide_logs = spy.on(runner.BuiltInMainRunner, 'hide_logs') - - runner.BuiltInMainRunner.toggle_logs(running_app) - - local call_info = api.nvim_buf_call.calls[1] - assert.equals(call_info.vals[1], 1) - call_info.vals[2]() - - assert.spy(spy_hide_logs).was_not_called() - assert.spy(spy_set_up_buffer).was_called() - - mock.revert(api) - end) - - it('BuiltInMainRunner:stop when job_id is nil', function() - local running_app = runner.RunningApp() - running_app.job_id = nil - - local fn_job_stop_spy = spy.on(vim.fn, 'jobstop') - local fn_job_wait_spy = spy.on(vim.fn, 'jobwait') - runner.BuiltInMainRunner.stop(running_app) - - assert.spy(fn_job_stop_spy).was_not_called() - assert.spy(fn_job_wait_spy).was_not_called() - end) - - it('BuiltInMainRunner:stop when job_id is not nil', function() - local running_app = runner.RunningApp() - running_app.job_id = 1 - - local fn_job_stop_spy = spy.on(vim.fn, 'jobstop') - local fn_job_wait_spy = spy.on(vim.fn, 'jobwait') - - runner.BuiltInMainRunner.stop(running_app) - - assert.spy(fn_job_stop_spy).was_called_with(1) - assert.spy(fn_job_wait_spy).was_called_with({ 1 }, 1000) - end) - - it( - 'BuiltInMainRunner:select_from_avaible_apps when no running apps', - function() - local build_in_main_runner = runner.BuiltInMainRunner() - build_in_main_runner.running_apps = {} - - assert.error(function() - build_in_main_runner:select_app_with_ui() - end) - end - ) - - it( - 'BuildInRunner:select_from_running_apps when only one running app', - function() - local build_in_main_runner = runner.BuiltInMainRunner() - local running_app = runner.RunningApp({ projectName = 'projectName' }) - build_in_main_runner.running_apps = { running_app } - - local selected_app = build_in_main_runner:select_app_with_ui() - assert.equals(selected_app, running_app) - end - ) - - it( - 'BuildInRunner:select_from_running_apps when multiple running apps', - function() - local running_app1 = runner.RunningApp({ - projectName = 'projectName1', - mainClass = 'mainClass1', - }) - local running_app2 = runner.RunningApp({ - projectName = 'projectName2', - mainClass = 'mainClass2', - }) - - local build_in_main_runner = runner.BuiltInMainRunner() - build_in_main_runner.running_apps[running_app1.dap_config.mainClass] = - running_app1 - build_in_main_runner.running_apps[running_app2.dap_config.mainClass] = - running_app2 - - build_in_main_runner.change_current_app = function(_) end - - local spy_change_current_app = - spy.on(build_in_main_runner, 'change_current_app') - - ui.select_from_dap_configs = function(configs) - assert(#configs == 2) - return running_app2.dap_config - end - - local result = build_in_main_runner:select_app_with_ui() - assert.equals(result, running_app2) - - assert.spy(spy_change_current_app).was_called() - end - ) - - it('BuildInRunner:select_app_with_dap_config when no config', function() - local build_in_main_runner = runner.BuiltInMainRunner() - assert.error(function() - build_in_main_runner:select_app_with_dap_config() - end) - end) - - it( - 'BuildInRunner:select_app_with_dap_config when config is not found', - function() - local build_in_main_runner = runner.BuiltInMainRunner() - build_in_main_runner.running_apps = {} - - local config = { projectName = 'projectName', mainClass = 'mainClass' } - local selected_app = - build_in_main_runner:select_app_with_dap_config(config) - - assert.equals(selected_app.dap_config, config) - end - ) - - it('BuildInRunner:select_app_with_dap_config when config is found', function() - local build_in_main_runner = runner.BuiltInMainRunner() - build_in_main_runner.running_apps = {} - - local config1 = { projectName = 'projectName1', mainClass = 'mainClass1' } - local config2 = { projectName = 'projectName2', mainClass = 'mainClass2' } - - build_in_main_runner.running_apps[config1.mainClass] = - runner.RunningApp(config1) - build_in_main_runner.running_apps[config2.mainClass] = - runner.RunningApp(config2) - - local selected_app = - build_in_main_runner:select_app_with_dap_config(config2) - assert.equals(selected_app.dap_config, config2) - end) - - it('BuildInRunner:change_current_app', function() - local build_in_main_runner = runner.BuiltInMainRunner() - local running_app1 = runner.RunningApp({ projectName = 'projectName1' }) - local running_app2 = runner.RunningApp({ projectName = 'projectName2' }) - - runner.BuiltInMainRunner.hide_logs = function(selected_app) - assert.equals(selected_app, running_app2) - end - - local spy_hide_logs = spy.on(runner.BuiltInMainRunner, 'hide_logs') - - build_in_main_runner.current_app = running_app1 - - build_in_main_runner.hide_logs = function(selected_app) - assert.equals(selected_app, running_app1) - end - - assert.spy(spy_hide_logs).was_not_called() - build_in_main_runner.current_app = running_app2 - build_in_main_runner:change_current_app(running_app1) - end) - - it('BuildInRunner:change_current_app when dap config is equal', function() - local build_in_main_runner = runner.BuiltInMainRunner() - local running_app1 = runner.RunningApp({ projectName = 'projectName1' }) - - local spy_hide_logs = spy.on(runner.BuiltInMainRunner, 'hide_logs') - - build_in_main_runner.current_app = running_app1 - - build_in_main_runner.hide_logs = function(selected_app) - assert.equals(selected_app, running_app1) - end - - build_in_main_runner:change_current_app(running_app1) - - assert.spy(spy_hide_logs).was_not_called() - build_in_main_runner.current_app = running_app1 - end) -end) diff --git a/tests/java/java_spec.lua b/tests/java/java_spec.lua deleted file mode 100644 index 61a939e..0000000 --- a/tests/java/java_spec.lua +++ /dev/null @@ -1,18 +0,0 @@ -local plugin = require('java') -local mock = require('luassert.mock') - -describe('setup', function() - it('setup function', function() - assert('setup function is available', plugin.setup) - end) - - describe('check runner function available:', function() - local mock_runner = mock(plugin.runner, true) - - it('run_app', function() - mock_runner.run_app.returns({}) - - assert.same(plugin.runner.run_app(), {}) - end) - end) -end) From 7b82808493ec1c1e4c2b291f344417bd828e5afc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 25 Jun 2024 23:22:52 +0530 Subject: [PATCH 5/5] chore(main): release 1.6.0 (#201) * chore(main): release 1.6.0 * Update CHANGELOG.md --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Srinesh Nisala --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fb7ad98..5d755cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [1.6.0](https://github.com/nvim-java/nvim-java/compare/v1.5.1...v1.6.0) (2024-06-25) + + +### Features + +* handle multiple running app ([#182](https://github.com/nvim-java/nvim-java/issues/182)) ([#191](https://github.com/nvim-java/nvim-java/issues/191)) ([ca5cfdb](https://github.com/nvim-java/nvim-java/commit/ca5cfdba0d0629a829d16fa838808be0d5db8baa)) + ## [1.5.1](https://github.com/nvim-java/nvim-java/compare/v1.5.0...v1.5.1) (2024-05-29)