-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Add local_for_callback option to Macro.Env.expand_import #14620
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
base: main
Are you sure you want to change the base?
Add local_for_callback option to Macro.Env.expand_import #14620
Conversation
lib/elixir/lib/macro/env.ex
Outdated
end | ||
|
||
case :elixir_dispatch.expand_import(meta, name, arity, env, extra, allow_locals, trace) do | ||
case :elixir_dispatch.expand_import(meta, name, arity, env, extra, allow_locals, trace, local_for_callback) do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of adding a new option, we can augment allow_locals
. If it is false, it is disabled, if it is true, it is the default implementation (elixir_locals
), otherwise it is a custom function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done on the erlang side. Do you also want that on the elixir API side?
We can definitely get this in. I have dropped some comments, some of them are about refactoring the current code, but I can also do that after merging. |
Allow hooking into local macro resolution
a1349a8
to
997eb4c
Compare
use one param
@josevalim I removed the
|
@lukaszsamson so please keep the extra for now. we can merge it and i will investigate it later :) |
lib/elixir/lib/macro/env.ex
Outdated
- When `true`, uses a default resolver that looks for public macros in | ||
the current module | ||
- When a function, uses the function as a custom local resolver. The function | ||
must have the signature: `(meta, name, arity, kinds, env) -> function() | false` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't really need the kinds
, do we? I think it can be hidden from the API so we keep this as a 4 arity function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could hide kinds and assume it's a macro resolver.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let’s do that, since it is for expansion (so it has to be macros)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
lib/elixir/lib/macro/env.ex
Outdated
@@ -96,7 +96,7 @@ defmodule Macro.Env do | |||
] | |||
|
|||
@type expand_import_opts :: [ | |||
allow_locals: boolean(), | |||
allow_locals: boolean() | (Macro.metadata(), atom(), arity(), [atom()], t() -> any()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we return any
or does it have to be AST?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually the return type is false | function()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, so we should update it!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
This PR adds a new option
:local_for_callback
toMacro.Env.expand_import
in order to allow hooking into local macro resolution and providing a custom resolver.Rationale:
In ElixirSense minicompiler I need to resolve local macros using the metadata extracted from the AST. The current mechanism relying on
:elixir_def.local_for
is not going to work correctly when there is no real compilation in process. The current hacky code usingextra
filled with__info__(:macros)
only returns public macros and with that only those already compiled and loadable. The result is improper tracking of references in traversed code.Example code using the new option:
The PR is based on the current code used in ElixirSense. I'm opening it as a draft. If there is will to merge this I'll work on tests.
Related PR hooking into
define_import
:#13628