From 1f1c3025f1ea8dc05c92a6c12f72583917799bc2 Mon Sep 17 00:00:00 2001 From: Matt Enlow Date: Thu, 20 Feb 2025 11:47:14 -0700 Subject: [PATCH 1/3] fix for <1.17 --- lib/style/blocks.ex | 7 +++++-- test/style/blocks_test.exs | 14 +++++++++++++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/lib/style/blocks.ex b/lib/style/blocks.ex index ac8e7a5..7d9ee92 100644 --- a/lib/style/blocks.ex +++ b/lib/style/blocks.ex @@ -53,10 +53,13 @@ defmodule Styler.Style.Blocks do # to `case single_statement do success -> body; ...elses end` def run({{:with, m, [{:<-, am, [success, single_statement]}, [body, elses]]}, zm}, ctx) do {{:__block__, do_meta, [:do]}, body} = body - {{:__block__, _else_meta, [:else]}, elses} = elses + {{:__block__, _, [:else]}, elses} = elses clauses = [{{:__block__, am, [:do]}, [{:->, do_meta, [[success], body]} | elses]}] + # fun fact: i added the do/end meta just because i noticed it was missing while debugging something + # and it fixed the bug 🤷 + case_meta = [do: [line: do_meta], end: [line: Style.max_line(elses)], line: m[:line]] # recurse in case this new case should be rewritten to a `if`, etc - run({{:case, m, [single_statement, clauses]}, zm}, ctx) + run({{:case, case_meta, [single_statement, clauses]}, zm}, ctx) end # `with true <- x, do: bar` =>`if x, do: bar` diff --git a/test/style/blocks_test.exs b/test/style/blocks_test.exs index 83cbab4..7be3c07 100644 --- a/test/style/blocks_test.exs +++ b/test/style/blocks_test.exs @@ -239,7 +239,7 @@ defmodule Styler.Style.BlocksTest do end end - describe "with statements" do + describe "with" do test "replacement due to no (or all removed) arrows" do assert_style( """ @@ -787,6 +787,18 @@ defmodule Styler.Style.BlocksTest do end """ end + + test "elixir1.17+ stab regressions" do + assert_style """ + with :ok <- foo, do: :bar, else: (_ -> :baz) + """, + """ + case foo do + :ok -> :bar + _ -> :baz + end + """ + end end test "Credo.Check.Refactor.CondStatements" do From 7c879af2a070fc472b28dc4abb6add8c81ba50a7 Mon Sep 17 00:00:00 2001 From: Matt Enlow Date: Thu, 20 Feb 2025 11:50:22 -0700 Subject: [PATCH 2/3] prettier --- test/style/blocks_test.exs | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/test/style/blocks_test.exs b/test/style/blocks_test.exs index 7be3c07..cf2d164 100644 --- a/test/style/blocks_test.exs +++ b/test/style/blocks_test.exs @@ -789,15 +789,17 @@ defmodule Styler.Style.BlocksTest do end test "elixir1.17+ stab regressions" do - assert_style """ - with :ok <- foo, do: :bar, else: (_ -> :baz) - """, - """ - case foo do - :ok -> :bar - _ -> :baz - end - """ + assert_style( + """ + with :ok <- foo, do: :bar, else: (_ -> :baz) + """, + """ + case foo do + :ok -> :bar + _ -> :baz + end + """ + ) end end From db5ba1451049d6dad262bbf5fa7982acebb1fd53 Mon Sep 17 00:00:00 2001 From: Matt Enlow Date: Thu, 20 Feb 2025 12:04:28 -0700 Subject: [PATCH 3/3] 1.17+ --- CHANGELOG.md | 4 +++- lib/style/blocks.ex | 24 +++++++++++++++++++++--- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ebaff7..7468937 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,8 @@ they can and will change without that change being reflected in Styler's semanti #### Ex1.17+ -Replace `:timer.units(x)` with the new `to_timeout(unit: x)` for `hours|minutes|seconds` +- Replace `:timer.units(x)` with the new `to_timeout(unit: x)` for `hours|minutes|seconds` +- Handle `, else: (_ -> x)` bugs introduced by `(_ -> x)` being termed a literal (#219, h/t @iamhassangm) #### Ex1.18+ @@ -48,6 +49,7 @@ This release taught Styler to try just that little bit harder when doing alias l ### Fixes - `pipes`: handle pipifying when the first arg is itself a pipe: `c(a |> b, d)` => `a |> b() |> c(d)` (#214, h/t @kybishop) +- `with`: correctly handle a stabby `with` `, else: (_ -> :ok)` being rewritten to a case (#219, h/t @iamhassangm) ## 1.3.3 diff --git a/lib/style/blocks.ex b/lib/style/blocks.ex index 7d9ee92..fd51be1 100644 --- a/lib/style/blocks.ex +++ b/lib/style/blocks.ex @@ -54,10 +54,28 @@ defmodule Styler.Style.Blocks do def run({{:with, m, [{:<-, am, [success, single_statement]}, [body, elses]]}, zm}, ctx) do {{:__block__, do_meta, [:do]}, body} = body {{:__block__, _, [:else]}, elses} = elses + + elses = + case elses do + # unwrap a stab ala `, else: (_ -> :ok)`. these became literals in 1.17 + {:__block__, _, [[{:->, _, _}] = stab]} -> stab + elses -> elses + end + + # drops keyword formatting etc + do_meta = [line: do_meta[:line]] clauses = [{{:__block__, am, [:do]}, [{:->, do_meta, [[success], body]} | elses]}] - # fun fact: i added the do/end meta just because i noticed it was missing while debugging something - # and it fixed the bug 🤷 - case_meta = [do: [line: do_meta], end: [line: Style.max_line(elses)], line: m[:line]] + end_line = Style.max_line(elses) + 1 + + # fun fact: i added the detailed meta just because i noticed it was missing while debugging something ... + # ... and it fixed the bug 🤷 + case_meta = [ + end_of_expression: [newlines: 1, line: end_line], + do: do_meta, + end: [line: end_line], + line: m[:line] + ] + # recurse in case this new case should be rewritten to a `if`, etc run({{:case, case_meta, [single_statement, clauses]}, zm}, ctx) end