Skip to content

Commit 2cc4fd2

Browse files
author
José Valim
committed
Deprecate is_regex/1 and is_range/1
Conflicts: lib/elixir/lib/string.ex
1 parent 4637b57 commit 2cc4fd2

File tree

11 files changed

+105
-77
lines changed

11 files changed

+105
-77
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
* Deprecations
99
* [Kernel] `%` for sigils is deprecated in favor of `~`
10+
* [Kernel] `is_range/1` and `is_regex/1` are deprecated in favor of `Range.range?/1` and `Regex.regex?/1`
1011

1112
* Backwards incompatible changes
1213

lib/elixir/lib/kernel.ex

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1739,23 +1739,19 @@ defmodule Kernel do
17391739
end
17401740
end
17411741

1742-
@doc """
1743-
Checks if the given argument is a regex.
1744-
1745-
Works in guard clauses.
1746-
"""
1742+
@doc false
17471743
defmacro is_regex(thing) do
1744+
IO.puts :stderr, "is_regex/1 is deprecated in favor of Regex.regex?/1\n" <>
1745+
Exception.format_stacktrace(__CALLER__.stacktrace)
17481746
quote do
17491747
Kernel.is_record(unquote(thing), Regex)
17501748
end
17511749
end
17521750

1753-
@doc """
1754-
Checks if the given argument is a range.
1755-
1756-
Works in guard clauses.
1757-
"""
1751+
@doc false
17581752
defmacro is_range(thing) do
1753+
IO.puts :stderr, "is_range/1 is deprecated in favor of Range.range?/1\n" <>
1754+
Exception.format_stacktrace(__CALLER__.stacktrace)
17591755
quote do
17601756
Kernel.is_record(unquote(thing), Range)
17611757
end

lib/elixir/lib/range.ex

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,20 @@ defmodule Range do
2626
def last({ Range, _, last }) do
2727
last
2828
end
29+
30+
@doc """
31+
Returns true if the given argument is a range.
32+
33+
## Examples
34+
35+
iex> Range.range?(1..3)
36+
true
37+
iex> Range.range?(0)
38+
false
39+
40+
"""
41+
def range?({ Range, _, _ }), do: true
42+
def range?(_), do: false
2943
end
3044

3145
defprotocol Range.Iterator do

lib/elixir/lib/regex.ex

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,20 @@ defmodule Regex do
120120
:re.run(string, compiled, [{ :capture, :none }]) == :match
121121
end
122122

123+
@doc """
124+
Returns true if the given argument is a regex.
125+
126+
## Examples
127+
128+
iex> Regex.regex?(~r/foo/)
129+
true
130+
iex> Regex.regex?(0)
131+
false
132+
133+
"""
134+
def regex?(regex()), do: true
135+
def regex?(_), do: false
136+
123137
@doc """
124138
Runs the regular expression against the given string until the first match.
125139
It returns a list with all captures or `nil` if no match occurred.

lib/elixir/lib/string.ex

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -224,18 +224,18 @@ defmodule String do
224224

225225
def split(binary, "", options), do: split(binary, ~r"", options)
226226

227-
def split(binary, pattern, options) when is_regex(pattern) do
228-
Regex.split(pattern, binary, options)
229-
end
230-
231227
def split(binary, pattern, options) do
232-
opts = if options[:global] != false, do: [:global], else: []
233-
splits = :binary.split(binary, pattern, opts)
234-
235-
if Keyword.get(options, :trim, false) do
236-
lc split inlist splits, split != "", do: split
228+
if Regex.regex?(pattern) do
229+
Regex.split(pattern, binary, options)
237230
else
238-
splits
231+
opts = if options[:global] != false, do: [:global], else: []
232+
splits = :binary.split(binary, pattern, opts)
233+
234+
if Keyword.get(options, :trim, false) do
235+
lc split inlist splits, split != "", do: split
236+
else
237+
splits
238+
end
239239
end
240240
end
241241

@@ -521,13 +521,13 @@ defmodule String do
521521

522522
def replace(subject, pattern, replacement, options \\ [])
523523

524-
def replace(subject, pattern, replacement, options) when is_regex(pattern) do
525-
Regex.replace(pattern, subject, replacement, global: options[:global])
526-
end
527-
528524
def replace(subject, pattern, replacement, options) do
529-
opts = translate_replace_options(options)
530-
:binary.replace(subject, pattern, replacement, opts)
525+
if Regex.regex?(pattern) do
526+
Regex.replace(pattern, subject, replacement, global: options[:global])
527+
else
528+
opts = translate_replace_options(options)
529+
:binary.replace(subject, pattern, replacement, opts)
530+
end
531531
end
532532

533533
defp translate_replace_options(options) do

lib/elixir/test/doc_test.exs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ defmodule KernelTest do
2222
doctest OptionParser
2323
doctest Path
2424
doctest Protocol.Consolidation
25+
doctest Range
2526
doctest Regex
2627
doctest Set
2728
doctest Stream

lib/elixir/test/elixir/range_test.exs

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ defmodule RangeTest do
2121
assert (1..3).last == 3
2222
end
2323

24-
test :is_range do
25-
assert is_range(range)
26-
refute is_range(not_range)
24+
test :range? do
25+
assert Range.range?(1..3)
26+
refute Range.range?(0)
2727
end
2828

2929
test :enum do
@@ -46,12 +46,4 @@ defmodule RangeTest do
4646
assert inspect(1..3) == "1..3"
4747
assert inspect(3..1) == "3..1"
4848
end
49-
50-
defp range do
51-
1..3
52-
end
53-
54-
defp not_range do
55-
1
56-
end
5749
end

lib/elixir/test/elixir/regex_test.exs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ defmodule RegexTest do
1717
end
1818

1919
test :compile! do
20-
assert is_record(Regex.compile!("foo"), Regex)
21-
assert is_regex(Regex.compile!("foo"))
20+
assert Regex.regex?(Regex.compile!("foo"))
2221

2322
assert_raise Regex.CompileError, ~r/position 0$/, fn ->
2423
Regex.compile!("*foo")
@@ -27,7 +26,7 @@ defmodule RegexTest do
2726

2827
test :compile do
2928
{ :ok, regex } = Regex.compile("foo")
30-
assert is_regex(regex)
29+
assert Regex.regex?(regex)
3130
assert { :error, _ } = Regex.compile("*foo")
3231
assert { :error, _ } = Regex.compile("foo", "y")
3332
end
@@ -37,6 +36,11 @@ defmodule RegexTest do
3736
assert "foo\nbar" =~ regex
3837
end
3938

39+
test :regex? do
40+
assert Regex.regex?(~r/foo/)
41+
refute Regex.regex?(0)
42+
end
43+
4044
test :source do
4145
assert Regex.source(Regex.compile!("foo")) == "foo"
4246
end

lib/ex_unit/lib/ex_unit/assertions.ex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -332,9 +332,9 @@ defmodule ExUnit.Assertions do
332332
def assert_raise(exception, message, function) when is_function(function) do
333333
error = assert_raise(exception, function)
334334

335-
is_match = case message do
336-
re when is_regex(re) -> error.message =~ re
337-
bin when is_binary(bin) -> error.message == bin
335+
is_match = cond do
336+
is_binary(message) -> error.message == message
337+
Regex.regex?(message) -> error.message =~ message
338338
end
339339

340340
assert is_match, message, error.message,

lib/mix/lib/mix/deps/loader.ex

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -55,44 +55,41 @@ defmodule Mix.Deps.Loader do
5555
"""
5656
def vsn_match?(nil, _actual, _app),
5757
do: true
58-
def vsn_match?(req, actual, _app) when is_regex(req),
59-
do: actual =~ req
6058
def vsn_match?(req, actual, app) do
61-
case Version.parse(actual) do
62-
{ :ok, version } ->
63-
case Version.parse_requirement(req) do
64-
{ :ok, req } ->
65-
Version.match?(version, req)
66-
:error ->
67-
raise Mix.Error, message: "Invalid requirement #{req} for app #{app}"
68-
end
69-
70-
:error ->
71-
raise Mix.Error, message: "The application #{app} specified a non Semantic Version #{actual}. " <>
72-
"Mix can only match the requirement #{req} against Semantic Versions, to match against any " <>
73-
"version, please use a regex as requirement"
59+
if Regex.regex?(req) do
60+
actual =~ req
61+
else
62+
case Version.parse(actual) do
63+
{ :ok, version } ->
64+
case Version.parse_requirement(req) do
65+
{ :ok, req } ->
66+
Version.match?(version, req)
67+
:error ->
68+
raise Mix.Error, message: "Invalid requirement #{req} for app #{app}"
69+
end
70+
71+
:error ->
72+
raise Mix.Error, message: "The application #{app} specified a non Semantic Version #{actual}. " <>
73+
"Mix can only match the requirement #{req} against Semantic Versions, to match against any " <>
74+
"version, please use a regex as requirement"
75+
end
7476
end
7577
end
7678

7779
## Helpers
7880

7981
defp to_dep(tuple, scms, from, manager \\ nil) do
80-
dep = with_scm_and_app(tuple, scms).from(from).manager(manager)
81-
82-
if match?({ _, req, _ } when is_regex(req), tuple) and
83-
not String.ends_with?(from, "rebar.config") do
84-
invalid_dep_format(tuple)
85-
end
86-
87-
dep
82+
with_scm_and_app(tuple, scms).from(from).manager(manager)
8883
end
8984

9085
defp with_scm_and_app({ app, opts }, scms) when is_atom(app) and is_list(opts) do
9186
with_scm_and_app({ app, nil, opts }, scms)
9287
end
9388

94-
defp with_scm_and_app({ app, req, opts }, scms) when is_atom(app) and
95-
(is_binary(req) or is_regex(req) or req == nil) and is_list(opts) do
89+
defp with_scm_and_app({ app, req, opts } = other, scms) when is_atom(app) and is_list(opts) do
90+
unless is_binary(req) or Regex.regex?(req) or nil?(req) do
91+
invalid_dep_format(other)
92+
end
9693

9794
dest = Path.join(Mix.Project.deps_path, app)
9895
build = Path.join([Mix.Project.build_path, "lib", app])
@@ -148,8 +145,16 @@ defmodule Mix.Deps.Loader do
148145
end
149146

150147
defp invalid_dep_format(dep) do
151-
raise Mix.Error, message: ~s(Dependency specified in the wrong format: #{inspect dep}, ) <>
152-
~s(expected { app :: atom, opts :: Keyword.t } | { app :: atom, requirement :: String.t, opts :: Keyword.t })
148+
raise Mix.Error, message: """
149+
Dependency specified in the wrong format:
150+
151+
#{inspect dep}
152+
153+
Expected:
154+
155+
{ app :: atom, opts :: Keyword.t } |
156+
{ app :: atom, requirement :: String.t | regex, opts :: Keyword.t }
157+
"""
153158
end
154159

155160
## Fetching

0 commit comments

Comments
 (0)