Skip to content

Commit 7aa1759

Browse files
committed
Improve pipe completion if the user adds an accidental extra pipe
If we autocomplete pipes and the user still accidentally adds the second one, we currently end up autocompleting in both cases and end up with 4 pipes. This commits makes it so that if the user inserted a second pipe after the autocomplete, we remove the pipe we added automatically and avoid adding yet another one, resulting in two pipes.
1 parent ae88127 commit 7aa1759

File tree

2 files changed

+87
-6
lines changed

2 files changed

+87
-6
lines changed

lib/ruby_lsp/requests/on_type_formatting.rb

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,34 @@ def run
6262

6363
sig { void }
6464
def handle_pipe
65-
return unless /((?<=do)|(?<={))\s+\|/.match?(@previous_line)
65+
current_line = @lines[@position[:line]]
66+
return unless /((?<=do)|(?<={))\s+\|/.match?(current_line)
67+
68+
line = T.must(current_line)
69+
70+
# If the current character is a pipe and both previous ones are pipes too, then we autocompleted a pipe and the
71+
# user inserted a third one. In this case, we need to avoid adding a fourth and remove the previous one
72+
if line[@position[:character] - 2] == "|" &&
73+
line[@position[:character] - 1] == "|" &&
74+
line[@position[:character]] == "|"
75+
76+
@edits << Interface::TextEdit.new(
77+
range: Interface::Range.new(
78+
start: Interface::Position.new(
79+
line: @position[:line],
80+
character: @position[:character],
81+
),
82+
end: Interface::Position.new(
83+
line: @position[:line],
84+
character: @position[:character] + 1,
85+
),
86+
),
87+
new_text: "",
88+
)
89+
else
90+
add_edit_with_text("|")
91+
end
6692

67-
add_edit_with_text("|")
6893
move_cursor_to(@position[:line], @position[:character])
6994
end
7095

test/requests/on_type_formatting_test.rb

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,14 @@ def test_adding_missing_pipe
6868
)
6969
document.parse
7070

71-
edits = RubyLsp::Requests::OnTypeFormatting.new(document, { line: 0, character: 11 }, "|").run
71+
edits = RubyLsp::Requests::OnTypeFormatting.new(document, { line: 0, character: 12 }, "|").run
7272
expected_edits = [
7373
{
74-
range: { start: { line: 0, character: 11 }, end: { line: 0, character: 11 } },
74+
range: { start: { line: 0, character: 12 }, end: { line: 0, character: 12 } },
7575
newText: "|",
7676
},
7777
{
78-
range: { start: { line: 0, character: 11 }, end: { line: 0, character: 11 } },
78+
range: { start: { line: 0, character: 12 }, end: { line: 0, character: 12 } },
7979
newText: "$0",
8080
},
8181
]
@@ -94,10 +94,66 @@ def test_pipe_is_not_added_in_regular_or_pipe
9494
)
9595
document.parse
9696

97-
edits = RubyLsp::Requests::OnTypeFormatting.new(document, { line: 0, character: 11 }, "|").run
97+
edits = RubyLsp::Requests::OnTypeFormatting.new(document, { line: 0, character: 2 }, "|").run
9898
assert_empty(T.must(edits))
9999
end
100100

101+
def test_pipe_is_removed_if_user_adds_manually_after_completion
102+
document = RubyLsp::Document.new(source: +"", version: 1, uri: "file:///fake.rb")
103+
104+
document.push_edits(
105+
[{
106+
range: { start: { line: 0, character: 0 }, end: { line: 0, character: 0 } },
107+
text: "[].each do |",
108+
}],
109+
version: 2,
110+
)
111+
document.parse
112+
113+
document.push_edits(
114+
[{
115+
range: { start: { line: 0, character: 12 }, end: { line: 0, character: 12 } },
116+
text: "|",
117+
}],
118+
version: 3,
119+
)
120+
edits = RubyLsp::Requests::OnTypeFormatting.new(document, { line: 0, character: 12 }, "|").run
121+
expected_edits = [
122+
{
123+
range: { start: { line: 0, character: 12 }, end: { line: 0, character: 12 } },
124+
newText: "|",
125+
},
126+
{
127+
range: { start: { line: 0, character: 12 }, end: { line: 0, character: 12 } },
128+
newText: "$0",
129+
},
130+
]
131+
assert_equal(expected_edits.to_json, T.must(edits).to_json)
132+
assert_equal("[].each do ||", document.source)
133+
134+
# Push the third pipe manually after the completion happened
135+
document.push_edits(
136+
[{
137+
range: { start: { line: 0, character: 13 }, end: { line: 0, character: 13 } },
138+
text: "|",
139+
}],
140+
version: 3,
141+
)
142+
143+
edits = RubyLsp::Requests::OnTypeFormatting.new(document, { line: 0, character: 13 }, "|").run
144+
expected_edits = [
145+
{
146+
range: { start: { line: 0, character: 13 }, end: { line: 0, character: 14 } },
147+
newText: "",
148+
},
149+
{
150+
range: { start: { line: 0, character: 13 }, end: { line: 0, character: 13 } },
151+
newText: "$0",
152+
},
153+
]
154+
assert_equal(expected_edits.to_json, T.must(edits).to_json)
155+
end
156+
101157
def test_comment_continuation
102158
document = RubyLsp::Document.new(source: +"", version: 1, uri: "file:///fake.rb")
103159

0 commit comments

Comments
 (0)