Skip to content

Commit

Permalink
fix range parsing for non-trival ranges (Closes #119)
Browse files Browse the repository at this point in the history
  • Loading branch information
novaugust committed Jan 18, 2024
1 parent df7b97e commit 7ce6b8a
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 54 deletions.
14 changes: 7 additions & 7 deletions lib/style/deprecations.ex
Original file line number Diff line number Diff line change
Expand Up @@ -65,19 +65,19 @@ defmodule Styler.Style.Deprecations do
# silences "function is unused warnings" on ex < 1.16
if Version.match?(System.version(), ">= 1.16.0-dev") do
defp add_step_to_decreasing_range({:.., rm, [first, {_, lm, _} = last]} = range) do
start = extract_value_from_range(first)
stop = extract_value_from_range(last)

if start > stop do
with {:ok, start} <- extract_value_from_range(first),
{:ok, stop} <- extract_value_from_range(last),
true <- start > stop do
step = {:__block__, [token: "1", line: lm[:line]], [1]}
{:"..//", rm, [first, last, step]}
else
range
_ -> range
end
end

# Extracts the positive or negative integer from the given range block
defp extract_value_from_range({:__block__, _, [value]}), do: value
defp extract_value_from_range({:-, _, [{:__block__, _, [value]}]}), do: -value
defp extract_value_from_range({:__block__, _, [value]}) when is_integer(value), do: {:ok, value}
defp extract_value_from_range({:-, _, [{:__block__, _, [value]}]}) when is_integer(value), do: {:ok, -value}
defp extract_value_from_range(_), do: :non_int
end
end
66 changes: 19 additions & 47 deletions test/style/deprecations_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -48,53 +48,25 @@ defmodule Styler.Style.DeprecationsTest do
)
end

test "negative steps with Enum.slice/2" do
assert_style("Enum.slice([1, 2, 3, 4], 1..-2)", "Enum.slice([1, 2, 3, 4], 1..-2//1)")
assert_style("Enum.slice([1, 2, 3, 4], -1..-2)", "Enum.slice([1, 2, 3, 4], -1..-2//1)")
assert_style("Enum.slice([1, 2, 3, 4], 2..1)", "Enum.slice([1, 2, 3, 4], 2..1//1)")
assert_style("Enum.slice([1, 2, 3, 4, 5], 1..3)", "Enum.slice([1, 2, 3, 4, 5], 1..3)")

assert_style(
"enumerable |> Enum.map(& &1) |> Enum.slice(1..-2)",
"enumerable |> Enum.map(& &1) |> Enum.slice(1..-2//1)"
)

assert_style(
"enumerable |> Enum.map(& &1) |> Enum.slice(-1..-2)",
"enumerable |> Enum.map(& &1) |> Enum.slice(-1..-2//1)"
)

assert_style(
"enumerable |> Enum.map(& &1) |> Enum.slice(2..1)",
"enumerable |> Enum.map(& &1) |> Enum.slice(2..1//1)"
)

assert_style(
"enumerable |> Enum.map(& &1) |> Enum.slice(1..3)",
"enumerable |> Enum.map(& &1) |> Enum.slice(1..3)"
)
end

test "negative steps with String.slice/2" do
assert_style(~s|String.slice("elixir", 2..-1)|, ~s|String.slice("elixir", 2..-1//1)|)
assert_style(~s|String.slice("elixir", 1..-2)|, ~s|String.slice("elixir", 1..-2//1)|)
assert_style(~s|String.slice("elixir", -4..-1)|)
assert_style(~s|String.slice("elixir", ..)|)
assert_style(~s|String.slice("elixir", 0..-1//2)|)

assert_style(
~s{"ELIXIR" |> String.downcase() |> String.slice(2..-1)},
~s{"ELIXIR" |> String.downcase() |> String.slice(2..-1//1)}
)

assert_style(
~s{"ELIXIR" |> String.downcase() |> String.slice(1..-2)},
~s{"ELIXIR" |> String.downcase() |> String.slice(1..-2//1)}
)

assert_style(~s{"ELIXIR" |> String.downcase() |> String.slice(-4..-1)})
assert_style(~s{"ELIXIR" |> String.downcase() |> String.slice(..)})
assert_style(~s{"ELIXIR" |> String.downcase() |> String.slice(0..-1//2)})
test "negative steps with [Enum|String].slice/2" do
for mod <- ~w(Enum String) do
assert_style("#{mod}.slice(x, 1..-2)", "#{mod}.slice(x, 1..-2//1)")
assert_style("#{mod}.slice(x, -1..-2)", "#{mod}.slice(x, -1..-2//1)")
assert_style("#{mod}.slice(x, 2..1)", "#{mod}.slice(x, 2..1//1)")
assert_style("#{mod}.slice(x, 1..3)")
assert_style("#{mod}.slice(x, ..)")

# piped
assert_style("foo |> bar() |> #{mod}.slice(1..-2)", "foo |> bar() |> #{mod}.slice(1..-2//1)")
assert_style("foo |> bar() |> #{mod}.slice(-1..-2)", "foo |> bar() |> #{mod}.slice(-1..-2//1)")
assert_style("foo |> bar() |> #{mod}.slice(2..1)", "foo |> bar() |> #{mod}.slice(2..1//1)")
assert_style("foo |> bar() |> #{mod}.slice(1..3)")

# non-trivial ranges
assert_style "#{mod}.slice(x, y..z)"
assert_style "#{mod}.slice(x, (y - 1)..f)"
assert_style("foo |> bar() |> #{mod}.slice(x..y)")
end
end
end
end

0 comments on commit 7ce6b8a

Please sign in to comment.