From 77a60796dbb6431804215f42954fc4bed25c47ae Mon Sep 17 00:00:00 2001 From: s1n7ax Date: Wed, 24 Jul 2024 13:23:11 +0530 Subject: [PATCH 1/4] feat: move all client commands to java-refactor --- lua/java-refactor/action.lua | 273 +++++++++++++++++++ lua/java-refactor/api/code-action.lua | 38 +++ lua/java-refactor/code-action-handlers.lua | 190 +++++++++++++ lua/java-refactor/init.lua | 26 +- lua/java-refactor/lsp-refactor-commands.lua | 76 ------ lua/java-refactor/refactor-commands.lua | 7 + lua/java-refactor/utils/instance-factory.lua | 12 + 7 files changed, 545 insertions(+), 77 deletions(-) create mode 100644 lua/java-refactor/action.lua create mode 100644 lua/java-refactor/api/code-action.lua create mode 100644 lua/java-refactor/code-action-handlers.lua delete mode 100644 lua/java-refactor/lsp-refactor-commands.lua create mode 100644 lua/java-refactor/utils/instance-factory.lua diff --git a/lua/java-refactor/action.lua b/lua/java-refactor/action.lua new file mode 100644 index 0000000..667bd5b --- /dev/null +++ b/lua/java-refactor/action.lua @@ -0,0 +1,273 @@ +local ui = require('java.utils.ui') +local class = require('java-core.utils.class') +local JdtlsClient = require('java-core.ls.clients.jdtls-client') +local RefactorCommands = require('java-refactor.refactor-commands') +local notify = require('java-core.utils.notify') +local List = require('java-core.utils.list') + +---@class java-refactor.Action +---@field client vim.lsp.Client +---@field jdtls java-core.JdtlsClient +local Action = class() + +---@param client vim.lsp.Client +function Action:_init(client) + self.client = client + self.jdtls = JdtlsClient(client) + self.refactor = RefactorCommands(client) +end + +---@class java-refactor.RenameAction +---@field length number +---@field offset number +---@field uri string + +---@param params java-refactor.RenameAction[] +function Action:rename(params) + for _, rename in ipairs(params) do + local buffer = vim.uri_to_bufnr(rename.uri) + + local line + + vim.api.nvim_buf_call(buffer, function() + line = vim.fn.byte2line(rename.offset) + end) + + local start_char = rename.offset - vim.fn.line2byte(line) + 1 + + vim.api.nvim_win_set_cursor(0, { line, start_char }) + + vim.lsp.buf.rename(nil, { + name = 'jdtls', + bufnr = buffer, + }) + end +end + +---@param params nvim.CodeActionParamsResponse +function Action:generate_constructor(params) + local status = self.jdtls:java_check_constructors_status(params.params) + + if not status or not status.constructors then + return + end + + local selected_constructor = ui.select( + 'Select super class constructor(s).', + status.constructors, + function(constructor) + return string.format( + '%s %s', + constructor.name, + table.concat(constructor.parameters, ', ') + ) + end + ) + + if not selected_constructor then + return + end + + local selected_fields = ui.multi_select( + 'Select Fields:', + status.fields, + function(field) + return field.name + end + ) + + local edit = self.jdtls:java_generate_constructor({ + context = params.params, + constructors = { selected_constructor }, + fields = selected_fields or {}, + }) + + vim.lsp.util.apply_workspace_edit(edit, 'utf-8') +end + +---@param params nvim.CodeActionParamsResponse +function Action:generate_to_string(params) + local status = self.jdtls:java_check_to_string_status(params.params) + + if status.exists then + local prompt = string.format( + 'Method "toString()" already exists in the Class %s. Do you want to replace the implementation?', + status.type + ) + local choice = ui.select(prompt, { 'Replace', 'Cancel' }) + + if choice ~= 'Replace' then + return + end + end + + local fields = ui.multi_select( + 'Select the fields to include in the toString() method.', + status.fields, + function(field) + return field.name + end + ) + + if not fields then + return + end + + local edit = self.jdtls:java_generate_to_string({ + context = params.params, + fields = fields, + }) + + vim.lsp.util.apply_workspace_edit(edit, 'utf-8') +end + +---@param params nvim.CodeActionParamsResponse +function Action:generate_hash_code_and_equals(params) + local status = self.jdtls:java_check_hash_code_equals_status(params.params) + + if not status or not status.fields or #status.fields < 1 then + local message = string.format( + 'The operation is not applicable to the type %s.', + status.type + ) + notify.warn(message) + return + end + + local regenerate = false + + if status.existingMethods and #status.existingMethods > 0 then + local prompt = string.format( + 'Methods %s already exists in the Class %s. Do you want to regenerate the implementation?', + 'Regenerate', + 'Cancel' + ) + + local choice = ui.select(prompt, { 'Regenerate', 'Cancel' }) + + if choice == 'Regenerate' then + regenerate = true + end + end + + local fields = ui.multi_select( + 'Select the fields to include in the hashCode() and equals() methods.', + status.fields, + function(field) + return field.name + end + ) + + if not fields or #fields < 1 then + return + end + + local edit = self.jdtls:java_generate_hash_code_equals({ + context = params.params, + fields = fields, + regenerate = regenerate, + }) + + vim.lsp.util.apply_workspace_edit(edit, 'utf-8') +end + +---@param params nvim.CodeActionParamsResponse +function Action:generate_delegate_mothods_prompt(params) + local status = self.jdtls:java_check_delegate_methods_status(params.params) + + if not status or not status.delegateFields or #status.delegateFields < 1 then + notify.warn('All delegatable methods are already implemented.') + return + end + + local selected_delegate_field = ui.select( + 'Select target to generate delegates for.', + status.delegateFields, + function(field) + return field.field.name .. ': ' .. field.field.type + end + ) + + if not selected_delegate_field then + return + end + + if #selected_delegate_field.delegateMethods < 1 then + notify.warn('All delegatable methods are already implemented.') + return + end + + local selected_delegate_methods = ui.multi_select( + 'Select methods to generate delegates for.', + selected_delegate_field.delegateMethods, + function(method) + return string.format( + '%s.%s(%s)', + selected_delegate_field.field.name, + method.name, + table.concat(method.parameters, ', ') + ) + end + ) + + if not selected_delegate_methods or #selected_delegate_methods < 1 then + return + end + + local delegate_entries = List:new(selected_delegate_methods):map( + ---@param method jdtls.MethodBinding + function(method) + return { + field = selected_delegate_field.field, + delegateMethod = method, + } + end + ) + + local edit = self.jdtls:java_generate_delegate_methods({ + context = params.params, + delegateEntries = delegate_entries, + }) + + vim.lsp.util.apply_workspace_edit(edit, 'utf-8') +end + +---@param command lsp.Command +function Action:apply_refactoring_command(command) + local action_name = command.arguments[1] --[[@as jdtls.CodeActionCommand]] + local action_context = command.arguments[2] --[[@as lsp.CodeActionParams]] + local action_info = command.arguments[3] --[[@as lsp.LSPAny]] + + self.refactor:refactor(action_name, action_context, action_info) +end + +---comment +---@param is_full_compile boolean +---@return java-core.CompileWorkspaceStatus +function Action:build_workspace(is_full_compile) + return self.jdtls:java_build_workspace(is_full_compile, 0) +end + +function Action:clean_workspace() + local workpace_path = + vim.tbl_get(self.client, 'config', 'init_options', 'workspace') + + local prompt = string.format('Do you want to delete "%s"', workpace_path) + + local choice = ui.select(prompt, { 'Yes', 'No' }) + + if choice ~= 'Yes' then + return + end + + vim.fn.delete(workpace_path, 'rf') +end + +---@class java-refactor.ApplyRefactoringCommandParams +---@field bufnr number +---@field client_id number +---@field method string +---@field params lsp.CodeActionParams +---@field version number + +return Action diff --git a/lua/java-refactor/api/code-action.lua b/lua/java-refactor/api/code-action.lua new file mode 100644 index 0000000..646eadd --- /dev/null +++ b/lua/java-refactor/api/code-action.lua @@ -0,0 +1,38 @@ +local M = {} + +---@param action_type string +---@param filter? string +local function run_code_action(action_type, filter) + vim.lsp.buf.code_action({ + apply = true, + context = { + diagnostics = vim.lsp.diagnostic.get_line_diagnostics(0), + only = { action_type }, + }, + filter = filter and function(refactor) + return refactor.command.arguments[1] == filter + end or nil, + }) +end + +function M.extract_variable() + run_code_action('refactor.extract.variable', 'extractVariable') +end + +function M.extract_variable_all_occurrence() + run_code_action('refactor.extract.variable', 'extractVariableAllOccurrence') +end + +function M.extract_constant() + run_code_action('refactor.extract.constant') +end + +function M.extract_method() + run_code_action('refactor.extract.function') +end + +function M.extract_field() + run_code_action('refactor.extract.field') +end + +return M diff --git a/lua/java-refactor/code-action-handlers.lua b/lua/java-refactor/code-action-handlers.lua new file mode 100644 index 0000000..3cdcf93 --- /dev/null +++ b/lua/java-refactor/code-action-handlers.lua @@ -0,0 +1,190 @@ +local M = {} + +M.commands = { + ADD_TO_SOURCEPATH = 'java.project.addToSourcePath', + ADD_TO_SOURCEPATH_CMD = 'java.project.addToSourcePath.command', + APPLY_REFACTORING_COMMAND = 'java.action.applyRefactoringCommand', + APPLY_WORKSPACE_EDIT = 'java.apply.workspaceEdit', + BUILD_PROJECT = 'java.project.build', + CHANGE_BASE_TYPE = 'java.action.changeBaseType', + CHANGE_IMPORTED_PROJECTS = 'java.project.changeImportedProjects', + CHOOSE_IMPORTS = 'java.action.organizeImports.chooseImports', + CLEAN_SHARED_INDEXES = 'java.clean.sharedIndexes', + CLEAN_WORKSPACE = 'java.clean.workspace', + CLIPBOARD_ONPASTE = 'java.action.clipboardPasteAction', + COMPILE_WORKSPACE = 'java.workspace.compile', + CONFIGURATION_UPDATE = 'java.projectConfiguration.update', + CREATE_MODULE_INFO = 'java.project.createModuleInfo', + CREATE_MODULE_INFO_COMMAND = 'java.project.createModuleInfo.command', + EXECUTE_WORKSPACE_COMMAND = 'java.execute.workspaceCommand', + FILESEXPLORER_ONPASTE = 'java.action.filesExplorerPasteAction', + GENERATE_ACCESSORS_PROMPT = 'java.action.generateAccessorsPrompt', + GENERATE_CONSTRUCTORS_PROMPT = 'java.action.generateConstructorsPrompt', + GENERATE_DELEGATE_METHODS_PROMPT = 'java.action.generateDelegateMethodsPrompt', + GENERATE_TOSTRING_PROMPT = 'java.action.generateToStringPrompt', + GET_ALL_JAVA_PROJECTS = 'java.project.getAll', + GET_CLASSPATHS = 'java.project.getClasspaths', + GET_DECOMPILED_SOURCE = 'java.decompile', + GET_PROJECT_SETTINGS = 'java.project.getSettings', + GET_WORKSPACE_PATH = '_java.workspace.path', + GOTO_LOCATION = 'editor.action.goToLocations', + HANDLE_PASTE_EVENT = 'java.edit.handlePasteEvent', + HASHCODE_EQUALS_PROMPT = 'java.action.hashCodeEqualsPrompt', + IGNORE_INCOMPLETE_CLASSPATH = 'java.ignoreIncompleteClasspath', + IGNORE_INCOMPLETE_CLASSPATH_HELP = 'java.ignoreIncompleteClasspath.help', + IMPORT_PROJECTS = 'java.project.import', + IMPORT_PROJECTS_CMD = 'java.project.import.command', + IS_TEST_FILE = 'java.project.isTestFile', + LEARN_MORE_ABOUT_CLEAN_UPS = '_java.learnMoreAboutCleanUps', + LEARN_MORE_ABOUT_REFACTORING = '_java.learnMoreAboutRefactorings', + LIST_SOURCEPATHS = 'java.project.listSourcePaths', + LIST_SOURCEPATHS_CMD = 'java.project.listSourcePaths.command', + LOMBOK_CONFIGURE = 'java.lombokConfigure', + MANUAL_CLEANUP = 'java.action.doCleanup', + MARKDOWN_API_RENDER = 'markdown.api.render', + METADATA_FILES_GENERATION = '_java.metadataFilesGeneration', + NAVIGATE_TO_SUPER_IMPLEMENTATION_COMMAND = 'java.action.navigateToSuperImplementation', + NOT_COVERED_EXECUTION = '_java.notCoveredExecution', + NULL_ANALYSIS_SET_MODE = 'java.compile.nullAnalysis.setMode', + OPEN_BROWSER = 'vscode.open', + OPEN_CLIENT_LOG = 'java.open.clientLog', + OPEN_FILE = 'java.open.file', + OPEN_FORMATTER = 'java.open.formatter.settings', + OPEN_JSON_SETTINGS = 'workbench.action.openSettingsJson', + OPEN_LOGS = 'java.open.logs', + OPEN_OUTPUT = 'java.open.output', + OPEN_SERVER_LOG = 'java.open.serverLog', + OPEN_SERVER_STDERR_LOG = 'java.open.serverStderrLog', + OPEN_SERVER_STDOUT_LOG = 'java.open.serverStdoutLog', + OPEN_STATUS_SHORTCUT = '_java.openShortcuts', + OPEN_TYPE_HIERARCHY = 'java.navigate.openTypeHierarchy', + ORGANIZE_IMPORTS = 'java.action.organizeImports', + ORGANIZE_IMPORTS_SILENTLY = 'java.edit.organizeImports', + OVERRIDE_METHODS_PROMPT = 'java.action.overrideMethodsPrompt', + PROJECT_CONFIGURATION_STATUS = 'java.projectConfiguration.status', + REFRESH_BUNDLES = 'java.reloadBundles', + REFRESH_BUNDLES_COMMAND = '_java.reloadBundles.command', + RELOAD_WINDOW = 'workbench.action.reloadWindow', + REMOVE_FROM_SOURCEPATH = 'java.project.removeFromSourcePath', + REMOVE_FROM_SOURCEPATH_CMD = 'java.project.removeFromSourcePath.command', + RENAME_COMMAND = 'java.action.rename', + RESOLVE_PASTED_TEXT = 'java.project.resolveText', + RESOLVE_SOURCE_ATTACHMENT = 'java.project.resolveSourceAttachment', + RESOLVE_TYPE_HIERARCHY = 'java.navigate.resolveTypeHierarchy', + RESOLVE_WORKSPACE_SYMBOL = 'java.project.resolveWorkspaceSymbol', + RESTART_LANGUAGE_SERVER = 'java.server.restart', + RUNTIME_VALIDATION_OPEN = 'java.runtimeValidation.open', + SHOW_CLASS_HIERARCHY = 'java.action.showClassHierarchy', + SHOW_JAVA_IMPLEMENTATIONS = 'java.show.implementations', + SHOW_JAVA_REFERENCES = 'java.show.references', + SHOW_REFERENCES = 'editor.action.showReferences', + SHOW_SERVER_TASK_STATUS = 'java.show.server.task.status', + SHOW_SUBTYPE_HIERARCHY = 'java.action.showSubtypeHierarchy', + SHOW_SUPERTYPE_HIERARCHY = 'java.action.showSupertypeHierarchy', + SHOW_TYPE_HIERARCHY = 'java.action.showTypeHierarchy', + SMARTSEMICOLON_DETECTION = 'java.edit.smartSemicolonDetection', + SWITCH_SERVER_MODE = 'java.server.mode.switch', + TEMPLATE_VARIABLES = '_java.templateVariables', + UPDATE_SOURCE_ATTACHMENT = 'java.project.updateSourceAttachment', + UPDATE_SOURCE_ATTACHMENT_CMD = 'java.project.updateSourceAttachment.command', + UPGRADE_GRADLE_WRAPPER = 'java.project.upgradeGradle', + UPGRADE_GRADLE_WRAPPER_CMD = 'java.project.upgradeGradle.command', +} + +---@param message string +---@param func fun(action: java-refactor.Action) +local run = function(message, func) + local runner = require('async.runner') + local get_error_handler = require('java-refactor.utils.error_handler') + local instance = require('java-refactor.utils.instance-factory') + + runner(function() + func(instance.get_action()) + end) + .catch(get_error_handler(message)) + .run() +end + +M.handlers = { + ---@param params java-refactor.RenameAction[] + [M.commands.RENAME_COMMAND] = function(params) + run('Failed to rename the symbol', function(action) + action:rename(params) + end) + end, + + ---@param params nvim.CodeActionParamsResponse + [M.commands.GENERATE_CONSTRUCTORS_PROMPT] = function(_, params) + run('Failed to generate constructor', function(action) + action:generate_constructor(params) + end) + end, + + ---@param params nvim.CodeActionParamsResponse + [M.commands.GENERATE_TOSTRING_PROMPT] = function(_, params) + run('Failed to generate toString', function(action) + action:generate_to_string(params) + end) + end, + + ---@param params nvim.CodeActionParamsResponse + [M.commands.HASHCODE_EQUALS_PROMPT] = function(_, params) + run('Failed to generate hash code and equals', function(action) + action:generate_hash_code_and_equals(params) + end) + end, + + ---@param params nvim.CodeActionParamsResponse + [M.commands.GENERATE_DELEGATE_METHODS_PROMPT] = function(_, params) + run('Failed to generate delegate methods', function(action) + action:generate_delegate_mothods_prompt(params) + end) + end, + + ---@param command lsp.Command + [M.commands.APPLY_REFACTORING_COMMAND] = function(command) + run('Failed to apply refactoring command', function(action) + action:apply_refactoring_command(command) + end) + end, + + ---@param is_full_build boolean + [M.commands.COMPILE_WORKSPACE] = function(is_full_build) + run('Failed to build workspace', function(action) + action:build_workspace(is_full_build) + end) + end, + + [M.commands.CLEAN_WORKSPACE] = function() + run('Failed to clean workspace', function(action) + action:clean_workspace() + end) + end, +} + +local ignored_commands = { M.commands.REFRESH_BUNDLES_COMMAND } + +for _, command in pairs(M.commands) do + if + not M.handlers[command] and not vim.tbl_contains(ignored_commands, command) + then + local message = string.format( + '"%s" is not supported yet!' + .. '\nPlease request the feature using below link' + .. '\nhttps://github.com/nvim-java/nvim-java/issues/new?assignees=' + .. '&labels=enhancement&projects=&template=feature_request.yml&title=feature%%3A+', + command + ) + + M.handlers[command] = function() + require('java-core.utils.notify').warn(message) + + return vim.lsp.rpc_response_error( + vim.lsp.protocol.ErrorCodes.MethodNotFound, + 'Not implemented yes' + ) + end + end +end + +return M diff --git a/lua/java-refactor/init.lua b/lua/java-refactor/init.lua index 42d2acb..1d4863f 100644 --- a/lua/java-refactor/init.lua +++ b/lua/java-refactor/init.lua @@ -1 +1,25 @@ -require('java-refactor.lsp-refactor-commands') +local event = require('java-core.utils.event') + +local group = vim.api.nvim_create_augroup('java-refactor-command-register', {}) + +local setup = function() + -- setting all the vim.lsp.commands + local code_action_handler = require('java-refactor.code-action-handlers') + + for key, handler in pairs(code_action_handler.handlers) do + vim.lsp.commands[key] = handler + end + + -- setting all the user commands and APIs + local code_action_api = require('java-refactor.api.code-action') + + for api_name, api in pairs(code_action_api) do + require('java').register_api({ 'refactor', api_name }, api, { range = 2 }) + end +end + +event.on_jdtls_attach({ + group = group, + once = true, + callback = setup, +}) diff --git a/lua/java-refactor/lsp-refactor-commands.lua b/lua/java-refactor/lsp-refactor-commands.lua deleted file mode 100644 index 65ccbd1..0000000 --- a/lua/java-refactor/lsp-refactor-commands.lua +++ /dev/null @@ -1,76 +0,0 @@ -local runner = require('async.runner') -local get_error_handler = require('java-refactor.utils.error_handler') -local RefactorCommands = require('java-refactor.refactor-commands') - -local M = { - commands = { - ---@class java-refactor.RenameAction - ---@field length number - ---@field offset number - ---@field uri string - - ---Rename a given item - ---@param arguments java-refactor.RenameAction[] - ['java.action.rename'] = function(arguments) - for _, rename in ipairs(arguments) do - local buffer = vim.uri_to_bufnr(rename.uri) - - local line - - vim.api.nvim_buf_call(buffer, function() - line = vim.fn.byte2line(rename.offset) - end) - - local start_char = rename.offset - vim.fn.line2byte(line) + 1 - - vim.api.nvim_win_set_cursor(0, { line, start_char }) - - vim.lsp.buf.rename(nil, { - name = 'jdtls', - bufnr = buffer, - }) - end - end, - - ---comment - ---@param command lsp.Command - ---@param params java-refactor.ApplyRefactoringCommandParams - ['java.action.applyRefactoringCommand'] = function(command, params) - runner(function() - local action_name = command.arguments[1] --[[@as jdtls.CodeActionCommand]] - local action_context = command.arguments[2] --[[@as lsp.CodeActionParams]] - local action_info = command.arguments[3] --[[@as lsp.LSPAny]] - - local client = vim.lsp.get_client_by_id(params.client_id) - - ---@type java-refactor.RefactorCommands - local refactor_commands = RefactorCommands(client) - refactor_commands:refactor(action_name, action_context, action_info) - end) - .catch(get_error_handler('Failed to run refactoring command')) - .run() - end, - }, -} - -local id - -id = vim.api.nvim_create_autocmd('LspAttach', { - callback = function(args) - local client = vim.lsp.get_client_by_id(args.data.client_id) - if client and client.name == 'jdtls' then - for name, command in pairs(M.commands) do - vim.lsp.commands[name] = command - end - - vim.api.nvim_del_autocmd(id) - end - end, -}) - ----@class java-refactor.ApplyRefactoringCommandParams ----@field bufnr number ----@field client_id number ----@field method string ----@field params lsp.CodeActionParams ----@field version number diff --git a/lua/java-refactor/refactor-commands.lua b/lua/java-refactor/refactor-commands.lua index 81b0556..bcc651e 100644 --- a/lua/java-refactor/refactor-commands.lua +++ b/lua/java-refactor/refactor-commands.lua @@ -85,6 +85,7 @@ function RefactorCommands:refactor(action_name, action_context, action_info) end end +---@private ---@param action_info jdtls.CodeActionMoveTypeCommandInfo function RefactorCommands:move_file(action_info) if not action_info or not action_info.uri then @@ -135,6 +136,7 @@ function RefactorCommands:move_file(action_info) RefactorCommands.perform_refactor_edit(changes) end +---@private ---@param action_context lsp.CodeActionParams ---@param action_info jdtls.CodeActionMoveTypeCommandInfo function RefactorCommands:move_instance_method(action_context, action_info) @@ -184,6 +186,7 @@ function RefactorCommands:move_instance_method(action_context, action_info) self:perform_move('moveInstanceMethod', action_context, selected_destination) end +---@private ---@param action_context lsp.CodeActionParams ---@param action_info jdtls.CodeActionMoveTypeCommandInfo function RefactorCommands:move_static_member(action_context, action_info) @@ -221,6 +224,7 @@ function RefactorCommands:move_static_member(action_context, action_info) self:perform_move('moveStaticMember', action_context, selected_class) end +---@private ---@param action_context lsp.CodeActionParams ---@param action_info jdtls.CodeActionMoveTypeCommandInfo function RefactorCommands:move_type(action_context, action_info) @@ -279,6 +283,7 @@ function RefactorCommands:move_type(action_context, action_info) end end +---@private ---@param move_kind string ---@param action_context lsp.CodeActionParams ---@param destination? jdtls.InstanceMethodMoveDestination | jdtls.ResourceMoveDestination | lsp.SymbolInformation @@ -293,6 +298,7 @@ function RefactorCommands:perform_move(move_kind, action_context, destination) RefactorCommands.perform_refactor_edit(changes) end +---@private ---@param changes jdtls.RefactorWorkspaceEdit function RefactorCommands.perform_refactor_edit(changes) if not changes then @@ -314,6 +320,7 @@ function RefactorCommands.perform_refactor_edit(changes) end end +---@private ---@param prompt string ---@param project_name string ---@param exclude string[] diff --git a/lua/java-refactor/utils/instance-factory.lua b/lua/java-refactor/utils/instance-factory.lua new file mode 100644 index 0000000..0b2d6ad --- /dev/null +++ b/lua/java-refactor/utils/instance-factory.lua @@ -0,0 +1,12 @@ +local M = {} + +---@return java-refactor.Action +function M.get_action() + local InstanceFactory = require('java-core.utils.instance-factory') + local Action = require('java-refactor.action') + local client = InstanceFactory.get_client() + + return Action(client) +end + +return M From 98db44a21726c46a6f9dd52ee4a05f4f1e6d5e89 Mon Sep 17 00:00:00 2001 From: s1n7ax Date: Wed, 24 Jul 2024 19:08:44 +0530 Subject: [PATCH 2/4] chore: code rename --- lua/java-refactor/action.lua | 2 +- .../{refactor-commands.lua => refactor.lua} | 40 +++++++++---------- 2 files changed, 21 insertions(+), 21 deletions(-) rename lua/java-refactor/{refactor-commands.lua => refactor.lua} (89%) diff --git a/lua/java-refactor/action.lua b/lua/java-refactor/action.lua index 667bd5b..0572bee 100644 --- a/lua/java-refactor/action.lua +++ b/lua/java-refactor/action.lua @@ -1,7 +1,7 @@ local ui = require('java.utils.ui') local class = require('java-core.utils.class') local JdtlsClient = require('java-core.ls.clients.jdtls-client') -local RefactorCommands = require('java-refactor.refactor-commands') +local RefactorCommands = require('java-refactor.refactor') local notify = require('java-core.utils.notify') local List = require('java-core.utils.list') diff --git a/lua/java-refactor/refactor-commands.lua b/lua/java-refactor/refactor.lua similarity index 89% rename from lua/java-refactor/refactor-commands.lua rename to lua/java-refactor/refactor.lua index bcc651e..d2b3e21 100644 --- a/lua/java-refactor/refactor-commands.lua +++ b/lua/java-refactor/refactor.lua @@ -27,12 +27,12 @@ local available_actions = List:new({ -- 'extractInterface', }):concat(refactor_edit_request_needed_actions) ----@class java-refactor.RefactorCommands +---@class java-refactor.Refactor ---@field jdtls_client java-core.JdtlsClient -local RefactorCommands = class() +local Refactor = class() ---@param client vim.lsp.Client -function RefactorCommands:_init(client) +function Refactor:_init(client) self.jdtls_client = JdtlsClient(client) end @@ -40,7 +40,7 @@ end ---@param action_name jdtls.CodeActionCommand ---@param action_context lsp.CodeActionParams ---@param action_info lsp.LSPAny -function RefactorCommands:refactor(action_name, action_context, action_info) +function Refactor:refactor(action_name, action_context, action_info) if not vim.tbl_contains(available_actions, action_name) then notify.error( string.format('Refactoring command "%s" is not supported', action_name) @@ -49,7 +49,7 @@ function RefactorCommands:refactor(action_name, action_context, action_info) end if vim.tbl_contains(refactor_edit_request_needed_actions, action_name) then - local formatting_options = RefactorCommands.make_formatting_options() + local formatting_options = Refactor.make_formatting_options() local selections if vim.tbl_contains(refactor_edit_request_needed_actions, action_name) then @@ -64,7 +64,7 @@ function RefactorCommands:refactor(action_name, action_context, action_info) vim.api.nvim_get_current_buf() ) - RefactorCommands.perform_refactor_edit(changes) + Refactor.perform_refactor_edit(changes) elseif action_name == 'moveFile' then self:move_file(action_info --[[@as jdtls.CodeActionMoveTypeCommandInfo]]) elseif action_name == 'moveType' then @@ -87,7 +87,7 @@ end ---@private ---@param action_info jdtls.CodeActionMoveTypeCommandInfo -function RefactorCommands:move_file(action_info) +function Refactor:move_file(action_info) if not action_info or not action_info.uri then return end @@ -133,13 +133,13 @@ function RefactorCommands:move_file(action_info) destination = selected_destination, }) - RefactorCommands.perform_refactor_edit(changes) + Refactor.perform_refactor_edit(changes) end ---@private ---@param action_context lsp.CodeActionParams ---@param action_info jdtls.CodeActionMoveTypeCommandInfo -function RefactorCommands:move_instance_method(action_context, action_info) +function Refactor:move_instance_method(action_context, action_info) local move_des = self.jdtls_client:get_move_destination({ moveKind = 'moveInstanceMethod', sourceUris = { action_context.textDocument.uri }, @@ -189,7 +189,7 @@ end ---@private ---@param action_context lsp.CodeActionParams ---@param action_info jdtls.CodeActionMoveTypeCommandInfo -function RefactorCommands:move_static_member(action_context, action_info) +function Refactor:move_static_member(action_context, action_info) local exclude = List:new() if action_info.enclosingTypeName then @@ -227,7 +227,7 @@ end ---@private ---@param action_context lsp.CodeActionParams ---@param action_info jdtls.CodeActionMoveTypeCommandInfo -function RefactorCommands:move_type(action_context, action_info) +function Refactor:move_type(action_context, action_info) if not action_info or not action_info.supportedDestinationKinds then return end @@ -287,7 +287,7 @@ end ---@param move_kind string ---@param action_context lsp.CodeActionParams ---@param destination? jdtls.InstanceMethodMoveDestination | jdtls.ResourceMoveDestination | lsp.SymbolInformation -function RefactorCommands:perform_move(move_kind, action_context, destination) +function Refactor:perform_move(move_kind, action_context, destination) local changes = self.jdtls_client:java_move({ moveKind = move_kind, sourceUris = { action_context.textDocument.uri }, @@ -295,12 +295,12 @@ function RefactorCommands:perform_move(move_kind, action_context, destination) destination = destination, }) - RefactorCommands.perform_refactor_edit(changes) + Refactor.perform_refactor_edit(changes) end ---@private ---@param changes jdtls.RefactorWorkspaceEdit -function RefactorCommands.perform_refactor_edit(changes) +function Refactor.perform_refactor_edit(changes) if not changes then notify.warn('No edits suggested for the code action') return @@ -313,7 +313,7 @@ function RefactorCommands.perform_refactor_edit(changes) vim.lsp.util.apply_workspace_edit(changes.edit, 'utf-8') if changes.command then - RefactorCommands.run_lsp_client_command( + Refactor.run_lsp_client_command( changes.command.command, changes.command.arguments ) @@ -324,7 +324,7 @@ end ---@param prompt string ---@param project_name string ---@param exclude string[] -function RefactorCommands:select_target_class(prompt, project_name, exclude) +function Refactor:select_target_class(prompt, project_name, exclude) local classes = self.jdtls_client:java_search_symbols({ query = '*', projectName = project_name, @@ -347,7 +347,7 @@ end ---@private ---@param command_name string ---@param arguments any -function RefactorCommands.run_lsp_client_command(command_name, arguments) +function Refactor.run_lsp_client_command(command_name, arguments) local command = vim.lsp.commands[command_name] if not command then @@ -360,7 +360,7 @@ end ---@private ---@return lsp.FormattingOptions -function RefactorCommands.make_formatting_options() +function Refactor.make_formatting_options() return { tabSize = vim.bo.tabstop, insertSpaces = vim.bo.expandtab, @@ -371,7 +371,7 @@ end ---@param refactor_type jdtls.CodeActionCommand ---@param params lsp.CodeActionParams ---@return jdtls.SelectionInfo[] -function RefactorCommands:get_selections(refactor_type, params) +function Refactor:get_selections(refactor_type, params) local selections = List:new() local buffer = vim.api.nvim_get_current_buf() @@ -413,4 +413,4 @@ end ---@field supportedDestinationKinds string[] ---@field uri? string -return RefactorCommands +return Refactor From c6189efa2f0b02030f611c8cf8bd8e4387568844 Mon Sep 17 00:00:00 2001 From: s1n7ax Date: Wed, 24 Jul 2024 22:36:39 +0530 Subject: [PATCH 3/4] organize code --- lua/java-refactor/api/build.lua | 19 ++++ lua/java-refactor/api/code-action.lua | 38 ------- lua/java-refactor/api/refactor.lua | 38 +++++++ lua/java-refactor/client-command-handlers.lua | 102 ++++++++++++++++++ ...action-handlers.lua => client-command.lua} | 101 +---------------- lua/java-refactor/init.lua | 36 +++++-- 6 files changed, 186 insertions(+), 148 deletions(-) create mode 100644 lua/java-refactor/api/build.lua delete mode 100644 lua/java-refactor/api/code-action.lua create mode 100644 lua/java-refactor/api/refactor.lua create mode 100644 lua/java-refactor/client-command-handlers.lua rename lua/java-refactor/{code-action-handlers.lua => client-command.lua} (63%) diff --git a/lua/java-refactor/api/build.lua b/lua/java-refactor/api/build.lua new file mode 100644 index 0000000..60e8fcb --- /dev/null +++ b/lua/java-refactor/api/build.lua @@ -0,0 +1,19 @@ +---@param client_command jdtls.ClientCommand +local function run_client_command(client_command, ...) + local handlers = require('java-refactor.client-command-handlers') + handlers[client_command](...) +end + +local M = { + build_workspace = function() + local ClientCommand = require('java-refactor.client-command') + run_client_command(ClientCommand.COMPILE_WORKSPACE, true) + end, + + clean_workspace = function() + local ClientCommand = require('java-refactor.client-command') + run_client_command(ClientCommand.CLEAN_WORKSPACE) + end, +} + +return M diff --git a/lua/java-refactor/api/code-action.lua b/lua/java-refactor/api/code-action.lua deleted file mode 100644 index 646eadd..0000000 --- a/lua/java-refactor/api/code-action.lua +++ /dev/null @@ -1,38 +0,0 @@ -local M = {} - ----@param action_type string ----@param filter? string -local function run_code_action(action_type, filter) - vim.lsp.buf.code_action({ - apply = true, - context = { - diagnostics = vim.lsp.diagnostic.get_line_diagnostics(0), - only = { action_type }, - }, - filter = filter and function(refactor) - return refactor.command.arguments[1] == filter - end or nil, - }) -end - -function M.extract_variable() - run_code_action('refactor.extract.variable', 'extractVariable') -end - -function M.extract_variable_all_occurrence() - run_code_action('refactor.extract.variable', 'extractVariableAllOccurrence') -end - -function M.extract_constant() - run_code_action('refactor.extract.constant') -end - -function M.extract_method() - run_code_action('refactor.extract.function') -end - -function M.extract_field() - run_code_action('refactor.extract.field') -end - -return M diff --git a/lua/java-refactor/api/refactor.lua b/lua/java-refactor/api/refactor.lua new file mode 100644 index 0000000..2616243 --- /dev/null +++ b/lua/java-refactor/api/refactor.lua @@ -0,0 +1,38 @@ +---@param action_type string +---@param filter? string +local function run_code_action(action_type, filter) + vim.lsp.buf.code_action({ + apply = true, + context = { + diagnostics = vim.lsp.diagnostic.get_line_diagnostics(0), + only = { action_type }, + }, + filter = filter and function(refactor) + return refactor.command.arguments[1] == filter + end or nil, + }) +end + +local M = { + extract_variable = function() + run_code_action('refactor.extract.variable', 'extractVariable') + end, + + extract_variable_all_occurrence = function() + run_code_action('refactor.extract.variable', 'extractVariableAllOccurrence') + end, + + extract_constant = function() + run_code_action('refactor.extract.constant') + end, + + extract_method = function() + run_code_action('refactor.extract.function') + end, + + extract_field = function() + run_code_action('refactor.extract.field') + end, +} + +return M diff --git a/lua/java-refactor/client-command-handlers.lua b/lua/java-refactor/client-command-handlers.lua new file mode 100644 index 0000000..23d4d4c --- /dev/null +++ b/lua/java-refactor/client-command-handlers.lua @@ -0,0 +1,102 @@ +local ClientCommand = require('java-refactor.client-command') + +---@param message string +---@param func fun(action: java-refactor.Action) +local run = function(message, func) + local runner = require('async.runner') + local get_error_handler = require('java-refactor.utils.error_handler') + local instance = require('java-refactor.utils.instance-factory') + + runner(function() + func(instance.get_action()) + end) + .catch(get_error_handler(message)) + .run() +end + +local M = { + ---@param params java-refactor.RenameAction[] + [ClientCommand.RENAME_COMMAND] = function(params) + run('Failed to rename the symbol', function(action) + action:rename(params) + end) + end, + + ---@param params nvim.CodeActionParamsResponse + [ClientCommand.GENERATE_CONSTRUCTORS_PROMPT] = function(_, params) + run('Failed to generate constructor', function(action) + action:generate_constructor(params) + end) + end, + + ---@param params nvim.CodeActionParamsResponse + [ClientCommand.GENERATE_TOSTRING_PROMPT] = function(_, params) + run('Failed to generate toString', function(action) + action:generate_to_string(params) + end) + end, + + ---@param params nvim.CodeActionParamsResponse + [ClientCommand.HASHCODE_EQUALS_PROMPT] = function(_, params) + run('Failed to generate hash code and equals', function(action) + action:generate_hash_code_and_equals(params) + end) + end, + + ---@param params nvim.CodeActionParamsResponse + [ClientCommand.GENERATE_DELEGATE_METHODS_PROMPT] = function(_, params) + run('Failed to generate delegate methods', function(action) + action:generate_delegate_mothods_prompt(params) + end) + end, + + ---@param command lsp.Command + [ClientCommand.APPLY_REFACTORING_COMMAND] = function(command) + run('Failed to apply refactoring command', function(action) + action:apply_refactoring_command(command) + end) + end, + + ---@param is_full_build boolean + [ClientCommand.COMPILE_WORKSPACE] = function(is_full_build) + run('Failed to build workspace', function(action) + action:build_workspace(is_full_build) + require('java-core.utils.notify').info('Successfully built the workspace') + end) + end, + + [ClientCommand.CLEAN_WORKSPACE] = function() + run('Failed to clean workspace', function(action) + action:clean_workspace() + require('java-core.utils.notify').info( + 'Successfully cleared the workspace cache' + .. '\nPlease close and reopen neovim to restart JDTLS' + ) + end) + end, +} + +local ignored_commands = { ClientCommand.REFRESH_BUNDLES_COMMAND } + +for _, command in pairs(ClientCommand) do + if not M[command] and not vim.tbl_contains(ignored_commands, command) then + local message = string.format( + '"%s" is not supported yet!' + .. '\nPlease request the feature using below link' + .. '\nhttps://github.com/nvim-java/nvim-java/issues/new?assignees=' + .. '&labels=enhancement&projects=&template=feature_request.yml&title=feature%%3A+', + command + ) + + M[command] = function() + require('java-core.utils.notify').warn(message) + + return vim.lsp.rpc_response_error( + vim.lsp.protocol.ErrorCodes.MethodNotFound, + 'Not implemented yes' + ) + end + end +end + +return M diff --git a/lua/java-refactor/code-action-handlers.lua b/lua/java-refactor/client-command.lua similarity index 63% rename from lua/java-refactor/code-action-handlers.lua rename to lua/java-refactor/client-command.lua index 3cdcf93..aadd352 100644 --- a/lua/java-refactor/code-action-handlers.lua +++ b/lua/java-refactor/client-command.lua @@ -1,6 +1,5 @@ -local M = {} - -M.commands = { +---@enum jdtls.ClientCommand +local M = { ADD_TO_SOURCEPATH = 'java.project.addToSourcePath', ADD_TO_SOURCEPATH_CMD = 'java.project.addToSourcePath.command', APPLY_REFACTORING_COMMAND = 'java.action.applyRefactoringCommand', @@ -91,100 +90,4 @@ M.commands = { UPGRADE_GRADLE_WRAPPER_CMD = 'java.project.upgradeGradle.command', } ----@param message string ----@param func fun(action: java-refactor.Action) -local run = function(message, func) - local runner = require('async.runner') - local get_error_handler = require('java-refactor.utils.error_handler') - local instance = require('java-refactor.utils.instance-factory') - - runner(function() - func(instance.get_action()) - end) - .catch(get_error_handler(message)) - .run() -end - -M.handlers = { - ---@param params java-refactor.RenameAction[] - [M.commands.RENAME_COMMAND] = function(params) - run('Failed to rename the symbol', function(action) - action:rename(params) - end) - end, - - ---@param params nvim.CodeActionParamsResponse - [M.commands.GENERATE_CONSTRUCTORS_PROMPT] = function(_, params) - run('Failed to generate constructor', function(action) - action:generate_constructor(params) - end) - end, - - ---@param params nvim.CodeActionParamsResponse - [M.commands.GENERATE_TOSTRING_PROMPT] = function(_, params) - run('Failed to generate toString', function(action) - action:generate_to_string(params) - end) - end, - - ---@param params nvim.CodeActionParamsResponse - [M.commands.HASHCODE_EQUALS_PROMPT] = function(_, params) - run('Failed to generate hash code and equals', function(action) - action:generate_hash_code_and_equals(params) - end) - end, - - ---@param params nvim.CodeActionParamsResponse - [M.commands.GENERATE_DELEGATE_METHODS_PROMPT] = function(_, params) - run('Failed to generate delegate methods', function(action) - action:generate_delegate_mothods_prompt(params) - end) - end, - - ---@param command lsp.Command - [M.commands.APPLY_REFACTORING_COMMAND] = function(command) - run('Failed to apply refactoring command', function(action) - action:apply_refactoring_command(command) - end) - end, - - ---@param is_full_build boolean - [M.commands.COMPILE_WORKSPACE] = function(is_full_build) - run('Failed to build workspace', function(action) - action:build_workspace(is_full_build) - end) - end, - - [M.commands.CLEAN_WORKSPACE] = function() - run('Failed to clean workspace', function(action) - action:clean_workspace() - end) - end, -} - -local ignored_commands = { M.commands.REFRESH_BUNDLES_COMMAND } - -for _, command in pairs(M.commands) do - if - not M.handlers[command] and not vim.tbl_contains(ignored_commands, command) - then - local message = string.format( - '"%s" is not supported yet!' - .. '\nPlease request the feature using below link' - .. '\nhttps://github.com/nvim-java/nvim-java/issues/new?assignees=' - .. '&labels=enhancement&projects=&template=feature_request.yml&title=feature%%3A+', - command - ) - - M.handlers[command] = function() - require('java-core.utils.notify').warn(message) - - return vim.lsp.rpc_response_error( - vim.lsp.protocol.ErrorCodes.MethodNotFound, - 'Not implemented yes' - ) - end - end -end - return M diff --git a/lua/java-refactor/init.lua b/lua/java-refactor/init.lua index 1d4863f..7f5dbc7 100644 --- a/lua/java-refactor/init.lua +++ b/lua/java-refactor/init.lua @@ -1,25 +1,39 @@ local event = require('java-core.utils.event') +local M = {} + local group = vim.api.nvim_create_augroup('java-refactor-command-register', {}) -local setup = function() - -- setting all the vim.lsp.commands - local code_action_handler = require('java-refactor.code-action-handlers') +event.on_jdtls_attach({ + group = group, + once = true, + callback = function() + M.reg_client_commands() + M.reg_refactor_commands() + M.reg_build_commands() + end, +}) + +M.reg_client_commands = function() + local code_action_handlers = require('java-refactor.client-command-handlers') - for key, handler in pairs(code_action_handler.handlers) do + for key, handler in pairs(code_action_handlers) do vim.lsp.commands[key] = handler end +end - -- setting all the user commands and APIs - local code_action_api = require('java-refactor.api.code-action') +M.reg_refactor_commands = function() + local code_action_api = require('java-refactor.api.refactor') for api_name, api in pairs(code_action_api) do require('java').register_api({ 'refactor', api_name }, api, { range = 2 }) end end -event.on_jdtls_attach({ - group = group, - once = true, - callback = setup, -}) +M.reg_build_commands = function() + local code_action_api = require('java-refactor.api.build') + + for api_name, api in pairs(code_action_api) do + require('java').register_api({ 'build', api_name }, api, {}) + end +end From 14cd6749711c87c41d04740acffb253f4c15d5ba Mon Sep 17 00:00:00 2001 From: s1n7ax Date: Wed, 24 Jul 2024 22:42:04 +0530 Subject: [PATCH 4/4] fix: lint error --- lua/java-refactor/action.lua | 2 +- lua/java-refactor/client-command-handlers.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lua/java-refactor/action.lua b/lua/java-refactor/action.lua index 0572bee..d78baa4 100644 --- a/lua/java-refactor/action.lua +++ b/lua/java-refactor/action.lua @@ -23,7 +23,7 @@ end ---@field uri string ---@param params java-refactor.RenameAction[] -function Action:rename(params) +function Action.rename(params) for _, rename in ipairs(params) do local buffer = vim.uri_to_bufnr(rename.uri) diff --git a/lua/java-refactor/client-command-handlers.lua b/lua/java-refactor/client-command-handlers.lua index 23d4d4c..8e56ac5 100644 --- a/lua/java-refactor/client-command-handlers.lua +++ b/lua/java-refactor/client-command-handlers.lua @@ -18,7 +18,7 @@ local M = { ---@param params java-refactor.RenameAction[] [ClientCommand.RENAME_COMMAND] = function(params) run('Failed to rename the symbol', function(action) - action:rename(params) + action.rename(params) end) end,