Skip to content

Commit

Permalink
fix it up
Browse files Browse the repository at this point in the history
  • Loading branch information
novaugust committed Apr 8, 2024
1 parent fa67edc commit 3cb10f2
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 21 deletions.
1 change: 1 addition & 0 deletions .formatter.exs
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@
assert_style: 2
],
plugins: [Styler],
styler: [alias_lifting_exclude: []],
line_length: 122
]
61 changes: 50 additions & 11 deletions lib/style/module_directives.ex
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ defmodule Styler.Style.ModuleDirectives do
* `Credo.Check.Readability.UnnecessaryAliasExpansion`
* `Credo.Check.Design.AliasUsage`
## Strict Layout
## Breakages
**This can break your code.**
### Strict Layout: alias referents
Modules directives are sorted into the following order:
* `@shortdoc`
Expand Down Expand Up @@ -63,6 +65,26 @@ defmodule Styler.Style.ModuleDirectives do
```
For now, it's up to you to come up with a fix for this issue. Sorry!
### Strict Layout: interwoven conflicting aliases
Ideally no one writes code like this as it's hard for our human brains to notice the context switching!
Still, it's a possible source of breakages in Styler.
alias Foo.Bar
Bar.Baz.bop()
alias Baz.Bar
Bar.Baz.bop()
# becomes
alias Baz.Bar
alias Baz.Bar.Baz
alias Foo.Bar
Baz.bop() # was Foo.Bar.Baz, is now Baz.Bar.Baz
Baz.bop()
"""
@behaviour Styler.Style

Expand Down Expand Up @@ -223,22 +245,36 @@ defmodule Styler.Style.ModuleDirectives do
end

defp lift_aliases(aliases, requires, nondirectives) do
excluded =
Enum.reduce(aliases, Styler.Config.get(:lifting_excludes), fn
{:alias, _, [{:__aliases__, _, aliases}]}, excluded -> MapSet.put(excluded, List.last(aliases))
{:alias, _, [{:__aliases__, _, _}, [{_as, {:__aliases__, _, [as]}}]]}, excluded -> MapSet.put(excluded, as)
aliasing =
Map.new(aliases, fn
{:alias, _, [{:__aliases__, _, aliases}]} -> {List.last(aliases), aliases}
{:alias, _, [{:__aliases__, _, aliases}, [{_as, {:__aliases__, _, [as]}}]]} -> {as, aliases}
# `alias __MODULE__` or other oddities
{:alias, _, _}, excluded -> excluded
{:alias, _, _} -> {nil, nil}
end)

excluded = aliasing |> Map.keys() |> MapSet.new() |> MapSet.union(Styler.Config.get(:lifting_excludes))

liftable = find_liftable_aliases(requires ++ nondirectives, excluded)

if Enum.any?(liftable) do
# This is a silly hack that helps comments stay put.
# the `cap_line` algo was designed to handle high-line stuff moving up into low line territory, so we set our
# new node to have an abritrarily high line annnnd comments behave! i think.
line = 99_999
new_aliases = Enum.map(liftable, &{:alias, [line: line], [{:__aliases__, [last: [line: line], line: line], &1}]})

new_aliases =
Enum.map(liftable, fn [first | rest] = modules ->
# if there's an existing alias for this alias, make sure the new one we make is the compound alias
modules =
case aliasing[first] do
nil -> modules
parent_alias -> parent_alias ++ rest
end

{:alias, [line: line], [{:__aliases__, [last: [line: line], line: line], modules}]}
end)

aliases = expand_and_sort(aliases ++ new_aliases)
requires = do_lift_aliases(requires, liftable)
nondirectives = do_lift_aliases(nondirectives, liftable)
Expand Down Expand Up @@ -272,10 +308,13 @@ defmodule Styler.Style.ModuleDirectives do
{{:quote, _, _}, _} = zipper, acc ->
{:skip, zipper, acc}

{{:__aliases__, _, [_, _, _ | _] = aliases}, _} = zipper, {lifts, excluded} = acc ->
if List.last(aliases) in excluded or List.first(aliases) in excluded or not Enum.all?(aliases, &is_atom/1),
do: {:skip, zipper, acc},
else: {:skip, zipper, {Map.update(lifts, aliases, false, fn _ -> true end), excluded}}
{{:__aliases__, _, [_, _, _ | _] = modlist}, _} = zipper, {lifts, excluded} = acc ->
acc =
if Enum.any?(modlist, &(not is_atom(&1))) or List.last(modlist) in excluded,
do: acc,
else: {Map.update(lifts, modlist, false, fn _ -> true end), excluded}

{:skip, zipper, acc}

zipper, acc ->
{:cont, zipper, acc}
Expand Down
23 changes: 13 additions & 10 deletions test/style/module_directives/alias_lifting_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -136,19 +136,22 @@ defmodule Styler.Style.ModuleDirectives.AliasLiftingTest do
end

test "deep nesting of an alias" do
assert_style("""
alias Foo.Bar.Baz
assert_style(
"""
alias Foo.Bar.Baz
Baz.Bop.Boom.wee()
Baz.Bop.Boom.wee()
Baz.Bop.Boom.wee()
Baz.Bop.Boom.wee()
""", """
alias Foo.Bar.Baz
alias Foo.Bar.Baz.Bop.Boom
""",
"""
alias Foo.Bar.Baz
alias Foo.Bar.Baz.Bop.Boom
Boom.wee()
Boom.wee()
""")
Boom.wee()
Boom.wee()
"""
)
end

describe "comments stay put" do
Expand Down

0 comments on commit 3cb10f2

Please sign in to comment.