Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion lib/elixir/lib/regex.ex
Original file line number Diff line number Diff line change
Expand Up @@ -1008,6 +1008,9 @@ defmodule Regex do

pattern_ast =
cond do
is_nil(regex.re_pattern) ->
nil

# TODO: Remove this when we require Erlang/OTP 28+
# Before OTP 28.0, patterns did not contain any refs and could be safely be escaped
:erlang.system_info(:otp_release) < [?2, ?8] ->
Expand All @@ -1018,7 +1021,8 @@ defmodule Regex do
{:ok, exported} = :re.compile(regex.source, [:export] ++ regex.opts)

quote do
:re.import(unquote(Macro.escape(exported)))
require Regex
Regex.__import_pattern__(unquote(Macro.escape(exported)))
end

# TODO: Remove this when we require Erlang/OTP 28.1+
Expand All @@ -1041,4 +1045,15 @@ defmodule Regex do
}
end
end

@doc false
defmacro __import_pattern__(pattern) do
if __CALLER__.context in [:match, :guard] do
raise ArgumentError, "escaped"
end

quote do
:re.import(unquote(pattern))
end
end
end
10 changes: 8 additions & 2 deletions lib/elixir/test/elixir/macro_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,14 @@ defmodule MacroTest do
[],
[
__struct__: Regex,
re_pattern:
{{:., [], [:re, :import]}, [], [{:{}, [], [:re_exported_pattern | _]}]},
re_pattern: {
:__block__,
[],
[
{:__assert_assert_no_match_or_guard_scope__, _, _},
{{:., [], [:re, :import]}, [], [{:{}, [], [:re_exported_pattern | _]}]}
]
},
source: "foo",
opts: []
]
Expand Down
19 changes: 19 additions & 0 deletions lib/elixir/test/elixir/regex_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,25 @@ defmodule RegexTest do
end
end

@tag :re_import
test "module attribute in match context" do
assert_raise(
ArgumentError,
~r/invalid expression in match, an escaped Regex is not allowed in patterns such as function clauses/,
fn ->
Code.eval_quoted(
quote do
defmodule ModAttrGuard do
@regex ~r/example/
def example?(@regex), do: true
def example?(_), do: false
end
end
)
end
)
end

test "multiline" do
refute Regex.match?(~r/^b$/, "a\nb\nc")
assert Regex.match?(~r/^b$/m, "a\nb\nc")
Expand Down
Loading