DocShell.Generate.ExDoc (DocShell v0.1.0)

Copy Markdown View Source

Extracts documentation from compiled modules through the BEAM docs chunk.

This reads the same Docs chunk that h MyApp.Accounts and ExDoc read, so what comes out is whatever the compiler actually stored — no source parsing, no separate Markdown pass over .ex files, and no chance of the artifact disagreeing with IEx. The modules must be compiled and loadable; in practice that means running inside the host application, which is what mix doc_shell.build arranges.

Each module becomes one entry:

%{
  "id" => "MyApp.Accounts",
  "title" => "MyApp.Accounts",
  "kind" => "module",
  "ast" => [...],
  "meta" => %{
    "module" => "MyApp.Accounts",
    "language" => "elixir",
    "moduledoc" => "present",
    "members" => [...]
  }
}

ast is the module documentation parsed by DocShell.Ast. members lists every documented function, macro, callback, and type with its kind, name, arity, signatures, raw documentation, and metadata such as since or deprecated. Member documentation is left as Markdown text rather than parsed, because a page usually renders a member list lazily and parsing every member of every module up front is work most renderers throw away.

Modules without documentation

A module compiled with --no-docs, or from Erlang without a chunk, is skipped rather than treated as an error — extract/1 simply omits it. A module that has a chunk but fails to read is an error, tagged with the module name.

Modules that have a chunk but no prose are a different case, and they are deliberately still returned, with an empty ast. meta["moduledoc"] says which situation each one is in:

  • "present" — the module has documentation
  • "hidden" — the author wrote @moduledoc false
  • "none" — no @moduledoc at all

Extraction stays complete because callers use it for more than rendering: a documentation-coverage report needs the undocumented modules precisely because they are undocumented, and dropping them here would make every codebase look fully documented.

Filtering for display happens later, in DocShell.Presentation.StaticGenerator, which skips empty entries by default so mix doc_shell.build does not fill a navigation tree with internal modules that opted out.

Modules are sorted by name so the artifact is stable across builds.

Summary

Functions

Extracts documentation for a list of compiled modules.

Extracts one compiled module.

Functions

extract(modules)

@spec extract([module()]) :: {:ok, [map()]} | {:error, term()}

Extracts documentation for a list of compiled modules.

Undocumented modules are omitted. The first module that fails to read short-circuits the run and returns {:error, {module, reason}}.

extract_module(module)

@spec extract_module(module()) :: {:ok, map() | nil} | {:error, term()}

Extracts one compiled module.

Returns {:ok, nil} when the module carries no docs chunk, which callers treat as "nothing to document" rather than as a failure.