Skip to content

Commit fc6fb5d

Browse files
authored
fix with rewrites when keyword with an else stab (#220)
Closes #219 fixes for both <1.17 and >=1.17
1 parent 74d6fd2 commit fc6fb5d

File tree

3 files changed

+41
-4
lines changed

3 files changed

+41
-4
lines changed

CHANGELOG.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ they can and will change without that change being reflected in Styler's semanti
99

1010
#### Ex1.17+
1111

12-
Replace `:timer.units(x)` with the new `to_timeout(unit: x)` for `hours|minutes|seconds`
12+
- Replace `:timer.units(x)` with the new `to_timeout(unit: x)` for `hours|minutes|seconds`
13+
- Handle `, else: (_ -> x)` bugs introduced by `(_ -> x)` being termed a literal (#219, h/t @iamhassangm)
1314

1415
#### Ex1.18+
1516

@@ -48,6 +49,7 @@ This release taught Styler to try just that little bit harder when doing alias l
4849
### Fixes
4950

5051
- `pipes`: handle pipifying when the first arg is itself a pipe: `c(a |> b, d)` => `a |> b() |> c(d)` (#214, h/t @kybishop)
52+
- `with`: correctly handle a stabby `with` `, else: (_ -> :ok)` being rewritten to a case (#219, h/t @iamhassangm)
5153

5254
## 1.3.3
5355

lib/style/blocks.ex

+23-2
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,31 @@ defmodule Styler.Style.Blocks do
5353
# to `case single_statement do success -> body; ...elses end`
5454
def run({{:with, m, [{:<-, am, [success, single_statement]}, [body, elses]]}, zm}, ctx) do
5555
{{:__block__, do_meta, [:do]}, body} = body
56-
{{:__block__, _else_meta, [:else]}, elses} = elses
56+
{{:__block__, _, [:else]}, elses} = elses
57+
58+
elses =
59+
case elses do
60+
# unwrap a stab ala `, else: (_ -> :ok)`. these became literals in 1.17
61+
{:__block__, _, [[{:->, _, _}] = stab]} -> stab
62+
elses -> elses
63+
end
64+
65+
# drops keyword formatting etc
66+
do_meta = [line: do_meta[:line]]
5767
clauses = [{{:__block__, am, [:do]}, [{:->, do_meta, [[success], body]} | elses]}]
68+
end_line = Style.max_line(elses) + 1
69+
70+
# fun fact: i added the detailed meta just because i noticed it was missing while debugging something ...
71+
# ... and it fixed the bug 🤷
72+
case_meta = [
73+
end_of_expression: [newlines: 1, line: end_line],
74+
do: do_meta,
75+
end: [line: end_line],
76+
line: m[:line]
77+
]
78+
5879
# recurse in case this new case should be rewritten to a `if`, etc
59-
run({{:case, m, [single_statement, clauses]}, zm}, ctx)
80+
run({{:case, case_meta, [single_statement, clauses]}, zm}, ctx)
6081
end
6182

6283
# `with true <- x, do: bar` =>`if x, do: bar`

test/style/blocks_test.exs

+15-1
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ defmodule Styler.Style.BlocksTest do
239239
end
240240
end
241241

242-
describe "with statements" do
242+
describe "with" do
243243
test "replacement due to no (or all removed) arrows" do
244244
assert_style(
245245
"""
@@ -787,6 +787,20 @@ defmodule Styler.Style.BlocksTest do
787787
end
788788
"""
789789
end
790+
791+
test "elixir1.17+ stab regressions" do
792+
assert_style(
793+
"""
794+
with :ok <- foo, do: :bar, else: (_ -> :baz)
795+
""",
796+
"""
797+
case foo do
798+
:ok -> :bar
799+
_ -> :baz
800+
end
801+
"""
802+
)
803+
end
790804
end
791805

792806
test "Credo.Check.Refactor.CondStatements" do

0 commit comments

Comments
 (0)