什么是 rustdoc?
中文翻译注(The Chinese translation of The rustdoc Book):
- 👉 查看更多 Rust 官方文档中英文双语教程,包括双语版《Rust 程序设计语言》(出版书名为《Rust 权威指南》),本站还提供了 Rust 标准库中文版。
- 《rustdoc 手册》(rustdoc Book 中文版)翻译自 rustdoc Book,内容已全部翻译完成,查看此书的 Github 翻译项目和源码。
- 本文版最后更新时间:2022-02-04。
- 本书主要译者:David,Rust 中文翻译项目组 成员。
- 本站支持文档中英文切换,点击页面右上角语言图标可切换到相同章节的英文页面,英文版每天都会自动同步一次官方的最新版本。
- 若发现当前页表达错误或帮助我们改进翻译,可点击右上角的编辑按钮打开该页对应源码文件进行编辑和修改,Rust 中文资源的开源组织发展离不开大家,感谢您的支持和帮助!
标准 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.
1This text is the contents of the footnote, which will be rendered
towards the bottom.
角标数字会根据角标位置自动生成。
Tables(表格)
表格可以可以通过竖线和短横线来表示表格的行和列。被转换为符合 HTML 形状的表格。比如:
| Header1 | Header2 |
|---------|---------|
| abc | def |
这个例子会被渲染成类似这样:
Header1 Header2 abc def
阅读 GitHub Tables extension 的说明获取更多细节。
Task lists
任务列表可以用于检查需要完成的条目。 比如:
- [x] Complete task
- [ ] Incomplete task
会被渲染成:
- Complete task
- Incomplete task
阅读 task list extension 获得更多细节。
Smart punctuation(标点符号)
一些 ASCII 符号可以自动转换为更好看的 Unicode 符号:
ASCII sequence | Unicode |
---|---|
-- | – |
--- | — |
... | … |
" | “ 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
Using this flag looks like this:
$ rustdoc -V
$ rustdoc --version
This will show rustdoc
's version, which will look something
like this:
rustdoc 1.17.0 (56124baa9 2017-04-24)
-v
/--verbose
: more verbose output
Using this flag looks like this:
$ rustdoc -v src/lib.rs
$ rustdoc --verbose src/lib.rs
This enables "verbose mode", which means that more information will be written
to standard out. What is written depends on the other flags you've passed in.
For example, with --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
Using this flag looks like this:
$ rustdoc src/lib.rs -o target/doc
$ rustdoc src/lib.rs --out-dir target/doc
By default, rustdoc
's output appears in a directory named doc
in
the current working directory. With this flag, it will place all output
into the directory you specify.
--crate-name
: controlling the name of the crate
Using this flag looks like this:
$ rustdoc src/lib.rs --crate-name mycrate
By default, rustdoc
assumes that the name of your crate is the same name
as the .rs
file. --crate-name
lets you override this assumption with
whatever name you choose.
--document-private-items
: Show items that are not public
Using this flag looks like this:
$ rustdoc src/lib.rs --document-private-items
By default, rustdoc
only documents items that are publicly reachable.
#![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
Using this flag looks like this:
$ rustdoc src/lib.rs -L target/debug/deps
$ rustdoc src/lib.rs --library-path target/debug/deps
If your crate has dependencies, rustdoc
needs to know where to find them.
Passing --library-path
gives rustdoc
a list of places to look for these
dependencies.
This flag takes any number of directories as its argument, and will use all of them when searching.
--cfg
: passing configuration flags
Using this flag looks like this:
$ rustdoc src/lib.rs --cfg feature="foo"
This flag accepts the same values as rustc --cfg
, and uses it to configure
compilation. The example above uses feature
, but any of the cfg
values
are acceptable.
--extern
: specify a dependency's location
Using this flag looks like this:
$ rustdoc src/lib.rs --extern lazy-static=/path/to/lazy-static
Similar to --library-path
, --extern
is about specifying the location
of a dependency. --library-path
provides directories to search in, --extern
instead lets you specify exactly which dependency is located where.
-C
/--codegen
: pass codegen options to rustc
Using this flag looks like this:
$ 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
When rustdoc generates documentation, looks for documentation tests, or executes documentation tests, it needs to compile some rust code, at least part-way. This flag allows you to tell rustdoc to provide some extra codegen options to rustc when it runs these compilations. Most of the time, these options won't affect a regular documentation run, but if something depends on target features to be enabled, or documentation tests need to use some additional options, this flag allows you to affect that.
The arguments to this flag are the same as those for the -C
flag on rustc. Run rustc -C help
to
get the full list.
--test
: run code examples as tests
Using this flag looks like this:
$ rustdoc src/lib.rs --test
This flag will run your code examples as tests. For more, see the chapter on documentation tests.
See also --test-args
.
--test-args
: pass options to test runner
Using this flag looks like this:
$ rustdoc src/lib.rs --test --test-args ignored
This flag will pass options to the test runner when running documentation tests. For more, see the chapter on documentation tests.
See also --test
.
--target
: generate documentation for the specified target triple
Using this flag looks like this:
$ rustdoc src/lib.rs --target x86_64-pc-windows-gnu
Similar to the --target
flag for rustc
, this generates documentation
for a target triple that's different than your host triple.
All of the usual caveats of cross-compiling code apply.
--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)]
。
任何标注了 #[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
预处理的完整算法:
- 一些常用的
allow
属性会被插入,包括unused_variables
,unused_assignments
,unused_mut
,unused_attributes
, 和dead_code
。小型示例经常出发这些警告。 - 如果存在
#![doc(test(attr(...)))]
的属性会被加入。 #![foo]
属性会被作为 crate 属性保留。- 如果例子不包含
extern crate
, 并且#![doc(test(no_crate_inject))]
没有被指定,extern crate <mycrate>;
被插入(注意#[macro_use]
要手动写一般)。 - 最后,如果例子不包含
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
andy
:#![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
, edition2018
和 edition2021
告诉 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
, super
和 crate
。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:
- doctests will only run on the appropriate platforms, and
- 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:
- These items aren't accounted by default:
- struct/union field
- enum variant
- constant
- static
- typedef
- 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!
官方
- Learn Rust
- Rust By Example
- Rust Reference
- RFC 1574: More API Documentation Conventions
- RFC 1946: Intra Rustdoc Links