Skip to content

Commit 64cfd2a

Browse files
authored
Merge pull request #812 from Shopify/vs/improve_pipe_completion_on_manual_insert
Improve pipe completion if the user adds an accidental extra pipe
2 parents beb39e4 + 7aa1759 commit 64cfd2a

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)