diff options
author | José Valim <jose.valim@gmail.com> | 2015-09-27 18:04:56 +0200 |
---|---|---|
committer | José Valim <jose.valim@gmail.com> | 2015-09-27 18:04:56 +0200 |
commit | 31d6fbf3b75bcabb2a31e6d5f7ce3a26d6ba7a91 (patch) | |
tree | efe44da353378600db0ee984b78c07969618a581 | |
parent | 835f8b974dfcf4507f11d7401e58567f611894c9 (diff) | |
parent | 31a30afafdf5b82c086bd91efaa879ba3397ad75 (diff) | |
download | elixir-31d6fbf3b75bcabb2a31e6d5f7ce3a26d6ba7a91.tar.gz |
Merge pull request #3783 from eksperimental/fix_range_integer2
Fix Range validation
-rw-r--r-- | lib/elixir/lib/kernel.ex | 8 | ||||
-rw-r--r-- | lib/elixir/lib/range.ex | 19 | ||||
-rw-r--r-- | lib/elixir/test/elixir/range_test.exs | 11 |
3 files changed, 30 insertions, 8 deletions
diff --git a/lib/elixir/lib/kernel.ex b/lib/elixir/lib/kernel.ex index 7ed359af6..38af77415 100644 --- a/lib/elixir/lib/kernel.ex +++ b/lib/elixir/lib/kernel.ex @@ -2444,16 +2444,18 @@ defmodule Kernel do defmacro first .. last do case is_float(first) or is_float(last) or is_atom(first) or is_atom(last) or - is_binary(first) or is_binary(last) do + is_binary(first) or is_binary(last) or + is_list(first) or is_list(last) do true -> raise ArgumentError, - "ranges (left .. right) expect both sides to be integers, " <> + "ranges (first .. last) expect both sides to be integers, " <> "got: #{Macro.to_string({:.., [], [first, last]})}" false -> {:%{}, [], [__struct__: Elixir.Range, first: first, last: last]} end end + @doc """ Provides a short-circuit operator that evaluates and returns the second expression only if the first one evaluates to `true` @@ -2677,7 +2679,7 @@ defmodule Kernel do {:%{}, [], [__struct__: Elixir.Range, first: first, last: last]} -> in_range(left, Macro.expand(first, __CALLER__), Macro.expand(last, __CALLER__)) _ -> - raise ArgumentError, <<"invalid args for operator in, it expects a compile time list ", + raise ArgumentError, <<"invalid args for operator \"in\", it expects a compile time list ", "or range on the right side when used in guard expressions, got: ", Macro.to_string(right) :: binary>> end diff --git a/lib/elixir/lib/range.ex b/lib/elixir/lib/range.ex index 0f34001aa..4d4a7cf68 100644 --- a/lib/elixir/lib/range.ex +++ b/lib/elixir/lib/range.ex @@ -31,12 +31,13 @@ defmodule Range do @doc """ Creates a new range. """ - def new(first, last) do + @spec new(integer, integer) :: t + def new(first, last) when is_integer(first) and is_integer(last) do %Range{first: first, last: last} end @doc """ - Returns `true` if the given argument is a range. + Returns `true` if the given `term` is a range. ## Examples @@ -47,6 +48,12 @@ defmodule Range do false """ + # @spec range?(term) :: boolean + @spec range?(arg) :: false when arg: %Range{first: nil, last: nil} + @spec range?(arg) :: true when arg: %Range{} + @spec range?(term) :: false + def range?(term) + def range?(%Range{first: nil, last: nil}), do: false def range?(%Range{}), do: true def range?(_), do: false end @@ -95,10 +102,14 @@ defimpl Enumerable, for: Range do end end - defp validate_range!(first, last) when is_integer(first) and is_integer(last), do: :ok + defp validate_range!(first, last) when is_integer(first) + and is_integer(last), + do: :ok + defp validate_range!(first, last) do raise ArgumentError, - "ranges (left .. right) expect both sides to be integers, got: #{inspect first..last}" + "ranges (first .. last) expect both sides to be integers, " <> + "got: #{Macro.to_string({:.., [], [first, last]})}" end end diff --git a/lib/elixir/test/elixir/range_test.exs b/lib/elixir/test/elixir/range_test.exs index 924644e22..d25883ba3 100644 --- a/lib/elixir/test/elixir/range_test.exs +++ b/lib/elixir/test/elixir/range_test.exs @@ -42,9 +42,18 @@ defmodule RangeTest do test "integer only" do x = 1.0 y = 3.0 - message = "ranges (left .. right) expect both sides to be integers, got: 1.0..3.0" + message = "ranges (first .. last) expect both sides to be integers, got: 1.0..3.0" assert_raise ArgumentError, message, fn -> Enum.map(x..y, &(&1 * 2)) end + + first = [] + last = [] + message = "ranges (first .. last) expect both sides to be integers, got: []..[]" + assert_raise ArgumentError, message, fn -> + first..last + Enum.map(first..last, &(&1)) + end + end end |