Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: adobe/elixir-styler
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.4.0
Choose a base ref
...
head repository: adobe/elixir-styler
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: main
Choose a head ref
  • 9 commits
  • 13 files changed
  • 3 contributors

Commits on Feb 21, 2025

  1. Add OTP26/27 but only run for 1.17/1.18

    halfdan committed Feb 21, 2025
    Copy the full SHA
    3d5a485 View commit details
  2. Merge pull request #222 from halfdan/expand-matrix

    Add OTP26/27 but only run for 1.17/1.18
    novaugust authored Feb 21, 2025
    Copy the full SHA
    d3318fd View commit details
  3. fix with redundant body + non-arrow behind redundant clause. Closes #…

    novaugust committed Feb 21, 2025
    Copy the full SHA
    941d067 View commit details

Commits on Feb 24, 2025

  1. link to quokka

    novaugust committed Feb 24, 2025

    Verified

    This commit was signed with the committer’s verified signature.
    Copy the full SHA
    9990eb6 View commit details

Commits on Mar 3, 2025

  1. Copy the full SHA
    3b0571e View commit details
  2. Copy the full SHA
    8fe1ca0 View commit details

Commits on Mar 6, 2025

  1. dont crash on invalid defs

    novaugust committed Mar 6, 2025
    Copy the full SHA
    13320e9 View commit details
  2. fix CI for older elixir

    novaugust committed Mar 6, 2025
    Copy the full SHA
    1df5f1d View commit details

Commits on Mar 17, 2025

  1. v1.4.1

    novaugust committed Mar 17, 2025
    Copy the full SHA
    be4dcec View commit details
Showing with 350 additions and 249 deletions.
  1. +7 −2 .github/workflows/ci.yml
  2. +19 −0 CHANGELOG.md
  3. +3 −1 README.md
  4. +24 −22 lib/style/blocks.ex
  5. +11 −19 lib/style/defs.ex
  6. +43 −0 lib/style/single_node.ex
  7. +1 −1 lib/styler.ex
  8. +1 −1 mix.exs
  9. +2 −0 test/style/blocks_test.exs
  10. +208 −202 test/style/defs_test.exs
  11. +4 −0 test/style/deprecations_test.exs
  12. +1 −1 test/style/pipes_test.exs
  13. +26 −0 test/style/single_node_test.exs
9 changes: 7 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -9,8 +9,13 @@ jobs:
name: Ex${{matrix.elixir}}/OTP${{matrix.otp}}
strategy:
matrix:
elixir: ['1.15.8', '1.16.3', '1.17.3', '1.18.2']
otp: ['25.3.2']
elixir: ["1.15.8", "1.16.3", "1.17.3", "1.18.2"]
otp: ["25.3.2", "26.2.5", "27.2.4"]
exclude:
- elixir: "1.15.8"
otp: "27.2.4"
- elixir: "1.16.3"
otp: "27.2.4"
steps:
- uses: actions/checkout@v4
- uses: erlef/setup-beam@v1
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -5,6 +5,25 @@ they can and will change without that change being reflected in Styler's semanti

## main

## 1.4.1

### Improvements

- `to_timeout/1` rewrites to use the next largest unit in some simple instances

```elixir
# before
to_timeout(second: 60 * m)
to_timeout(day: 7)
# after
to_timeout(minute: m)
to_timeout(week: 1)
```

### Fixes

- fixed styler raising when encountering invalid function definition ast

## 1.4

- A very nice change in alias lifting means Styler will make sure that your code is _using_ the aliases that it's specified.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -76,7 +76,9 @@ Styler's only current configuration option is `:alias_lifting_exclude`, which ac

#### No Credo-Style Enable/Disable

Styler [will not add configuration](https://github.com/adobe/elixir-styler/pull/127#issuecomment-1912242143) for ad-hoc enabling/disabling of rewrites. Sorry! Its implementation simply does not support that approach. There are however many forks out there that have attempted this; please explore the [Github forks tab](https://github.com/adobe/elixir-styler/forks) to see if there's a project that suits your needs or that you can draw inspiration from.
Styler [will not add configuration](https://github.com/adobe/elixir-styler/pull/127#issuecomment-1912242143) for ad-hoc enabling/disabling of rewrites. Sorry!

However, Smartrent has a fork of Styler named [Quokka](https://github.com/smartrent/quokka) that allows for finegrained control of Styler. Maybe it's what you're looking for. If not, you can always fork it or Styler as a starting point for your own tool!

Ultimately Styler is @adobe's internal tool that we're happy to share with the world. We're delighted if you like it as is, and just as excited if it's a starting point for you to make something even better for yourself.

46 changes: 24 additions & 22 deletions lib/style/blocks.ex
Original file line number Diff line number Diff line change
@@ -187,35 +187,37 @@ defmodule Styler.Style.Blocks do

# drop singleton identity else clauses like `else foo -> foo end`
elses =
case elses do
[{{_, _, [:else]}, [{:->, _, [[left], right]}]}] -> if nodes_equivalent?(left, right), do: [], else: elses
_ -> elses
with [{{_, _, [:else]}, [{:->, _, [[left], right]}]}] <- elses,
true <- nodes_equivalent?(left, right),
do: [],
else: (_ -> elses)

# Remove Redundant body
{postroll, reversed_clauses, do_body} =
if Enum.empty?(postroll) and Enum.empty?(elses) and nodes_equivalent?(lhs, do_body) do
# removing redundant RHS can expose more non-arrows behind it, so repeat our postroll process
{postroll, reversed_clauses} = Enum.split_while(rest, &(not left_arrow?(&1)))
{postroll, reversed_clauses, rhs}
else
{postroll, reversed_clauses, do_body}
end

# Put the postroll into the body
{reversed_clauses, do_body} =
cond do
# Put the postroll into the body
Enum.any?(postroll) ->
{node, do_body_meta, do_children} = do_body
do_children = if node == :__block__, do: do_children, else: [do_body]
do_body = {:__block__, Keyword.take(do_body_meta, [:line]), Enum.reverse(postroll, do_children)}
{reversed_clauses, do_body}

# Credo.Check.Refactor.RedundantWithClauseResult
Enum.empty?(elses) and nodes_equivalent?(lhs, do_body) ->
{rest, rhs}

# no change
true ->
{reversed_clauses, do_body}
if Enum.any?(postroll) do
{node, do_body_meta, do_children} = do_body
do_children = if node == :__block__, do: do_children, else: [do_body]
do_body = {:__block__, Keyword.take(do_body_meta, [:line]), Enum.reverse(postroll, do_children)}
{reversed_clauses, do_body}
else
{reversed_clauses, do_body}
end

do_line = do_meta[:line]
final_clause_line = final_clause_meta[:line]

do_line =
cond do
do_meta[:format] == :keyword && final_clause_line + 1 >= do_line -> do_line
do_meta[:format] == :keyword && final_clause_line + 1 >= do_meta[:line] -> do_meta[:line]
do_meta[:format] == :keyword -> final_clause_line + 1
true -> final_clause_line
end
@@ -243,12 +245,12 @@ defmodule Styler.Style.Blocks do
|> Zipper.prepend_siblings(preroll)
|> run(ctx)

# the # of `<-` canged, so we should have another look at this with statement
# the # of `<-` changed, so we should have another look at this with statement
Enum.any?(postroll) ->
run(zipper, ctx)

true ->
# of clauess didn't change, so don't reecurse or we'll loop FOREEEVEERR
# of clauses didn't change, so don't reecurse or we'll loop FOREEEVEERR
{:cont, zipper, ctx}
end
end
30 changes: 11 additions & 19 deletions lib/style/defs.ex
Original file line number Diff line number Diff line change
@@ -62,19 +62,18 @@ defmodule Styler.Style.Defs do
end
end

# all the other kinds of defs!
# @TODO all paths here skip, which means that `def a .. quote do def b ...` won't style `def b`
def run({{def, def_meta, [head, body]}, _} = zipper, ctx) when def in [:def, :defp] do
def run({{def, def_meta, [head, [{{:__block__, dm, [:do]}, {_, bm, _}} | _] = body]}, _} = zipper, ctx)
when def in [:def, :defp] do
def_line = def_meta[:line]
end_line = def_meta[:end][:line] || bm[:closing][:line] || dm[:line]

if do_meta = def_meta[:do] do
# This is a def with a do end block
end_line = def_meta[:end][:line]

if def_line == end_line do
cond do
def_line == end_line ->
{:skip, zipper, ctx}
else
do_line = do_meta[:line]

# def do end
Keyword.has_key?(def_meta, :do) ->
do_line = dm[:line]
delta = def_line - do_line

def_meta =
@@ -92,19 +91,12 @@ defmodule Styler.Style.Defs do
|> Style.shift_comments(do_line..end_line, delta)

{:skip, Zipper.replace(zipper, node), %{ctx | comments: comments}}
end
else
# This is a def with a keyword do
[{{:__block__, do_meta, [:do]}, {_, body_meta, _}}] = body
end_line = body_meta[:closing][:line] || do_meta[:line]

if def_line == end_line do
{:skip, zipper, ctx}
else
# def , do:
true ->
node = Style.set_line({def, def_meta, [head, body]}, def_line)
comments = Style.displace_comments(ctx.comments, def_line..end_line)
{:skip, Zipper.replace(zipper, node), %{ctx | comments: comments}}
end
end
end

43 changes: 43 additions & 0 deletions lib/style/single_node.ex
Original file line number Diff line number Diff line change
@@ -186,6 +186,49 @@ 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)}

defp style({:to_timeout, meta, [[{{:__block__, um, [unit]}, {:*, _, [left, right]}}]]} = node)
when unit in ~w(day hour minute second millisecond)a do
[l, r] =
Enum.map([left, right], fn
{_, _, [x]} -> x
_ -> nil
end)

{step, next_unit} =
case unit do
:day -> {7, :week}
:hour -> {24, :day}
:minute -> {60, :hour}
:second -> {60, :minute}
:millisecond -> {1000, :second}
end

if step in [l, r] do
n = if l == step, do: right, else: left
style({:to_timeout, meta, [[{{:__block__, um, [next_unit]}, n}]]})
else
node
end
end

defp style({:to_timeout, meta, [[{{:__block__, um, [unit]}, {:__block__, tm, [n]}}]]} = node) do
step_up =
case {unit, n} do
{:day, 7} -> :week
{:hour, 24} -> :day
{:minute, 60} -> :hour
{:second, 60} -> :minute
{:millisecond, 1000} -> :second
_ -> nil
end

if step_up do
{:to_timeout, meta, [[{{:__block__, um, [step_up]}, {:__block__, [token: "1", line: tm[:line]], [1]}}]]}
else
node
end
end

defp style(node), do: node

defp replace_into({:., dm, [{_, am, _} = enum, _]}, collectable, rest) do
2 changes: 1 addition & 1 deletion lib/styler.ex
Original file line number Diff line number Diff line change
@@ -21,10 +21,10 @@ defmodule Styler do
@styles [
Styler.Style.ModuleDirectives,
Styler.Style.Pipes,
Styler.Style.Deprecations,
Styler.Style.SingleNode,
Styler.Style.Defs,
Styler.Style.Blocks,
Styler.Style.Deprecations,
Styler.Style.Configs,
Styler.Style.CommentDirectives
]
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ defmodule Styler.MixProject do
use Mix.Project

# Don't forget to bump the README when doing non-patch version changes
@version "1.4.0"
@version "1.4.1"
@url "https://github.com/adobe/elixir-styler"

def project do
2 changes: 2 additions & 0 deletions test/style/blocks_test.exs
Original file line number Diff line number Diff line change
@@ -727,6 +727,7 @@ defmodule Styler.Style.BlocksTest do
assert_style(
"""
with {:ok, a} <- foo(),
x = y,
{:ok, b} <- bar(a) do
{:ok, b}
else
@@ -735,6 +736,7 @@ defmodule Styler.Style.BlocksTest do
""",
"""
with {:ok, a} <- foo() do
x = y
bar(a)
end
"""
Loading