什么是 rustdoc?

中文翻译注(The Chinese translation of The rustdoc Book):

标准 Rust 版本包含了名为 rustdoc 的工具。它的作用是为 Rust 项目生成文档,Rustdoc 接受一个 crate 根目录或者一个 markdown 文件作为参数,生成 HTML,CSS 和 JavaScript 文件。

基本使用

让我们试用一下,使用 Cargo 创建一个新项目

$ cargo new docs --lib
$ cd docs

src/lib.rs 中,Cargo 生成了一些示例代码,将其删除并替换为下面的代码:


#![allow(unused)]
fn main() {
/// foo is a function
fn foo() {}
}

然后我们运行 rustdoc。我们可以在 crate 根路径执行下面的命令:

$ rustdoc src/lib.rs

这会创建一个新目录 doc,其中包含一个网站。在我们的例子中,主页面是 doc/lib/index.html。如果你使用浏览器打开,可以看到一个带有搜索栏的页面,在顶部可以看到“Crate lib”,页面没有内容。

配置 rustdoc

现在有两个问题:第一,为什么我们的包名字是“lib”?第二,为什么没有任何内容?

第一个问题的原因是因为 rustdoc 试图更好用,像 rustc, 就假定我们 crate 的名字就是 crate 根目录文件的名字。为了修复这个问题,可以通过命令行传递参数:

$ rustdoc src/lib.rs --crate-name docs

现在,将生成doc/docs/index.html 文件,页面名称为“Crate docs”。

对于第二个问题,因为我们的 foo 函数不是公共的;rustdoc 默认只会为公共函数生成文档,如果我们将代码修改为


#![allow(unused)]
fn main() {
/// foo is a function
pub fn foo() {}
}

然后重新运行 rustdoc

$ rustdoc src/lib.rs --crate-name docs

现在我们生成了文档,打开 doc/docs/index.html,显示了 foo 函数的连接页面,文件位置是 doc/docs/fn.foo.html。在函数的页面上,你可以看到我们写的注释“foo is a function”。

通过 Cargo 使用 rustdoc

Cargo 整合了 rustdoc,使得生成文档更容易。代替 rustdoc 命令,我们可以这样做:

$ cargo doc

实际上,会这样调用 rustdoc:

$ rustdoc --crate-name docs src/lib.rs -o <path>/docs/target/doc -L
dependency=<path>/docs/target/debug/deps

你可以使用 cargo doc --verbose 看到这个过程。

它会自动生成正确的 crate 名称 --crate-name,同时指向 src/lib.rs。但是其他的参数表示什么呢?

  • -o 控制文档的输出。请注意,Cargo 会把生成的文档放在target目录,而不是顶层的 doc 目录,。这是 Cargo 项目中生成文件的惯用位置。
  • -L 帮助 rustdoc 找到代码的依赖,如果我们的项目有依赖,也会生成依赖的文档。

Outer 和 inner 文档

/// 语法用来对下面一个 item 生成文档,所以称为 outer 文档。还有另一种语法://!,用来生成 item 内部的文档,叫做 inner 文档,通常用来对整个 crate 生成文档,因为是 crate 的根,没有 item 在前面。所以为了生成整个 crate 的文档,你需要使用 //!语法,例如:


#![allow(unused)]
fn main() {
//! This is my first rust crate
}

当这样用的时候,会生成 item 内部的文档,也就是 crate 自己。

为了获取更多 //! 的信息,请看 the Book

利用单独的 Markdown 文件

rustdoc 可以为单独的 markdown 文件生成 HTML。让我们尝试一下,创建 README.md,并输入如下内容:

# Docs

This is a project to test out `rustdoc`.

[Here is a link!](https://www.rust-lang.org)

## Example

```rust
fn foo() -> i32 {
    1 + 1
}
```

然后运行 rustdoc 命令:

$ rustdoc README.md

你能发现生成的 docs/doc/README.html 文件。

不过现在 Cargo 不能这样操作 markdown 文件。

总结

本节涵盖了 rustdoc 的基本使用方法。本书的剩余部分会展示 rustdoc 所有的可选功能,以及如何使用它们。

如何阅读 rustdoc 的输出

Rustdoc 的 HTML 文件包含了一个友好且有用的导航界面,使用户可以更轻松地导航和理解您的代码。本章涵盖了该界面的主要功能,对于文档作者和用户来说都是一个很好的的开端。

结构

rustdoc 的输出包含三部分,左侧是整个页面的快速导航,展示了当前条目的上下文信息。页面的右侧大版面由顶部的搜索和下面的文档页面主体组成。

Item 文档

屏幕的主要区域展示的是 item 的文档。

顶端是一览信息:

  • item 的类型和名称,比如 "Struct std::time::Duration";
  • 复制 crate 路径的按钮;
  • 展开和收起 item 顶层文档的按钮 ([+] or [-]);
  • 指向源代码 ([src]) 的链接如果已配置并且存在,(如果通过 cargo doc --no-deps 创建文档)则源码可能无效;
  • 如果 item 是标准库,会展示 item 稳定的版本。

下面是 item 的主要文档,包括函数签名,Rust 类型的 fields 列表或者 variants。最后,该页面列出了关联函数以及 trait 实现,包括 rustdoc 知道的自动和空白实现。

导航

subheadings,variants,fields 和文档中很多元素都是锚,可以被链接,这是可以准确传递你表达的好方法。当鼠标悬停或给定键盘焦点时,印刷符号 "§" 出现在带有锚点的行旁边。

导航栏

比如,当查看 crate 根文档的时候,会展示所有的 crate 文档的 modules,structs,traits,functions,macros 的快速链接。在顶部,它会在当前 crate 名称和版本旁边或者当前 item 旁边展示 configurable logo

主题选择和搜索栏

当在支持 JavaScript 的浏览器中打开 rustdoc 的输出时,页面顶部会出现一个接口,左侧是主题选择(一个画笔图标),搜索栏,帮助提示和配置按钮。【译者注:主题选择已经在配置设置中】

主题选择

点击主题选择会列出可选主题,默认是 ayu, light, and dark

搜索栏

在搜索栏输入内容,会模糊匹配搜索当前的文档

默认搜索结果显示按照名称的结果,意味着模糊匹配 item 的名称,匹配的名称显示在左侧,如果有描述会显示在右侧,点击 item,你会跳转到对应的页面

还有两种结果,按照参数搜索,展示函数参数中类型的匹配结果,按返回值搜索,展示函数返回值类型的搜索结构。这两种搜索结果在你不知道函数名称,但是知道你想要的类型时非常有用。

当在搜索栏输入时,可以通过冒号前缀来限制搜索结果的类型(比如 mod:

快捷键

按下 S 焦点会移动到搜索框,按下 ? 会展示帮助界面,其中包括所有快捷键以及说明。按下 T 焦点移动到主题选择。【译者注:主题选择通过搜索栏的右侧 setting 按钮唤出】

当焦点在搜索结果时,左右箭头可以切换搜索的 tab,上下箭头可以移动关注的搜索结果。按下回车键可以打开高亮的结果。

当焦点在 item 文档时,加号和减号可以展开收起文档的小结。

如何写文档

好的文档并不自然。存在一些矛盾的目标使得写好文档很困难。即要求对领域很专业又要写出对新手很友好的文档。文档因此经常隐去一些细节,或者留给读者一些未解答的问题。

Rust 文档有一些原则指导任何人来写文档,从而每个人都有机会来使用代码。

本章不仅覆盖如何编写文档,还介绍了如何写出文档。尽可能清晰完整非常重要。根据经验:你编写的文档越多你的 crate 越好。如果 item 是公共的,就应该有文档。

开始

编写 crate 文档首先应该从首页开始。例如 hashbrown crate 级别的文档总结了这个 crate 的角色是什么,说明了使用的详细技术,以及为什么你需要这个 crate。

在介绍了 crate 之后,首页给出使用 crate 的代码示例很重要。在代码例子中展示库如何使用,不要使用裁剪过的代码, 使得用户可以直接复制粘贴就能运行。

futures 使用内联注释逐行解释使用 Future 的复杂性,因为用户接触 rust 的 Future 的第一个例子可能就是这个。

backtrace 文档描述了整个使用过程,说明了 Cargo.toml 文件应该如何修改,传递命令行参数给编译器,并展示了一个使用 backtrace 的例子。

最后,首页会成为如何使用 crate 的综合参考,就像 regex。在这个首页,所有的依赖被列出,边缘情况被列出,实际例子被列出。然后首页继续展示如何使用正则表达式,然后还列出了 crate 的特性。

不要担心你的新 crate 与已经开发一段时间的 crate 比较。要是文档逐步完善,请逐步开始添加介绍,示例和特性。罗马不是一天建成的!

lib.rs 的第一行开始会是首页,它们与 rustdoc 其他部分不同,要以 //! 开始表明这是模块级别或者 crate 级别的文档。这是一个简单的例子:


#![allow(unused)]
fn main() {
//! Fast and easy queue abstraction.
//!
//! Provides an abstraction over a queue.  When the abstraction is used
//! there are these advantages:
//! - Fast
//! - [`Easy`]
//!
//! [`Easy`]: http://thatwaseasy.example.com

/// This module makes it easy.
pub mod easy {

    /// Use the abstraction function to do this specific thing.
    pub fn abstraction() {}

}
}

理想情况下,文档第一行是没有技术细节的句子,但是很好的描述了在 Rust 生态中的位置。 阅读这行后,用户应该知道 crate 是否满足他们的需要。

文档组成

无论是 modules, structs, funtions, macros:代码的公共 API 都应该有文档。很少有人嫌弃文档太多!

每个 item 的文档应该都以下面的结构构成:

[short sentence explaining what it is]

[more detailed explanation]

[at least one code example that users can copy/paste to try it]

[even more advanced explanations if necessary]

编写文档时,基本结构应该很容易遵循;你可能认为代码示例微不足道,但是它真的很重要, 能帮助用户理解 item 是什么,如何使用,以及存在的目的是什么。

让我们看一个来自 standard library 的例子, std::env::args() 函数:

Returns the arguments which this program was started with (normally passed
via the command line).

The first element is traditionally the path of the executable, but it can be
set to arbitrary text, and may not even exist. This means this property should
not be relied upon for security purposes.

On Unix systems shell usually expands unquoted arguments with glob patterns
(such as `*` and `?`). On Windows this is not done, and such arguments are
passed as-is.

# Panics

The returned iterator will panic during iteration if any argument to the
process is not valid unicode. If this is not desired,
use the [`args_os`] function instead.

# Examples

```
use std::env;

// Prints each argument on a separate line
for argument in env::args() {
    println!("{}", argument);
}
```

[`args_os`]: ./fn.args_os.html

在第一个空行之间的所有内容都会被用于搜索和模块的简介。比如,上面的 std::enve::args() 函数就会在展示在 std::env 模块文档中。将摘要保持在一行是良好习惯:简介是好文档的目标。

因为类型系统很好定义了函数的参数和返回值类型,所以将其显式写入文档没有好处,尤其是 rustdoc 会自动在函数签名中添加指向类型的超链接。

在上面的例子中,Panics 小节解释了代码何时可能会意外退出,可以帮助读者规避 panic。如果你知道代码的边缘情况,尽可能增加 panic 小节。

如同你所看到的,它遵循了给出的结构建议:简短描述函数的作用,然后提供了更多信息以及最后提供了代码示例。

Markdown

rustdoc 使用 CommonMark Markdown specification。你可能会对它们的网站感兴趣:

补充了标准 CommonMark 语法, rustdoc 支持几种扩展:

Strikethrough(删除线)

文本可以通过两个波浪线来渲染删除线:

An example of ~~strikethrough text~~.

这个例子会渲染成:

An example of strikethrough text.

这使用 GitHub Strikethrough extension

Footnotes(角标)

角标会生成一个小号数字链接,点击数字链接会跳转到这个 item 的位置。角标标签类似与链接语法。例子如下:

This is an example of a footnote[^note].

[^note]: This text is the contents of the footnote, which will be rendered
    towards the bottom.

这个例子会渲染成:

This is an example of a footnote1.

1
This text is the contents of the footnote, which will be rendered
towards the bottom.

角标数字会根据角标位置自动生成。

Tables(表格)

表格可以可以通过竖线和短横线来表示表格的行和列。被转换为符合 HTML 形状的表格。比如:

| Header1 | Header2 |
|---------|---------|
| abc     | def     |

这个例子会被渲染成类似这样:

Header1Header2
abcdef

阅读 GitHub Tables extension 的说明获取更多细节。

Task lists

任务列表可以用于检查需要完成的条目。 比如:

- [x] Complete task
- [ ] Incomplete task

会被渲染成:

  • Complete task
  • Incomplete task

阅读 task list extension 获得更多细节。

Smart punctuation(标点符号)

一些 ASCII 符号可以自动转换为更好看的 Unicode 符号:

ASCII sequenceUnicode
--
---
...
"“ or ”, depending on context
'‘ or ’, depending on context

所以,不需要手工输入这些 Unicode 符号!

什么包含(和排除)

说起来项目中的所有内容都需要有文档简单正确,但是我们如何才能做到,以及是否还有内容没有文档?

在顶层的 src/lib.rs 或者你的二进制项目 main.rs 文件中,包含下面的属性:


#![allow(unused)]
#![warn(missing_docs)]
fn main() {
}

现在运行 cargo doc,检查输出,这是一个例子:

 Documenting docdemo v0.1.0 (/Users/username/docdemo)
warning: missing documentation for the crate
 --> src/main.rs:1:1
  |
1 | / #![warn(missing_docs)]
2 | |
3 | | fn main() {
4 | |     println!("Hello, world!");
5 | | }
  | |_^
  |
note: the lint level is defined here
 --> src/main.rs:1:9
  |
1 | #![warn(missing_docs)]
  |         ^^^^^^^^^^^^

warning: 1 warning emitted

    Finished dev [unoptimized + debuginfo] target(s) in 2.96s

作为一个库作者,加入 lint #![deny(missing_docs)] 是一个确保项目拥有良好文档的好方法,#![warn(missing_docs)] 是通向良好文档的好方法。除了文档,#![deny(missing_doc_code_examples)] 确保每个函数有一个使用示例。在我们上面的例子中,添加 crate 级别的 lint 来警告。

下面的章节有更多 lints 的细节 Lints

例子

当然这很简单,但是文档的力量之一是展示的代码易于理解,而不是生产级别。文档通常会忽略错误处理,因为例子需要排除一些不必要的内容保持简单。

Async 是一个好例子。为了执行 async 例子,一个 executor 是需要的,例子中通常会省略它,让用户自己将 async 代码放到自己的运行时。

最好不要在例子中使用 unwrap(),并且如果错误处理使得例子难以理解应该被隐藏起来。

/// Example
/// ```rust
/// let fourtytwo = "42".parse::<u32>()?;
/// println!("{} + 10 = {}", fourtytwo, fourtytwo+10);
/// ```

当 rustdoc wrap 这些到 main 函数中,会编译错误因为 ParseIntError trait 没有实现。为了同时帮助读者和测试,这个例子还需要增加些额外代码:

/// Example
/// ```rust
/// # main() -> Result<(), std::num::ParseIntError> {
/// let fortytwo = "42".parse::<u32>()?;
/// println!("{} + 10 = {}", fortytwo, fortytwo+10);
/// #     Ok(())
/// # }
/// ```

这两个例子在文档页面是相同的,但是对你 crate 的使用者有一些额外的信息。更多的文档测试内容在接下来的 [文档测试] 章节中。

什么被排除

默认情况下,你的公共接口可能会默认包含在 rustdoc 输出中。#[doc(hidden)] 属性可以隐藏实现细节来鼓励本 crate 的惯用法。

比如,一个内部的 macro! 使得 crate 更容易实现如果对用户暴露会使得用户困惑。一个内部的Error类型可能存在,并且 impl 细节应该被隐藏,如同 API Guidelines 中描述的一样。

自定义输出

传递一个自定义 css 文件给 rustdoc 定义文档的款式是可行的。

rustdoc --extend-css custom.css src/lib.rs

一个良好的例子就是使用这个特性来创建本书的暗黑主题。记住,暗黑主题也包含在点击画笔的输出中。使用可选参数可以很容易使用自定义主题 .css 文件:

rustdoc --theme awesome.css src/lib.rs

这是一个新主题 Ayu 的例子。

Command-line arguments

这里是可以传递给 rustdoc 的参数列表:

-h/--help: help

这样使用:

$ rustdoc -h
$ rustdoc --help

这会展示 rustdoc 内置的帮助,包含了大量可用的命令行 flags。

有些 flags 是未稳定的;这个页面只会只包好稳定的参数,--help 会包含所有的。

-V/--version: version information

使用该flag的方式如下:

$ rustdoc -V
$ rustdoc --version

这将显示 rustdoc 的版本,如下所示:

rustdoc 1.17.0 (56124baa9 2017-04-24)

-v/--verbose: more verbose output

使用该flag的方式如下:

$ rustdoc -v src/lib.rs
$ rustdoc --verbose src/lib.rs

这将启用 "冗长模式",即会将更多信息写入标准输出。 写入的内容取决于你传入的其它标志。 例如,使用 --version

$ rustdoc --verbose --version
rustdoc 1.17.0 (56124baa9 2017-04-24)
binary: rustdoc
commit-hash: hash
commit-date: date
host: host-triple
release: 1.17.0
LLVM version: 3.9

-o/--out-dir: output directory path

使用该flag的方式如下:

$ rustdoc src/lib.rs -o target/doc
$ rustdoc src/lib.rs --out-dir target/doc

默认情况下,rustdoc 的输出会出现在当前工作目录下名为 doc 的目录中。 使用此标记后,它将把所有输出到你指定的目录。

--crate-name: controlling the name of the crate

使用该flag的方式如下:

$ rustdoc src/lib.rs --crate-name mycrate

默认情况下,"rustdoc"会假定你的 crate 名称与".rs "文件相同。 您可以使用 --crate-name 来覆盖这一假设。

--document-private-items: Show items that are not public

使用该flag的方式如下:

$ rustdoc src/lib.rs --document-private-items

默认情况下,rustdoc 只记录可公开访问的项目。


#![allow(unused)]
fn main() {
pub fn public() {} // this item is public and will be documented
mod private { // this item is private and will not be documented
    pub fn unreachable() {} // this item is public, but unreachable, so it will not be documented
}
}

--document-private-items documents all items, even if they're not public.

-L/--library-path: where to look for dependencies

使用该flag的方式如下:

$ rustdoc src/lib.rs -L target/debug/deps
$ rustdoc src/lib.rs --library-path target/debug/deps

如果你的 crate 有依赖库,rustdoc 需要知道在哪里可以找到它们。 传递 --library-path 会给 rustdoc 提供一个查找这些依赖项的列表。

这个标志可以接受任意数量的目录作为参数,并在搜索时使用所有的目录。

--cfg: passing configuration flags

使用该flag的方式如下:

$ rustdoc src/lib.rs --cfg feature="foo"

该flag接受与 rustc --cfg 相同的值,并用它来配置编译。 上面的例子使用了 feature,但任何 cfg 值都可以接受。

--extern: specify a dependency's location

使用该flag的方式如下:

$ rustdoc src/lib.rs --extern lazy-static=/path/to/lazy-static

与"--library-path "类似,"--extern "是关于指定的位置。 library-path "提供了搜索目录,而"--extern则可以让你精 确地指定依赖项的位置。

-C/--codegen: pass codegen options to rustc

使用该flag的方式如下:

$ rustdoc src/lib.rs -C target_feature=+avx
$ rustdoc src/lib.rs --codegen target_feature=+avx

$ rustdoc --test src/lib.rs -C target_feature=+avx
$ rustdoc --test src/lib.rs --codegen target_feature=+avx

$ rustdoc --test README.md -C target_feature=+avx
$ rustdoc --test README.md --codegen target_feature=+avx

当 rustdoc 生成文档、查找文档测试或执行文档测试时,它需要编译一些 rust 代码,至少是部分编译。 测试时,需要编译一些 rust 代码,至少是部分编译。这个flag允许你告诉 rustdoc 在运行这些编译时向 rustc 提供一些额外的 codegen 选项。 大多数情况下这些选项不会影响正常的文档运行,但如果某些内容依赖于目标特性 或者文档测试需要使用一些额外的选项,这个flag允许你影响。

该标志的参数与 rustc 的 -C 标志相同。运行 rustc -C help 以 获得完整的列表。

--test: run code examples as tests

使用该flag的方式如下:

$ rustdoc src/lib.rs --test

该flag将把你的代码示例作为测试运行。更多信息,请参阅(document-tests.md)。

另请参阅 --test-args

--test-args: pass options to test runner

使用该flag的方式如下:

$ rustdoc src/lib.rs --test --test-args ignored

运行文档测试时,该flag将向测试运行器传递选项。 更多信息,请参阅(document-tests.md)。

另请参阅 --test

--target: generate documentation for the specified target triple

使用该flag的方式如下:

$ rustdoc src/lib.rs --target x86_64-pc-windows-gnu

rustc--target 标志类似,它会为与主机三元组不同的目标三元组生成文档。

交叉编译代码的所有常见注意事项均适用。

--default-theme: set the default theme

Using this flag looks like this:

$ rustdoc src/lib.rs --default-theme=ayu

Sets the default theme (for users whose browser has not remembered a previous theme selection from the on-page theme picker).

The supplied value should be the lowercase version of the theme name. The set of available themes can be seen in the theme picker in the generated output.

Note that the set of available themes - and their appearance - is not necessarily stable from one rustdoc version to the next. If the requested theme does not exist, the builtin default (currently light) is used instead.

--markdown-css: include more CSS files when rendering markdown

Using this flag looks like this:

$ rustdoc README.md --markdown-css foo.css

When rendering Markdown files, this will create a <link> element in the <head> section of the generated HTML. For example, with the invocation above,

<link rel="stylesheet" type="text/css" href="foo.css" />

will be added.

When rendering Rust files, this flag is ignored.

--html-in-header: include more HTML in

Using this flag looks like this:

$ rustdoc src/lib.rs --html-in-header header.html
$ rustdoc README.md --html-in-header header.html

This flag takes a list of files, and inserts them into the <head> section of the rendered documentation.

--html-before-content: include more HTML before the content

Using this flag looks like this:

$ rustdoc src/lib.rs --html-before-content extra.html
$ rustdoc README.md --html-before-content extra.html

This flag takes a list of files, and inserts them inside the <body> tag but before the other content rustdoc would normally produce in the rendered documentation.

--html-after-content: include more HTML after the content

Using this flag looks like this:

$ rustdoc src/lib.rs --html-after-content extra.html
$ rustdoc README.md --html-after-content extra.html

This flag takes a list of files, and inserts them before the </body> tag but after the other content rustdoc would normally produce in the rendered documentation.

--markdown-playground-url: control the location of the playground

Using this flag looks like this:

$ rustdoc README.md --markdown-playground-url https://play.rust-lang.org/

When rendering a Markdown file, this flag gives the base URL of the Rust Playground, to use for generating Run buttons.

--markdown-no-toc: don't generate a table of contents

Using this flag looks like this:

$ rustdoc README.md --markdown-no-toc

When generating documentation from a Markdown file, by default, rustdoc will generate a table of contents. This flag suppresses that, and no TOC will be generated.

-e/--extend-css: extend rustdoc's CSS

Using this flag looks like this:

$ rustdoc src/lib.rs -e extra.css
$ rustdoc src/lib.rs --extend-css extra.css

With this flag, the contents of the files you pass are included at the bottom of Rustdoc's theme.css file.

While this flag is stable, the contents of theme.css are not, so be careful! Updates may break your theme extensions.

--sysroot: override the system root

Using this flag looks like this:

$ rustdoc src/lib.rs --sysroot /path/to/sysroot

Similar to rustc --sysroot, this lets you change the sysroot rustdoc uses when compiling your code.

--edition: control the edition of docs and doctests

Using this flag looks like this:

$ rustdoc src/lib.rs --edition 2018
$ rustdoc --test src/lib.rs --edition 2018

This flag allows rustdoc to treat your rust code as the given edition. It will compile doctests with the given edition as well. As with rustc, the default edition that rustdoc will use is 2015 (the first edition).

--theme: add a theme to the documentation output

Using this flag looks like this:

$ rustdoc src/lib.rs --theme /path/to/your/custom-theme.css

rustdoc's default output includes two themes: light (the default) and dark. This flag allows you to add custom themes to the output. Giving a CSS file to this flag adds it to your documentation as an additional theme choice. The theme's name is determined by its filename; a theme file named custom-theme.css will add a theme named custom-theme to the documentation.

--check-theme: verify custom themes against the default theme

Using this flag looks like this:

$ rustdoc --check-theme /path/to/your/custom-theme.css

While rustdoc's HTML output is more-or-less consistent between versions, there is no guarantee that a theme file will have the same effect. The --theme flag will still allow you to add the theme to your documentation, but to ensure that your theme works as expected, you can use this flag to verify that it implements the same CSS rules as the official light theme.

--check-theme is a separate mode in rustdoc. When rustdoc sees the --check-theme flag, it discards all other flags and only performs the CSS rule comparison operation.

--crate-version: control the crate version

Using this flag looks like this:

$ rustdoc src/lib.rs --crate-version 1.3.37

When rustdoc receives this flag, it will print an extra "Version (version)" into the sidebar of the crate root's docs. You can use this flag to differentiate between different versions of your library's documentation.

@path: load command-line flags from a path

If you specify @path on the command-line, then it will open path and read command line options from it. These options are one per line; a blank line indicates an empty option. The file can use Unix or Windows style line endings, and must be encoded as UTF-8.

--passes: add more rustdoc passes

This flag is deprecated. For more details on passes, see the chapter on them.

--no-defaults: don't run default passes

This flag is deprecated. For more details on passes, see the chapter on them.

-r/--input-format: input format

This flag is deprecated and has no effect.

Rustdoc only supports Rust source code and Markdown input formats. If the file ends in .md or .markdown, rustdoc treats it as a Markdown file. Otherwise, it assumes that the input file is Rust.

--nocapture

When this flag is used with --test, the output (stdout and stderr) of your tests won't be captured by rustdoc. Instead, the output will be directed to your terminal, as if you had run the test executable manually. This is especially useful for debugging your tests!

#[doc] 属性

#[doc] 属性可以让你控制 rustdoc 工作的各个方面。

#[doc] 最基本的作用就是处理文档内容。就是说,/// 就是 #[doc] 的语法糖。下面的两行注释是一样的:


#![allow(unused)]
fn main() {
/// This is a doc comment.
#[doc = " This is a doc comment."]
fn f() {}
}

(请注意属性版本的开始的空格。)

在大多数情况下,///#[doc] 更容易使用。一种后面更容易使用的场景是给宏生成文档;collapse-docs 会组合多个 #[doc]属性为一条文档注释,比如:


#![allow(unused)]
fn main() {
#[doc = "This is"]
#[doc = " a "]
#[doc = "doc comment"]
fn f() {}
}

这样可能感觉更灵活。注意这跟下面的写法是一样的:


#![allow(unused)]
fn main() {
#[doc = "This is\n a \ndoc comment"]
fn f() {}
}

给出的文档会渲染成 markdown,会删除换行符。

另一个有用的场景是引入外部文件:

#[doc = include_str!("../README.md")]
fn f() {}

doc 属性有更多的选项!不会包含在输出中,但是可以控制输出的表示。我们将它们分为两大类:在 crate 层面使用的,和在 item 层面使用的。

crate 层面

这些选项控制文档在 crate 层面如何表示。

html_favicon_url

这个 doc 属性让你控制你的文档图标。


#![allow(unused)]
#![doc(html_favicon_url = "https://example.com/favicon.ico")]
fn main() {
}

这会在你的文档中加入 <link rel="shortcut icon" href="{}">,属性的值会填入 {}

如果你不使用这个属性,就没有图标。

html_logo_url

这个 doc 属性可以让你控制左上角的 logo。


#![allow(unused)]
#![doc(html_logo_url = "https://example.com/logo.jpg")]
fn main() {
}

这会在你的文档中加入 <a href='index.html'><img src='{}' alt='logo' width='100'></a>,属性的值会填入 {}

如果你不使用这个属性,就没有 logo。

html_playground_url

这个 doc 属性让你控制文档示例中的 "run" 按钮的请求到哪里。


#![allow(unused)]
#![doc(html_playground_url = "https://playground.example.com/")]
fn main() {
}

现在,当你按下 "run",会向对应网站发出请求。

如果你没有使用这个属性,没有运行按钮。

issue_tracker_base_url

这个 doc 属性在标准库中使用最多;当一个特性未稳定时,需要提供 issue number 来追踪这个特性。rustdoc 使用这个 number,加入到给定的基本 URL 来链接到追踪的网址。


#![allow(unused)]
#![doc(issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")]
fn main() {
}

html_root_url

#[doc(html_root_url = "…")] 属性的值表明了生成外部 crate 的 URL。当 rustdoc 需要生成一个外部 crate item 的链接时,首先检查本地外部 crate 的文档,如果存在直接链接指向。如果失败,就会使用 --extern-html-root-url 命令行参数的值,如果没有这个参数,才会使用 html_root_url ,如果还是无效,外部 item 不会链接。


#![allow(unused)]
#![doc(html_root_url = "https://docs.rs/serde/1.0")]
fn main() {
}

html_no_source

默认情况下,rustdoc 会包含你的源码链接到文档中。 但是如果你这样写:


#![allow(unused)]
#![doc(html_no_source)]
fn main() {
}

就不会。

test(no_crate_inject)

默认情况下,rustdoc 会自动加一行 extern crate my_crate; 到每个文档测试中。 但是如果你这样写了:


#![allow(unused)]
#![doc(test(no_crate_inject))]
fn main() {
}

就不会。

test(attr(...))

这个 doc 属性允许你对你所有的文档测试加上某个属性。比如,如果你想要你的文档测试存在警告时失败,可以这样写:


#![allow(unused)]
#![doc(test(attr(deny(warnings))))]
fn main() {
}

item 层面

这些 #[doc] 属性单独给 item 使用,控制 item 文档表示。

inline and no_inline

这两个属性可以用于 use 声明。比如,考虑如下 Rust 代码:

pub use bar::Bar;

/// bar docs
pub mod bar {
    /// the docs for Bar
    pub struct Bar;
}
fn main() {}

文档会生成 "Re-exports" 小节,表示 pub use bar::Bar; 其中 Bar 会链接到自己的页面。

如果我们将代码改为:

#[doc(inline)]
pub use bar::Bar;
pub mod bar { pub struct Bar; }
fn main() {}

Bar 就会出现在 Structs 小节,就像 Bar 就定义在顶层一样,而不是 pub use 的。

然后我们修改原始的例子,使 bar 私有:

pub use bar::Bar;

/// bar docs
mod bar {
    /// the docs for Bar
    pub struct Bar;
}
fn main() {}

这里,因为 bar 不是公共的,Bar 没有自己的页面,所有没有链接可以指向。rustdoc 将会内联定义,所以会得到与 #[doc(inline)] 一样的结果:Bar 就会出现在 Structs 小节,就像 Bar 就定义在顶层一样。如果我们加上 no_inline 属性:

#[doc(no_inline)]
pub use bar::Bar;

/// bar docs
mod bar {
    /// the docs for Bar
    pub struct Bar;
}
fn main() {}

现在我们有了 Re-exports,并且 Bar 没有链接到任何页面。

一个特殊情况:在 Rust 2018 以及更高版本,如果你 pub use 你的依赖,rustdoc 不会作为 modules 内联除非你加上 #[doc(inline)]

hidden

任何标注了 #[doc(hidden)] 的 item 不会出现在文档中,除非 strip-hidden pass 被删除。

alias

这个属性给搜索索引增加了别名。

让我们举个例子:


#![allow(unused)]
fn main() {
#[doc(alias = "TheAlias")]
pub struct SomeType;
}

现在,如果你输入 "TheAlias" 搜索,也会显示 SomeType。当然如果你输入 SomeType 也会显示 SomeType

FFI 例子

文档属性在写 c 库的 bingding 时尤其有用。比如,我们有一个下面这样的 C 函数:

int lib_name_do_something(Obj *obj);

它输入一个指向 Obj 类型的指针返回一个整数。在 Rust 中,可能会这样写:

pub struct Obj {
    inner: *mut ffi::Obj,
}

impl Obj {
    pub fn do_something(&mut self) -> i32 {
        unsafe { ffi::lib_name_do_something(self.inner) }
    }
}

函数已经被转换为一个方法便于使用。但是如果你想要寻找 Rust 相当的 lib_name_do_something,你没有办法做到。

为了避免这个限制,我们只需要在 do_something 方法加上 #[doc(alias = "lib_name_do_something")],然后就可以了!

用户可以直接搜索 lib_name_do_something 然后找到Obj::do_something

文档测试

rustdoc 支持将你文档中的代码示例作为测试执行。这确保了文档中的代码示例保持更新。

基本写法是这样的:


#![allow(unused)]
fn main() {
/// # Examples
///
/// ```
/// let x = 5;
/// ```
fn f() {}
}

三个反引号中的代码块。如果有一个文件名叫做foo.rs,运行rustdoc --test foo.rs会提取这个例子,然后作为测试执行。

需要注意的是,如果代码块没有设置语言,rustdoc 默认是 Rust 代码,所以下面的:

```rust
let x = 5;
```

跟这个是相等的

```
let x = 5;
```

还有一些微妙之处!请阅读获得更多详情。

文档测试通过或者失败

就像常规的单元测试,常规的文档测试也需要编译和运行“通过”。所以如果需要计算给出一个结果,可以使用assert!系列宏来检查:


#![allow(unused)]
fn main() {
let foo = "foo";
assert_eq!(foo, "foo");
}

这样,如果计算返回的结果不符合预期,代码就会 panic,文档测试会失败。

预处理例子

在上面的例子中,你注意到奇怪的事情:没有main函数!如果强制你为每个例子写main,增加了难度。 所以rustdoc在运行例子前会帮你处理好这个。这里是rustdoc预处理的完整算法:

  1. 一些常用的 allow 属性会被插入,包括 unused_variables, unused_assignments, unused_mut, unused_attributes, 和 dead_code。小型示例经常出发这些警告。
  2. 如果存在 #![doc(test(attr(...)))] 的属性会被加入。
  3. #![foo] 属性会被作为 crate 属性保留。
  4. 如果例子不包含 extern crate, 并且 #![doc(test(no_crate_inject))] 没有被指定,extern crate <mycrate>; 被插入(注意 #[macro_use] 要手动写一般)。
  5. 最后,如果例子不包含 fn main,剩下的代码会被 main 函数 wrap:fn main() { your_code }

对于第 4 条的详细解释,请阅读下面的“宏的文档”

隐藏例子的一部分

有时,你需要一些初始代码,或者一些会分散文档注意力的代码,但是它们对测试工作是必要的。考虑下面的示例代码:


#![allow(unused)]
fn main() {
/// ```
/// /// Some documentation.
/// # fn foo() {} // this function will be hidden
/// println!("Hello, World!");
/// ```
fn f() {}
}

会渲染为:


#![allow(unused)]
fn main() {
/// Some documentation.
fn foo() {}
println!("Hello, World!");
}

没错,这是对的,你可以加一些以 # 开头的行,在输出中它们会隐藏,但是编译代码会用到。你可以利用这一点。在这个例子中,文档注释需要使用函数,但是我只想给你看文档注释,我需要加入函数的定义。同时,需要满足编译器编译,而隐藏这部分代码使得示例更清晰。你可以使用这个技术写出详细的示例代码并且保留你的可测试性文档。

比如,想象我们想要给这些代码写文档:


#![allow(unused)]
fn main() {
let x = 5;
let y = 6;
println!("{}", x + y);
}

文档注释最终可能是这样的:

First, we set x to five:


#![allow(unused)]
fn main() {
let x = 5;
let y = 6;
println!("{}", x + y);
}

Next, we set y to six:


#![allow(unused)]
fn main() {
let x = 5;
let y = 6;
println!("{}", x + y);
}

Finally, we print the sum of x and y:


#![allow(unused)]
fn main() {
let x = 5;
let y = 6;
println!("{}", x + y);
}

为了保持每个代码块可测试,我们要在每个代码块都有完整代码,但是我们不想文档读者每次都看到全部行代码:

First, we set `x` to five:

```
let x = 5;
# let y = 6;
# println!("{}", x + y);
```

Next, we set `y` to six:

```
# let x = 5;
let y = 6;
# println!("{}", x + y);
```

Finally, we print the sum of `x` and `y`:

```
# let x = 5;
# let y = 6;
println!("{}", x + y);
```

通过复制例子的所有代码,例子可以通过编译,同时使用 # 在文档中有些部分被隐藏。

# 的隐藏可以使用两个 ## 来消除。 如果我们有一行注释,以 # 开头,那么这样写:


#![allow(unused)]
fn main() {
let s = "foo
# bar # baz";
}

我们可以转义第一个 # 来注释它:

/// let s = "foo
/// ## bar # baz";

在文档测试中使用 ?

当写例子时,很少会包含完整的错误处理,因为错误处理会增加很多样板代码。取而代之,你可能更希望这样:


#![allow(unused)]
fn main() {
/// ```
/// use std::io;
/// let mut input = String::new();
/// io::stdin().read_line(&mut input)?;
/// ```
fn f() {}
}

问题是 ? 返回 Result<T, E>,测试函数不能返回任何东西,所以会有类型错误。

你可以通过自己增加返回 Result<T, E>main 函数来规避这个限制,因为 Result<T, E> 实现了 Termination trait:

/// A doc test using ?
///
/// ```
/// use std::io;
///
/// fn main() -> io::Result<()> {
///     let mut input = String::new();
///     io::stdin().read_line(&mut input)?;
///     Ok(())
/// }
/// ```
fn f() {}

与下节的 # 一起,你可以得到读者舒服,编译通过的完整解决方案:

/// ```
/// use std::io;
/// # fn main() -> io::Result<()> {
/// let mut input = String::new();
/// io::stdin().read_line(&mut input)?;
/// # Ok(())
/// # }
/// ```
fn f() {}

从 1.34.0 版本开始,也可以省略 fn main(),但是你必须消除错误类型的歧义:


#![allow(unused)]
fn main() {
/// ```
/// use std::io;
/// let mut input = String::new();
/// io::stdin().read_line(&mut input)?;
/// # Ok::<(), io::Error>(())
/// ```
fn f() {}
}

这是 ? 操作符隐式转换带来的不便,因为类型不唯一所以类型推断会出错。你必须写 (())rustdoc 才能理解你想要一个隐式返回值 Result 的函数。

在文档测试中显示警告

你可以通过运行 rustdoc --test --test-args=--show-output 在文档测试中显示警告(或者,如果你使用 cargo,cargo test --doc -- --show-output 也可以)。默认会隐藏 unused 警告,因为很多例子使用私有函数;你可以通过在例子顶部加入#![warn(unused)]来对没有使用的变量或者死代码进行警告。你还可以在 crate 根使用 #![doc(test(attr(warn(unused))))] 开启全局警告。

宏的文档

这里是一个宏的文档的例子:

/// Panic with a given message unless an expression evaluates to true.
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate foo;
/// # fn main() {
/// panic_unless!(1 + 1 == 2, “Math is broken.”);
/// # }
/// ```
///
/// ```should_panic
/// # #[macro_use] extern crate foo;
/// # fn main() {
/// panic_unless!(true == false, “I’m broken.”);
/// # }
/// ```
#[macro_export]
macro_rules! panic_unless {
    ($condition:expr, $($rest:expr),+) => ({ if ! $condition { panic!($($rest),+); } });
}
fn main() {}

你注意到三件事:我们需要自己增加 extern crate 一行,从而我们可以加上 #[macro_use] 属性。第二,我们需要自己增加 main(),理由同上。最后 # 的使用使得一些内容不会出现在输出中。

属性

代码块可以通过属性标注帮助 rustdoc 在测试例子代码时处理正确。

ignore 属性告诉 Rust 忽略你的代码。 这个属性很通用,并且考虑标注 文本或者使用#隐藏不想展示的部分。


#![allow(unused)]
fn main() {
/// ```ignore
/// fn foo() {
/// ```
fn foo() {}
}

should_panic 告诉 rustdoc 代码应该编译通过但是运行时会 panic。如果代码没有 panic,测试失败。


#![allow(unused)]
fn main() {
/// ```should_panic
/// assert!(false);
/// ```
fn foo() {}
}

no_run 属性会编译你的代码但是不运行它。这对于类似 "如果获取网页" 的例子很重要,你要确保它能编译但是不想在运行测试,因为测试环境可能没有网络。这个属性也可以被用来要求代码段有未定义行为。


#![allow(unused)]
fn main() {
/// ```no_run
/// loop {
///     println!("Hello, world");
/// }
/// ```
fn foo() {}
}

compile_fail 告诉 rustdoc 应该编译失败。如果便已通过,测试失败。 但是需要注意现在版本 Rust 编译失败可能在将来 Rust 版本编译成功。


#![allow(unused)]
fn main() {
/// ```compile_fail
/// let x = 5;
/// x += 2; // shouldn't compile!
/// ```
fn foo() {}
}

edition2015, edition2018edition2021 告诉 rustdoc 代码应该使用哪个 edition 版本的 Rust 来编译。


#![allow(unused)]
fn main() {
/// Only runs on the 2018 edition.
///
/// ```edition2018
/// let result: Result<i32, ParseIntError> = try {
///     "1".parse::<i32>()?
///         + "2".parse::<i32>()?
///         + "3".parse::<i32>()?
/// };
/// ```
fn foo() {}
}

语法参考

代码块的 exact 语法,包括边缘情况,可以在 CommonMark 说明的 [Fenced Code Blocks] 一节找到。

Rustdoc 也接受 indented 代码块作为 fenced 代码块的替代:不使用三个反引号,而是每行以四个或者以上空格开始。

    let foo = "foo";
    assert_eq!(foo, "foo");

这也在 CommonMark 说明中的 Indented Code Blocks 小节。

但是通常更常用的是 fenced 代码块。不仅是 fenced 代码块更符合 Rust 惯用法,而且 indented 代码块无法使用诸如 ignore 或者 should_panic 这些属性。

收集文档测试时包含 item

Rustdoc 文档测试可以做到一些单元测试无法做到的事,可以扩展你的文档测试但是不出现在文档中。意味着,rustdoc 允许你有不出现在 文档中,但是会进行文档测试的 item,所以你可以利用文档测试这个功能使测试不出现在文档中,或者任意找一个私有 item 包含它。

当编译 crate 用来测试文档时(使用--test),rustdoc会设置 #[cfg(doctest)]。注意这只会在公共 item 上设置;如果你需要测试私有 item,你需要写单元测试。

在这个例子中,我们增加不会编译的文档测试,确保我们的结构体只会获取有效数据:


#![allow(unused)]
fn main() {
/// We have a struct here. Remember it doesn't accept negative numbers!
pub struct MyStruct(pub usize);

/// ```compile_fail
/// let x = my_crate::MyStruct(-5);
/// ```
#[cfg(doctest)]
pub struct MyStructOnlyTakesUsize;
}

注意结构 MyStructOnlyTakesUsize 不是你的 crate 公共 API。#[cfg(doctest)] 的使用使得这个结构体只会在 rustdoc 收集文档测试时存在。这意味着当传递 --test 给 rustdoc 时才存在,在公共文档中是隐藏的。

另一个可能用到 #[cfg(doctest)] 的是你的 README 文件中的文档测试。 比如你可以在 lib.rs 写下面的代码来运行 README 中的文档测试:


#![allow(unused)]
fn main() {
#[doc = include_str!("../README.md")]
#[cfg(doctest)]
pub struct ReadmeDoctests;
}

这会在你的隐藏结构体 ReadmeDoctests 中包含你的 README 作为文档,也会作为文档测试来执行。

通过名称链接 item

Rustdoc 能够使用 item 的路径直接内部链接。这称为 'intra-doc link'。

比如,下面的代码可以链接 Bar 的页面:


#![allow(unused)]
fn main() {
/// This struct is not [Bar]
pub struct Foo1;

/// This struct is also not [bar](Bar)
pub struct Foo2;

/// This struct is also not [bar][b]
///
/// [b]: Bar
pub struct Foo3;

/// This struct is also not [`Bar`]
pub struct Foo4;

/// This struct *is* [`Bar`]!
pub struct Bar;
}

不像常规的 markdown,[bar][Bar] 语法也被支持,不需要[Bar]: ... 链接。

反引号会被删除,所以 [`Option`] 可以正确地链接到Option

有效链接

你可以链接作用域的任何东西,使用路径,包括 Self, self, supercrate。Associated items (functions, types, and constants) 也是支持的,但是 不能是空的 trait 实现。Rustdoc 还支持 the standard library documentation 列出的原始类型链接。

你还可以链接范型参数,比如 Vec<T>。链接会如同你写了 [`Vec<T>`](Vec). 但是,Fully-qualified syntax(比如,<Vec as IntoIterator>::into_iter()) 还 没有被支持


#![allow(unused)]
fn main() {
use std::sync::mpsc::Receiver;

/// This is a version of [`Receiver<T>`] with support for [`std::future`].
///
/// You can obtain a [`std::future::Future`] by calling [`Self::recv()`].
pub struct AsyncReceiver<T> {
    sender: Receiver<T>
}

impl<T> AsyncReceiver<T> {
    pub async fn recv() -> T {
        unimplemented!()
    }
}
}

Rustdoc 允许使用 URL fragment specifiers,就如同普通的链接:


#![allow(unused)]
fn main() {
/// This is a special implementation of [positional parameters].
///
/// [positional parameters]: std::fmt#formatting-parameters
struct MySpecialFormatter;
}

Namespaces and Disambiguators(消歧义符)

Rust 中的路径有三种命名空间:type, value 和 macro。Item name 在命名空间内必须唯一,但是可以与其他命名空间的 item 同名。在歧义的情况下,rustdoc 会警告歧义,并给出消除歧义的建议。


#![allow(unused)]
fn main() {
/// See also: [`Foo`](struct@Foo)
struct Bar;

/// This is different from [`Foo`](fn@Foo)
struct Foo {}

fn Foo() {}
}

这些前缀展示在文档时会被删除,所以 [struct@Foo] 会被渲染成 Foo

你也可以在函数名后加上 () 和在宏名后面加上 ! 消除歧义:


#![allow(unused)]
fn main() {
/// This is different from [`foo!`]
fn foo() {}

/// This is different from [`foo()`]
macro_rules! foo {
  () => {}
}
}

警告,re-exports, and scoping

即使 item 被 re-exported,链接也在 item 定义的模块内解析。如果来自另一个 crate 的链接解析失败,不会给出警告。


#![allow(unused)]
fn main() {
mod inner {
    /// Link to [f()]
    pub struct S;
    pub fn f() {}
}
pub use inner::S; // the link to `f` will still resolve correctly
}

当一个 item 被 re-export,rustdoc 允许加入额外的文档。额外的文档在 re-export 的作用域中解析,允许你链接 re-export 的 item,并且如果解析失败会给出警告。


#![allow(unused)]
fn main() {
/// See also [foo()]
pub use std::process::Command;

pub fn foo() {}
}

这对于过程宏非常有用,过程宏必须定义在自己的 crate 中。

注意:因为 macro_ruls! 宏的作用域是整个 Rust,macro_rules! 的 intra-doc 链接在 relative to the crate root 解析,而不是定义的模块内。

如果链接看起来不像是 intra-doc 链接,它们会被忽略并且不会生成警告,即使链接解析失败。比如,任何包含了 / 或者 [] 字符的链接都被忽略。

Lints

rustdoc 提供 lints 来帮助你编写以及测试文档。你可以像使用其他 lints 来使用它们:


#![allow(unused)]
#![allow(rustdoc::broken_intra_doc_links)] // allows the lint, no diagnostics will be reported
#![warn(rustdoc::broken_intra_doc_links)] // warn if there are broken intra-doc links
#![deny(rustdoc::broken_intra_doc_links)] // error if there are broken intra-doc links
fn main() {
}

注意,出了 missing_docs,这些 lints 只有当运行 rustdoc 的时候才会生效,rustc 不会。

这是rustdoc lints 的列表:

broken_intra_doc_links

这个 lint 是默认警告。这个 lint 当 intra-doc link 解析错误时会提示。比如:


#![allow(unused)]
fn main() {
/// I want to link to [`Nonexistent`] but it doesn't exist!
pub fn foo() {}
}

你会得到警告:

warning: unresolved link to `Nonexistent`
 --> test.rs:1:24
  |
1 | /// I want to link to [`Nonexistent`] but it doesn't exist!
  |                        ^^^^^^^^^^^^^ no item named `Nonexistent` in `test`

当存在歧义时也会得到警告,以及如何消除歧义的建议:


#![allow(unused)]
fn main() {
/// [`Foo`]
pub fn function() {}

pub enum Foo {}

pub fn Foo(){}
}
warning: `Foo` is both an enum and a function
 --> test.rs:1:6
  |
1 | /// [`Foo`]
  |      ^^^^^ ambiguous link
  |
  = note: `#[warn(rustdoc::broken_intra_doc_links)]` on by default
help: to link to the enum, prefix with the item type
  |
1 | /// [`enum@Foo`]
  |      ^^^^^^^^^^
help: to link to the function, add parentheses
  |
1 | /// [`Foo()`]
  |      ^^^^^^^

private_intra_doc_links

这个 lint 是默认警告. 这个 lint 会在 intra-doc links 从一个公共 item 连接一个私有 item 时提示。 比如:


#![allow(unused)]
#![warn(rustdoc::private_intra_doc_links)] // note: unnecessary - warns by default.

fn main() {
/// [private]
pub fn public() {}
fn private() {}
}

会给出这个文档中链接时损坏的:

warning: public documentation for `public` links to private item `private`
 --> priv.rs:1:6
  |
1 | /// [private]
  |      ^^^^^^^ this item is private
  |
  = note: `#[warn(rustdoc::private_intra_doc_links)]` on by default
  = note: this link will resolve properly if you pass `--document-private-items`

注意到取决于你是否传递 --document-private-items 参数会有不同的行为!如果你有私有 item 的文档,尽管会有警告,仍然会生成这个链接:

warning: public documentation for `public` links to private item `private`
 --> priv.rs:1:6
  |
1 | /// [private]
  |      ^^^^^^^ this item is private
  |
  = note: `#[warn(rustdoc::private_intra_doc_links)]` on by default
  = note: this link resolves only because you passed `--document-private-items`, but will break without

missing_docs

这个 lint 默认允许。缺少文档时提示。比如:

#![warn(missing_docs)]

pub fn undocumented() {}
fn main() {}

undocumented 函数会有下面的警告:

warning: missing documentation for a function
  --> your-crate/lib.rs:3:1
   |
 3 | pub fn undocumented() {}
   | ^^^^^^^^^^^^^^^^^^^^^

注意不像其他 lint,这个 lint 也对 rustc 有效。

missing_crate_level_docs

这个 lint 是默认允许。提示 crate 根没有文档。 比如:


#![allow(unused)]
#![warn(rustdoc::missing_crate_level_docs)]
fn main() {
}

会生成下面的警告:

warning: no documentation found for this crate's top-level module
  |
  = help: The following guide may be of use:
          https://doc.rust-lang.org/nightly/rustdoc/how-to-write-documentation.html

当前默认是允许的,但是计划未来默认警告。这可以不使用missing_docs这种严重的警告,介绍给新用户如何给他们的 crate 写文档。

missing_doc_code_examples

这个 lint 默认允许 并且 nightly-only。当文档缺少代码示例时提示。比如:

#![warn(rustdoc::missing_doc_code_examples)]

/// There is no code example!
pub fn no_code_example() {}
fn main() {}

no_code_example 函数会有下面的警告:

warning: Missing code example in this documentation
  --> your-crate/lib.rs:3:1
   |
LL | /// There is no code example!
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

为了修复这个 lint,你需要在文档块中加入代码示例:


#![allow(unused)]
fn main() {
/// There is no code example!
///
/// ```
/// println!("calling no_code_example...");
/// no_code_example();
/// println!("we called no_code_example!");
/// ```
pub fn no_code_example() {}
}

private_doc_tests

这个 lint 默认允许。 提示私有 item 有文档测试。 比如:

#![warn(rustdoc::private_doc_tests)]

mod foo {
    /// private doc test
    ///
    /// ```
    /// assert!(false);
    /// ```
    fn bar() {}
}
fn main() {}

提示:

warning: Documentation test in private item
  --> your-crate/lib.rs:4:1
   |
 4 | /     /// private doc test
 5 | |     ///
 6 | |     /// ```
 7 | |     /// assert!(false);
 8 | |     /// ```
   | |___________^

invalid_codeblock_attributes

这个 lint 默认警告。提示文档例子中的代码块属性有潜在的错误。比如:


#![allow(unused)]
#![warn(rustdoc::invalid_codeblock_attributes)]  // note: unnecessary - warns by default.

fn main() {
/// Example.
///
/// ```should-panic
/// assert_eq!(1, 2);
/// ```
pub fn foo() {}
}

提示:

warning: unknown attribute `should-panic`. Did you mean `should_panic`?
 --> src/lib.rs:1:1
  |
1 | / /// Example.
2 | | ///
3 | | /// ```should-panic
4 | | /// assert_eq!(1, 2);
5 | | /// ```
  | |_______^
  |
  = note: `#[warn(rustdoc::invalid_codeblock_attributes)]` on by default
  = help: the code block will either not be tested if not marked as a rust one or won't fail if it doesn't panic when running

上面的例子中,正确的拼写是 should_panic。可以提示一些常用的属性 typo 错误。

invalid_html_tags

这个 lint 默认允许 并且是 nightly-only。提示没有关闭的或者无效的 HTML tag。 比如:


#![allow(unused)]
#![warn(rustdoc::invalid_html_tags)]

fn main() {
/// <h1>
/// </script>
pub fn foo() {}
}

提示:

warning: unopened HTML tag `script`
 --> foo.rs:1:1
  |
1 | / /// <h1>
2 | | /// </script>
  | |_____________^
  |
  note: the lint level is defined here
 --> foo.rs:1:9
  |
1 | #![warn(rustdoc::invalid_html_tags)]
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: unclosed HTML tag `h1`
 --> foo.rs:1:1
  |
1 | / /// <h1>
2 | | /// </script>
  | |_____________^

warning: 2 warnings emitted

invalid_rust_codeblocks

这个 lint 默认警告。提示文档中的 Rust 代码块无效(比如,空的,无法被解析为 Rust 代码)。比如:


#![allow(unused)]
fn main() {
/// Empty code blocks (with and without the `rust` marker):
///
/// ```rust
/// ```
///
/// Invalid syntax in code blocks:
///
/// ```rust
/// '<
/// ```
pub fn foo() {}
}

提示:

warning: Rust code block is empty
 --> lint.rs:3:5
  |
3 |   /// ```rust
  |  _____^
4 | | /// ```
  | |_______^
  |
  = note: `#[warn(rustdoc::invalid_rust_codeblocks)]` on by default

warning: could not parse code block as Rust code
  --> lint.rs:8:5
   |
8  |   /// ```rust
   |  _____^
9  | | /// '<
10 | | /// ```
   | |_______^
   |
   = note: error from rustc: unterminated character literal

bare_urls

这个 lint 默认警告。提示 Url 不是一个链接。 比如:


#![allow(unused)]
#![warn(rustdoc::bare_urls)] // note: unnecessary - warns by default.

fn main() {
/// http://example.org
/// [http://example.net]
pub fn foo() {}
}

会出现:

warning: this URL is not a hyperlink
 --> links.rs:1:5
  |
1 | /// http://example.org
  |     ^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<http://example.org>`
  |
  = note: `#[warn(rustdoc::bare_urls)]` on by default

warning: this URL is not a hyperlink
 --> links.rs:3:6
  |
3 | /// [http://example.net]
  |      ^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<http://example.net>`

warning: 2 warnings emitted

高级特性

本页列出的特性不属于其他的主要类别

#[cfg(doc)]: 文档平台相关或者特性相关信息

对于条件编译,rustdoc 会与编译器相同的方式处理。只生成目标主机可用的文档,其他的被 “过滤掉”。当对于不同目标提供不同的东西并且你希望文档反映你所有的可用项目,这可能会有问题。

如果你希望确保 rustdoc 可以看到某个 item,而忽略目标的平台相关信息,你可以使用 #[cfg(doc)]。Rustdoc 会在构建文档时设置它,所以使用了这个的 item 会确保生成到文档中,比如 #[cfg(any(windows, doc))] 会在 Windows 上构建以及生成所有的文档。

请注意 cfg 不会传递到文档测试中。

比如:


#![allow(unused)]
fn main() {
/// Token struct that can only be used on Windows.
#[cfg(any(windows, doc))]
pub struct WindowsToken;
/// Token struct that can only be used on Unix.
#[cfg(any(unix, doc))]
pub struct UnixToken;
}

这里,各自的 tokens 只能在各自的平台上使用,但是会同时出现在文档中。

特定平台文档之间的交互

Rustdoc 没有什么如同你在每种平台运行一次的魔法方法来编译文档(这种魔法方式被称为 'holy grail of rustdoc')。代替的是,会一次读到你所有的代码,与 Rust 编译器通过参数 --cfg doc 读到的一样。但是,Rustdoc 有一个技巧可以在接收到特定平台代码时处理它。

为你的 crate 生成文档,Rustdoc 只需要知道你的公共函数签名。尤其是,不需要知道你的函数实现,所以会忽略所有函数体类型错误和名称解析错误。注意,这不适用函数体之外的东西:因为 Rustdoc 会记录类型,需要知道类型是什么。比如,无论平台如何,这些代码可以工作:

pub fn f() {
    use std::os::windows::ffi::OsStrExt;
}

但是这些不行,因为函数签名中存在为止类型:

pub fn f() -> std::os::windows::ffi::EncodeWide<'static> {
    unimplemented!()
}

更多的代码示例,请参考 the rustdoc test suite

增加文档搜索的 item 别名

这个特性可以通过 doc(alias) 属性增加 rustdoc 搜索 item 的别名。比如:


#![allow(unused)]
fn main() {
#[doc(alias = "x")]
#[doc(alias = "big")]
pub struct BigX;
}

然后,当搜索时,你可以输入 "x" 或者 "big",搜索结果优先显示 BigX 结构。

文档别名也有一些限制:你不能使用 " 或者空格。

你可以使用列表一次增加多个别名:


#![allow(unused)]
fn main() {
#[doc(alias("x", "big"))]
pub struct BigX;
}

不稳定特性

Rustdoc is under active development, and like the Rust compiler, some features are only available on nightly releases. Some of these features are new and need some more testing before they're able to be released to the world at large, and some of them are tied to features in the Rust compiler that are unstable. Several features here require a matching #![feature(...)] attribute to enable, and thus are more fully documented in the Unstable Book. Those sections will link over there as necessary.

Nightly-gated functionality

These features just require a nightly build to operate. Unlike the other features on this page, these don't need to be "turned on" with a command-line flag or a #![feature(...)] attribute in your crate. This can give them some subtle fallback modes when used on a stable release, so be careful!

Error numbers for compile-fail doctests

As detailed in the chapter on documentation tests, you can add a compile_fail attribute to a doctest to state that the test should fail to compile. However, on nightly, you can optionally add an error number to state that a doctest should emit a specific error number:

```compile_fail,E0044
extern { fn some_func<T>(x: T); }
```

This is used by the error index to ensure that the samples that correspond to a given error number properly emit that error code. However, these error codes aren't guaranteed to be the only thing that a piece of code emits from version to version, so this is unlikely to be stabilized in the future.

Attempting to use these error numbers on stable will result in the code sample being interpreted as plain text.

Extensions to the #[doc] attribute

These features operate by extending the #[doc] attribute, and thus can be caught by the compiler and enabled with a #![feature(...)] attribute in your crate.

#[doc(cfg)]: Recording what platforms or features are required for code to be present

You can use #[doc(cfg(...))] to tell Rustdoc exactly which platform items appear on. This has two effects:

  1. doctests will only run on the appropriate platforms, and
  2. When Rustdoc renders documentation for that item, it will be accompanied by a banner explaining that the item is only available on certain platforms.

#[doc(cfg)] is intended to be used alongside #[cfg(doc)]. For example, #[cfg(any(windows, doc))] will preserve the item either on Windows or during the documentation process. Then, adding a new attribute #[doc(cfg(windows))] will tell Rustdoc that the item is supposed to be used on Windows. For example:


#![allow(unused)]
#![feature(doc_cfg)]

fn main() {
/// Token struct that can only be used on Windows.
#[cfg(any(windows, doc))]
#[doc(cfg(windows))]
pub struct WindowsToken;

/// Token struct that can only be used on Unix.
#[cfg(any(unix, doc))]
#[doc(cfg(unix))]
pub struct UnixToken;

/// Token struct that is only available with the `serde` feature
#[cfg(feature = "serde")]
#[doc(cfg(feature = "serde"))]
#[derive(serde::Deserialize)]
pub struct SerdeToken;
}

In this sample, the tokens will only appear on their respective platforms, but they will both appear in documentation.

#[doc(cfg(...))] was introduced to be used by the standard library and currently requires the #![feature(doc_cfg)] feature gate. For more information, see its chapter in the Unstable Book and its tracking issue.

doc_auto_cfg: Automatically generate #[doc(cfg)]

doc_auto_cfg is an extension to the #[doc(cfg)] feature. With it, you don't need to add #[doc(cfg(...)] anymore unless you want to override the default behaviour. So if we take the previous source code:


#![allow(unused)]
#![feature(doc_auto_cfg)]

fn main() {
/// Token struct that can only be used on Windows.
#[cfg(any(windows, doc))]
pub struct WindowsToken;

/// Token struct that can only be used on Unix.
#[cfg(any(unix, doc))]
pub struct UnixToken;

/// Token struct that is only available with the `serde` feature
#[cfg(feature = "serde")]
#[derive(serde::Deserialize)]
pub struct SerdeToken;
}

It'll render almost the same, the difference being that doc will also be displayed. To fix this, you can use doc_cfg_hide:


#![allow(unused)]
#![feature(doc_cfg_hide)]
#![doc(cfg_hide(doc))]
fn main() {
}

And doc won't show up anymore!

Adding your trait to the "Notable traits" dialog

Rustdoc keeps a list of a few traits that are believed to be "fundamental" to types that implement them. These traits are intended to be the primary interface for their implementers, and are often most of the API available to be documented on their types. For this reason, Rustdoc will track when a given type implements one of these traits and call special attention to it when a function returns one of these types. This is the "Notable traits" dialog, accessible as a circled i button next to the function, which, when clicked, shows the dialog.

In the standard library, some of the traits that are part of this list are Iterator, Future, io::Read, and io::Write. However, rather than being implemented as a hard-coded list, these traits have a special marker attribute on them: #[doc(notable_trait)]. This means that you can apply this attribute to your own trait to include it in the "Notable traits" dialog in documentation.

The #[doc(notable_trait)] attribute currently requires the #![feature(doc_notable_trait)] feature gate. For more information, see its chapter in the Unstable Book and its tracking issue.

Exclude certain dependencies from documentation

The standard library uses several dependencies which, in turn, use several types and traits from the standard library. In addition, there are several compiler-internal crates that are not considered to be part of the official standard library, and thus would be a distraction to include in documentation. It's not enough to exclude their crate documentation, since information about trait implementations appears on the pages for both the type and the trait, which can be in different crates!

To prevent internal types from being included in documentation, the standard library adds an attribute to their extern crate declarations: #[doc(masked)]. This causes Rustdoc to "mask out" types from these crates when building lists of trait implementations.

The #[doc(masked)] attribute is intended to be used internally, and requires the #![feature(doc_masked)] feature gate. For more information, see its chapter in the Unstable Book and its tracking issue.

Document primitives

This is for Rust compiler internal use only.

Since primitive types are defined in the compiler, there's no place to attach documentation attributes. The #[doc(primitive)] attribute is used by the standard library to provide a way to generate documentation for primitive types, and requires #![feature(rustdoc_internals)] to enable.

Document keywords

This is for Rust compiler internal use only.

Rust keywords are documented in the standard library (look for match for example).

To do so, the #[doc(keyword = "...")] attribute is used. Example:


#![allow(unused)]
#![feature(rustdoc_internals)]

fn main() {
/// Some documentation about the keyword.
#[doc(keyword = "keyword")]
mod empty_mod {}
}

Unstable command-line arguments

These features are enabled by passing a command-line flag to Rustdoc, but the flags in question are themselves marked as unstable. To use any of these options, pass -Z unstable-options as well as the flag in question to Rustdoc on the command-line. To do this from Cargo, you can either use the RUSTDOCFLAGS environment variable or the cargo rustdoc command.

--markdown-before-content: include rendered Markdown before the content

Using this flag looks like this:

$ rustdoc src/lib.rs -Z unstable-options --markdown-before-content extra.md
$ rustdoc README.md -Z unstable-options --markdown-before-content extra.md

Just like --html-before-content, this allows you to insert extra content inside the <body> tag but before the other content rustdoc would normally produce in the rendered documentation. However, instead of directly inserting the file verbatim, rustdoc will pass the files through a Markdown renderer before inserting the result into the file.

--markdown-after-content: include rendered Markdown after the content

Using this flag looks like this:

$ rustdoc src/lib.rs -Z unstable-options --markdown-after-content extra.md
$ rustdoc README.md -Z unstable-options --markdown-after-content extra.md

Just like --html-after-content, this allows you to insert extra content before the </body> tag but after the other content rustdoc would normally produce in the rendered documentation. However, instead of directly inserting the file verbatim, rustdoc will pass the files through a Markdown renderer before inserting the result into the file.

--playground-url: control the location of the playground

Using this flag looks like this:

$ rustdoc src/lib.rs -Z unstable-options --playground-url https://play.rust-lang.org/

When rendering a crate's docs, this flag gives the base URL of the Rust Playground, to use for generating Run buttons. Unlike --markdown-playground-url, this argument works for standalone Markdown files and Rust crates. This works the same way as adding #![doc(html_playground_url = "url")] to your crate root, as mentioned in the chapter about the #[doc] attribute. Please be aware that the official Rust Playground at https://play.rust-lang.org does not have every crate available, so if your examples require your crate, make sure the playground you provide has your crate available.

If both --playground-url and --markdown-playground-url are present when rendering a standalone Markdown file, the URL given to --markdown-playground-url will take precedence. If both --playground-url and #![doc(html_playground_url = "url")] are present when rendering crate docs, the attribute will take precedence.

--sort-modules-by-appearance: control how items on module pages are sorted

Using this flag looks like this:

$ rustdoc src/lib.rs -Z unstable-options --sort-modules-by-appearance

Ordinarily, when rustdoc prints items in module pages, it will sort them alphabetically (taking some consideration for their stability, and names that end in a number). Giving this flag to rustdoc will disable this sorting and instead make it print the items in the order they appear in the source.

--show-type-layout: add a section to each type's docs describing its memory layout

Using this flag looks like this:

$ rustdoc src/lib.rs -Z unstable-options --show-type-layout

When this flag is passed, rustdoc will add a "Layout" section at the bottom of each type's docs page that includes a summary of the type's memory layout as computed by rustc. For example, rustdoc will show the size in bytes that a value of that type will take in memory.

Note that most layout information is completely unstable and may even differ between compilations.

--resource-suffix: modifying the name of CSS/JavaScript in crate docs

Using this flag looks like this:

$ rustdoc src/lib.rs -Z unstable-options --resource-suffix suf

When rendering docs, rustdoc creates several CSS and JavaScript files as part of the output. Since all these files are linked from every page, changing where they are can be cumbersome if you need to specially cache them. This flag will rename all these files in the output to include the suffix in the filename. For example, light.css would become light-suf.css with the above command.

--extern-html-root-url: control how rustdoc links to non-local crates

Using this flag looks like this:

$ rustdoc src/lib.rs -Z unstable-options --extern-html-root-url some-crate=https://example.com/some-crate/1.0.1

Ordinarily, when rustdoc wants to link to a type from a different crate, it looks in two places: docs that already exist in the output directory, or the #![doc(doc_html_root)] set in the other crate. However, if you want to link to docs that exist in neither of those places, you can use these flags to control that behavior. When the --extern-html-root-url flag is given with a name matching one of your dependencies, rustdoc use that URL for those docs. Keep in mind that if those docs exist in the output directory, those local docs will still override this flag.

-Z force-unstable-if-unmarked

Using this flag looks like this:

$ rustdoc src/lib.rs -Z force-unstable-if-unmarked

This is an internal flag intended for the standard library and compiler that applies an #[unstable] attribute to any dependent crate that doesn't have another stability attribute. This allows rustdoc to be able to generate documentation for the compiler crates and the standard library, as an equivalent command-line argument is provided to rustc when building those crates.

--index-page: provide a top-level landing page for docs

This feature allows you to generate an index-page with a given markdown file. A good example of it is the rust documentation index.

With this, you'll have a page which you can custom as much as you want at the top of your crates.

Using index-page option enables enable-index-page option as well.

--enable-index-page: generate a default index page for docs

This feature allows the generation of a default index-page which lists the generated crates.

--static-root-path: control how static files are loaded in HTML output

Using this flag looks like this:

$ rustdoc src/lib.rs -Z unstable-options --static-root-path '/cache/'

This flag controls how rustdoc links to its static files on HTML pages. If you're hosting a lot of crates' docs generated by the same version of rustdoc, you can use this flag to cache rustdoc's CSS, JavaScript, and font files in a single location, rather than duplicating it once per "doc root" (grouping of crate docs generated into the same output directory, like with cargo doc). Per-crate files like the search index will still load from the documentation root, but anything that gets renamed with --resource-suffix will load from the given path.

--persist-doctests: persist doctest executables after running

Using this flag looks like this:

$ rustdoc src/lib.rs --test -Z unstable-options --persist-doctests target/rustdoctest

This flag allows you to keep doctest executables around after they're compiled or run. Usually, rustdoc will immediately discard a compiled doctest after it's been tested, but with this option, you can keep those binaries around for farther testing.

--show-coverage: calculate the percentage of items with documentation

Using this flag looks like this:

$ rustdoc src/lib.rs -Z unstable-options --show-coverage

It generates something like this:

+-------------------------------------+------------+------------+------------+------------+
| File                                | Documented | Percentage |   Examples | Percentage |
+-------------------------------------+------------+------------+------------+------------+
| lib.rs                              |          4 |     100.0% |          1 |      25.0% |
+-------------------------------------+------------+------------+------------+------------+
| Total                               |          4 |     100.0% |          1 |      25.0% |
+-------------------------------------+------------+------------+------------+------------+

If you want to determine how many items in your crate are documented, pass this flag to rustdoc. When it receives this flag, it will count the public items in your crate that have documentation, and print out the counts and a percentage instead of generating docs.

Some methodology notes about what rustdoc counts in this metric:

  • Rustdoc will only count items from your crate (i.e. items re-exported from other crates don't count).
  • Docs written directly onto inherent impl blocks are not counted, even though their doc comments are displayed, because the common pattern in Rust code is to write all inherent methods into the same impl block.
  • Items in a trait implementation are not counted, as those impls will inherit any docs from the trait itself.
  • By default, only public items are counted. To count private items as well, pass --document-private-items at the same time.

Public items that are not documented can be seen with the built-in missing_docs lint. Private items that are not documented can be seen with Clippy's missing_docs_in_private_items lint.

Calculating code examples follows these rules:

  1. These items aren't accounted by default:
  • struct/union field
  • enum variant
  • constant
  • static
  • typedef
  1. If one of the previously listed items has a code example, then it'll be counted.

JSON output

When using --output-format json with this option, it will display the coverage information in JSON format. For example, here is the JSON for a file with one documented item and one undocumented item:


#![allow(unused)]
fn main() {
/// This item has documentation
pub fn foo() {}

pub fn no_documentation() {}
}
{"no_std.rs":{"total":3,"with_docs":1,"total_examples":3,"with_examples":0}}

Note that the third item is the crate root, which in this case is undocumented.

-w/--output-format: output format

--output-format json emits documentation in the experimental JSON format. --output-format html has no effect, and is also accepted on stable toolchains.

It can also be used with --show-coverage. Take a look at its documentation for more information.

--enable-per-target-ignores: allow ignore-foo style filters for doctests

Using this flag looks like this:

$ rustdoc src/lib.rs -Z unstable-options --enable-per-target-ignores

This flag allows you to tag doctests with compiletest style ignore-foo filters that prevent rustdoc from running that test if the target triple string contains foo. For example:


#![allow(unused)]
fn main() {
///```ignore-foo,ignore-bar
///assert!(2 == 2);
///```
struct Foo;
}

This will not be run when the build target is super-awesome-foo or less-bar-awesome. If the flag is not enabled, then rustdoc will consume the filter, but do nothing with it, and the above example will be run for all targets. If you want to preserve backwards compatibility for older versions of rustdoc, you can use


#![allow(unused)]
fn main() {
///```ignore,ignore-foo
///assert!(2 == 2);
///```
struct Foo;
}

In older versions, this will be ignored on all targets, but on newer versions ignore-gnu will override ignore.

--runtool, --runtool-arg: program to run tests with; args to pass to it

Using these options looks like this:

$ rustdoc src/lib.rs -Z unstable-options --runtool runner --runtool-arg --do-thing --runtool-arg --do-other-thing

These options can be used to run the doctest under a program, and also pass arguments to that program. For example, if you want to run your doctests under valgrind you might run

$ rustdoc src/lib.rs -Z unstable-options --runtool valgrind

Another use case would be to run a test inside an emulator, or through a Virtual Machine.

--with-examples: include examples of uses of items as documentation

This option, combined with --scrape-examples-target-crate and --scrape-examples-output-path, is used to implement the functionality in RFC #3123. Uses of an item (currently functions / call-sites) are found in a crate and its reverse-dependencies, and then the uses are included as documentation for that item. This feature is intended to be used via cargo doc --scrape-examples, but the rustdoc-only workflow looks like:

$ rustdoc examples/ex.rs -Z unstable-options \
    --extern foobar=target/deps/libfoobar.rmeta \
    --scrape-examples-target-crate foobar \
    --scrape-examples-output-path output.calls
$ rustdoc src/lib.rs -Z unstable-options --with-examples output.calls

First, the library must be checked to generate an rmeta. Then a reverse-dependency like examples/ex.rs is given to rustdoc with the target crate being documented (foobar) and a path to output the calls (output.calls). Then, the generated calls file can be passed via --with-examples to the subsequent documentation of foobar.

Website 特性

这些特性是关于使用rustdoc生成的网站。

自定义搜索引擎

如果你经常参考在线 Rust 文档,你会喜欢使用一个自定义搜索引擎。这能让你使用导航地址栏直接搜索 rustdoc 网站。大多数浏览器支持这种特性,让你来定义一个包含 %S(你搜索的内容)的 URL 模版,比如对于标准库你可以使用这个模板:

https://doc.rust-lang.org/stable/std/?search=%s

注意这会列出你搜索到的所有结果。如果你想要直接打开搜索到的第一个结果可以使用下面的模板:

https://doc.rust-lang.org/stable/std/?search=%s&go_to_first=true

这个 URL 在末尾加入了go_to_first=true搜索参数,会自动跳转到第一个搜索结果。

Passes

Rustdoc 有一个概念叫做 "passes"。在 rustdoc 命令最终生成文档之前存在一些转换。

自定义 passes 被废弃了,已经可用的 passes 不会稳定可能随时会在发布中更改

过去最常用的自定义 passes 是 strip-private pass。你现在可以更容易的做到这个,通过传递参数 --document-private-items.

References

有很多良好的 rustdoc 参考,如果你知道其他的好资源,请提交 PR!

官方

社区