Skip to content

Commit e9d0084

Browse files
authored
improvement: add Igniter.Libs.Phoenix.web_module_for_router/2 (#393)
1 parent a4b5364 commit e9d0084

2 files changed

Lines changed: 70 additions & 0 deletions

File tree

lib/igniter/libs/phoenix.ex

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,41 @@ defmodule Igniter.Libs.Phoenix do
9292
Module.concat(web_module(igniter), suffix)
9393
end
9494

95+
@doc """
96+
Returns the web module that the given `router` belongs to.
97+
98+
Reads the router's `use <WebModule>, :router` declaration, which is the module
99+
that generated modules (`use <WebModule>, :controller`, `:verified_routes`,
100+
etc.) should reference. This lets installers place generated modules alongside
101+
the selected router rather than assuming the application's default web module.
102+
103+
Falls back to `web_module/1` when the router uses `Phoenix.Router` directly or
104+
cannot be found.
105+
"""
106+
@spec web_module_for_router(Igniter.t(), module()) :: {Igniter.t(), module()}
107+
def web_module_for_router(igniter, router) do
108+
case Igniter.Project.Module.find_module(igniter, router) do
109+
{:ok, {igniter, _source, zipper}} ->
110+
{igniter, web_module_from_router_use(zipper) || web_module(igniter)}
111+
112+
{:error, igniter} ->
113+
{igniter, web_module(igniter)}
114+
end
115+
end
116+
117+
defp web_module_from_router_use(zipper) do
118+
with {:ok, use_call} <-
119+
Igniter.Code.Function.move_to_function_call(zipper, :use, 2, fn call ->
120+
Igniter.Code.Function.argument_equals?(call, 1, :router)
121+
end),
122+
{:ok, arg} <- Igniter.Code.Function.move_to_nth_argument(use_call, 0),
123+
{:__aliases__, _, parts} <- Igniter.Code.Common.expand_aliases(arg).node do
124+
Module.concat(parts)
125+
else
126+
_ -> nil
127+
end
128+
end
129+
95130
@doc "Gets the list of endpoints that use a given router"
96131
@spec endpoints_for_router(igniter :: Igniter.t(), router :: module()) ::
97132
{Igniter.t(), list(module())}

test/igniter/libs/phoenix_test.exs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,41 @@ defmodule Igniter.Libs.PhoenixTest do
7171
assert Igniter.Libs.Phoenix.web_module_name(test_project(), "Suffix") == TestWeb.Suffix
7272
end
7373

74+
describe "web_module_for_router/2" do
75+
test "reads the web module from the router's `use _, :router` declaration" do
76+
igniter =
77+
test_project()
78+
|> Igniter.create_new_file("lib/admin_web/router.ex", """
79+
defmodule AdminWeb.Router do
80+
use AdminWeb, :router
81+
end
82+
""")
83+
|> apply_igniter!()
84+
85+
assert {_igniter, AdminWeb} =
86+
Igniter.Libs.Phoenix.web_module_for_router(igniter, AdminWeb.Router)
87+
end
88+
89+
test "falls back to `web_module/1` for a `use Phoenix.Router` router" do
90+
igniter =
91+
test_project()
92+
|> Igniter.create_new_file("lib/plain/router.ex", """
93+
defmodule Plain.Router do
94+
use Phoenix.Router
95+
end
96+
""")
97+
|> apply_igniter!()
98+
99+
assert {_igniter, TestWeb} =
100+
Igniter.Libs.Phoenix.web_module_for_router(igniter, Plain.Router)
101+
end
102+
103+
test "falls back to `web_module/1` when the router cannot be found" do
104+
assert {_igniter, TestWeb} =
105+
Igniter.Libs.Phoenix.web_module_for_router(test_project(), Missing.Router)
106+
end
107+
end
108+
74109
describe "list_web_modules/1" do
75110
test "finds web modules that are one level deep and end with Web" do
76111
igniter =

0 commit comments

Comments
 (0)