Skip to content

Commit 84d8066

Browse files
authored
More precise error message when escaping a regex with a ref (#14560)
* More precise error message when escaping a regex with a ref * Refactor as do_quote_map_value * Yet another refactoring proposal
1 parent b1053b7 commit 84d8066

File tree

2 files changed

+24
-10
lines changed

2 files changed

+24
-10
lines changed

lib/elixir/src/elixir_quote.erl

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -164,15 +164,7 @@ do_escape(BitString, _) when is_bitstring(BitString) ->
164164
end;
165165

166166
do_escape(Map, Q) when is_map(Map) ->
167-
TT =
168-
[if
169-
is_reference(V) ->
170-
argument_error(<<('Elixir.Kernel':inspect(Map, []))/binary, " contains a reference (",
171-
('Elixir.Kernel':inspect(V, []))/binary, ") and therefore it cannot be escaped ",
172-
"(it must be defined within a function instead). ", (bad_escape_hint())/binary>>);
173-
true ->
174-
{do_quote(K, Q), do_quote(V, Q)}
175-
end || {K, V} <- lists:sort(maps:to_list(Map))],
167+
TT = [escape_map_key_value(K, V, Map, Q) || {K, V} <- lists:sort(maps:to_list(Map))],
176168
{'%{}', [], TT};
177169

178170
do_escape([], _) ->
@@ -206,6 +198,28 @@ do_escape(Fun, _) when is_function(Fun) ->
206198
do_escape(Other, _) ->
207199
bad_escape(Other).
208200

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

lib/elixir/test/elixir/macro_test.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ defmodule MacroTest do
143143

144144
test "inspects container when a reference cannot be escaped" do
145145
assert_raise ArgumentError, ~r"~r/foo/ contains a reference", fn ->
146-
Macro.escape(%{~r/foo/ | re_pattern: make_ref()})
146+
Macro.escape(%{~r/foo/ | re_pattern: {:re_pattern, 0, 0, 0, make_ref()}})
147147
end
148148
end
149149
end

0 commit comments

Comments
 (0)