@@ -109,12 +109,14 @@ defmodule Phoenix.Router.Helpers do
109109 end )
110110
111111 trailing_slash? = Enum . any? ( routes , fn { route , _ } -> route . trailing_slash? end )
112-
113112 groups = Enum . group_by ( routes , fn { route , _exprs } -> route . helper end )
114113
115114 impls =
116- for { _helper , group } <- groups ,
117- { route , exprs } <- Enum . sort_by ( group , fn { _ , exprs } -> length ( exprs . binding ) end ) ,
115+ for { _helper , helper_routes } <- groups ,
116+ { _ , [ { route , exprs } | _ ] } <-
117+ helper_routes
118+ |> Enum . group_by ( fn { route , exprs } -> [ length ( exprs . binding ) | route . plug_opts ] end )
119+ |> Enum . sort ( ) ,
118120 do: defhelper ( route , exprs )
119121
120122 catch_all = Enum . map ( groups , & defhelper_catch_all / 1 )
@@ -143,8 +145,8 @@ defmodule Phoenix.Router.Helpers do
143145 end
144146
145147 defcatch_all = quote @ anno do
146- defcatch_all = fn helper , lengths , routes ->
147- for length <- lengths do
148+ defcatch_all = fn helper , binding_lengths , params_lengths , routes ->
149+ for length <- binding_lengths do
148150 binding = List . duplicate ( { :_ , [ ] , nil } , length )
149151 arity = length + 2
150152
@@ -153,15 +155,20 @@ defmodule Phoenix.Router.Helpers do
153155 raise_route_error ( unquote ( helper ) , :path , unquote ( arity ) , action , [ ] )
154156 end
155157
156- def unquote ( :"#{ helper } _path" ) ( conn_or_endpoint , action , unquote_splicing ( binding ) , params ) do
157- path ( conn_or_endpoint , "/" )
158- raise_route_error ( unquote ( helper ) , :path , unquote ( arity + 1 ) , action , params )
159- end
160-
161158 def unquote ( :"#{ helper } _url" ) ( conn_or_endpoint , action , unquote_splicing ( binding ) ) do
162159 url ( conn_or_endpoint )
163160 raise_route_error ( unquote ( helper ) , :url , unquote ( arity ) , action , [ ] )
164161 end
162+ end
163+
164+ for length <- params_lengths do
165+ binding = List . duplicate ( { :_ , [ ] , nil } , length )
166+ arity = length + 2
167+
168+ def unquote ( :"#{ helper } _path" ) ( conn_or_endpoint , action , unquote_splicing ( binding ) , params ) do
169+ path ( conn_or_endpoint , "/" )
170+ raise_route_error ( unquote ( helper ) , :path , unquote ( arity + 1 ) , action , params )
171+ end
165172
166173 def unquote ( :"#{ helper } _url" ) ( conn_or_endpoint , action , unquote_splicing ( binding ) , params ) do
167174 url ( conn_or_endpoint )
@@ -332,15 +339,27 @@ defmodule Phoenix.Router.Helpers do
332339 |> Enum . map ( fn { routes , exprs } -> { routes . plug_opts , Enum . map ( exprs . binding , & elem ( & 1 , 0 ) ) } end )
333340 |> Enum . sort ( )
334341
335- lengths =
342+ params_lengths =
336343 routes
337344 |> Enum . map ( fn { _ , bindings } -> length ( bindings ) end )
338345 |> Enum . uniq ( )
339346
347+ # Each helper defines catch alls like this:
348+ #
349+ # def helper_path(context, action, ...binding)
350+ # def helper_path(context, action, ...binding, params)
351+ #
352+ # Given the helpers are ordered by binding length, the additional
353+ # helper with param for a helper_path/n will always override the
354+ # binding for helper_path/n+1, so we skip those here to avoid warnings.
355+ binding_lengths =
356+ Enum . reject ( params_lengths , & ( & 1 - 1 in params_lengths ) )
357+
340358 quote do
341359 defcatch_all . (
342360 unquote ( helper ) ,
343- unquote ( lengths ) ,
361+ unquote ( binding_lengths ) ,
362+ unquote ( params_lengths ) ,
344363 unquote ( Macro . escape ( routes ) )
345364 )
346365 end
0 commit comments