Skip to content

Commit

Permalink
well, it works
Browse files Browse the repository at this point in the history
  • Loading branch information
novaugust committed May 20, 2024
1 parent f4ef354 commit fe10475
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 33 deletions.
43 changes: 27 additions & 16 deletions lib/style/module_directives.ex
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,7 @@ defmodule Styler.Style.ModuleDirectives do
nondirectives: [],
dealiases: %{},
attrs: MapSet.new(),
attr_lifts: [],
assignments: []
attr_lifts: []
}

defp lift_module_attrs({node, _, _} = ast, %{attrs: attrs} = acc) do
Expand Down Expand Up @@ -243,8 +242,8 @@ defmodule Styler.Style.ModuleDirectives do
%{acc | nondirectives: [ast | acc.nondirectives], attrs: MapSet.put(acc.attrs, attr)}

{directive, _, _} = ast, acc when directive in @directives ->
{ast, acc} = ast |> lift_module_attrs(acc)
ast = ast |> expand()
{ast, acc} = lift_module_attrs(ast, acc)
ast = expand(ast)
# import and used get hoisted above aliases, so need to dealias
ast = if directive in ~w(import use)a, do: Dealias.apply(acc.dealiases, ast), else: ast
dealiases = if directive == :alias, do: Dealias.put(acc.dealiases, ast), else: acc.dealiases
Expand All @@ -265,30 +264,42 @@ defmodule Styler.Style.ModuleDirectives do
end)
|> lift_aliases()

acc =
# Not happy with it, but this does the work to move module attribute assignments above the module or quote or whatever
# Given that it'll only be run once and not again, i'm okay with it being inefficient
{acc, parent} =
if Enum.any?(acc.attr_lifts) do
lifts = acc.attr_lifts

nondirectives = Enum.map(acc.nondirectives, fn
{:@, m, [{attr, am, _}]} = ast -> if attr in lifts, do: {:@, m, [{attr, am, [{attr, am, nil}]}]}, else: ast
ast -> ast
end)
nondirectives =
Enum.map(acc.nondirectives, fn
{:@, m, [{attr, am, _}]} = ast -> if attr in lifts, do: {:@, m, [{attr, am, [{attr, am, nil}]}]}, else: ast
ast -> ast
end)

assignments =
Enum.flat_map(acc.nondirectives, fn
{:@, m, [{attr, am, [val]}]} -> if attr in lifts, do: [{:=, m, [{attr, am, nil}, val]}], else: []
_ -> []
end)

{past, _} = parent

assignments = Enum.flat_map(acc.nondirectives, fn
{:@, m, [{attr, am, [val]}]} -> if attr in lifts, do: [{:=, m, [{attr, am, nil}, val]}], else: []
_ -> []
end)
parent =
parent
|> Zipper.up()
|> Style.find_nearest_block()
|> Zipper.prepend_siblings(assignments)
|> Zipper.find(&(&1 == past))

%{acc | nondirectives: nondirectives, assignments: assignments}
{%{acc | nondirectives: nondirectives}, parent}
else
acc
{acc, parent}
end

nondirectives = acc.nondirectives

directives =
[
acc.assignments,
acc.shortdoc,
acc.moduledoc,
acc.behaviour,
Expand Down
58 changes: 41 additions & 17 deletions test/style/module_directives_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -574,25 +574,49 @@ defmodule Styler.Style.ModuleDirectivesTest do
)
end

test "module attribute variable extraction" do
assert_style(
"""
defmodule MyGreatLibrary do
@library_options [...]
@moduledoc make_pretty_docs(@library_options)
use OptionsMagic, my_opts: @library_options
end
""",
"""
describe "module attribute lifting" do
test "replaces uses in other attributes and `use` correctly" do
assert_style(
"""
defmodule MyGreatLibrary do
@library_options [...]
@moduledoc make_pretty_docs(@library_options)
use OptionsMagic, my_opts: @library_options
end
""",
"""
library_options = [...]
defmodule MyGreatLibrary do
@moduledoc make_pretty_docs(library_options)
use OptionsMagic, my_opts: unquote(library_options)
@library_options library_options
end
"""
)
end

defmodule MyGreatLibrary do
test "works with `quote`" do
assert_style(
"""
quote do
@library_options [...]
@moduledoc make_pretty_docs(@library_options)
use OptionsMagic, my_opts: @library_options
end
""",
"""
library_options = [...]
@moduledoc make_pretty_docs(library_options)
use OptionsMagic, my_opts: unquote(library_options)
@library_options library_options
end
"""
)
quote do
@moduledoc make_pretty_docs(library_options)
use OptionsMagic, my_opts: unquote(library_options)
@library_options library_options
end
"""
)
end
end
end

0 comments on commit fe10475

Please sign in to comment.