Skip to content

Commit

Permalink
tests for then(& &1 $infix_op). fixed a bug when dividing by one?
Browse files Browse the repository at this point in the history
  • Loading branch information
novaugust committed Jan 26, 2024
1 parent 4fd18d3 commit 5e19efb
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 7 deletions.
16 changes: 12 additions & 4 deletions lib/style/pipes.ex
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ defmodule Styler.Style.Pipes do
@literal ~w(__block__ __aliases__ unquote)a
@value_constructors ~w(% %{} .. ..// <<>> @ {} ^ & fn from)a
@kernel_ops ~w(++ -- && || in - * + / > < <= >= == and or != !== === <>)a
@special_ops ~w(<- ||| &&& <<< >>> <<~ ~>> <~ ~> <~> <|> ^^^ ~~~)a
@special_ops ~w(<- ||| &&& <<< >>> <<~ ~>> <~ ~> <~>)a
@special_ops @literal ++ @value_constructors ++ @kernel_ops ++ @special_ops

def run({{:|>, _, _}, _} = zipper, ctx) do
Expand Down Expand Up @@ -152,8 +152,7 @@ defmodule Styler.Style.Pipes do

# a |> fun => a |> fun()
defp fix_pipe({:|>, m, [lhs, {fun, m2, nil}]}), do: {:|>, m, [lhs, {fun, m2, []}]}
# a |> then(&fun/1) |> c => a |> fun() |> c()
defp fix_pipe({:|>, m, [lhs, {:then, _, [{:&, _, [{:/, _, [{fun, m2, _}, _]}]}]}]}), do: {:|>, m, [lhs, {fun, m2, []}]}

# a |> then(&fun(&1, d)) |> c => a |> fun(d) |> c()
defp fix_pipe({:|>, m, [lhs, {:then, _, [{:&, _, [{fun, m2, [{:&, _, _} | args]}]}]}]} = pipe) do
rewrite = {fun, m2, args}
Expand All @@ -164,13 +163,22 @@ defmodule Styler.Style.Pipes do
pipe

fun in @special_ops ->
if fun in @kernel_ops, do: {:|>, m, [lhs, {{:., m2, [{:__aliases__, m2, [:Kernel]}, fun]}, m2, args}]}, else: pipe
# we only rewrite unary/infix operators if they're in the Kernel namespace.
# everything else stays as-is in the `then/2` because we can't know what module they're from
if fun in @kernel_ops,
do: {:|>, m, [lhs, {{:., m2, [{:__aliases__, m2, [:Kernel]}, fun]}, m2, args}]},
else: pipe

true ->
{:|>, m, [lhs, rewrite]}
end
end

# a |> then(&fun/1) |> c => a |> fun() |> c()
# recurses to add the `()` to `fun` as it gets unwound
defp fix_pipe({:|>, m, [lhs, {:then, _, [{:&, _, [{:/, _, [fun, {:__block__, _, [1]}]}]}]}]}),
do: fix_pipe({:|>, m, [lhs, fun]})

# Credo.Check.Readability.PipeIntoAnonymousFunctions
# rewrite anonymous function invocation to use `then/2`
# `a |> (& &1).() |> c()` => `a |> then(& &1) |> c()`
Expand Down
15 changes: 12 additions & 3 deletions test/style/pipes_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -500,17 +500,26 @@ defmodule Styler.Style.PipesTest do

test "rewrites then/2 when the passed function is a named function reference" do
assert_style "a |> then(&fun/1) |> c", "a |> fun() |> c()"
assert_style "a |> then(&(&1 / 1)) |> c", "a |> Kernel./(1) |> c()"
assert_style "a |> then(&DateTime.from_is8601/1) |> c", "a |> DateTime.from_is8601() |> c()"
assert_style "a |> then(&DateTime.from_is8601/1)", "DateTime.from_is8601(a)"
assert_style "a |> then(&fun(&1)) |> c", "a |> fun() |> c()"
assert_style "a |> then(&fun(&1, d)) |> c", "a |> fun(d) |> c()"
assert_style "a |> then(&fun(d, &1)) |> c()"
assert_style "a |> then(&fun(&1, d, %{foo: &1})) |> c()"

# Unary operators
# then + kernel ops
assert_style "a |> then(&(-&1)) |> c", "a |> Kernel.-() |> c()"
assert_style "a |> then(&(+&1)) |> c", "a |> Kernel.+() |> c()"

assert_style "a |> then(&fun(d, &1)) |> c()"
assert_style "a |> then(&fun(&1, d, %{foo: &1})) |> c()"
for op <- ~w(++ -- && || in - * + / > < <= >= == and or != !== === <>) do
assert_style "a |> then(&(&1 #{op} x)) |> c", "a |> Kernel.#{op}(x) |> c()"
end

# Doesn't rewrite non-kernel operators
for op <- ~w(<- ||| &&& <<< >>> <<~ ~>> <~ ~> <~>) do
assert_style "a |> then(&(&1 #{op} x)) |> c()"
end
end

test "adds parens to 1-arity pipes" do
Expand Down

0 comments on commit 5e19efb

Please sign in to comment.