You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Provide an API to access documentation metadata at compile time #8095
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.:
defmoduleMyApp.EventdoimportEvents@moduledocfalse@doc""" Creation of new submission """@docdeprecated: "Foo"defeventSubmissionCreated,id: any(),name: String.t(),author: [map()]end
While basic implementation is dumb easy documentation is quite challenging. What I have achieved is:
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.
changed the title [-]There is no way to programatically access to documentation metadata[/-][+]Provide an API to access documentation metadata at compile time[/+]on Aug 16, 2018
The documentation metadata and related fields is stored as private fields on the table, that's why you can't access it and you shouldn't rely on the compiler internals for this. :)
The other thing is that, even if we provide a way to access metadata, then you would also need a way to remove the documentation because there is no actual function definition. It feels like the best way to go here is to use your own attribute, such as @eventdoc, especially because you won't pretend that you are defining a function when it is actually a module.
The proper solution here would be to make @doc and friends an accumulated attribute, so accessing @doc would return all previously set values:
@doc"foo"@docbar: 1@doc#=> [{2, bar: 1}, {1, "foo"}]
This would also allow us to get rid of special cases in both Module and Kernel. The trouble with doing this now is that it will break code that expects @doc to always be a binary (or similar). So we can only do it on Elixir 2.0.
Reacted by Tiago Moraes, Dimitar Panayotov and zoey
@mguimas unfortunately a metadata can be named :doc, so that would be ambiguous, we will probably use a tuple-based format, such as {"doc", meta: "data"}, or a map: %{doc: "...", metadata: [...]}.
Activity
fertapric commentedon Aug 16, 2018
I would add "at compile time" to the title, because once compiled I think you can access the documentation using
Code.fetch_docs/1:)[-]There is no way to programatically access to documentation metadata[/-][+]Provide an API to access documentation metadata at compile time[/+]josevalim commentedon Aug 16, 2018
The documentation metadata and related fields is stored as private fields on the table, that's why you can't access it and you shouldn't rely on the compiler internals for this. :)
The other thing is that, even if we provide a way to access metadata, then you would also need a way to remove the documentation because there is no actual function definition. It feels like the best way to go here is to use your own attribute, such as
@eventdoc, especially because you won't pretend that you are defining a function when it is actually a module.josevalim commentedon Aug 16, 2018
The proper solution here would be to make
@docand friends an accumulated attribute, so accessing@docwould return all previously set values:This would also allow us to get rid of special cases in both Module and Kernel. The trouble with doing this now is that it will break code that expects
@docto always be a binary (or similar). So we can only do it on Elixir 2.0.hauleth commentedon Aug 16, 2018
@josevalim I agree that in this particular situation it makes sense to use custom attribute instead, but imagine something like that:
And while you maybe do not want to share most docs between them then currently supported tags makes sense for them (like
:sinceor:deprecated).mguimas commentedon May 9, 2019
@josevalim Instead of this
could you consider this
?
josevalim commentedon Jun 23, 2020
@mguimas unfortunately a metadata can be named
:doc, so that would be ambiguous, we will probably use a tuple-based format, such as{"doc", meta: "data"}, or a map:%{doc: "...", metadata: [...]}.hauleth commentedon Jun 23, 2020
@josevalim I would vote for the tuple + keyword list so:
Would result with:
mguimas commentedon Jun 23, 2020
@josevalim I believe that a good data structure is one that makes it is easy to use
Enumto traverse the information associated with the@docentries.So in the example
perhaps a good solution is
[:foo, {:bar, 1}, {:bar, 2}, :bar]which respects not only the contents, but also the order of the doc entries.
Nezteb commentedon Dec 22, 2023
@hauleth @josevalim It's been 3 years; I don't think this issue has been resolved, but I figured I'd check in with both of you to verify. 😄
wojtekmach commentedon Dec 22, 2023
It’s not. It’s marked for Elixir v2.0.
Nezteb commentedon Dec 22, 2023
Ah my bad. I'm on mobile and didn't scroll down to see the addition of the 2.0 milestone. 🤦♂️
Disregard me!