Skip to content

Commit fb065b7

Browse files
authored
Fix Code.Fragment.surround_context for keyword keys (#13843)
1 parent 5eddb4b commit fb065b7

File tree

2 files changed

+53
-2
lines changed

2 files changed

+53
-2
lines changed

lib/elixir/lib/code/fragment.ex

+15-2
Original file line numberDiff line numberDiff line change
@@ -590,7 +590,8 @@ defmodule Code.Fragment do
590590
| {:sigil, charlist}
591591
| {:struct, inside_struct}
592592
| {:unquoted_atom, charlist}
593-
| {:keyword, charlist},
593+
| {:keyword, charlist}
594+
| {:key, charlist},
594595
inside_dot:
595596
{:alias, charlist}
596597
| {:alias, inside_alias, charlist}
@@ -640,7 +641,16 @@ defmodule Code.Fragment do
640641
maybe_operator(reversed_pre, post, line, opts)
641642

642643
{:identifier, reversed_post, rest} ->
643-
{rest, _} = strip_spaces(rest, 0)
644+
{keyword_key?, rest} =
645+
case rest do
646+
[?: | tail] when tail == [] or hd(tail) in @space ->
647+
{true, rest}
648+
649+
_ ->
650+
{rest, _} = strip_spaces(rest, 0)
651+
{false, rest}
652+
end
653+
644654
reversed = reversed_post ++ reversed_pre
645655

646656
case codepoint_cursor_context(reversed, opts) do
@@ -656,6 +666,9 @@ defmodule Code.Fragment do
656666
{{:dot, _, [_ | _]} = dot, offset} ->
657667
build_surround(dot, reversed, line, offset)
658668

669+
{{:local_or_var, acc}, offset} when keyword_key? ->
670+
build_surround({:key, acc}, reversed, line, offset)
671+
659672
{{:local_or_var, acc}, offset} when hd(rest) == ?( ->
660673
build_surround({:local_call, acc}, reversed, line, offset)
661674

lib/elixir/test/elixir/code_fragment_test.exs

+38
Original file line numberDiff line numberDiff line change
@@ -1110,6 +1110,44 @@ defmodule CodeFragmentTest do
11101110

11111111
assert CF.surround_context(":", {1, 1}) == :none
11121112
end
1113+
1114+
test "keyword keys" do
1115+
for i <- 2..4 do
1116+
assert CF.surround_context("[foo:", {1, i}) == %{
1117+
context: {:key, ~c"foo"},
1118+
begin: {1, 2},
1119+
end: {1, 5}
1120+
}
1121+
end
1122+
1123+
for i <- 10..12 do
1124+
assert CF.surround_context("[foo: 1, bar: 2]", {1, i}) == %{
1125+
context: {:key, ~c"bar"},
1126+
begin: {1, 10},
1127+
end: {1, 13}
1128+
}
1129+
end
1130+
1131+
assert CF.surround_context("if foo?, do: bar()", {1, 10}) == %{
1132+
context: {:key, ~c"do"},
1133+
begin: {1, 10},
1134+
end: {1, 12}
1135+
}
1136+
end
1137+
1138+
test "keyword false positives" do
1139+
assert CF.surround_context("<<foo::", {1, 3}) == %{
1140+
context: {:local_or_var, ~c"foo"},
1141+
begin: {1, 3},
1142+
end: {1, 6}
1143+
}
1144+
1145+
assert CF.surround_context("[foo :atom", {1, 2}) == %{
1146+
context: {:local_or_var, ~c"foo"},
1147+
begin: {1, 2},
1148+
end: {1, 5}
1149+
}
1150+
end
11131151
end
11141152

11151153
describe "container_cursor_to_quoted/2" do

0 commit comments

Comments
 (0)