How to check a macro was called in a module

Hello folks,
I have a module of macros that helps me to implement some UI. I load it with use top of any module I want.
Every module uses 1 or more macros, for example:

Module A → macro A, macro B and C
Module B → macro J, macro G

now I want to check if Module A loaded B macro whether not, but in Module C

function_exported? and macro_exported? didn’t work because it is not a function at first and the second kernel function to check macro just works when I address it the module of macros not the module loaded this macro

defmodule A do

  use MacroModule,
      redirect: __MODULE__,
      router: Routes

 # paginate macro I loaded in this module
 paginate(:tags, user_id: false)
end

Now I want to check, did A module load paginate macro? But in C module like:

defmodule C do

   if A.paginate do
   ....
   end
end

How can I check this ? Thanks

1 Like

What do you mean by loading a macro.
requiring/importing it and being available to be used, or calling it?

If you can provide a minimal working example, it will be really helpful.

1 Like

Thank you for your response,

As I said above, I loaded it with use or whatever you said. But after loading them I want to check Module A, what macro it called? Macro A or Macro B.
If I want to explain this clearly! I need to know my module used (paginate or not to use this) this paginate is a macro I loaded it on my Module A.

EX:

defmodule AdminBlogTagsLive do

  use MishkaHtml.Helpers.LiveCRUD,
      redirect: __MODULE__,
      router: Routes

 # My custom macros
  paginate(:tags, user_id: false)

  list_search_and_action()

  delete_list_item(:tags, DeleteErrorComponent, false)

  selected_menue("MishkaHtmlWeb.AdminBlogTagsLive")

  update_list(:tags, false)
end

now how can you check if AdminBlogTagsLive loaded or called update_list or paginate macro?

So you are calling your macros in AdminBlogTagsLive at compile time?

1 Like

Yes, because of this I can not call him directly. This macro defends some functions in my module.

My macro:

Example using this in a module:

I think you could store this information in an ETS table at compile time. Have you already looked into it?

1 Like

this is a good way, I am using Mnesia instead of ETS in my project, but I think I should edit my DB query, it can helps me. I just want to learn about macro.

Thank you again.

1 Like

The simplest way to check is to define a function in those macros, then check for that. For instance, Ecto.Schema's schema macro ultimately defines a __schema__/1 function that makes the configuration passed to the macro available to the outside world.

3 Likes

I think you could simply use a module attribute to annotate your code:

  defmacro paginate(field_assigned, user_id: user_id)  do
    quote do
      Module.register_attribute(__MODULE__, :paginate)

      @impl Phoenix.LiveView
      def handle_params(%{"page" => page, "count" => count} = params, _url, socket) do
        ...
      end
   end
 end

And then in your consuming code:

if Module.has_attribute?(__MODULE__, :paginate) do
  # do something
end
1 Like

I think he wants to check whether the module has been called from a third module, therefore the modules have already been compiled and the modules attributes cannot be accessed.

Module A requires B, calls macro from B.
And he wants module C to know if macro from B was called by A.

1 Like

Should be easily doable with compiler hooks. But you shouldn’t do this.

1 Like