Hi everyone, I want to create a macro, and this macro should check is there a specific function inside the module is using this macro or not?
for Example it checks 2 functions like: validator and main_validator, if yes, the macro uses it to create a function named builder
the builder uses these functions. when user call the macro it creates for it the builder function.
defmodule AaMacro do
defmacro test_macro(opts \\ , do: block) do
# It should check is there function I want if yes
def builder(props) do
defmodule AaModule do
def validator(prop) do
Based on my knowledge and have read this post, the __info__ function is not working in compile time
Is there a way to check a function inside the module that uses our macro, the way like @before_compile and Module.defines? works, but I can not check is there x function with :url atom as the first entry?
defmodule AA do
... our macro
def x(:url, value) do
def x(:image, value) do
I think I need to check ast? but how can access to the module ast to check, because I do not have the module file path, there is just module name like AA inside my macro?
There’s no difference between these three functions in normal Elixir code:
def many_heads(:foo, x), do: ...
def many_heads(:bar, x), do: ...
def one_head(arg, x) do
case arg do
:foo -> ...
:bar -> ...
def one_head_with_a_function(arg, x) do
defp inner_function(:foo, x), do: ...
defp inner_function(:bar, x), do: ...
It would be impractical / impossible to write a macro that checks what you’re trying to check that treats all of many_heads, one_head and one_head_with_a_function alike - but it would be very confusing to write a macro that treats them differently.
The usual practice in this situation would be to split the function so that independently-overridable pieces have distinct names - url_validator(...) instead of validator(:url, ...).
You can also require the modules that need to implement validator and main_validator to have a behavior.
This isn’t solid, but if these modules are to use your own custom module, you can force them to have this behavior in __using__ macro and then you’d get warnings (or errors, if you pass —warnings-as-errors to mix) when they don’t implement required functions.