From 308c17c732eb29f5332b1f5e0e347206591f8660 Mon Sep 17 00:00:00 2001 From: s1n7ax Date: Sun, 24 Mar 2024 19:28:57 +0530 Subject: [PATCH] feat: add code refactoring APIs --- .../ls/clients/java-debug-client.lua | 12 +- lua/java-core/ls/clients/java-test-client.lua | 16 +-- lua/java-core/ls/clients/jdtls-client.lua | 111 ++++++++++++++---- .../ls/servers/jdtls/lspconfig-types.lua | 6 +- 4 files changed, 103 insertions(+), 42 deletions(-) diff --git a/lua/java-core/ls/clients/java-debug-client.lua b/lua/java-core/ls/clients/java-debug-client.lua index 1e635da..d8b652c 100644 --- a/lua/java-core/ls/clients/java-debug-client.lua +++ b/lua/java-core/ls/clients/java-debug-client.lua @@ -17,7 +17,7 @@ end ---Returns a list of main classes in the current workspace ---@return JavaDebugResolveMainClassRecord[] # resolved main class function DebugClient:resolve_main_class() - return self:execute_command('vscode.java.resolveMainClass') + return self:workspace_execute_command('vscode.java.resolveMainClass') end ---Returns module paths and class paths of a given main class @@ -25,7 +25,7 @@ end ---@param main_class string ---@return string[][] # resolved class and module paths function DebugClient:resolve_classpath(main_class, project_name) - return self:execute_command( + return self:workspace_execute_command( 'vscode.java.resolveClasspath', { main_class, project_name } ) @@ -36,7 +36,7 @@ end ---@param main_class string ---@return string # path to java executable function DebugClient:resolve_java_executable(main_class, project_name) - return self:execute_command('vscode.java.resolveJavaExecutable', { + return self:workspace_execute_command('vscode.java.resolveJavaExecutable', { main_class, project_name, }) @@ -54,7 +54,7 @@ function DebugClient:check_project_settings( inheritedOptions, expectedOptions ) - return self:execute_command( + return self:workspace_execute_command( 'vscode.java.checkProjectSettings', vim.fn.json_encode({ className = main_class, @@ -68,7 +68,7 @@ end ---Starts a debug session and returns the port number ---@return integer # port number of the debug session function DebugClient:start_debug_session() - return self:execute_command('vscode.java.startDebugSession') + return self:workspace_execute_command('vscode.java.startDebugSession') end ---@enum CompileWorkspaceStatus @@ -91,7 +91,7 @@ function DebugClient:build_workspace( file_path, is_full_build ) - return self:execute_command( + return self:workspace_execute_command( 'vscode.java.buildWorkspace', vim.fn.json_encode({ mainClass = main_class, diff --git a/lua/java-core/ls/clients/java-test-client.lua b/lua/java-core/ls/clients/java-test-client.lua index c58d3bb..870cde9 100644 --- a/lua/java-core/ls/clients/java-test-client.lua +++ b/lua/java-core/ls/clients/java-test-client.lua @@ -24,12 +24,8 @@ local JdtlsClient = require('java-core.ls.clients.jdtls-client') ---@field children java-core.TestDetailsWithRange[] ---@class java-core.TestRange ----@field start CursorPoint ----@field end CursorPoint - ----@class CursorPoint ----@field line integer ----@field character integer +---@field start nvim.CursorPoint +---@field end nvim.CursorPoint ---@class java-core.TestClient: java-core.JdtlsClient local TestClient = class(JdtlsClient) @@ -41,7 +37,7 @@ end ---Returns a list of project details in the current root ---@return java-core.TestDetails[] # test details of the projects function TestClient:find_java_projects() - return self:execute_command( + return self:workspace_execute_command( 'vscode.java.test.findJavaProjects', { vim.uri_from_fname(self.client.config.root_dir) } ) @@ -52,7 +48,7 @@ end ---@param token? string ---@return java-core.TestDetailsWithChildren[] # test package details function TestClient:find_test_packages_and_types(handler, token) - return self:execute_command( + return self:workspace_execute_command( 'vscode.java.test.findTestPackagesAndTypes', { handler, token } ) @@ -63,7 +59,7 @@ end ---@param token? string ---@return java-core.TestDetailsWithChildrenAndRange[] # test details function TestClient:find_test_types_and_methods(file_uri, token) - return self:execute_command( + return self:workspace_execute_command( 'vscode.java.test.findTestTypesAndMethods', { file_uri, token } ) @@ -88,7 +84,7 @@ end ---@param args JavaCoreTestResolveJUnitLaunchArgumentsParams ---@return JavaCoreTestJunitLaunchArguments # junit launch arguments function TestClient:resolve_junit_launch_arguments(args) - local launch_args = self:execute_command( + local launch_args = self:workspace_execute_command( 'vscode.java.test.junit.argument', vim.fn.json_encode(args) ) diff --git a/lua/java-core/ls/clients/jdtls-client.lua b/lua/java-core/ls/clients/jdtls-client.lua index 32b2e2c..1860e01 100644 --- a/lua/java-core/ls/clients/jdtls-client.lua +++ b/lua/java-core/ls/clients/jdtls-client.lua @@ -3,6 +3,37 @@ local class = require('java-core.utils.class') local async = require('java-core.utils.async') local await = async.wait_handle_error +---@alias jdtls.RequestMethod +---| 'workspace/executeCommand' +---| 'java/inferSelection' +---| 'java/getRefactorEdit' + +---@alias jdtls.CodeActionCommand +---| 'extractVariable' +---| 'assignVariable' +---| 'extractVariableAllOccurrence' +---| 'extractConstant' +---| 'extractMethod' +---| 'extractField' +---| 'extractInterface' +---| 'changeSignature' +---| 'assignField' +---| 'convertVariableToField' +---| 'invertVariable' +---| 'introduceParameter' +---| 'convertAnonymousClassToNestedCommand') { + +---@class jdtls.RefactorWorkspaceEdit +---@field edit lsp.WorkspaceEdit +---@field command? lsp.Command +---@field errorMessage? string + +---@class jdtls.SelectionInfo +---@field name string +---@field length number +---@field offset number +---@field params? string[] + ---@class java-core.JdtlsClient ---@field client LspClient local JdtlsClient = class() @@ -23,44 +54,82 @@ function JdtlsClient:new(args) return o end ----Executes a workspace/executeCommand and returns the result ----@param command string ----@param arguments? string | string[] ----@param buffer? integer ----@return any -function JdtlsClient:execute_command(command, arguments, buffer) - log.debug('executing: workspace/executeCommand - ' .. command) - - local cmd_info = { - command = command, - arguments = arguments, - } +---Sends a LSP request +---@param method jdtls.RequestMethod +---@param params lsp.ExecuteCommandParams +---@param buffer? number +function JdtlsClient:request(method, params, buffer) + log.debug('sending LSP request: ' .. method) return await(function(callback) local on_response = function(err, result) if err then - log.error(command .. ' failed! arguments: ', arguments, ' error: ', err) + log.error(method .. ' failed! arguments: ', params, ' error: ', err) else - log.debug(command .. ' success! response: ', result) + log.debug(method .. ' success! response: ', result) end callback(err, result) end - return self.client.request( - 'workspace/executeCommand', - cmd_info, - on_response, - buffer - ) + return self.client.request(method, params, on_response, buffer) end) end +---Executes a workspace/executeCommand and returns the result +---@param command string workspace command to execute +---@param params? lsp.LSPAny[] +---@param buffer? integer +---@return lsp.LSPAny +function JdtlsClient:workspace_execute_command(command, params, buffer) + return self:request('workspace/executeCommand', { + command = command, + arguments = params, + }, buffer) +end + +---Returns more information about the object the cursor is on +---@param command jdtls.RequestMethod +---@param params lsp.CodeActionParams +---@param buffer? number +---@return jdtls.SelectionInfo[] +function JdtlsClient:java_infer_selection(command, params, buffer) + return self:request('java/inferSelection', { + command = command, + context = params, + }, buffer) +end + +---Returns refactor details +---@param command jdtls.CodeActionCommand +---@param context lsp.CodeActionParams +---@param options lsp.FormattingOptions +---@param command_arguments jdtls.SelectionInfo[]; +---@param buffer? number +---@return jdtls.RefactorWorkspaceEdit +function JdtlsClient:java_get_refactor_edit( + command, + context, + options, + command_arguments, + buffer +) + local params = { + command = command, + context = context, + options = options, + commandArguments = command_arguments, + } + + return self:request('java/getRefactorEdit', params, buffer) +end + ---Returns the decompiled class file content ---@param uri string uri of the class file ---@return string # decompiled file content function JdtlsClient:java_decompile(uri) - return self:execute_command('java.decompile', { uri }) + ---@type string + return self:workspace_execute_command('java.decompile', { uri }) end function JdtlsClient:get_capability(...) diff --git a/lua/java-core/ls/servers/jdtls/lspconfig-types.lua b/lua/java-core/ls/servers/jdtls/lspconfig-types.lua index 19384cf..60af083 100644 --- a/lua/java-core/ls/servers/jdtls/lspconfig-types.lua +++ b/lua/java-core/ls/servers/jdtls/lspconfig-types.lua @@ -29,10 +29,6 @@ ---`workspace/didChangeConfiguration` notification from the Nvim client to the language server. ---These settings allow a user to change optional runtime settings of the language server. ----@class LspClientRequestParameters ----@field command string ----@field arguments string | string[] | nil - ---@class LspClientResponse ---@field err LspClientResponseError @@ -55,7 +51,7 @@ ---@field name string ---@field notify fun(method: string, params: object): boolean ---@field offset_encoding string ----@field request fun(method:string,params:LspClientRequestParameters,callback:LspClientRequest, bufnr?:number): any +---@field request fun(method:string, params:lsp.ExecuteCommandParams,callback:LspClientRequest, bufnr?:number): any ---@field request_sync function ---@field requests object ---@field rpc object