Skip to content

Commit 76f292e

Browse files
authored
Fix extracting a method without another declaration to anchor replacement (#2429)
1 parent 3388ef8 commit 76f292e

File tree

3 files changed

+94
-16
lines changed

3 files changed

+94
-16
lines changed

lib/ruby_lsp/requests/code_action_resolve.rb

+32-16
Original file line numberDiff line numberDiff line change
@@ -207,27 +207,43 @@ def refactor_method
207207

208208
# Find the closest method declaration node, so that we place the refactor in a valid position
209209
node_context = RubyDocument.locate(@document.parse_result.value, start_index, node_types: [Prism::DefNode])
210-
closest_def = T.cast(node_context.node, Prism::DefNode)
211-
return Error::InvalidTargetRange if closest_def.nil?
210+
closest_node = node_context.node
211+
return Error::InvalidTargetRange unless closest_node
212212

213-
end_keyword_loc = closest_def.end_keyword_loc
214-
return Error::InvalidTargetRange if end_keyword_loc.nil?
213+
target_range = if closest_node.is_a?(Prism::DefNode)
214+
end_keyword_loc = closest_node.end_keyword_loc
215+
return Error::InvalidTargetRange unless end_keyword_loc
215216

216-
end_line = end_keyword_loc.end_line - 1
217-
character = end_keyword_loc.end_column
218-
indentation = " " * end_keyword_loc.start_column
219-
target_range = {
220-
start: { line: end_line, character: character },
221-
end: { line: end_line, character: character },
222-
}
217+
end_line = end_keyword_loc.end_line - 1
218+
character = end_keyword_loc.end_column
219+
indentation = " " * end_keyword_loc.start_column
223220

224-
new_method_source = <<~RUBY.chomp
221+
new_method_source = <<~RUBY.chomp
225222
226223
227-
#{indentation}def #{NEW_METHOD_NAME}
228-
#{indentation} #{extracted_source}
229-
#{indentation}end
230-
RUBY
224+
#{indentation}def #{NEW_METHOD_NAME}
225+
#{indentation} #{extracted_source}
226+
#{indentation}end
227+
RUBY
228+
229+
{
230+
start: { line: end_line, character: character },
231+
end: { line: end_line, character: character },
232+
}
233+
else
234+
new_method_source = <<~RUBY
235+
#{indentation}def #{NEW_METHOD_NAME}
236+
#{indentation} #{extracted_source.gsub("\n", "\n ")}
237+
#{indentation}end
238+
239+
RUBY
240+
241+
line = [0, source_range.dig(:start, :line) - 1].max
242+
{
243+
start: { line: line, character: source_range.dig(:start, :character) },
244+
end: { line: line, character: source_range.dig(:start, :character) },
245+
}
246+
end
231247

232248
Interface::CodeAction.new(
233249
title: CodeActions::EXTRACT_TO_METHOD_TITLE,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
{
2+
"params": {
3+
"kind": "refactor.extract",
4+
"title": "Refactor: Extract Method",
5+
"data": {
6+
"range": {
7+
"start": {
8+
"line": 0,
9+
"character": 0
10+
},
11+
"end": {
12+
"line": 2,
13+
"character": 6
14+
}
15+
},
16+
"uri": "file:///fake"
17+
}
18+
},
19+
"result": {
20+
"title": "Refactor: Extract Method",
21+
"edit": {
22+
"documentChanges": [
23+
{
24+
"textDocument": {
25+
"uri": "file:///fake",
26+
"version": null
27+
},
28+
"edits": [
29+
{
30+
"range": {
31+
"start": {
32+
"line": 0,
33+
"character": 0
34+
},
35+
"end": {
36+
"line": 0,
37+
"character": 0
38+
}
39+
},
40+
"newText": "def new_method\n a = 5 + 2\n a * 10\n \nend\n\n"
41+
},
42+
{
43+
"range": {
44+
"start": {
45+
"line": 0,
46+
"character": 0
47+
},
48+
"end": {
49+
"line": 2,
50+
"character": 6
51+
}
52+
},
53+
"newText": "new_method"
54+
}
55+
]
56+
}
57+
]
58+
}
59+
}
60+
}
+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
a = 5 + 2
2+
a * 10

0 commit comments

Comments
 (0)