Packages
igniter
0.3.30
0.8.2
0.8.1
0.8.0
0.7.9
0.7.8
0.7.7
0.7.6
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.30
0.6.29
0.6.28
0.6.27
0.6.26
0.6.25
0.6.24
0.6.23
0.6.22
0.6.21
0.6.20
0.6.19
0.6.18
0.6.17
0.6.16
0.6.15
0.6.14
0.6.13
0.6.12
0.6.11
0.6.10
0.6.9
0.6.8
0.6.7
0.6.6
0.6.5
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.52
0.5.51
0.5.50
0.5.49
0.5.48
0.5.47
0.5.46
0.5.45
0.5.44
0.5.43
0.5.42
0.5.41
0.5.40
0.5.39
0.5.38
0.5.37
0.5.36
0.5.35
0.5.34
0.5.33
0.5.32
0.5.31
0.5.30
0.5.29
0.5.28
0.5.27
0.5.26
0.5.25
0.5.24
0.5.23
0.5.22
0.5.21
0.5.20
0.5.19
0.5.18
0.5.17
0.5.16
0.5.15
0.5.14
0.5.13
0.5.12
0.5.11
0.5.10
0.5.9
0.5.8
0.5.7
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.78
0.3.77
0.3.76
0.3.75
0.3.74
0.3.73
0.3.72
0.3.71
0.3.70
0.3.69
0.3.68
0.3.67
0.3.66
0.3.65
0.3.64
0.3.63
0.3.62
0.3.61
0.3.60
0.3.59
0.3.58
0.3.57
0.3.56
0.3.55
0.3.54
0.3.53
0.3.52
0.3.51
0.3.50
0.3.49
0.3.48
0.3.47
0.3.46
0.3.45
0.3.44
0.3.43
0.3.42
0.3.41
0.3.40
0.3.39
0.3.38
0.3.37
0.3.36
0.3.35
0.3.34
0.3.33
0.3.32
0.3.31
0.3.30
0.3.29
0.3.28
0.3.27
0.3.26
0.3.25
0.3.24
0.3.23
0.3.22
0.3.21
0.3.20
0.3.19
0.3.18
0.3.17
0.3.16
0.3.15
0.3.14
0.3.13
0.3.12
0.3.11
0.3.10
0.3.9
0.3.8
0.3.7
0.3.6
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.13
0.2.12
0.2.11
0.2.10
0.2.9
0.2.8
0.2.7
0.2.6
0.2.5
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.1.8
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
A code generation and project patching framework
Current section
Files
Jump to
Current section
Files
lib/igniter/libs/phoenix.ex
defmodule Igniter.Libs.Phoenix do
@moduledoc "Codemods & utilities for working with Phoenix"
@doc """
Returns the web module name for the current app
"""
@spec web_module_name() :: module()
@deprecated "Use `web_module/0` instead."
def web_module_name do
Module.concat([inspect(Igniter.Code.Module.module_name_prefix(Igniter.new())) <> "Web"])
end
@doc """
Returns the web module name for the current app
"""
@spec web_module(Igniter.t()) :: module()
def web_module(igniter) do
Module.concat([inspect(Igniter.Code.Module.module_name_prefix(igniter)) <> "Web"])
end
@doc """
Generates a module name that lives in the Web directory of the current app.
"""
@spec web_module_name(String.t()) :: module()
@deprecated "Use `web_module_name/1` instead."
def web_module_name(suffix) do
Module.concat(inspect(Igniter.Code.Module.module_name_prefix(Igniter.new())) <> "Web", suffix)
end
@spec web_module_name(Igniter.t(), String.t()) :: module()
def web_module_name(igniter, suffix) do
Module.concat(inspect(Igniter.Code.Module.module_name_prefix(igniter)) <> "Web", suffix)
end
@spec endpoints_for_router(igniter :: Igniter.t(), router :: module()) ::
{Igniter.t(), list(module())}
def endpoints_for_router(igniter, router) do
Igniter.Code.Module.find_all_matching_modules(igniter, fn _module, zipper ->
with {:ok, _} <- Igniter.Code.Module.move_to_use(zipper, Phoenix.Endpoint),
{:ok, _} <-
Igniter.Code.Function.move_to_function_call_in_current_scope(
zipper,
:plug,
[1, 2],
&Igniter.Code.Function.argument_equals?(&1, 0, router)
) do
true
else
_ ->
false
end
end)
end
def add_scope(igniter, route, contents, opts \\ []) do
{igniter, router} =
case Keyword.fetch(opts, :router) do
{:ok, router} ->
{igniter, router}
:error ->
select_router(igniter)
end
scope_code =
case Keyword.fetch(opts, :arg2) do
{:ok, arg2} ->
contents = Sourceror.parse_string!(contents)
quote do
scope unquote(route), unquote(arg2) do
unquote(contents)
end
end
|> Sourceror.to_string()
_ ->
"""
scope #{inspect(route)} do
#{contents}
end
"""
end
if router do
Igniter.Code.Module.find_and_update_module!(igniter, router, fn zipper ->
case move_to_scope_location(igniter, zipper) do
{:ok, zipper, append_or_prepend} ->
{:ok, Igniter.Code.Common.add_code(zipper, scope_code, append_or_prepend)}
:error ->
{:warning,
Igniter.Util.Warning.formatted_warning(
"Could not add a scope for #{inspect(route)} to your router. Please add it manually.",
scope_code
)}
end
end)
else
Igniter.add_warning(
igniter,
Igniter.Util.Warning.formatted_warning(
"Could not add a scope for #{inspect(route)} to your router. Please add it manually.",
scope_code
)
)
end
end
def add_pipeline(igniter, name, contents, opts \\ []) do
{igniter, router} =
case Keyword.fetch(opts, :router) do
{:ok, router} ->
{igniter, router}
:error ->
select_router(igniter)
end
pipeline_code = """
pipeline #{inspect(name)} do
#{contents}
end
"""
if router do
Igniter.Code.Module.find_and_update_module!(igniter, router, fn zipper ->
Igniter.Code.Function.move_to_function_call(zipper, :pipeline, 2, fn zipper ->
Igniter.Code.Function.argument_matches_predicate?(
zipper,
0,
&Igniter.Code.Common.nodes_equal?(&1, name)
)
end)
|> case do
{:ok, _} ->
if Keyword.get(opts, :warn_on_present?, true) do
{:warning,
Igniter.Util.Warning.formatted_warning(
"The #{name} pipeline already exists in the router. Attempting to add scope: ",
pipeline_code
)}
else
{:ok, zipper}
end
_ ->
case move_to_pipeline_location(igniter, zipper) do
{:ok, zipper, append_or_prepend} ->
{:ok, Igniter.Code.Common.add_code(zipper, pipeline_code, append_or_prepend)}
:error ->
{:warning,
Igniter.Util.Warning.formatted_warning(
"Could not add the #{name} pipline to your router. Please add it manually.",
pipeline_code
)}
end
end
end)
else
Igniter.add_warning(
igniter,
Igniter.Util.Warning.formatted_warning(
"Could not add the #{name} pipline to your router. Please add it manually.",
pipeline_code
)
)
end
end
def select_router(igniter, label \\ "Which router should be modified?") do
case list_routers(igniter) do
{igniter, []} ->
{igniter, nil}
{igniter, [router]} ->
{igniter, router}
{igniter, routers} ->
router_numbers =
routers
|> Enum.with_index()
|> Enum.map_join("\n", fn {router, index} ->
"#{index}. #{inspect(router)}"
end)
case String.trim(
Mix.shell().prompt(label <> "\n" <> router_numbers <> "\nInput router number ❯ ")
) do
"" ->
select_router(igniter, label)
router ->
case Integer.parse(router) do
{int, ""} ->
{igniter, Enum.at(routers, int)}
_ ->
Mix.shell().info("Expected a number, got: #{router}")
select_router(igniter, label)
end
end
end
end
def list_routers(igniter) do
Igniter.Code.Module.find_all_matching_modules(igniter, fn _mod, zipper ->
move_to_router_use(igniter, zipper) != :error
end)
end
defp move_to_router_use(igniter, zipper) do
with :error <-
Igniter.Code.Function.move_to_function_call(zipper, :use, 2, fn zipper ->
Igniter.Code.Function.argument_matches_predicate?(
zipper,
0,
&Igniter.Code.Common.nodes_equal?(&1, router_using(igniter))
) &&
Igniter.Code.Function.argument_matches_predicate?(
zipper,
1,
&Igniter.Code.Common.nodes_equal?(&1, :router)
)
end) do
Igniter.Code.Module.move_to_use(zipper, Phoenix.Router)
end
end
defp move_to_pipeline_location(igniter, zipper) do
with {:pipeline, :error} <-
{:pipeline,
Igniter.Code.Function.move_to_function_call_in_current_scope(zipper, :pipeline, 2)},
:error <-
Igniter.Code.Function.move_to_function_call_in_current_scope(zipper, :scope, [2, 3, 4]) do
case move_to_router_use(igniter, zipper) do
{:ok, zipper} -> {:ok, zipper, :after}
:error -> :error
end
else
{:pipeline, {:ok, zipper}} ->
{:ok, zipper, :before}
{:ok, zipper} ->
{:ok, zipper, :before}
end
end
defp move_to_scope_location(igniter, zipper) do
with :error <-
Igniter.Code.Function.move_to_function_call_in_current_scope(zipper, :scope, [2, 3, 4]),
{:pipeline, :error} <- {:pipeline, last_pipeline(zipper)} do
case move_to_router_use(igniter, zipper) do
{:ok, zipper} -> {:ok, zipper, :after}
:error -> :error
end
else
{:ok, zipper} ->
{:ok, zipper, :before}
{:pipeline, {:ok, zipper}} ->
{:ok, zipper, :after}
end
end
defp last_pipeline(zipper) do
case Igniter.Code.Function.move_to_function_call_in_current_scope(zipper, :pipeline, 2) do
{:ok, zipper} ->
with zipper when not is_nil(zipper) <- Sourceror.Zipper.right(zipper),
{:ok, zipper} <- last_pipeline(zipper) do
{:ok, zipper}
else
_ ->
{:ok, zipper}
end
:error ->
:error
end
end
defp router_using(igniter) do
Module.concat([to_string(Igniter.Code.Module.module_name_prefix(igniter)) <> "Web"])
end
end