diff options
author | Cade Ward <cadebward+github@gmail.com> | 2019-10-16 08:22:20 -0600 |
---|---|---|
committer | Eric Meadows-Jönsson <eric.meadows.jonsson@gmail.com> | 2019-10-16 16:22:20 +0200 |
commit | 1ae0e436f7b389a8009ce6d60eb5b9ef14745bc2 (patch) | |
tree | 492f23834f2db53b12bc0b5e332815de198fc376 | |
parent | 706b3b122f6b4c226593595d2df3ca9db2c06f0a (diff) | |
download | elixir-1ae0e436f7b389a8009ce6d60eb5b9ef14745bc2.tar.gz |
Add guard to String.replace/4 for better error messages (#9398)
-rw-r--r-- | lib/elixir/lib/string.ex | 27 | ||||
-rw-r--r-- | lib/elixir/test/elixir/string_test.exs | 8 |
2 files changed, 23 insertions, 12 deletions
diff --git a/lib/elixir/lib/string.ex b/lib/elixir/lib/string.ex index 578eaee0a..43c396836 100644 --- a/lib/elixir/lib/string.ex +++ b/lib/elixir/lib/string.ex @@ -1381,35 +1381,38 @@ defmodule String do """ @spec replace(t, pattern | Regex.t(), t | (t -> t | iodata), keyword) :: t def replace(subject, pattern, replacement, options \\ []) + when is_binary(subject) and + (is_binary(replacement) or is_function(replacement, 1)) and + is_list(options) do + replace_guarded(subject, pattern, replacement, options) + end - def replace(subject, %{__struct__: Regex} = regex, replacement, options) - when is_binary(replacement) or is_function(replacement, 1) do + defp replace_guarded(subject, %{__struct__: Regex} = regex, replacement, options) do Regex.replace(regex, subject, replacement, options) end - def replace(subject, "", "", _) when is_binary(subject) do + defp replace_guarded(subject, "", "", _) do subject end - def replace(subject, "", replacement, options) - when is_binary(subject) and is_binary(replacement) do + defp replace_guarded(subject, "", replacement_binary, options) + when is_binary(replacement_binary) do if Keyword.get(options, :global, true) do - IO.iodata_to_binary([replacement | intersperse_bin(subject, replacement)]) + IO.iodata_to_binary([replacement_binary | intersperse_bin(subject, replacement_binary)]) else - replacement <> subject + replacement_binary <> subject end end - def replace(subject, "", replacement, options) - when is_binary(subject) and is_function(replacement, 1) do + defp replace_guarded(subject, "", replacement_fun, options) do if Keyword.get(options, :global, true) do - IO.iodata_to_binary([replacement.("") | intersperse_fun(subject, replacement)]) + IO.iodata_to_binary([replacement_fun.("") | intersperse_fun(subject, replacement_fun)]) else - IO.iodata_to_binary([replacement.("") | subject]) + IO.iodata_to_binary([replacement_fun.("") | subject]) end end - def replace(subject, pattern, replacement, options) when is_binary(subject) do + defp replace_guarded(subject, pattern, replacement, options) do if insert = Keyword.get(options, :insert_replaced) do IO.warn( "String.replace/4 with :insert_replaced option is deprecated. " <> diff --git a/lib/elixir/test/elixir/string_test.exs b/lib/elixir/test/elixir/string_test.exs index dcd1231a3..012a0cee4 100644 --- a/lib/elixir/test/elixir/string_test.exs +++ b/lib/elixir/test/elixir/string_test.exs @@ -446,6 +446,14 @@ defmodule StringTest do end end + describe "replace/4" do + test "with incorrect params" do + assert_raise FunctionClauseError, "no function clause matching in String.replace/4", fn -> + String.replace("a,b,c", "a,b,c", ",", "") + end + end + end + test "duplicate/2" do assert String.duplicate("abc", 0) == "" assert String.duplicate("abc", 1) == "abc" |