查看源码 文档
Erlang 中的文档通过 -moduledoc
和 -doc
属性完成。 例如
-module(arith).
-moduledoc """
A module for basic arithmetic.
""".
-export([add/2]).
-doc "Adds two numbers.".
add(One, Two) -> One + Two.
-moduledoc
属性必须位于第一个 -doc
属性或函数声明之前。它记录了模块的整体用途。
-doc
属性始终位于它所文档化的函数或属性之前。可以文档化的属性包括用户定义的类型(-type
和 -opaque
)和行为模块属性(-callback
)。
默认情况下,文档属性使用的格式是 Markdown,但可以通过设置模块文档元数据来更改。
编写 Markdown 的一个好的起点是 基本的写作和格式语法。
有关 -moduledoc
和 -doc
属性中允许包含的内容的详细信息,请参阅文档属性。
-doc
属性自 Erlang/OTP 27 起可用。
文档元数据
可以向文档条目添加元数据。您可以通过添加一个以映射作为参数的 -moduledoc
或 -doc
属性来完成此操作。例如
-module(arith).
-moduledoc """
A module for basic arithmetic.
""".
-moduledoc #{since => "1.0"}.
-export([add/2]).
-doc "Adds two numbers.".
-doc(#{since => "1.0"}).
add(One, Two) -> One + Two.
元数据由文档工具使用,以向用户提供额外信息。可以有多个元数据文档条目,在这种情况下,映射将合并,如果存在重复的键,则以最新的为准。示例
-doc "Adds two numbers.".
-doc #{since => "1.0", author => "Joe"}.
-doc #{since => "2.0"}.
add(One, Two) -> One + Two.
这将导致元数据条目为 #{since => "2.0", author => "Joe"}
。
元数据映射中的键和值可以是任何类型,但建议键仅使用原子,值使用字符串。
外部文档文件
-moduledoc
和 -doc
也可以放在外部文件中。为此,使用 -doc {file, "path/to/doc.md"}
来指向文档。使用的路径是相对于 -doc
属性所在的文件而言的。 例如
%% doc/add.md
Adds two numbers.
和
%% src/arith.erl
-doc({file, "add.md"}).
add(One, Two) -> One + Two.
文档化模块
模块描述应包括如何使用 API 以及不同函数协同工作的示例的详细信息。这里是使用图像和其他图表更好地展示模块使用情况的好地方。与其在 moduledoc
属性中编写长文本,不如将其分解到外部页面中。
moduledoc
属性应以简短的段落描述模块开始,然后深入更详细的内容。例如
-module(arith).
-moduledoc """
A module for basic arithmetic.
This module can be used to add and subtract values. For example:
```erlang
1> arith:substract(arith:add(2, 3), 1).
4
```
""".
Moduledoc 元数据
对于 -moduledoc
,有三个保留的元数据键
since
- 显示模块在应用程序的哪个版本中添加。如果添加此项,则其中所有函数、类型和回调也将收到相同的since
值,除非在函数、类型或回调的元数据中指定。deprecated
- 在文档中显示一段文本,解释它已被弃用以及应改用什么。format
- 用于此模块中所有文档的格式。默认值为text/markdown
。它应该使用格式的MIME 类型编写。
示例
-moduledoc {file, "arith.asciidoc"}.
-moduledoc #{since => "0.1", format => "text/asciidoc"}.
-moduledoc #{deprecated => "Use the Erlang arithmetic operators instead."}.
文档化函数、用户定义的类型和回调
可以使用 -doc
属性来文档化函数、类型和回调。每个条目都应以简短的段落描述实体的目的开始,然后在需要时深入更详细的内容。
不建议在此文档中包含图像或图表,因为它被 IDE 和 c:h/1
使用来向用户显示文档。
例如
-doc """
A number that can be used by the arith module.
We use a special number here so that we know
that this number comes from this module.
""".
-opaque number() :: {arith, erlang:number()}.
-doc """
Adds two numbers.
### Example:
```
1> arith:add(arith:number(1), arith:number(2)). {number, 3}
```
""".
-spec add(number(), number()) -> number().
add({number, One}, {number, Two}) -> {number, One + Two}.
Doc 元数据
对于 -doc
,有四个保留的元数据键
since => unicode:chardata()
- 显示模块在应用程序的哪个版本中添加。deprecated => unicode:chardata()
- 在文档中显示一段文本,解释它已被弃用以及应改用什么。如果存在将函数标记为已弃用的-deprecated
属性,则编译器将自动插入此键。equiv => unicode:chardata() | F/A | F(...)
- 注释此函数等效于此模块中的另一个函数。可以使用Func/Arity
、Func(Args)
或 unicode 字符串来描述等效性。例如-doc #{equiv => add/3}. add(One, Two) -> add(One, Two, []). add(One, Two, Options) -> ...
或
-doc #{equiv => add(One, Two, [])}. -spec add(One :: number(), Two :: number()) -> number(). add(One, Two) -> add(One, Two, []). add(One, Two, Options) -> ...
进入 EEP-48 文档块元数据的条目是将该值转换为字符串。
exported => boolean()
- 一个boolean/0
,表示条目是否为exported
。此值由编译器自动设置,不应由用户设置。
文档签名
文档签名是一段简短的文本,用于描述函数及其参数。默认情况下,它是通过查看 -spec
或函数中的参数名称来确定的。例如
add(One, Two) -> One + Two.
-spec sub(One :: integer(), Two :: integer()) -> integer().
sub(X, Y) -> X - Y.
将具有 add(One, Two)
和 sub(One, Two)
的签名。
对于类型或回调,签名来源于类型或回调规范。例如
-type number(Value) :: {number, Value}.
%% signature will be `number(Value)`
-opaque number() :: {number, number()}.
%% signature will be `number()`
-callback increment(In :: number()) -> Out.
%% signature will be `increment(In)`
-callback increment(In) -> Out when In :: number().
%% signature will be `increment(In)`
如果无法从代码中“轻松”找出好的签名,则改为使用 MFA 语法。例如:add/2
、number/1
、increment/1
可以通过将其作为 -doc
属性的第一行来提供自定义签名。提供的签名必须采用函数声明的形式,直到 ->
。 例如
-doc """
add(One, Two)
Adds two numbers.
""".
add(A, B) -> A + B.
将创建签名 add(One, Two)
。签名将从文档字符串中删除,因此在上面的示例中,只有文本 "Adds two numbers"
将是文档的一部分。这适用于函数、类型和回调。
Markdown 中的链接
在 Markdown 中编写文档时,会在任何看起来像 MFA 的内联代码段中自动找到链接。例如
-doc "See `sub/2` for more details".
如果存在,将创建指向当前模块中 sub/2
函数的链接。也可以使用 `sub/2`
作为链接目标。例如
-doc "See [subtract](`sub/2`) for more details".
-doc "See [`sub/2`] for more details".
-doc """
See [subtract] for more details
[subtract]: `sub/2`
""".
-doc """
See [subtract][1] for more details
[1]: `sub/2`
""".
上面的示例导致创建相同的链接。
该链接也可以链接到其他实体
远程函数
- 使用module:function/arity
语法。
示例
-doc "See `arith:sub/2` for more details".
模块
- 编写带有m
前缀的模块。使用锚点跳转到模块中的特定位置。
示例
-doc "See `m:arith` for more details".
-doc "See `m:arith#anchor` for more details".
类型
- 使用与本地/远程函数相同的语法,但添加t
前缀。
示例
-doc "See `t:number/0` for more details".
-doc "See `t:arith:number/0` for more details".
回调
- 使用与本地/远程函数相同的语法,但添加c
前缀。
示例
-doc "See `c:increment/0` for more details".
-doc "See `c:arith:increment/0` for more details".
额外页面
- 对于当前应用程序中的额外页面,使用正常链接,例如 "[release notes](notes.md)
"。对于另一个应用程序中的额外页面,使用e
前缀并说明该页面所属的应用程序。也可以使用锚点跳转到页面中的特定位置。
示例
-doc "See `e:stdlib:unicode_usage` for more details".
-doc "See `e:stdlib:unicode_usage#notes-about-raw-filenames` for more details".
什么是可见的与隐藏的?
Erlang 应用程序
通常由各种公共和私有模块组成。也就是说,应该由其他应用程序使用的模块和不应该使用的模块。默认情况下,应用程序中的所有模块都是可见的,但是通过设置 -moduledoc false.
可以将特定模块隐藏为可用 API 的一部分。
Erlang 模块由公共和私有函数和类型属性组成。默认情况下,所有导出的函数、导出的类型和回调都被认为是可见的,并且是模块公共 API 的一部分。此外,任何其他可见类型属性引用的任何非导出类型也是可见的,但不被认为是公共 API 的一部分。例如
-export([example/0]).
-type private() :: one.
-spec example() -> private().
example() -> one.
在上面的代码中,函数 example/0
被导出,并且它引用了未导出的类型 private/0
。因此,example/0
和 private/0
都将被标记为可见。 private/0
类型将具有元数据字段 exported
设置为 false
,以表明它不是公共 API 的一部分。
如果要使可见实体隐藏,则需要将 -doc
属性设置为 false
。让我们重新访问之前的示例
-export([example/0]).
-type private() :: one.
-spec example() -> private().
-doc false.
example() -> one.
函数 example/0
被导出,但显式标记为隐藏;因此,example/0
和 private/0
都将被隐藏。
添加到自动隐藏的实体(未导出的函数或类型)的任何文档都将被忽略,并且会生成警告。可以使用注释来文档化此类函数。
编译和获取文档
默认情况下,Erlang 编译器会在编译模块时将文档插入到 EEP-48 文档块中。通过将 no_docs 标志传递给 compile:file/1
,或将 +no_docs
传递给 erlc,则不会插入文档块。
然后可以使用 code:get_doc/1
检索文档,或使用 shell 内置命令 h/1
)查看。例如
1> h(arith).
arith
A module for basic arithmetic.
2> h(arith, add).
add(One, Two)
Adds two numbers.
使用 ExDoc 生成 HTML/ePub 文档
ExDoc 内置了从 Markdown 生成文档的支持。最简单的方法是使用 rebar3_ex_doc 插件。要设置 rebar3 项目以使用 ExDoc 生成文档,请将以下内容添加到您的 rebar3.config
。
%% Enable the plugin
{plugins, [rebar3_ex_doc]}.
{ex_doc, [
{extras, ["README.md"]},
{main, "README.md"},
{source_url, "https://github.com/namespace/your_app"}
]}.
配置完成后,您可以运行 rebar3 ex_doc
来将文档生成到 doc/index.html
。有关更多详细信息和选项,请参阅 rebar3_ex_doc 文档。
您还可以从 github 下载 最新的 escript 捆绑包,并从命令行运行它。通过运行 ex_doc --help
可以找到有关使用 escript 的文档。
如果您正在编写文档,并且将使用 ExDoc 来生成 HTML/ePub,强烈建议您阅读其文档。