Skip to content

feat: move all client commands to java-refactor #14

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
273 changes: 273 additions & 0 deletions lua/java-refactor/action.lua
Original file line number Diff line number Diff line change
@@ -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')
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
19 changes: 19 additions & 0 deletions lua/java-refactor/api/build.lua
Original file line number Diff line number Diff line change
@@ -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
38 changes: 38 additions & 0 deletions lua/java-refactor/api/refactor.lua
Original file line number Diff line number Diff line change
@@ -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
Loading
Loading