mirror of
https://github.com/ash-project/igniter.git
synced 2024-09-19 13:02:51 +12:00
refactor: simplify zipper usage (#45)
* build: add otp version to elixir in .tool-versions * refactor: don't make subtree zippers unless needed in `Igniter.Code.Common` * refactor: internal function in `Igniter.Code.Common` * docs: add docstring for `Igniter.Code.Common.use_aliases/2` * refactor: simplify zipper usage Refactored using these two general rules: 1. Don't make subtrees unnecessarily zipper |> Zipper.subtree() |> Zipper.root() # is equivalent to zipper |> Zipper.node() 2. Access `zipper.node` when appropriate zipper |> Zipper.node() |> case do ... end # is equivalent to case zipper.node do ... end * fix: remove redundant case clause in `Igniter.Code.Common`
This commit is contained in:
parent
772a916684
commit
43a2f39943
9 changed files with 49 additions and 135 deletions
|
@ -1,2 +1,2 @@
|
|||
erlang 26.0.2
|
||||
elixir 1.17.1
|
||||
elixir 1.17.1-otp-26
|
||||
|
|
|
@ -61,8 +61,7 @@ defmodule Igniter.Code.Common do
|
|||
ast =
|
||||
unquote(zipper)
|
||||
|> Igniter.Code.Common.maybe_move_to_single_child_block()
|
||||
|> Zipper.subtree()
|
||||
|> Zipper.root()
|
||||
|> Zipper.node()
|
||||
|
||||
match?(unquote(pattern), ast)
|
||||
end
|
||||
|
@ -133,20 +132,14 @@ defmodule Igniter.Code.Common do
|
|||
end
|
||||
|
||||
defp do_add_code(zipper, new_code, placement, expand_env? \\ true) do
|
||||
current_code =
|
||||
zipper
|
||||
|> Zipper.subtree()
|
||||
|
||||
new_code =
|
||||
if expand_env? do
|
||||
use_aliases(new_code, current_code)
|
||||
use_aliases(new_code, zipper)
|
||||
else
|
||||
new_code
|
||||
end
|
||||
|
||||
current_code = Zipper.root(current_code)
|
||||
|
||||
case current_code do
|
||||
case zipper.node do
|
||||
{:__block__, meta, stuff} when length(stuff) > 1 or stuff == [] ->
|
||||
new_stuff =
|
||||
if placement == :after do
|
||||
|
@ -161,41 +154,28 @@ defmodule Igniter.Code.Common do
|
|||
zipper
|
||||
|> highest_adjacent_block()
|
||||
|> case do
|
||||
nil ->
|
||||
%Zipper{node: {:__block__, meta, stuff}} = upwards ->
|
||||
new_stuff =
|
||||
if placement == :after do
|
||||
List.wrap(stuff) ++ [new_code]
|
||||
else
|
||||
case List.wrap(stuff) do
|
||||
[first | rest] ->
|
||||
[first, new_code | rest]
|
||||
|
||||
_ ->
|
||||
[new_code | stuff]
|
||||
end
|
||||
end
|
||||
|
||||
Zipper.replace(upwards, {:__block__, meta, new_stuff})
|
||||
|
||||
_ ->
|
||||
if placement == :after do
|
||||
Zipper.replace(zipper, {:__block__, [], [code, new_code]})
|
||||
else
|
||||
Zipper.replace(zipper, {:__block__, [], [new_code, code]})
|
||||
end
|
||||
|
||||
upwards ->
|
||||
upwards
|
||||
|> Zipper.subtree()
|
||||
|> Zipper.root()
|
||||
|> case do
|
||||
{:__block__, meta, stuff} ->
|
||||
new_stuff =
|
||||
if placement == :after do
|
||||
List.wrap(stuff) ++ [new_code]
|
||||
else
|
||||
case List.wrap(stuff) do
|
||||
[first | rest] ->
|
||||
[first, new_code | rest]
|
||||
|
||||
_ ->
|
||||
[new_code | stuff]
|
||||
end
|
||||
end
|
||||
|
||||
Zipper.replace(upwards, {:__block__, meta, new_stuff})
|
||||
|
||||
_ ->
|
||||
if placement == :after do
|
||||
Zipper.replace(zipper, {:__block__, [], [code, new_code]})
|
||||
else
|
||||
Zipper.replace(zipper, {:__block__, [], [new_code, code]})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -205,36 +185,24 @@ defmodule Igniter.Code.Common do
|
|||
end
|
||||
|
||||
def replace_code(zipper, code) do
|
||||
current_code =
|
||||
zipper
|
||||
|> Zipper.subtree()
|
||||
|
||||
code = use_aliases(code, current_code)
|
||||
|
||||
code = use_aliases(code, zipper)
|
||||
Zipper.replace(zipper, code)
|
||||
end
|
||||
|
||||
defp highest_adjacent_block(zipper) do
|
||||
case Zipper.up(zipper) do
|
||||
nil ->
|
||||
%Zipper{node: {:__block__, _, _}} = upwards ->
|
||||
highest_adjacent_block(upwards) || upwards
|
||||
|
||||
_ ->
|
||||
nil
|
||||
|
||||
upwards ->
|
||||
upwards
|
||||
|> Zipper.node()
|
||||
|> case do
|
||||
{:__block__, _, _} ->
|
||||
case highest_adjacent_block(upwards) do
|
||||
nil -> upwards
|
||||
zipper -> zipper
|
||||
end
|
||||
|
||||
_ ->
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Replaces full module names in `new_code` with any aliases for that
|
||||
module found in the `current_code` environment.
|
||||
"""
|
||||
def use_aliases(new_code, current_code) do
|
||||
case current_env(current_code) do
|
||||
{:ok, env} ->
|
||||
|
@ -333,10 +301,7 @@ defmodule Igniter.Code.Common do
|
|||
def maybe_move_to_single_child_block(nil), do: nil
|
||||
|
||||
def maybe_move_to_single_child_block(zipper) do
|
||||
zipper
|
||||
|> Zipper.subtree()
|
||||
|> Zipper.root()
|
||||
|> case do
|
||||
case zipper.node do
|
||||
{:__block__, _, [_]} ->
|
||||
zipper
|
||||
|> Zipper.down()
|
||||
|
@ -360,10 +325,7 @@ defmodule Igniter.Code.Common do
|
|||
def maybe_move_to_block(nil), do: nil
|
||||
|
||||
def maybe_move_to_block(zipper) do
|
||||
zipper
|
||||
|> Zipper.subtree()
|
||||
|> Zipper.root()
|
||||
|> case do
|
||||
case zipper.node do
|
||||
{:__block__, _, _} ->
|
||||
zipper
|
||||
|> Zipper.down()
|
||||
|
@ -550,7 +512,6 @@ defmodule Igniter.Code.Common do
|
|||
|
||||
zipper
|
||||
|> Igniter.Code.Common.move_to_cursor(pattern)
|
||||
|> Zipper.subtree()
|
||||
|> Zipper.node()
|
||||
# => 10
|
||||
```
|
||||
|
@ -569,7 +530,7 @@ defmodule Igniter.Code.Common do
|
|||
|
||||
defp do_move_to_cursor(%Zipper{} = zipper, %Zipper{} = pattern_zipper) do
|
||||
cond do
|
||||
cursor?(pattern_zipper |> Zipper.subtree() |> Zipper.node()) ->
|
||||
pattern_zipper |> Zipper.node() |> cursor?() ->
|
||||
{:ok, zipper}
|
||||
|
||||
match_type = zippers_match(zipper, pattern_zipper) ->
|
||||
|
@ -593,17 +554,7 @@ defmodule Igniter.Code.Common do
|
|||
defp cursor?(_other), do: false
|
||||
|
||||
defp zippers_match(zipper, pattern_zipper) do
|
||||
zipper_node =
|
||||
zipper
|
||||
|> Zipper.subtree()
|
||||
|> Zipper.node()
|
||||
|
||||
pattern_node =
|
||||
pattern_zipper
|
||||
|> Zipper.subtree()
|
||||
|> Zipper.node()
|
||||
|
||||
case {zipper_node, pattern_node} do
|
||||
case {zipper.node, pattern_zipper.node} do
|
||||
{_, {:__, _, _}} ->
|
||||
:skip
|
||||
|
||||
|
@ -673,8 +624,7 @@ defmodule Igniter.Code.Common do
|
|||
@spec nodes_equal?(Zipper.t() | Macro.t(), Macro.t()) :: boolean
|
||||
def nodes_equal?(%Zipper{} = left, right) do
|
||||
with zipper when not is_nil(zipper) <- Zipper.up(left),
|
||||
{:defmodule, _, [{:__aliases__, _, parts}, _]} <-
|
||||
zipper |> Zipper.subtree() |> Zipper.node(),
|
||||
{:defmodule, _, [{:__aliases__, _, parts}, _]} <- Zipper.node(zipper),
|
||||
{:ok, env} <- current_env(zipper),
|
||||
true <- nodes_equal?({:__aliases__, [], [Module.concat([env.module | parts])]}, right) do
|
||||
true
|
||||
|
@ -682,7 +632,6 @@ defmodule Igniter.Code.Common do
|
|||
_ ->
|
||||
left
|
||||
|> expand_aliases()
|
||||
|> Zipper.subtree()
|
||||
|> Zipper.node()
|
||||
|> nodes_equal?(right)
|
||||
end
|
||||
|
@ -700,10 +649,7 @@ defmodule Igniter.Code.Common do
|
|||
|
||||
@spec expand_alias(Zipper.t()) :: Zipper.t()
|
||||
def expand_alias(zipper) do
|
||||
zipper
|
||||
|> Zipper.subtree()
|
||||
|> Zipper.node()
|
||||
|> case do
|
||||
case zipper.node do
|
||||
{:__aliases__, _, parts} ->
|
||||
case current_env(zipper) do
|
||||
{:ok, env} ->
|
||||
|
|
|
@ -13,12 +13,7 @@ defmodule Igniter.Code.Function do
|
|||
unquote(zipper),
|
||||
unquote(index),
|
||||
fn zipper ->
|
||||
code_at_node =
|
||||
zipper
|
||||
|> Sourceror.Zipper.subtree()
|
||||
|> Sourceror.Zipper.root()
|
||||
|
||||
match?(unquote(pattern), code_at_node)
|
||||
match?(unquote(pattern), zipper.node)
|
||||
end
|
||||
)
|
||||
end
|
||||
|
@ -87,8 +82,7 @@ defmodule Igniter.Code.Function do
|
|||
def function_call?(%Zipper{} = zipper, name, arity) do
|
||||
zipper
|
||||
|> Common.maybe_move_to_single_child_block()
|
||||
|> Zipper.subtree()
|
||||
|> Zipper.root()
|
||||
|> Zipper.node()
|
||||
|> case do
|
||||
{^name, _, args} ->
|
||||
Enum.count(args) == arity
|
||||
|
@ -112,8 +106,7 @@ defmodule Igniter.Code.Function do
|
|||
def function_call?(%Zipper{} = zipper, name) do
|
||||
zipper
|
||||
|> Common.maybe_move_to_single_child_block()
|
||||
|> Zipper.subtree()
|
||||
|> Zipper.root()
|
||||
|> Zipper.node()
|
||||
|> case do
|
||||
{^name, _, _} ->
|
||||
true
|
||||
|
@ -137,8 +130,7 @@ defmodule Igniter.Code.Function do
|
|||
def function_call?(%Zipper{} = zipper) do
|
||||
zipper
|
||||
|> Common.maybe_move_to_single_child_block()
|
||||
|> Zipper.subtree()
|
||||
|> Zipper.root()
|
||||
|> Zipper.node()
|
||||
|> case do
|
||||
{:|>, _, [{name, _, context} | _rest]} when is_atom(context) and is_atom(name) ->
|
||||
true
|
||||
|
@ -391,10 +383,7 @@ defmodule Igniter.Code.Function do
|
|||
end
|
||||
|
||||
defp pipeline?(zipper) do
|
||||
zipper
|
||||
|> Zipper.subtree()
|
||||
|> Zipper.root()
|
||||
|> case do
|
||||
case zipper.node do
|
||||
{:|>, _, _} -> true
|
||||
_ -> false
|
||||
end
|
||||
|
|
|
@ -117,10 +117,7 @@ defmodule Igniter.Code.Keyword do
|
|||
value = Common.use_aliases(value, zipper)
|
||||
|
||||
to_append =
|
||||
zipper
|
||||
|> Zipper.subtree()
|
||||
|> Zipper.node()
|
||||
|> case do
|
||||
case zipper.node do
|
||||
[{{:__block__, meta, _}, _} | _] ->
|
||||
if meta[:format] do
|
||||
{{:__block__, [format: meta[:format]], [key]}, {:__block__, [], [value]}}
|
||||
|
@ -172,10 +169,7 @@ defmodule Igniter.Code.Keyword do
|
|||
end) do
|
||||
:error ->
|
||||
to_append =
|
||||
zipper
|
||||
|> Zipper.subtree()
|
||||
|> Zipper.node()
|
||||
|> case do
|
||||
case zipper.node do
|
||||
[{{:__block__, meta, _}, {:__block__, _, _}} | _] ->
|
||||
value =
|
||||
value
|
||||
|
|
|
@ -136,10 +136,7 @@ defmodule Igniter.Code.Map do
|
|||
end
|
||||
|
||||
defp map_keys_format(zipper) do
|
||||
zipper
|
||||
|> Zipper.subtree()
|
||||
|> Zipper.node()
|
||||
|> case do
|
||||
case zipper.node do
|
||||
value when is_list(value) ->
|
||||
Enum.all?(value, fn
|
||||
{:__block__, meta, _} ->
|
||||
|
|
|
@ -156,17 +156,13 @@ defmodule Igniter.Code.Module do
|
|||
|> Rewrite.Source.get(:quoted)
|
||||
|> Zipper.zip()
|
||||
|> Zipper.traverse([], fn zipper, acc ->
|
||||
zipper
|
||||
|> Zipper.subtree()
|
||||
|> Zipper.node()
|
||||
|> case do
|
||||
case zipper.node do
|
||||
{:defmodule, _, [_, _]} ->
|
||||
{:ok, mod_zipper} = Igniter.Code.Function.move_to_nth_argument(zipper, 0)
|
||||
|
||||
module_name =
|
||||
mod_zipper
|
||||
|> Igniter.Code.Common.expand_alias()
|
||||
|> Zipper.subtree()
|
||||
|> Zipper.node()
|
||||
|> Igniter.Code.Module.to_module_name()
|
||||
|
||||
|
@ -265,7 +261,6 @@ defmodule Igniter.Code.Module do
|
|||
module <-
|
||||
zipper
|
||||
|> Igniter.Code.Common.expand_alias()
|
||||
|> Zipper.subtree()
|
||||
|> Zipper.node(),
|
||||
module when not is_nil(module) <- to_module_name(module),
|
||||
new_path when not is_nil(new_path) <-
|
||||
|
|
|
@ -8,10 +8,7 @@ defmodule Igniter.Code.Tuple do
|
|||
@doc "Returns `true` if the zipper is at a literal tuple, `false` if not."
|
||||
@spec tuple?(Zipper.t()) :: boolean()
|
||||
def tuple?(item) do
|
||||
item
|
||||
|> Zipper.subtree()
|
||||
|> Zipper.root()
|
||||
|> case do
|
||||
case item.node do
|
||||
{:{}, _, _} -> true
|
||||
{_, _} -> true
|
||||
_ -> false
|
||||
|
|
|
@ -89,7 +89,6 @@ defmodule Igniter.Project.Deps do
|
|||
end
|
||||
end) do
|
||||
current_declaration
|
||||
|> Zipper.subtree()
|
||||
|> Zipper.node()
|
||||
|> Sourceror.to_string()
|
||||
else
|
||||
|
|
|
@ -5,8 +5,7 @@ defmodule Igniter.Util.Debug do
|
|||
@doc "Puts the formatted code at the node of the zipper to the console"
|
||||
def puts_code_at_node(zipper) do
|
||||
zipper
|
||||
|> Zipper.subtree()
|
||||
|> Zipper.root()
|
||||
|> Zipper.node()
|
||||
|> Sourceror.to_string()
|
||||
|> then(&"==code==\n#{&1}\n==code==\n")
|
||||
|> IO.puts()
|
||||
|
@ -17,16 +16,14 @@ defmodule Igniter.Util.Debug do
|
|||
@doc "Returns the formatted code at the node of the zipper to the console"
|
||||
def code_at_node(zipper) do
|
||||
zipper
|
||||
|> Zipper.subtree()
|
||||
|> Zipper.root()
|
||||
|> Zipper.node()
|
||||
|> Sourceror.to_string()
|
||||
end
|
||||
|
||||
@doc "Puts the ast at the node of the zipper to the console"
|
||||
def puts_ast_at_node(zipper) do
|
||||
zipper
|
||||
|> Zipper.subtree()
|
||||
|> Zipper.root()
|
||||
|> Zipper.node()
|
||||
|> then(&"==ast==\n#{inspect(&1, pretty: true)}\n==ast==\n")
|
||||
|> IO.puts()
|
||||
|
||||
|
|
Loading…
Reference in a new issue