Functions inside __using__ and documentation

Hello,
I’ve got a question regarding documenting functions that lies inside a __using__ block.
These functions are not listed in documentation, which is understandable because they don’t really exists yet.
But for my particular case it would be very interesting to have doc about them for end users.
Currently my module is something like this:

defmodule UsingModule do
  defmacro __using__(opts) do
    quote bind_quoted: [opts: opts] do
      def do_stuff(arg) do 
        OtherModule.do_stuff(__MODULE__, arg)
      end
      
      def do_more_stuff(arg1, arg2) do 
        OtherModule.do_more_stuff(__MODULE__, arg1, arg2)
      end
    end
end

and my goal is to document:

  • UsingModule.do_stuff/1
  • UsingModule.do_more_stuff/2

For now, the only working solution I’ve found is… to add callback for each of these functions, like this:

@doc """
  Mighty doc for do_stuff
  """
  @callback do_stuff(String.t) :: :ok | {:error, String.t}
  
  @doc """
  Great doc for do_more_stuff
  """
  @callback do_more_stuff(String.t, integer) :: :ok | {:error, String.t}

This is a bit strange as I don’t want a behaviour…
Is this the way to go or is there a better way to achieve what I want?

thank you

Not really. However these will be documented in module where you will do use.

1 Like

In a case like this, I would document do_stuff and do_more_stuff in the module documentation top section, more or less like GenServer does with child_spec/1 here.

The reason is that these functions are not defined on your UsingModule, but instead will be defined in the module that calls use UsingModule. So the correct way to document them, in my opinion, is to say that use UsingModule will define do_stuff and do_more_stuff with some specific interface.

These functions don’t exis and never will. The will only exist in the module that calls use UsingModule.

To have more context, the module I’m working on is a Ecto.Repo-like without the adapter parts, this means too much functions to have them detailed in the head of the doc in a clear way.
Also I understand that functions will be documented in the module calling use UsingModule, I find it counter intuitive for end-users to search for documentation in their own project.

An other option would be to have a “fake” module in my package using use UsingModule, and this useless “fake” module will be used for API doc only…

I think you are right that it should be documented in your module. But not as a function documentation (as your module does not contain those functions), rather in the @moduledoc section. You can document that use UsingModule will define do_stuff and do_more_stuff in the end user’s module, and explain their interface there.

The core modules are usually documented this way (see the link to the GenServer docs in my previous message for an example).

I use this approach (an example module) in some libs I publish. I put the example in a directory that is compiled for :dev, :test and :doc but not for :prod. And then after I push the package I push the docs again, but using the :doc environment. That way the docs are available on hexdocs.pm but not part of the published packages.

I’ll go with the example module, it seems to be the cleanest solution imo.
Thank you.