Skip to content

Commit ae160d7

Browse files
committed
More precise error message when escaping a regex with a ref (elixir-lang#14560)
1 parent f76dc86 commit ae160d7

File tree

1 file changed

+24
-9
lines changed

1 file changed

+24
-9
lines changed

lib/elixir/src/elixir_quote.erl

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -160,15 +160,7 @@ do_escape(BitString, _) when is_bitstring(BitString) ->
160160
end;
161161

162162
do_escape(Map, Q) when is_map(Map) ->
163-
TT =
164-
[if
165-
?OTP_RELEASE >= 28, is_reference(V) ->
166-
argument_error(<<('Elixir.Kernel':inspect(Map, []))/binary, " contains a reference (",
167-
('Elixir.Kernel':inspect(V, []))/binary, ") and therefore it cannot be escaped ",
168-
"(it must be defined within a function instead). ", (bad_escape_hint())/binary>>);
169-
true ->
170-
{do_quote(K, Q), do_quote(V, Q)}
171-
end || {K, V} <- lists:sort(maps:to_list(Map))],
163+
TT = [escape_map_key_value(K, V, Map, Q) || {K, V} <- lists:sort(maps:to_list(Map))],
172164
{'%{}', [], TT};
173165

174166
do_escape([], _) ->
@@ -202,6 +194,29 @@ do_escape(Fun, _) when is_function(Fun) ->
202194
do_escape(Other, _) ->
203195
bad_escape(Other).
204196

197+
escape_map_key_value(K, V, Map, Q) ->
198+
MaybeRef = if
199+
?OTP_RELEASE < 28 -> nil;
200+
is_reference(V) -> V;
201+
is_tuple(V) -> find_tuple_ref(V, 1);
202+
true -> nil
203+
end,
204+
if
205+
is_reference(MaybeRef) ->
206+
argument_error(<<('Elixir.Kernel':inspect(Map, []))/binary, " contains a reference (",
207+
('Elixir.Kernel':inspect(MaybeRef, []))/binary, ") and therefore it cannot be escaped ",
208+
"(it must be defined within a function instead). ", (bad_escape_hint())/binary>>);
209+
true ->
210+
{do_quote(K, Q), do_quote(V, Q)}
211+
end.
212+
213+
find_tuple_ref(Tuple, Index) when Index > tuple_size(Tuple) -> nil;
214+
find_tuple_ref(Tuple, Index) ->
215+
case element(Index, Tuple) of
216+
Ref when is_reference(Ref) -> Ref;
217+
_ -> find_tuple_ref(Tuple, Index + 1)
218+
end.
219+
205220
bad_escape(Arg) ->
206221
argument_error(<<"cannot escape ", ('Elixir.Kernel':inspect(Arg, []))/binary, ". ",
207222
(bad_escape_hint())/binary>>).

0 commit comments

Comments
 (0)