Skip to content

Commit

Permalink
Merge pull request #2 from YangFong/style-all
Browse files Browse the repository at this point in the history
docs: reformat the document
  • Loading branch information
aaranxu committed Feb 4, 2022
2 parents e9b2fd1 + 5ea0a64 commit 4836472
Show file tree
Hide file tree
Showing 13 changed files with 144 additions and 171 deletions.
18 changes: 10 additions & 8 deletions src/advanced-features.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@

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

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

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

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

比如:

Expand All @@ -20,12 +20,12 @@ pub struct WindowsToken;
#[cfg(any(unix, doc))]
pub struct UnixToken;
```

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

### 特定平台文档之间的交互

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

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

Expand All @@ -34,6 +34,7 @@ pub fn f() {
use std::os::windows::ffi::OsStrExt;
}
```

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

```rust,ignore (platform-specific,rustdoc-specific-behavior)
Expand All @@ -42,23 +43,24 @@ pub fn f() -> std::os::windows::ffi::EncodeWide<'static> {
}
```

更多的代码示例,请参考 [the rustdoc test suite][realistic-async].
更多的代码示例,请参考 [the rustdoc test suite][realistic-async]

[#1998]: https://github.com/rust-lang/rust/issues/1998
[realistic-async]: https://github.com/rust-lang/rust/blob/b146000e910ccd60bdcde89363cb6aa14ecc0d95/src/test/rustdoc-ui/error-in-impl-trait/realistic-async.rs

## 增加文档搜索的 item 别名

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

```rust,no_run
#[doc(alias = "x")]
#[doc(alias = "big")]
pub struct BigX;
```

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

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

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

Expand Down
14 changes: 4 additions & 10 deletions src/command-line-arguments.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

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


## `-h`/`--help`: help

这样使用:
Expand All @@ -11,10 +10,10 @@
$ rustdoc -h
$ rustdoc --help
```
这会展示`rustdoc`内置的帮助,包含了大量可用的命令行 flags。

有些 flags 是未稳定的;这个页面只会只包好稳定的参数,`--help`会包含所有的
这会展示 `rustdoc` 内置的帮助,包含了大量可用的命令行 flags

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

## `-V`/`--version`: version information

Expand Down Expand Up @@ -69,7 +68,6 @@ 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:
Expand Down Expand Up @@ -117,7 +115,6 @@ 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:
Expand Down Expand Up @@ -222,7 +219,7 @@ 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
necessarily stable from one rustdoc version to the next. If the
requested theme does not exist, the builtin default (currently
`light`) is used instead.

Expand All @@ -238,7 +235,7 @@ When rendering Markdown files, this will create a `<link>` element in the
`<head>` section of the generated HTML. For example, with the invocation above,

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

will be added.
Expand Down Expand Up @@ -283,7 +280,6 @@ 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:
Expand All @@ -295,7 +291,6 @@ $ 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:
Expand All @@ -308,7 +303,6 @@ 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:
Expand Down
85 changes: 33 additions & 52 deletions src/documentation-tests.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,19 @@
需要注意的是,如果代码块没有设置语言,rustdoc 默认是 Rust 代码,所以下面的:
``````markdown
````markdown
```rust
let x = 5;
```
``````
````
跟这个是相等的
``````markdown
````markdown
```
let x = 5;
```
``````
````

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

Expand All @@ -49,15 +49,11 @@ assert_eq!(foo, "foo");
在上面的例子中,你注意到奇怪的事情:没有`main`函数!如果强制你为每个例子写`main`,增加了难度。
所以`rustdoc`在运行例子前会帮你处理好这个。这里是`rustdoc`预处理的完整算法:

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

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

Expand All @@ -82,10 +78,7 @@ assert_eq!(foo, "foo");
println!("Hello, World!");
```

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

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

Expand Down Expand Up @@ -123,7 +116,7 @@ println!("{}", x + y);
为了保持每个代码块可测试,我们要在每个代码块都有完整代码,但是我们不想文档读者每次都看到全部行代码:

``````markdown
````markdown
First, we set `x` to five:

```
Expand All @@ -147,11 +140,11 @@ Finally, we print the sum of `x` and `y`:
# let y = 6;
println!("{}", x + y);
```
``````
````

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

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

```rust
let s = "foo
Expand All @@ -165,7 +158,7 @@ let s = "foo
/// ## bar # baz";
```

## 在文档测试中使用 `?`
## 在文档测试中使用 `?`

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

Expand All @@ -177,9 +170,10 @@ let s = "foo
/// ```
# fn f() {}
```
问题是 `?` 返回 `Result<T, E>`,测试函数不能返回任何东西,所以会有类型错误。
你可以通过自己增加返回`Result<T, E>``main`函数来规避这个限制,因为`Result<T, E>`实现了`Termination` trait:
你可以通过自己增加返回 `Result<T, E>``main` 函数来规避这个限制,因为 `Result<T, E>` 实现了 `Termination` trait:
```rust,no_run
/// A doc test using ?
Expand All @@ -196,7 +190,7 @@ let s = "foo
# fn f() {}
```
与下节的`# `一起,你可以得到读者舒服,编译通过的完整解决方案:
与下节的 `# `一起,你可以得到读者舒服,编译通过的完整解决方案:
```rust,no_run
/// ```
Expand All @@ -209,7 +203,8 @@ let s = "foo
/// ```
# fn f() {}
```
从 1.34.0 版本开始,也可以省略`fn main()`,但是你必须消除错误类型的歧义:
从 1.34.0 版本开始,也可以省略 `fn main()`,但是你必须消除错误类型的歧义:
```rust,no_run
/// ```
Expand All @@ -221,15 +216,11 @@ let s = "foo
# fn f() {}
```
这是`?`操作符隐式转换带来的不便,因为类型不唯一所以类型推断会出错。你必须写`(())`,`rustdoc`才能理解你想要一个隐式返回值`Result`的函数。
这是 `?` 操作符隐式转换带来的不便,因为类型不唯一所以类型推断会出错。你必须写 `(())`,`rustdoc` 才能理解你想要一个隐式返回值 `Result` 的函数。
## 在文档测试中显示警告
你可以通过运行`rustdoc --test --test-args=--show-output`在文档测试中显示警告
(或者,如果你使用 cargo,`cargo test --doc -- --show-output`也可以)。
默认会隐藏`unused`警告,因为很多例子使用私有函数;
你可以通过在例子顶部加入`#![warn(unused)]`来对没有使用的变量或者死代码进行警告。
你还可以在 crate 根使用 [`#![doc(test(attr(warn(unused))))]`][test-attr] 开启全局警告。
你可以通过运行 `rustdoc --test --test-args=--show-output` 在文档测试中显示警告(或者,如果你使用 cargo,`cargo test --doc -- --show-output` 也可以)。默认会隐藏 `unused` 警告,因为很多例子使用私有函数;你可以通过在例子顶部加入`#![warn(unused)]`来对没有使用的变量或者死代码进行警告。你还可以在 crate 根使用 [`#![doc(test(attr(warn(unused))))]`][test-attr] 开启全局警告。
[test-attr]: ./the-doc-attribute.md#testattr
Expand Down Expand Up @@ -262,15 +253,13 @@ macro_rules! panic_unless {
# fn main() {}
```
你注意到三件事:我们需要自己增加 `extern crate` 一行,
从而我们可以加上 `#[macro_use]` 属性。
第二,我们需要自己增加 `main()`,理由同上。最后 `#` 的使用使得一些内容不会出现在输出中。
你注意到三件事:我们需要自己增加 `extern crate` 一行,从而我们可以加上 `#[macro_use]` 属性。第二,我们需要自己增加 `main()`,理由同上。最后 `#` 的使用使得一些内容不会出现在输出中。
## 属性
代码块可以通过属性标注帮助`rustdoc`在测试例子代码时处理正确。
代码块可以通过属性标注帮助 `rustdoc` 在测试例子代码时处理正确。
`ignore` 属性告诉 Rust 忽略你的代码。 这个属性很通用,并且考虑标注`文本`或者使用`#`隐藏不想展示的部分。
`ignore` 属性告诉 Rust 忽略你的代码。 这个属性很通用,并且考虑标注 `文本`或者使用`#`隐藏不想展示的部分。
```rust
/// ```ignore
Expand All @@ -288,10 +277,7 @@ macro_rules! panic_unless {
# fn foo() {}
```
`no_run` 属性会编译你的代码但是不运行它。
这对于类似"如果获取网页"的例子很重要,
你要确保它能编译但是不想在运行测试,
因为测试环境可能没有网络。这个属性也可以被用来要求代码段有未定义行为。
`no_run` 属性会编译你的代码但是不运行它。这对于类似 "如果获取网页" 的例子很重要,你要确保它能编译但是不想在运行测试,因为测试环境可能没有网络。这个属性也可以被用来要求代码段有未定义行为。
```rust
/// ```no_run
Expand All @@ -313,8 +299,7 @@ macro_rules! panic_unless {
# fn foo() {}
```
`edition2015`, `edition2018` 和 `edition2021` 告诉 `rustdoc`
代码应该使用哪个 edition 版本的 Rust 来编译。
`edition2015`, `edition2018` 和 `edition2021` 告诉 `rustdoc` 代码应该使用哪个 edition 版本的 Rust 来编译。
```rust
/// Only runs on the 2018 edition.
Expand All @@ -335,23 +320,21 @@ macro_rules! panic_unless {
Rustdoc 也接受 *indented* 代码块作为 fenced 代码块的替代:不使用三个反引号,而是每行以四个或者以上空格开始。
``````markdown
```markdown
let foo = "foo";
assert_eq!(foo, "foo");
``````
```

这也在 CommonMark 说明中的
[Indented Code Blocks](https://spec.commonmark.org/0.29/#indented-code-blocks)
小节。
这也在 CommonMark 说明中的 [Indented Code Blocks](https://spec.commonmark.org/0.29/#indented-code-blocks) 小节。

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

### 收集文档测试时包含 item

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

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

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

Expand All @@ -366,12 +349,10 @@ pub struct MyStruct(pub usize);
pub struct MyStructOnlyTakesUsize;
```

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

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

```rust,no_run
#[doc = include_str!("../README.md")]
Expand Down

0 comments on commit 4836472

Please sign in to comment.