@@ -96,7 +96,8 @@ defmodule Macro.Env do
96
96
]
97
97
98
98
@ type expand_import_opts :: [
99
- allow_locals: boolean ( ) ,
99
+ allow_locals:
100
+ boolean ( ) | ( Macro . metadata ( ) , atom ( ) , arity ( ) , t ( ) -> function ( ) | false ) ,
100
101
check_deprecations: boolean ( ) ,
101
102
trace: boolean ( )
102
103
]
@@ -555,8 +556,15 @@ defmodule Macro.Env do
555
556
556
557
## Options
557
558
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`
560
568
561
569
* `:check_deprecations` - when set to `false`, does not check for deprecations
562
570
when expanding macros
@@ -580,10 +588,16 @@ defmodule Macro.Env do
580
588
trace = Keyword . get ( opts , :trace , true )
581
589
module = env . module
582
590
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
583
593
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
587
601
end
588
602
589
603
case :elixir_dispatch . expand_import ( meta , name , arity , env , extra , allow_locals , trace ) do
0 commit comments