- Notifications
You must be signed in to change notification settings - Fork 3.5k
Description
Environment
- Elixir & Erlang/OTP versions (elixir --version): 1.7.2
- Operating system: macOS
Current behavior
I wanted to create macro that would allow me to remove boilerplate over generating structures for events in my application. To document such structures I wanted to use @doc
to simulate feeling that these are normal parts of the external module instead of being separate modules, ex.:
defmodule MyApp.Event do import Events @moduledoc false @doc """ Creation of new submission """ @doc deprecated: "Foo" defevent SubmissionCreated, id: any(), name: String.t(), author: [map()] end
While basic implementation is dumb easy documentation is quite challenging. What I have achieved is:
defmodule Events do @moduledoc false defmacro defevent(module, fields \\ []) do keys = Keyword.keys(fields) quote do docs = Module.get_attribute(__MODULE__, :doc) deprecated = case Module.get_attribute(__MODULE__, :deprecated) do nil -> [] value -> [deprecated: value] end {set, _} = :elixir_module.data_tables(__MODULE__) metadata = case :ets.lookup(set, {:doc, :meta}) do [{{:doc, :meta}, metadata, _}] -> deprecated ++ Keyword.new(metadata) [] -> deprecated end defmodule unquote(module) do if docs, do: Module.put_attribute(__MODULE__, :moduledoc, docs) if metadata != [], do: @moduledoc metadata @type t :: %__MODULE__{unquote_splicing(fields)} defstruct unquote(keys) end :elixir_module.delete_definition_attributes(__ENV__, nil, nil, nil, nil, nil) end end end
Which is fairly ok, except of the part where I need manually get data from ETS for documentation metadata. It cannot be mitigated by using Module.get_attribute/2
as it explicitly requires atom as a second argument while metadata are stored under {:doc, :meta}
.
Expected behavior
Somehow allow fetching documentation metadata in macros. This would allow macro writers to utilise that metadata in some way like example above.