Skip to content

Commit

Permalink
improvement: handle igniter not being compiled, and make it optional
Browse files Browse the repository at this point in the history
  • Loading branch information
zachdaniel committed Dec 19, 2024
1 parent 4a65000 commit 517201e
Show file tree
Hide file tree
Showing 10 changed files with 1,639 additions and 1,457 deletions.
140 changes: 71 additions & 69 deletions lib/ash/domain/igniter.ex
Original file line number Diff line number Diff line change
@@ -1,45 +1,87 @@
defmodule Ash.Domain.Igniter do
@moduledoc "Codemods for working with Ash.Domain modules"
if Code.ensure_loaded?(Igniter) do
defmodule Ash.Domain.Igniter do
@moduledoc "Codemods for working with Ash.Domain modules"

@doc "List all domain modules found in the project"
def list_domains(igniter) do
Igniter.Project.Module.find_all_matching_modules(igniter, fn _mod, zipper ->
zipper
|> Igniter.Code.Module.move_to_use(Ash.Domain)
|> case do
{:ok, _} ->
true
@doc "List all domain modules found in the project"
def list_domains(igniter) do
Igniter.Project.Module.find_all_matching_modules(igniter, fn _mod, zipper ->
zipper
|> Igniter.Code.Module.move_to_use(Ash.Domain)
|> case do
{:ok, _} ->
true

_ ->
false
end
end)
end
_ ->
false
end
end)
end

@doc "Adds a resource reference to a domain's `resources` block"
def add_resource_reference(igniter, domain, resource) do
{igniter, domains} = Ash.Domain.Igniter.list_domains(igniter)
@doc "Adds a resource reference to a domain's `resources` block"
def add_resource_reference(igniter, domain, resource) do
{igniter, domains} = Ash.Domain.Igniter.list_domains(igniter)

if domain in domains do
if domain in domains do
Igniter.Project.Module.find_and_update_module!(igniter, domain, fn zipper ->
case Igniter.Code.Function.move_to_function_call_in_current_scope(
zipper,
:resources,
1
) do
:error ->
code =
"""
resources do
resource #{inspect(resource)}
end
"""

{:ok, Igniter.Code.Common.add_code(zipper, code)}

{:ok, zipper} ->
with {:ok, zipper} <- Igniter.Code.Common.move_to_do_block(zipper),
:error <-
Igniter.Code.Function.move_to_function_call_in_current_scope(
zipper,
:resource,
1,
fn call ->
Igniter.Code.Function.argument_matches_predicate?(
call,
0,
&Igniter.Code.Common.nodes_equal?(&1, resource)
)
end
) do
{:ok, Igniter.Code.Common.add_code(zipper, "resource #{inspect(resource)}")}
else
_ ->
{:ok, zipper}
end
end
end)
else
igniter
|> Igniter.add_warning(
"Domain #{domain} was not an `Ash.Domain`, so could not add `#{inspect(resource)}` to its resource list."
)
end
end

@doc "Removes a resource reference from a domain's `resources` block"
def remove_resource_reference(igniter, domain, resource) do
Igniter.Project.Module.find_and_update_module!(igniter, domain, fn zipper ->
case Igniter.Code.Function.move_to_function_call_in_current_scope(
zipper,
:resources,
1
) do
:error ->
code =
"""
resources do
resource #{inspect(resource)}
end
"""

{:ok, Igniter.Code.Common.add_code(zipper, code)}
zipper

{:ok, zipper} ->
with {:ok, zipper} <- Igniter.Code.Common.move_to_do_block(zipper),
:error <-
{:ok, zipper} <-
Igniter.Code.Function.move_to_function_call_in_current_scope(
zipper,
:resource,
Expand All @@ -52,53 +94,13 @@ defmodule Ash.Domain.Igniter do
)
end
) do
{:ok, Igniter.Code.Common.add_code(zipper, "resource #{inspect(resource)}")}
{:ok, Sourceror.Zipper.remove(zipper)}
else
_ ->
{:ok, zipper}
end
end
end)
else
igniter
|> Igniter.add_warning(
"Domain #{domain} was not an `Ash.Domain`, so could not add `#{inspect(resource)}` to its resource list."
)
end
end

@doc "Removes a resource reference from a domain's `resources` block"
def remove_resource_reference(igniter, domain, resource) do
Igniter.Project.Module.find_and_update_module!(igniter, domain, fn zipper ->
case Igniter.Code.Function.move_to_function_call_in_current_scope(
zipper,
:resources,
1
) do
:error ->
zipper

{:ok, zipper} ->
with {:ok, zipper} <- Igniter.Code.Common.move_to_do_block(zipper),
{:ok, zipper} <-
Igniter.Code.Function.move_to_function_call_in_current_scope(
zipper,
:resource,
1,
fn call ->
Igniter.Code.Function.argument_matches_predicate?(
call,
0,
&Igniter.Code.Common.nodes_equal?(&1, resource)
)
end
) do
{:ok, Sourceror.Zipper.remove(zipper)}
else
_ ->
{:ok, zipper}
end
end
end)
end
end
44 changes: 23 additions & 21 deletions lib/ash/igniter.ex
Original file line number Diff line number Diff line change
@@ -1,29 +1,31 @@
defmodule Ash.Igniter do
@moduledoc "Codemods and utilities for working with Ash & Igniter"
if Code.ensure_loaded?(Igniter) do
defmodule Ash.Igniter do
@moduledoc "Codemods and utilities for working with Ash & Igniter"

@doc "Adds a codegen task, or updates the name to be `<old_name>_and_name`"
def codegen(igniter, name) do
has_codegen? =
Enum.any?(igniter.tasks, fn
{"ash.codegen", _args} ->
true
@doc "Adds a codegen task, or updates the name to be `<old_name>_and_name`"
def codegen(igniter, name) do
has_codegen? =
Enum.any?(igniter.tasks, fn
{"ash.codegen", _args} ->
true

_ ->
false
end)
_ ->
false
end)

if has_codegen? do
Map.update!(igniter, :tasks, fn tasks ->
Enum.map(tasks, fn
{"ash.codegen", [old_name | rest]} ->
{"ash.codegen", [old_name <> "_and_#{name}" | rest]}
if has_codegen? do
Map.update!(igniter, :tasks, fn tasks ->
Enum.map(tasks, fn
{"ash.codegen", [old_name | rest]} ->
{"ash.codegen", [old_name <> "_and_#{name}" | rest]}

task ->
task
task ->
task
end)
end)
end)
else
Igniter.add_task(igniter, "ash.codegen", [name])
else
Igniter.add_task(igniter, "ash.codegen", [name])
end
end
end
end
Loading

0 comments on commit 517201e

Please sign in to comment.