Links:
Last active
April 29, 2022 13:49
-
-
Save thiamsantos/55a62a20c9ab064f001a177b41bf5245 to your computer and use it in GitHub Desktop.
Expand multi-alias syntax using credo + sourceror
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Mix.install([ | |
:sourceror, | |
:credo | |
]) | |
defmodule AliasExpansion do | |
alias Sourceror.Zipper, as: Z | |
def expand_aliases(quoted) do | |
Z.zip(quoted) | |
|> Z.traverse(&expand_alias/1) | |
|> Z.root() | |
end | |
defp expand_alias( | |
{{:alias, alias_meta, [{{:., _, [left, :{}]}, call_meta, right}]}, _metadata} = zipper | |
) do | |
{_, _, base_segments} = left | |
leading_comments = alias_meta[:leading_comments] || [] | |
trailing_comments = call_meta[:trailing_comments] || [] | |
right | |
|> Enum.map(&segments_to_alias(base_segments, &1)) | |
|> put_leading_comments(leading_comments) | |
|> put_trailing_comments(trailing_comments) | |
|> Enum.reverse() | |
|> Enum.reduce(zipper, &Z.insert_right(&2, &1)) | |
|> Z.remove() | |
end | |
defp expand_alias(zipper), do: zipper | |
defp segments_to_alias(base_segments, {_, meta, segments}) do | |
{:alias, meta, [{:__aliases__, [], base_segments ++ segments}]} | |
end | |
defp put_leading_comments([first | rest], comments) do | |
[Sourceror.prepend_comments(first, comments) | rest] | |
end | |
defp put_trailing_comments(list, comments) do | |
case List.pop_at(list, -1) do | |
{nil, list} -> | |
list | |
{last, list} -> | |
last = | |
{:__block__, | |
[ | |
trailing_comments: comments, | |
end_of_expression: [newlines: 2] | |
], [last]} | |
list ++ [last] | |
end | |
end | |
end | |
locals_without_parens = [ | |
# Query | |
from: 2, | |
# Schema | |
field: 1, | |
field: 2, | |
field: 3, | |
timestamps: 1, | |
belongs_to: 2, | |
belongs_to: 3, | |
has_one: 2, | |
has_one: 3, | |
has_many: 2, | |
has_many: 3, | |
many_to_many: 2, | |
many_to_many: 3, | |
embeds_one: 2, | |
embeds_one: 3, | |
embeds_one: 4, | |
embeds_many: 2, | |
embeds_many: 3, | |
embeds_many: 4 | |
] | |
Credo.run(["--only", "Credo.Check.Readability.MultiAlias"]) | |
|> Credo.Execution.get_issues() | |
|> Enum.map(& &1.filename) | |
|> Enum.map(fn filename -> | |
filename | |
|> File.read!() | |
|> Sourceror.parse_string!() | |
|> AliasExpansion.expand_aliases() | |
|> Sourceror.to_string(locals_without_parens: locals_without_parens) | |
|> tap(&File.write!(filename, &1)) | |
end) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment