Skip to content

Commit

Permalink
handle more false positive cases
Browse files Browse the repository at this point in the history
  • Loading branch information
novaugust committed Nov 7, 2024
1 parent 8063005 commit 9dc7364
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 63 deletions.
42 changes: 37 additions & 5 deletions lib/style/pipes.ex
Original file line number Diff line number Diff line change
Expand Up @@ -131,12 +131,44 @@ defmodule Styler.Style.Pipes do
end

# a(b |> c[, ...args])
# maybe pipeify it
# The first argument to a function-looking node is a pipe.
# Maybe pipe the whole thing?
def run({{f, m, [{:|>, _, _} = pipe | args]}, _} = zipper, ctx) do
if Enum.any?(args, &Style.do_block?/1) do
{:cont, zipper, ctx}
else
{:cont, Zipper.replace(zipper, {:|>, m, [pipe, {f, m, args}]}), ctx}
parent =
case Zipper.up(zipper) do
{{parent, _, _}, _} -> parent
_ -> nil
end

stringified = is_atom(f) && to_string(f)

cond do
# this is likely a macro
# assert a |> b() |> c()
!m[:closing] ->
{:cont, zipper, ctx}

# leave bools alone as they often read better coming first, like when prepended with `not`
# [not ]is_nil(a |> b() |> c())
stringified && (String.starts_with?(stringified, "is_") or String.ends_with?(stringified, "?")) ->
{:cont, zipper, ctx}

# string interpolation, module attribute assignment, or prettier bools with not
parent in [:"::", :@, :not] ->
{:cont, zipper, ctx}

# double down on being good to exunit macros, and any other special ops
# ..., do: assert(a |> b |> c)
# not (a |> b() |> c())
f in [:assert, :refute | @special_ops] ->
{:cont, zipper, ctx}

# if a |> b() |> c(), do: ...
Enum.any?(args, &Style.do_block?/1) ->
{:cont, zipper, ctx}

true ->
{:cont, Zipper.replace(zipper, {:|>, m, [pipe, {f, m, args}]}), ctx}
end
end

Expand Down
122 changes: 64 additions & 58 deletions test/style/pipes_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ defmodule Styler.Style.PipesTest do
y
end
a(foo(if_result), b)
if_result |> foo() |> a(b)
"""
)
end
Expand Down Expand Up @@ -853,79 +853,85 @@ defmodule Styler.Style.PipesTest do

test "optimizing" do
assert_style(
"""
a
|> Enum.map(fn b ->
c
# a comment
d
end)
|> Enum.join(x)
|> Enum.each(...)
""",
"""
a
|> Enum.map_join(x, fn b ->
c
# a comment
d
end)
|> Enum.each(...)
"""
"""
a
|> Enum.map(fn b ->
c
# a comment
d
end)
|> Enum.join(x)
|> Enum.each(...)
""",
"""
a
|> Enum.map_join(x, fn b ->
c
# a comment
d
end)
|> Enum.each(...)
"""
)

assert_style(
"""
a
|> Enum.map(fn b ->
c
# a comment
d
end)
|> Enum.into(x)
|> Enum.each(...)
""",
"""
a
|> Enum.into(x, fn b ->
c
# a comment
d
end)
|> Enum.each(...)
"""
"""
a
|> Enum.map(fn b ->
c
# a comment
d
end)
|> Enum.into(x)
|> Enum.each(...)
""",
"""
a
|> Enum.into(x, fn b ->
c
# a comment
d
end)
|> Enum.each(...)
"""
)

assert_style(
"""
a
|> Enum.map(fn b ->
c
# a comment
d
end)
|> Keyword.new()
|> Enum.each(...)
""",
"""
a
|> Keyword.new(fn b ->
c
# a comment
d
end)
|> Enum.each(...)
"""
"""
a
|> Enum.map(fn b ->
c
# a comment
d
end)
|> Keyword.new()
|> Enum.each(...)
""",
"""
a
|> Keyword.new(fn b ->
c
# a comment
d
end)
|> Enum.each(...)
"""
)
end
end

describe "pipifying" do
test "no false positives" do
pipe = "a() |> b() |> c()"
assert_style pipe
assert_style String.replace(pipe, " |>", "\n|>")
assert_style "fn -> #{pipe} end"
assert_style "if #{pipe}, do: ..."
assert_style "x\n\n#{pipe}"
assert_style "@moduledoc #{pipe}"
assert_style "!(#{pipe})"
assert_style "not foo(#{pipe})"
assert_style ~s<"\#{#{pipe}}">
end

test "pipifying" do
Expand Down

0 comments on commit 9dc7364

Please sign in to comment.