diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d2851e8..f2706c87 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ ### Improvements * auto-fix `Credo.Check.Refactor.CondStatements`, detects any truthy atom, not just `true` +* if/unless rewrites: + - `Credo.Check.Refactor.NegatedConditionsWithElse` + - `Credo.Check.Refactor.NegatedConditionsInUnless` + - `Credo.Check.Refactor.UnlessWithElse` ## v0.9.0 diff --git a/README.md b/README.md index 367e0d4d..86eec936 100644 --- a/README.md +++ b/README.md @@ -68,8 +68,11 @@ Some of the rules have `priority: :high`, meaning Credo runs them unless you exp | `Credo.Check.Refactor.FilterCount` | in pipes only | | `Credo.Check.Refactor.MapInto` | in pipes only | | `Credo.Check.Refactor.MapJoin` | in pipes only | +| `Credo.Check.Refactor.NegatedConditionsInUnless` | | +| `Credo.Check.Refactor.NegatedConditionsWithElse` | | | `Credo.Check.Refactor.PipeChainStart` | allows ecto's `from`| | `Credo.Check.Refactor.RedundantWithClauseResult` | | +| `Credo.Check.Refactor.UnlessWithElse` | | | `Credo.Check.Refactor.WithClauses` | | ## Your first Styling diff --git a/lib/style/single_node.ex b/lib/style/single_node.ex index 997eac08..7cb9a3f9 100644 --- a/lib/style/single_node.ex +++ b/lib/style/single_node.ex @@ -212,6 +212,23 @@ defmodule Styler.Style.SingleNode do defp style({:case, cm, [head, [{do_, arrows}]]}), do: {:case, cm, [head, [{do_, rewrite_arrows(arrows)}]]} defp style({:fn, m, arrows}), do: {:fn, m, rewrite_arrows(arrows)} + # Credo.Check.Refactor.UnlessWithElse + # if adding a negation to the if is incorrect, we'll remove it on the recurse =) + defp style({:unless, m, [{_, hm, _} = head, [{do_block, do_body}, {else_block, else_body}]]}) do + style({:if, m, [{:!, hm, [head]}, [{do_block, else_body}, {else_block, do_body}]]}) + end + + # Credo.Check.Refactor.NegatedConditionsInUnless + defp style({:unless, m, [{negator, _, [expr]}, [{do_block, do_body}]]}) when negator in [:!, :not] do + style({:if, m, [expr, [{do_block, do_body}]]}) + end + + # Credo.Check.Refactor.NegatedConditionsWithElse + defp style({:if, m, [{negator, _, [expr]}, [{do_block, do_body}, {else_block, else_body}]]}) + when negator in [:!, :not] do + style({:if, m, [expr, [{do_block, else_body}, {else_block, do_body}]]}) + end + defp style(node), do: node defp rewrite_arrows(arrows) when is_list(arrows), diff --git a/test/style/single_node_test.exs b/test/style/single_node_test.exs index 01b11b79..e9d60b7a 100644 --- a/test/style/single_node_test.exs +++ b/test/style/single_node_test.exs @@ -519,4 +519,129 @@ defmodule Styler.Style.SingleNodeTest do """) end end + + describe "if/else" do + test "Credo.Check.Refactor.UnlessWithElse" do + for negator <- ["!", "not "] do + assert_style( + """ + unless #{negator} a do + b + else + c + end + """, + """ + if a do + c + else + b + end + """ + ) + end + + assert_style( + """ + unless a do + b + else + c + end + """, + """ + if a do + b + else + c + end + """ + ) + end + + test "Credo.Check.Refactor.NegatedConditionsInUnless" do + for negator <- ["!", "not "] do + assert_style("unless #{negator} foo, do: :bar", "if foo, do: :bar") + + assert_style( + """ + unless #{negator} foo do + bar + end + """, + """ + if foo do + bar + end + """ + ) + end + end + + test "Credo.Check.Refactor.NegatedConditionsWithElse" do + for negator <- ["!", "not "] do + assert_style("if #{negator}foo, do: :bar") + assert_style("if #{negator}foo, do: :bar, else: :baz", "if foo, do: :baz, else: :bar") + + assert_style(""" + if #{negator}foo do + bar + end + """) + + assert_style( + """ + if #{negator}foo do + bar + else + baz + end + """, + """ + if foo do + baz + else + bar + end + """ + ) + end + end + + test "recurses" do + assert_style( + """ + if !!val do + a + else + b + end + """, + """ + if val do + a + else + b + end + """ + ) + + assert_style( + """ + unless !! not true do + a + else + b + end + """, + """ + if true do + b + else + a + end + """ + ) + end + end end