Skip to content

Commit d3d83b1

Browse files
author
José Valim
committed
Merge pull request #1199 from alco/1148-match-tilde-op
Reimplement =~ to use Regex.match? or String.contains?
2 parents 78eb14e + 4a1dfcc commit d3d83b1

15 files changed

+152
-100
lines changed

lib/elixir/lib/kernel.ex

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2813,21 +2813,51 @@ defmodule Kernel do
28132813
defmacro left in right
28142814

28152815
@doc """
2816-
Matches the term on the left against the regular expression
2817-
on the right. It returns nil if not match happened or the
2818-
first match otherwise.
2816+
Matches the term on the left against the regular expression or string on the
2817+
right. Returns true if `left` matches `right` (if it's a regular expression)
2818+
or contains `right` (if it's a string).
28192819
28202820
## Examples
28212821
28222822
iex> "abcd" =~ %r/c(d)/
2823-
2
2823+
true
2824+
28242825
iex> "abcd" =~ %r/e/
2825-
nil
2826+
false
2827+
2828+
iex> "abcd" =~ "bc"
2829+
true
2830+
2831+
iex> "abcd" =~ "ad"
2832+
false
28262833
28272834
"""
2835+
# fast path for literal binaries
2836+
defmacro left =~ right when is_binary(right) do
2837+
quote do
2838+
String.contains?(unquote(left), unquote(right))
2839+
end
2840+
end
2841+
2842+
# fast path for literal binaries
2843+
defmacro left =~ ({:<<>>, _, [_bin]} = right) do
2844+
quote do
2845+
String.contains?(unquote(left), unquote(right))
2846+
end
2847+
end
2848+
2849+
# slow path for everything else
28282850
defmacro left =~ right do
28292851
quote do
2830-
Regex.index(unquote(right), unquote(left))
2852+
str = unquote(left)
2853+
case unquote(right) do
2854+
bin when is_binary(bin) ->
2855+
String.contains?(str, bin)
2856+
re when is_regex(re) ->
2857+
Regex.match?(re, str)
2858+
other ->
2859+
raise ArgumentError, message: "bad argument on the right side of =~: #{inspect other}"
2860+
end
28312861
end
28322862
end
28332863

lib/elixir/test/elixir/exception_test.exs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ defmodule Kernel.ExceptionTest do
3434
end
3535

3636
test :format_stacktrace_entry_with_fun do
37-
assert Exception.format_stacktrace_entry({fn(x) -> x end, [1], []}) =~ %r"\(1\)"
38-
assert Exception.format_stacktrace_entry({fn(x, y) -> { x, y } end, 2, []}) =~ %r"/2"
37+
assert Exception.format_stacktrace_entry({fn(x) -> x end, [1], []}) =~ %r/#Function<.+>\(1\)/
38+
assert Exception.format_stacktrace_entry({fn(x, y) -> { x, y } end, 2, []}) =~ %r"#Function<.+>/2"
3939
end
4040

4141
test :format_module_function_arity do

lib/elixir/test/elixir/hash_dict_test.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ defmodule HashDictTest do
165165
end
166166

167167
test :inspect do
168-
assert inspect(filled_dict(8)) =~ %r"#HashDict<"
168+
assert inspect(filled_dict(8)) =~ "#HashDict<"
169169
end
170170

171171
test :small_range_merge do

lib/elixir/test/elixir/kernel/warning_test.exs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ defmodule Kernel.WarningTest do
1212
def hello(arg), do: nil
1313
end
1414
"""
15-
end) =~ %r"variable arg is unused"
15+
end) =~ "variable arg is unused"
1616
after
1717
purge Sample
1818
end
@@ -24,7 +24,7 @@ defmodule Kernel.WarningTest do
2424
defp hello, do: nil
2525
end
2626
"""
27-
end) =~ %r"function hello/0 is unused"
27+
end) =~ "function hello/0 is unused"
2828

2929
assert capture_io(fn ->
3030
Code.eval_string """
@@ -33,7 +33,7 @@ defmodule Kernel.WarningTest do
3333
defp hello(1), do: :ok
3434
end
3535
"""
36-
end) =~ %r"function hello/1 is unused"
36+
end) =~ "function hello/1 is unused"
3737

3838
assert capture_io(fn ->
3939
Code.eval_string """
@@ -44,7 +44,7 @@ defmodule Kernel.WarningTest do
4444
defp d(x), do: x
4545
end
4646
"""
47-
end) =~ %r"function c/2 is unused"
47+
end) =~ "function c/2 is unused"
4848

4949
after
5050
purge [Sample1, Sample2, Sample3]
@@ -58,7 +58,7 @@ defmodule Kernel.WarningTest do
5858
defp b, do: a
5959
end
6060
"""
61-
end) =~ %r"function a/0 is unused"
61+
end) =~ "function a/0 is unused"
6262
after
6363
purge Sample
6464
end
@@ -70,7 +70,7 @@ defmodule Kernel.WarningTest do
7070
defmacrop hello, do: nil
7171
end
7272
"""
73-
end) =~ %r"macro hello/0 is unused"
73+
end) =~ "macro hello/0 is unused"
7474
after
7575
purge Sample
7676
end
@@ -83,7 +83,7 @@ defmodule Kernel.WarningTest do
8383
defp b(arg1 // 1, arg2 // 2, arg3 // 3), do: [arg1, arg2, arg3]
8484
end
8585
"""
86-
end) =~ %r"default arguments in b/3 are never used"
86+
end) =~ "default arguments in b/3 are never used"
8787

8888
assert capture_io(fn ->
8989
Code.eval_string """
@@ -92,7 +92,7 @@ defmodule Kernel.WarningTest do
9292
defp b(arg1 // 1, arg2 // 2, arg3 // 3), do: [arg1, arg2, arg3]
9393
end
9494
"""
95-
end) =~ %r"the first 2 default arguments in b/3 are never used"
95+
end) =~ "the first 2 default arguments in b/3 are never used"
9696

9797
assert capture_io(fn ->
9898
Code.eval_string """
@@ -101,7 +101,7 @@ defmodule Kernel.WarningTest do
101101
defp b(arg1 // 1, arg2 // 2, arg3 // 3), do: [arg1, arg2, arg3]
102102
end
103103
"""
104-
end) =~ %r"the first default argument in b/3 is never used"
104+
end) =~ "the first default argument in b/3 is never used"
105105

106106
assert capture_io(fn ->
107107
Code.eval_string """
@@ -127,7 +127,7 @@ defmodule Kernel.WarningTest do
127127
def a, do: nil
128128
end
129129
"""
130-
end) =~ %r"unused import Sample1"
130+
end) =~ "unused import Sample1"
131131
after
132132
purge [Sample1, Sample2]
133133
end
@@ -140,7 +140,7 @@ defmodule Kernel.WarningTest do
140140
def hello, do: nil
141141
end
142142
"""
143-
end) =~ %r"this clause cannot match because a previous clause at line 2 always matches"
143+
end) =~ "this clause cannot match because a previous clause at line 2 always matches"
144144
after
145145
purge Sample
146146
end
@@ -153,7 +153,7 @@ defmodule Kernel.WarningTest do
153153
def hello(arg // 0), do: nil
154154
end
155155
"""
156-
end) =~ %r"clause with defaults should be the first clause in def hello/1"
156+
end) =~ "clause with defaults should be the first clause in def hello/1"
157157
after
158158
purge Sample
159159
end
@@ -166,7 +166,7 @@ defmodule Kernel.WarningTest do
166166
def hello(arg // 1), do: nil
167167
end
168168
"""
169-
end) =~ %r"def hello/1 has default values and multiple clauses, use a separate clause for declaring defaults"
169+
end) =~ "def hello/1 has default values and multiple clauses, use a separate clause for declaring defaults"
170170
after
171171
purge Sample
172172
end
@@ -181,7 +181,7 @@ defmodule Kernel.WarningTest do
181181
def hello, do: :ok
182182
end
183183
"""
184-
end) =~ %r"function world/0 is unused"
184+
end) =~ "function world/0 is unused"
185185
after
186186
purge Sample
187187
end

lib/elixir/test/elixir/kernel_test.exs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,24 @@ defmodule KernelTest do
44
use ExUnit.Case, async: true
55

66
test :match do
7-
assert "abcd" =~ %r/c(d)/
8-
refute "abcd" =~ %r/e/
7+
assert ("abcd" =~ %r/c(d)/) == true
8+
assert ("abcd" =~ %r/e/) == false
9+
10+
string = "^ab+cd*$"
11+
assert (string =~ "ab+") == true
12+
assert (string =~ "bb") == false
13+
14+
assert_raise ArgumentError, "bad argument on the right side of =~: [\"^a\",\"*$\"]", fn ->
15+
string =~ ["^a", "*$"]
16+
end
17+
18+
assert_raise ArgumentError, "argument error", fn ->
19+
1234 =~ "hello"
20+
end
21+
22+
assert_raise ArgumentError, "argument error", fn ->
23+
1234 =~ %r"hello"
24+
end
925
end
1026

1127
test :nil? do

lib/elixir/test/elixir/regex_test.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ defmodule Regex.BinaryTest do
4040
end
4141

4242
test :unicode do
43-
assert ("josé" =~ %r"\p{Latin}$"u) == 3
43+
assert ("josé" =~ %r"\p{Latin}$"u)
4444
end
4545

4646
test :groups do

lib/ex_unit/test/ex_unit/cli_formatter_test.exs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ defmodule ExUnit.CLIFormatterTest do
2525
"""
2626

2727
out_put = exec_test("raising_test.exs")
28-
assert out_put =~ %r/stacktrace:/
29-
refute out_put =~ %r/ExUnit\.Runner/
28+
assert out_put =~ "stacktrace:"
29+
refute out_put =~ "ExUnit.Runner"
3030
after
3131
File.rm("raising_test.exs")
3232
end
@@ -44,7 +44,7 @@ defmodule ExUnit.CLIFormatterTest do
4444
"""
4545

4646
out_put = exec_test("failure_test.exs")
47-
assert out_put =~ %r/at failure_test.exs:6/
47+
assert out_put =~ "at failure_test.exs:6"
4848
after
4949
File.rm("failure_test.exs")
5050
end

lib/mix/test/mix/cli_test.exs

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ defmodule Mix.CLITest do
66
test "env" do
77
in_fixture "custom_mixfile", fn ->
88
env = System.cmd %b(MIX_ENV=prod #{elixir_executable} #{mix_executable} run "IO.puts Mix.env")
9-
assert env =~ %r"prod"
9+
assert env =~ "prod"
1010
end
1111
end
1212

1313
test "default task" do
1414
in_fixture "custom_mixfile", fn ->
1515
output = mix ""
1616
assert File.regular?("ebin/Elixir.A.beam")
17-
assert output =~ %r"Compiled lib/a.ex"
17+
assert output =~ "Compiled lib/a.ex"
1818
end
1919
end
2020

@@ -32,86 +32,86 @@ defmodule Mix.CLITest do
3232
assert File.regular?("ebin/Elixir.B.beam")
3333
assert File.regular?("ebin/Elixir.C.beam")
3434

35-
assert output =~ %r"Compiled lib/a\.ex"
35+
assert output =~ "Compiled lib/a.ex"
3636
end
3737
end
3838

3939
test "test smoke test" do
4040
in_fixture "custom_mixfile", fn ->
4141
output = mix "test"
4242
assert File.regular?("ebin/Elixir.A.beam")
43-
assert output =~ %r"1 tests, 0 failures"
43+
assert output =~ "1 tests, 0 failures"
4444

4545
output = mix "test test/hidden.ex --cover cover"
46-
assert output =~ %r"1 tests, 1 failures"
47-
assert output =~ %r"Generating cover results ... ok"
46+
assert output =~ "1 tests, 1 failures"
47+
assert output =~ "Generating cover results ... ok"
4848
assert File.regular?("cover/Elixir.A.html")
4949
end
5050
end
5151

5252
test "help smoke test" do
5353
in_fixture "only_mixfile", fn ->
5454
output = mix "help"
55-
assert output =~ %r"mix compile\s+# Compile source files"
56-
assert output =~ %r"mix hello\s+# Hello"
57-
refute output =~ %r"mix invalid"
55+
assert output =~ %r/mix compile\s+# Compile source files/
56+
assert output =~ %r/mix hello\s+# Hello/
57+
refute output =~ "mix invalid"
5858
end
5959
end
6060

6161
test "--help smoke test" do
6262
in_fixture "only_mixfile", fn ->
6363
output = mix "--help"
64-
assert output =~ %r"mix compile\s+# Compile source files"
65-
refute output =~ %r"mix invalid"
64+
assert output =~ %r/mix compile\s+# Compile source files/
65+
refute output =~ "mix invalid"
6666
end
6767
end
6868

6969
test "--version smoke test" do
7070
in_fixture "only_mixfile", fn ->
7171
output = mix "--version"
72-
assert output =~ %r"Elixir [0-9\.a-z]+"
73-
refute output =~ %r"Something silly"
72+
assert output =~ %r/Elixir [0-9\.a-z]+/
73+
refute output =~ "Something silly"
7474
end
7575
end
7676

7777
test "help TASK smoke test" do
7878
in_fixture "only_mixfile", fn ->
7979
output = mix "help compile"
80-
assert output =~ %r"# mix help compile"
81-
assert output =~ %r"## Command line options"
82-
assert output =~ %r"^Location:"m
80+
assert output =~ "# mix help compile"
81+
assert output =~ "## Command line options"
82+
assert output =~ %r/^Location:/m
8383
end
8484
end
8585

8686
test "do smoke test" do
8787
in_fixture "only_mixfile", fn ->
8888
output = mix "do compile --list, help compile"
89-
assert output =~ %r"# mix help compile"
90-
assert output =~ %r"mix compile.elixir #"
89+
assert output =~ "# mix help compile"
90+
assert output =~ "mix compile.elixir #"
9191
end
9292
end
9393

9494
test "new with tests smoke test" do
9595
in_tmp "new_with_tests", fn ->
9696
output = mix "new ."
97-
assert output =~ %r(\* creating lib/new_with_tests.ex)
97+
assert output =~ "* creating lib/new_with_tests.ex"
9898

9999
output = mix "test"
100100
assert File.regular?("ebin/Elixir.NewWithTests.beam")
101-
assert output =~ %r"1 tests, 0 failures"
101+
assert output =~ "1 tests, 0 failures"
102102
end
103103
end
104104

105105
test "new --sup with tests smoke test" do
106106
in_tmp "new_with_tests", fn ->
107107
output = mix "new . --sup"
108-
assert output =~ %r(\* creating lib/new_with_tests.ex)
109-
assert output =~ %r(\* creating lib/new_with_tests/supervisor.ex)
108+
assert output =~ "* creating lib/new_with_tests.ex"
109+
assert output =~ "* creating lib/new_with_tests/supervisor.ex"
110110

111111
output = mix "test"
112112
assert File.regular?("ebin/Elixir.NewWithTests.beam")
113-
assert output =~ %r"1 tests, 0 failures"
113+
assert output =~ "1 tests, 0 failures"
114114
end
115115
end
116116

117-
end
117+
end

0 commit comments

Comments
 (0)