Skip to content

Commit e741cbf

Browse files
committed
fix selection ranges crash with empty do end blocks
1 parent 1ba706d commit e741cbf

File tree

3 files changed

+54
-8
lines changed

3 files changed

+54
-8
lines changed

apps/language_server/lib/language_server/providers/selection_ranges.ex

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ defmodule ElixirLS.LanguageServer.Providers.SelectionRanges do
151151

152152
case end_token do
153153
:end ->
154-
if line < start_line + 1 or line > end_line - 1 do
154+
if line < start_line + 1 or line > end_line - 1 or start_line + 1 == end_line do
155155
# do not include inner range if cursor is outside, e.g.
156156
# do
157157
# ^
@@ -160,8 +160,14 @@ defmodule ElixirLS.LanguageServer.Providers.SelectionRanges do
160160
line_length = lines |> Enum.at(end_line - 1, "") |> String.length()
161161
inner_range = range(start_line + 1, 0, end_line - 1, line_length)
162162

163-
find_stop_token_range(stop_tokens_in_pair, pair, inner_range, line, character) ++
164-
[inner_range, outer_range | acc]
163+
if empty?(inner_range) do
164+
# degenerate case where the inner range is an empty line
165+
# in this case we should not include the inner range
166+
[outer_range | acc]
167+
else
168+
find_stop_token_range(stop_tokens_in_pair, pair, inner_range, line, character) ++
169+
[inner_range, outer_range | acc]
170+
end
165171
end
166172

167173
_ ->
@@ -238,13 +244,22 @@ defmodule ElixirLS.LanguageServer.Providers.SelectionRanges do
238244
{start_line, start_character}
239245
end
240246

247+
computed_range = range(start_line, start_character, end_line, end_character)
248+
241249
trimmed_range =
242-
intersection(
243-
range(start_line, start_character, end_line, end_character),
244-
inner_range
245-
)
250+
if not empty?(computed_range) do
251+
try do
252+
intersection(
253+
range(start_line, start_character, end_line, end_character),
254+
inner_range
255+
)
256+
rescue
257+
# No intersection possible
258+
ArgumentError -> nil
259+
end
260+
end
246261

247-
if in?(trimmed_range, {line, character}) do
262+
if trimmed_range && in?(trimmed_range, {line, character}) do
248263
{:halt, {token_tuple, [trimmed_range]}}
249264
else
250265
{:halt, {token_tuple, []}}

apps/language_server/lib/language_server/range_utils.ex

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ defmodule ElixirLS.LanguageServer.RangeUtils do
2929

3030
def valid?(_), do: false
3131

32+
def empty?(range(start_line, start_character, end_line, end_character)) do
33+
start_line == end_line and start_character == end_character
34+
end
35+
3236
def increasingly_narrowing?([left]), do: valid?(left)
3337

3438
def increasingly_narrowing?([left, right | rest]) do

apps/language_server/test/providers/selection_ranges_test.exs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1103,4 +1103,31 @@ defmodule ElixirLS.LanguageServer.Providers.SelectionRangesTest do
11031103
# s variable
11041104
assert_range(ranges, range(0, 15, 0, 16))
11051105
end
1106+
1107+
test "do not raise no intersection in degenerate stop token cases" do
1108+
text = """
1109+
if 1 do
1110+
:ok
1111+
end
1112+
"""
1113+
1114+
get_ranges(text, 1, 2)
1115+
1116+
text = """
1117+
if 1 do
1118+
1119+
end
1120+
"""
1121+
1122+
get_ranges(text, 1, 2)
1123+
1124+
text = """
1125+
if 1 do
1126+
:ok
1127+
1128+
end
1129+
"""
1130+
1131+
get_ranges(text, 1, 2)
1132+
end
11061133
end

0 commit comments

Comments
 (0)