Skip to content

Commit 35d8a83

Browse files
committed
feat: add moveType and moveStaticMember code actions
1 parent 7fe5643 commit 35d8a83

File tree

2 files changed

+213
-95
lines changed

2 files changed

+213
-95
lines changed

lua/java-refactor/lsp-refactor-commands.lua

Lines changed: 4 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ local get_error_handler = require('java-refactor.utils.error_handler')
33
local RefactorCommands = require('java-refactor.refactor-commands')
44

55
local M = {
6-
76
commands = {
87
---@class java-refactor.RenameAction
98
---@field length number
@@ -38,13 +37,15 @@ local M = {
3837
---@param params java-refactor.ApplyRefactoringCommandParams
3938
['java.action.applyRefactoringCommand'] = function(command, params)
4039
runner(function()
41-
local refactor_type = command.arguments[1] --[[@as jdtls.CodeActionCommand]]
40+
local action_name = command.arguments[1] --[[@as jdtls.CodeActionCommand]]
41+
local action_context = command.arguments[2] --[[@as lsp.CodeActionParams]]
42+
local action_info = command.arguments[3] --[[@as lsp.LSPAny]]
4243

4344
local client = vim.lsp.get_client_by_id(params.client_id)
4445

4546
---@type java-refactor.RefactorCommands
4647
local refactor_commands = RefactorCommands(client)
47-
refactor_commands:refactor(refactor_type, params.params)
48+
refactor_commands:refactor(action_name, action_context, action_info)
4849
end)
4950
.catch(get_error_handler('Failed to run refactoring command'))
5051
.run()
@@ -73,58 +74,3 @@ id = vim.api.nvim_create_autocmd('LspAttach', {
7374
---@field method string
7475
---@field params lsp.CodeActionParams
7576
---@field version number
76-
77-
--[[
78-
{
79-
arguments = {
80-
'extractField',
81-
{
82-
context = {
83-
diagnostics = {},
84-
triggerKind = 1,
85-
},
86-
range = {
87-
['end'] = {
88-
character = 9,
89-
line = 9,
90-
},
91-
start = {
92-
character = 9,
93-
line = 9,
94-
},
95-
},
96-
textDocument = {
97-
uri = 'file:///home/s1n7ax/Workspace/demo/src/main/java/com/example/demo/DemoApplication.java',
98-
},
99-
},
100-
},
101-
command = 'java.action.applyRefactoringCommand',
102-
title = 'Extract to field',
103-
})
104-
105-
{
106-
bufnr = 3,
107-
client_id = 2,
108-
method = "textDocument/codeAction",
109-
params = {
110-
context = {
111-
diagnostics = {},
112-
triggerKind = 1
113-
},
114-
range = {
115-
["end"] = {
116-
character = 9,
117-
line = 9
118-
},
119-
start = {
120-
character = 9,
121-
line = 9
122-
}
123-
},
124-
textDocument = {
125-
uri = "file:///home/s1n7ax/Workspace/demo/src/main/java/com/example/demo/DemoApplication.java"
126-
}
127-
},
128-
version = 4
129-
}
130-
]]

lua/java-refactor/refactor-commands.lua

Lines changed: 209 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@ local JdtlsClient = require('java-core.ls.clients.jdtls-client')
44
local List = require('java-core.utils.list')
55
local ui = require('java.utils.ui')
66

7+
local refactor_edit_request_needed_actions = {
8+
'convertVariableToField',
9+
'extractConstant',
10+
'extractField',
11+
'extractMethod',
12+
'extractVariable',
13+
'extractVariableAllOccurrence',
14+
}
15+
716
local selections_needed_refactoring_commands = {
817
'convertVariableToField',
918
'extractConstant',
@@ -13,7 +22,7 @@ local selections_needed_refactoring_commands = {
1322
'extractVariableAllOccurrence',
1423
}
1524

16-
local available_commands = {
25+
local available_actions = {
1726
'assignField',
1827
'assignVariable',
1928
-- 'changeSignature',
@@ -27,6 +36,10 @@ local available_commands = {
2736
'extractVariableAllOccurrence',
2837
'introduceParameter',
2938
'invertVariable',
39+
'moveFile',
40+
'moveInstanceMethod',
41+
'moveStaticMember',
42+
'moveType',
3043
}
3144

3245
---@class java-refactor.RefactorCommands
@@ -39,43 +52,210 @@ function RefactorCommands:_init(client)
3952
end
4053

4154
---Run refactor command
42-
---@param refactor_type jdtls.CodeActionCommand
43-
---@param params lsp.CodeActionParams
44-
function RefactorCommands:refactor(refactor_type, params)
45-
if not vim.tbl_contains(available_commands, refactor_type) then
55+
---@param action_name jdtls.CodeActionCommand
56+
---@param action_context lsp.CodeActionParams
57+
---@param action_info lsp.LSPAny
58+
function RefactorCommands:refactor(action_name, action_context, action_info)
59+
if not vim.tbl_contains(available_actions, action_name) then
4660
notify.error(
47-
string.format('Refactoring command "%s" is not supported', refactor_type)
61+
string.format('Refactoring command "%s" is not supported', action_name)
4862
)
4963
return
5064
end
5165

52-
params = params or RefactorCommands.make_action_params()
53-
local formatting_options = RefactorCommands.make_formatting_options()
54-
local selections
66+
if vim.tbl_contains(refactor_edit_request_needed_actions, action_name) then
67+
local formatting_options = RefactorCommands.make_formatting_options()
68+
local selections
69+
70+
if
71+
vim.tbl_contains(selections_needed_refactoring_commands, action_name)
72+
then
73+
selections = self:get_selections(action_name, action_context)
74+
end
75+
76+
local changes = self.jdtls_client:java_get_refactor_edit(
77+
action_name,
78+
action_context,
79+
formatting_options,
80+
selections,
81+
vim.api.nvim_get_current_buf()
82+
)
83+
84+
if not changes then
85+
notify.warn('No edits suggested for action')
86+
return
87+
end
88+
89+
vim.lsp.util.apply_workspace_edit(changes.edit, 'utf-8')
5590

56-
if selections_needed_refactoring_commands then
57-
selections = self:get_selections(refactor_type, params)
91+
RefactorCommands.run_lsp_client_command(
92+
changes.command.command,
93+
changes.command.arguments
94+
)
95+
elseif action_name == 'moveType' then
96+
self:move_type(
97+
action_context,
98+
action_info --[[@as jdtls.CodeActionMoveTypeCommandInfo]]
99+
)
100+
elseif action_name == 'moveStaticMember' then
101+
self:move_static_member(
102+
action_context,
103+
action_info --[[@as jdtls.CodeActionMoveTypeCommandInfo]]
104+
)
105+
end
106+
end
107+
108+
---@param action_context lsp.CodeActionParams
109+
---@param action_info jdtls.CodeActionMoveTypeCommandInfo
110+
function RefactorCommands:move_static_member(action_context, action_info)
111+
local exclude = List:new()
112+
113+
if action_info.enclosingTypeName then
114+
exclude:push(action_info.enclosingTypeName)
115+
if
116+
action_info.memberType == 55
117+
or action_info.memberType == 71
118+
or action_info.memberType == 81
119+
then
120+
exclude:push(
121+
action_info.enclosingTypeName .. '.' .. action_info.displayName
122+
)
123+
end
58124
end
59125

60-
local changes = self.jdtls_client:java_get_refactor_edit(
61-
refactor_type,
62-
params,
63-
formatting_options,
64-
selections,
65-
vim.api.nvim_get_current_buf()
126+
local project_name = action_info and action_info.projectName or nil
127+
local member_name = action_info
128+
and action_info.displayName
129+
and action_info.displayName
130+
or ''
131+
132+
local selected_class = self:select_target_class(
133+
string.format('Select the new class for the static member %s.', member_name),
134+
project_name,
135+
exclude
66136
)
67137

68-
if not changes then
69-
notify.warn('No edits suggested for action')
138+
if not selected_class then
70139
return
71140
end
72141

142+
local changes = self.jdtls_client:java_move({
143+
moveKind = 'moveStaticMember',
144+
sourceUris = { action_context.textDocument.uri },
145+
params = action_context,
146+
destination = selected_class,
147+
})
148+
73149
vim.lsp.util.apply_workspace_edit(changes.edit, 'utf-8')
74150

75-
RefactorCommands.run_lsp_client_command(
76-
changes.command.command,
77-
changes.command.arguments
151+
if changes.command then
152+
RefactorCommands.run_lsp_client_command(
153+
changes.command.command,
154+
changes.command.arguments
155+
)
156+
end
157+
end
158+
159+
---@param action_context lsp.CodeActionParams
160+
---@param action_info jdtls.CodeActionMoveTypeCommandInfo
161+
function RefactorCommands:move_type(action_context, action_info)
162+
if not action_info or not action_info.supportedDestinationKinds then
163+
return
164+
end
165+
166+
local selected_destination_kind = ui.select(
167+
'What would you like to do?',
168+
action_info.supportedDestinationKinds,
169+
function(kind)
170+
if kind == 'newFile' then
171+
return string.format(
172+
'Move type "%s" to new file',
173+
action_info.displayName
174+
)
175+
else
176+
return string.format(
177+
'Move type "%s" to another class',
178+
action_info.displayName
179+
)
180+
end
181+
end
78182
)
183+
184+
if not selected_destination_kind then
185+
return
186+
end
187+
188+
---@type jdtls.RefactorWorkspaceEdit
189+
local changes
190+
191+
if selected_destination_kind == 'newFile' then
192+
changes = self.jdtls_client:java_move({
193+
moveKind = 'moveTypeToNewFile',
194+
sourceUris = { action_context.textDocument.uri },
195+
params = action_context,
196+
})
197+
else
198+
local exclude = List:new()
199+
200+
if action_info.enclosingTypeName then
201+
exclude:push(action_info.enclosingTypeName)
202+
exclude:push(
203+
action_info.enclosingTypeName .. ':' .. action_info.displayName
204+
)
205+
end
206+
207+
local selected_class = self:select_target_class(
208+
string.format(
209+
'Select the new class for the type %s.',
210+
action_info.displayName
211+
),
212+
action_info.projectName,
213+
exclude
214+
)
215+
216+
if not selected_class then
217+
return
218+
end
219+
220+
changes = self.jdtls_client:java_move({
221+
moveKind = 'moveStaticMember',
222+
sourceUris = { action_context.textDocument.uri },
223+
params = action_context,
224+
destination = selected_class,
225+
})
226+
end
227+
228+
vim.lsp.util.apply_workspace_edit(changes.edit, 'utf-8')
229+
230+
if changes.command then
231+
RefactorCommands.run_lsp_client_command(
232+
changes.command.command,
233+
changes.command.arguments
234+
)
235+
end
236+
end
237+
238+
---@param prompt string
239+
---@param project_name string
240+
---@param exclude string[]
241+
function RefactorCommands:select_target_class(prompt, project_name, exclude)
242+
local classes = self.jdtls_client:java_search_symbols({
243+
query = '*',
244+
projectName = project_name,
245+
sourceOnly = true,
246+
})
247+
248+
---@type lsp.SymbolInformation[]
249+
local filtered_classes = List:new(classes):filter(function(cls)
250+
local type_name = cls.containerName .. '.' .. cls.name
251+
return not vim.tbl_contains(exclude, type_name)
252+
end)
253+
254+
local selected = ui.select(prompt, filtered_classes, function(cls)
255+
return cls.containerName .. '.' .. cls.name
256+
end)
257+
258+
return selected
79259
end
80260

81261
---@private
@@ -92,21 +272,6 @@ function RefactorCommands.run_lsp_client_command(command_name, arguments)
92272
command(arguments)
93273
end
94274

95-
---Returns action params
96-
---@private
97-
---@return lsp.CodeActionParams
98-
function RefactorCommands.make_action_params()
99-
---@type lsp.CodeActionParams
100-
local params = vim.lsp.util.make_range_params(0)
101-
102-
---@type lsp.CodeActionContext
103-
local context = { diagnostics = vim.lsp.diagnostic.get_line_diagnostics(0) }
104-
105-
params.context = context
106-
107-
return params
108-
end
109-
110275
---@private
111276
---@return lsp.FormattingOptions
112277
function RefactorCommands.make_formatting_options()
@@ -154,4 +319,11 @@ function RefactorCommands:get_selections(refactor_type, params)
154319
return selections
155320
end
156321

322+
---@class jdtls.CodeActionMoveTypeCommandInfo
323+
---@field displayName string
324+
---@field enclosingTypeName string
325+
---@field memberType number
326+
---@field projectName string
327+
---@field supportedDestinationKinds string[]
328+
157329
return RefactorCommands

0 commit comments

Comments
 (0)