Skip to content

Commit

Permalink
alias lifting: shrink when alias already exists. closes #201
Browse files Browse the repository at this point in the history
  • Loading branch information
novaugust committed Jan 24, 2025
1 parent 470b390 commit 7932147
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 12 deletions.
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,24 @@ they can and will change without that change being reflected in Styler's semanti

## main

### Improvements

- alias lifting: styler will now replace an expanded alias with its alias when the user has already defined that alias (#201, h/t me)

example:
alias A.B.C

A.B.C.foo()
A.B.C.bar()
A.B.C.baz()

becomes:
alias A.B.C

C.foo()
C.bar()
C.baz()

## 1.3.3

### Improvements
Expand Down
32 changes: 20 additions & 12 deletions lib/style/module_directives.ex
Original file line number Diff line number Diff line change
Expand Up @@ -282,8 +282,7 @@ defmodule Styler.Style.ModuleDirectives do
# we can't use the dealias map built into state as that's what things look like before sorting
# now that we've sorted, it could be different!
dealiases = AliasEnv.define(aliases)
excluded = dealiases |> Map.keys() |> Enum.into(Styler.Config.get(:lifting_excludes))
liftable = find_liftable_aliases(requires ++ nondirectives, excluded)
liftable = find_liftable_aliases(requires ++ nondirectives, dealiases)

if Enum.any?(liftable) do
# This is a silly hack that helps comments stay put.
Expand All @@ -306,7 +305,9 @@ defmodule Styler.Style.ModuleDirectives do
end
end

defp find_liftable_aliases(ast, excluded) do
defp find_liftable_aliases(ast, dealiases) do
excluded = dealiases |> Map.keys() |> Enum.into(Styler.Config.get(:lifting_excludes))

ast
|> Zipper.zip()
|> Zipper.reduce_while(%{}, fn
Expand All @@ -333,15 +334,22 @@ defmodule Styler.Style.ModuleDirectives do
last = List.last(aliases)

lifts =
if last in excluded or not Enum.all?(aliases, &is_atom/1) do
lifts
else
Map.update(lifts, last, {aliases, false}, fn
{^aliases, _} -> {aliases, true}
# if we have `Foo.Bar.Baz` and `Foo.Bar.Bop.Baz` both not aliased, we'll create a collision by lifting both
# grouping by last alias lets us detect these collisions
_ -> :collision_with_last
end)
cond do
# this alias already exists, they just wrote it out fully and are leaving it up to us to shorten it down!
dealiases[last] == aliases ->
Map.put(lifts, last, {aliases, true})

last in excluded or Enum.any?(aliases, &(not is_atom(&1))) ->
lifts

# track how often we see this alias - once we've seen it a second time we'll known
true ->
Map.update(lifts, last, {aliases, false}, fn
{^aliases, _} -> {aliases, true}
# if we have `Foo.Bar.Baz` and `Foo.Bar.Bop.Baz` both not aliased, we'll create a collision by lifting both
# grouping by last alias lets us detect these collisions
_ -> :collision_with_last
end)
end

{:skip, zipper, lifts}
Expand Down
19 changes: 19 additions & 0 deletions test/style/module_directives/alias_lifting_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,25 @@ defmodule Styler.Style.ModuleDirectives.AliasLiftingTest do
)
end

test "replaces known aliases" do
assert_style(
"""
alias A.B.C
A.B.C.foo()
A.B.C.foo()
A.B.C.foo()
""",
"""
alias A.B.C
C.foo()
C.foo()
C.foo()
"""
)
end

describe "comments stay put" do
test "comments before alias stanza" do
assert_style(
Expand Down

0 comments on commit 7932147

Please sign in to comment.