mirror of
https://github.com/ash-project/igniter.git
synced 2024-09-20 13:33:00 +12:00
147 lines
4.2 KiB
Elixir
147 lines
4.2 KiB
Elixir
defmodule Igniter.Application do
|
|
@moduledoc "Codemods and tools for working with Application modules."
|
|
|
|
require Igniter.Code.Common
|
|
require Igniter.Code.Function
|
|
|
|
alias Igniter.Code.Common
|
|
alias Sourceror.Zipper
|
|
|
|
@doc "Returns the name of the current application."
|
|
@spec app_name() :: atom()
|
|
def app_name do
|
|
Mix.Project.config()[:app]
|
|
end
|
|
|
|
@doc "Adds a new child to the `children` list in the application file"
|
|
@spec add_new_child(Igniter.t(), module() | {module, term()}) :: Igniter.t()
|
|
def add_new_child(igniter, to_supervise) do
|
|
project = Mix.Project.get!()
|
|
|
|
# TODO: Would be better to check the source and parse the app module out
|
|
# as something else may have set an app module
|
|
to_perform =
|
|
case project.application()[:mod] do
|
|
nil -> {:create_an_app, Igniter.Code.Module.module_name("Application")}
|
|
{mod, _} -> {:modify, mod}
|
|
mod -> {:modify, mod}
|
|
end
|
|
|
|
case to_perform do
|
|
{:create_an_app, mod} ->
|
|
igniter
|
|
|> create_app(mod)
|
|
|> do_add_child(mod, to_supervise)
|
|
|
|
{:modify, mod} ->
|
|
do_add_child(igniter, mod, to_supervise)
|
|
end
|
|
end
|
|
|
|
def create_app(igniter, application) do
|
|
igniter
|
|
|> point_to_application_in_mix_exs(application)
|
|
|> create_application_file(application)
|
|
end
|
|
|
|
def do_add_child(igniter, application, to_supervise) do
|
|
path = Igniter.Code.Module.proper_location(application)
|
|
|
|
diff_checker =
|
|
case to_supervise do
|
|
v when is_atom(v) ->
|
|
&Common.nodes_equal?/2
|
|
|
|
{v, _opts} when is_atom(v) ->
|
|
fn
|
|
{item, _}, {right, _} ->
|
|
Common.nodes_equal?(item, right)
|
|
|
|
item, {right, _} ->
|
|
Common.nodes_equal?(item, right)
|
|
|
|
_, _ ->
|
|
false
|
|
end
|
|
end
|
|
|
|
Igniter.update_elixir_file(igniter, path, fn zipper ->
|
|
with {:ok, zipper} <- Igniter.Code.Module.move_to_module_using(zipper, Application),
|
|
{:ok, zipper} <- Igniter.Code.Module.move_to_def(zipper, :start, 2) do
|
|
zipper
|
|
|> Igniter.Code.Function.move_to_function_call_in_current_scope(:=, [2], fn call ->
|
|
Igniter.Code.Function.argument_matches_pattern?(
|
|
call,
|
|
0,
|
|
{:children, _, context} when is_atom(context)
|
|
) &&
|
|
Igniter.Code.Function.argument_matches_pattern?(call, 1, v when is_list(v))
|
|
end)
|
|
|> case do
|
|
{:ok, zipper} ->
|
|
zipper
|
|
|> Zipper.down()
|
|
|> Zipper.rightmost()
|
|
|> Igniter.Code.List.append_new_to_list(to_supervise, diff_checker)
|
|
|
|
_ ->
|
|
{:error,
|
|
"Expected the `start/2` function in `#{path}` to have a `children = [...]` assignment."}
|
|
end
|
|
else
|
|
_ ->
|
|
{:error, "Expected `#{path}` to be an Application with a `start` function"}
|
|
end
|
|
end)
|
|
end
|
|
|
|
defp create_application_file(igniter, application) do
|
|
path = Igniter.Code.Module.proper_location(application)
|
|
|
|
contents = """
|
|
defmodule #{inspect(application)} do
|
|
@moduledoc false
|
|
|
|
use Application
|
|
|
|
@impl true
|
|
def start(_type, _args) do
|
|
children = []
|
|
|
|
opts = [strategy: :one_for_one, name: Foo.Supervisor]
|
|
Supervisor.start_link(children, opts)
|
|
end
|
|
end
|
|
"""
|
|
|
|
Igniter.create_new_elixir_file(igniter, path, contents)
|
|
end
|
|
|
|
defp point_to_application_in_mix_exs(igniter, application) do
|
|
Igniter.update_elixir_file(igniter, "mix.exs", fn zipper ->
|
|
case Igniter.Code.Module.move_to_module_using(zipper, Mix.Project) do
|
|
{:ok, zipper} ->
|
|
case Igniter.Code.Module.move_to_def(zipper, :application, 0) do
|
|
{:ok, zipper} ->
|
|
zipper
|
|
|> Zipper.rightmost()
|
|
|> Igniter.Code.Keyword.set_keyword_key(:mod, {application, []}, fn z ->
|
|
{:ok, Zipper.replace(z, {application, []})}
|
|
end)
|
|
|
|
_ ->
|
|
Common.add_code(zipper, """
|
|
def application do
|
|
[
|
|
mod: {#{inspect(application)}, []}
|
|
]
|
|
end
|
|
""")
|
|
end
|
|
|
|
_ ->
|
|
{:error, "Required a module using `Mix.Project` to exist in `mix.exs`"}
|
|
end
|
|
end)
|
|
end
|
|
end
|