@@ -96,7 +96,8 @@ defmodule Macro.Env do
9696 ]
9797
9898 @ type expand_import_opts :: [
99- allow_locals: boolean ( ) ,
99+ allow_locals:
100+ boolean ( ) | ( Macro . metadata ( ) , atom ( ) , arity ( ) , t ( ) -> function ( ) | false ) ,
100101 check_deprecations: boolean ( ) ,
101102 trace: boolean ( )
102103 ]
@@ -555,8 +556,15 @@ defmodule Macro.Env do
555556
556557 ## Options
557558
558- * `:allow_locals` - when set to `false`, it does not attempt to capture
559- local macros defined in the current module in `env`
559+ * `:allow_locals` - controls how local macros are resolved.
560+ Defaults to `true`.
561+
562+ - When `false`, does not attempt to capture local macros defined in the
563+ current module in `env`
564+ - When `true`, uses a default resolver that looks for public macros in
565+ the current module
566+ - When a function, uses the function as a custom local resolver. The function
567+ must have the signature: `(meta, name, arity, env) -> function() | false`
560568
561569 * `:check_deprecations` - when set to `false`, does not check for deprecations
562570 when expanding macros
@@ -580,10 +588,16 @@ defmodule Macro.Env do
580588 trace = Keyword . get ( opts , :trace , true )
581589 module = env . module
582590
591+ # When allow_locals is a callback, we don't need to pass module macros as extra
592+ # because the callback will handle local macro resolution
583593 extra =
584- case allow_locals and function_exported? ( module , :__info__ , 1 ) do
585- true -> [ { module , module . __info__ ( :macros ) } ]
586- false -> [ ]
594+ if is_function ( allow_locals , 4 ) do
595+ [ ]
596+ else
597+ case allow_locals and function_exported? ( module , :__info__ , 1 ) do
598+ true -> [ { module , module . __info__ ( :macros ) } ]
599+ false -> [ ]
600+ end
587601 end
588602
589603 case :elixir_dispatch . expand_import ( meta , name , arity , env , extra , allow_locals , trace ) do
0 commit comments