17
17
18
18
需要注意的是,如果代码块没有设置语言,rustdoc 默认是 Rust 代码,所以下面的:
19
19
20
- `````` markdown
20
+ ```` markdown
21
21
```rust
22
22
let x = 5;
23
23
```
24
- ``````
24
+ ````
25
25
26
26
跟这个是相等的
27
27
28
- `````` markdown
28
+ ```` markdown
29
29
```
30
30
let x = 5;
31
31
```
32
- ``````
32
+ ````
33
33
34
34
还有一些微妙之处!请阅读获得更多详情。
35
35
@@ -49,15 +49,11 @@ assert_eq!(foo, "foo");
49
49
在上面的例子中,你注意到奇怪的事情:没有` main ` 函数!如果强制你为每个例子写` main ` ,增加了难度。
50
50
所以` rustdoc ` 在运行例子前会帮你处理好这个。这里是` rustdoc ` 预处理的完整算法:
51
51
52
- 1 . 一些常用的 ` allow ` 属性会被插入,包括
53
- ` unused_variables ` , ` unused_assignments ` , ` unused_mut ` ,
54
- ` unused_attributes ` , 和 ` dead_code ` 。小型示例经常出发这些警告。
55
- 2 . 如果存在` #![doc(test(attr(...)))] ` 的属性会被加入。
52
+ 1 . 一些常用的 ` allow ` 属性会被插入,包括 ` unused_variables ` , ` unused_assignments ` , ` unused_mut ` , ` unused_attributes ` , 和 ` dead_code ` 。小型示例经常出发这些警告。
53
+ 2 . 如果存在 ` #![doc(test(attr(...)))] ` 的属性会被加入。
56
54
3 . ` #![foo] ` 属性会被作为 crate 属性保留。
57
- 4 . 如果例子不包含 ` extern crate ` , 并且
58
- ` #![doc(test(no_crate_inject))] ` 没有被指定,`extern crate
59
- <mycrate >;` 被插入(注意 ` #[ macro_use] ` 要手动写一般).
60
- 5 . 最后,如果例子不包含` fn main ` ,剩下的代码会被 main 函数 wrap:` fn main() { your_code } ` 。
55
+ 4 . 如果例子不包含 ` extern crate ` , 并且 ` #![doc(test(no_crate_inject))] ` 没有被指定,` extern crate <mycrate>; ` 被插入(注意 ` #[macro_use] ` 要手动写一般)。
56
+ 5 . 最后,如果例子不包含 ` fn main ` ,剩下的代码会被 main 函数 wrap:` fn main() { your_code } ` 。
61
57
62
58
对于第 4 条的详细解释,请阅读下面的“宏的文档”
63
59
@@ -82,10 +78,7 @@ assert_eq!(foo, "foo");
82
78
println! (" Hello, World!" );
83
79
```
84
80
85
- 没错,这是对的,你可以加一些以 ` # ` 开头的行,在输出中它们会隐藏,但是编译代码会用到。
86
- 你可以利用这一点。在这个例子中,文档注释需要使用函数,但是我只想给你看文档注释,我需要加入函数的定义。
87
- 同时,需要满足编译器编译,而隐藏这部分代码使得示例更清晰。
88
- 你可以使用这个技术写出详细的示例代码并且保留你的可测试性文档。
81
+ 没错,这是对的,你可以加一些以 ` # ` 开头的行,在输出中它们会隐藏,但是编译代码会用到。你可以利用这一点。在这个例子中,文档注释需要使用函数,但是我只想给你看文档注释,我需要加入函数的定义。同时,需要满足编译器编译,而隐藏这部分代码使得示例更清晰。你可以使用这个技术写出详细的示例代码并且保留你的可测试性文档。
89
82
90
83
比如,想象我们想要给这些代码写文档:
91
84
@@ -123,7 +116,7 @@ println!("{}", x + y);
123
116
124
117
为了保持每个代码块可测试,我们要在每个代码块都有完整代码,但是我们不想文档读者每次都看到全部行代码:
125
118
126
- `````` markdown
119
+ ````markdown
127
120
First , we set `x ` to five :
128
121
129
122
```
@@ -147,11 +140,11 @@ Finally, we print the sum of `x` and `y`:
147
140
# let y = 6;
148
141
println!("{}", x + y);
149
142
```
150
- ``````
143
+ ````
151
144
152
145
通过复制例子的所有代码,例子可以通过编译,同时使用 `# ` 在文档中有些部分被隐藏。
153
146
154
- `#`的隐藏可以使用两个`##`来消除。 如果我们有一行注释,以`#`开头,那么这样写:
147
+ `#` 的隐藏可以使用两个 `##` 来消除。 如果我们有一行注释,以 `#` 开头,那么这样写:
155
148
156
149
```rust
157
150
let s = "foo
@@ -165,7 +158,7 @@ let s = "foo
165
158
/// ## bar # baz";
166
159
```
167
160
168
- ## 在文档测试中使用 ` ? `
161
+ ## 在文档测试中使用 ` ? `
169
162
170
163
当写例子时,很少会包含完整的错误处理,因为错误处理会增加很多样板代码。取而代之,你可能更希望这样:
171
164
@@ -177,9 +170,10 @@ let s = "foo
177
170
/// ```
178
171
# fn f() {}
179
172
```
173
+
180
174
问题是 ` ? ` 返回 ` Result<T, E> ` ,测试函数不能返回任何东西,所以会有类型错误。
181
175
182
- 你可以通过自己增加返回` Result<T, E> ` 的 ` main ` 函数来规避这个限制,因为` Result<T, E> ` 实现了` Termination ` trait:
176
+ 你可以通过自己增加返回 ` Result<T, E> ` 的 ` main ` 函数来规避这个限制,因为 ` Result<T, E> ` 实现了 ` Termination ` trait:
183
177
184
178
``` rust,no_run
185
179
/// A doc test using ?
@@ -196,7 +190,7 @@ let s = "foo
196
190
# fn f() {}
197
191
```
198
192
199
- 与下节的` # ` 一起,你可以得到读者舒服,编译通过的完整解决方案:
193
+ 与下节的 ` # ` 一起,你可以得到读者舒服,编译通过的完整解决方案:
200
194
201
195
``` rust,no_run
202
196
/// ```
@@ -209,7 +203,8 @@ let s = "foo
209
203
/// ```
210
204
# fn f() {}
211
205
```
212
- 从 1.34.0 版本开始,也可以省略` fn main() ` ,但是你必须消除错误类型的歧义:
206
+
207
+ 从 1.34.0 版本开始,也可以省略 ` fn main() ` ,但是你必须消除错误类型的歧义:
213
208
214
209
``` rust,no_run
215
210
/// ```
@@ -221,15 +216,11 @@ let s = "foo
221
216
# fn f() {}
222
217
```
223
218
224
- 这是` ? ` 操作符隐式转换带来的不便,因为类型不唯一所以类型推断会出错。你必须写` (()) ` ,` rustdoc ` 才能理解你想要一个隐式返回值` Result ` 的函数。
219
+ 这是 ` ? ` 操作符隐式转换带来的不便,因为类型不唯一所以类型推断会出错。你必须写 ` (()) ` ,` rustdoc ` 才能理解你想要一个隐式返回值 ` Result ` 的函数。
225
220
226
221
## 在文档测试中显示警告
227
222
228
- 你可以通过运行` rustdoc --test --test-args=--show-output ` 在文档测试中显示警告
229
- (或者,如果你使用 cargo,` cargo test --doc -- --show-output ` 也可以)。
230
- 默认会隐藏` unused ` 警告,因为很多例子使用私有函数;
231
- 你可以通过在例子顶部加入` #![warn(unused)] ` 来对没有使用的变量或者死代码进行警告。
232
- 你还可以在 crate 根使用 [ ` #![doc(test(attr(warn(unused))))] ` ] [ test-attr ] 开启全局警告。
223
+ 你可以通过运行 ` rustdoc --test --test-args=--show-output ` 在文档测试中显示警告(或者,如果你使用 cargo,` cargo test --doc -- --show-output ` 也可以)。默认会隐藏 ` unused ` 警告,因为很多例子使用私有函数;你可以通过在例子顶部加入` #![warn(unused)] ` 来对没有使用的变量或者死代码进行警告。你还可以在 crate 根使用 [ ` #![doc(test(attr(warn(unused))))] ` ] [ test-attr ] 开启全局警告。
233
224
234
225
[ test-attr ] : ./the-doc-attribute.md#testattr
235
226
@@ -262,15 +253,13 @@ macro_rules! panic_unless {
262
253
# fn main () {}
263
254
```
264
255
265
- 你注意到三件事:我们需要自己增加 ` extern crate ` 一行,
266
- 从而我们可以加上 ` #[macro_use] ` 属性。
267
- 第二,我们需要自己增加 ` main() ` ,理由同上。最后 ` # ` 的使用使得一些内容不会出现在输出中。
256
+ 你注意到三件事:我们需要自己增加 ` extern crate ` 一行,从而我们可以加上 ` #[macro_use] ` 属性。第二,我们需要自己增加 ` main() ` ,理由同上。最后 ` # ` 的使用使得一些内容不会出现在输出中。
268
257
269
258
## 属性
270
259
271
- 代码块可以通过属性标注帮助` rustdoc ` 在测试例子代码时处理正确。
260
+ 代码块可以通过属性标注帮助 ` rustdoc ` 在测试例子代码时处理正确。
272
261
273
- ` ignore ` 属性告诉 Rust 忽略你的代码。 这个属性很通用,并且考虑标注` 文本 ` 或者使用` # ` 隐藏不想展示的部分。
262
+ ` ignore ` 属性告诉 Rust 忽略你的代码。 这个属性很通用,并且考虑标注 ` 文本 ` 或者使用` # ` 隐藏不想展示的部分。
274
263
275
264
``` rust
276
265
/// ```ignore
@@ -288,10 +277,7 @@ macro_rules! panic_unless {
288
277
# fn foo () {}
289
278
```
290
279
291
- ` no_run ` 属性会编译你的代码但是不运行它。
292
- 这对于类似"如果获取网页"的例子很重要,
293
- 你要确保它能编译但是不想在运行测试,
294
- 因为测试环境可能没有网络。这个属性也可以被用来要求代码段有未定义行为。
280
+ ` no_run ` 属性会编译你的代码但是不运行它。这对于类似 "如果获取网页" 的例子很重要,你要确保它能编译但是不想在运行测试,因为测试环境可能没有网络。这个属性也可以被用来要求代码段有未定义行为。
295
281
296
282
``` rust
297
283
/// ```no_run
@@ -313,8 +299,7 @@ macro_rules! panic_unless {
313
299
# fn foo () {}
314
300
```
315
301
316
- ` edition2015 ` , ` edition2018 ` 和 ` edition2021 ` 告诉 ` rustdoc `
317
- 代码应该使用哪个 edition 版本的 Rust 来编译。
302
+ ` edition2015 ` , ` edition2018 ` 和 ` edition2021 ` 告诉 ` rustdoc ` 代码应该使用哪个 edition 版本的 Rust 来编译。
318
303
319
304
``` rust
320
305
/// Only runs on the 2018 edition.
@@ -335,23 +320,21 @@ macro_rules! panic_unless {
335
320
336
321
Rustdoc 也接受 * indented* 代码块作为 fenced 代码块的替代:不使用三个反引号,而是每行以四个或者以上空格开始。
337
322
338
- `````` markdown
323
+ ``` markdown
339
324
let foo = "foo";
340
325
assert_eq!(foo, "foo");
341
- ``````
326
+ ```
342
327
343
- 这也在 CommonMark 说明中的
344
- [ Indented Code Blocks] ( https://spec.commonmark.org/0.29/#indented-code-blocks )
345
- 小节。
328
+ 这也在 CommonMark 说明中的 [ Indented Code Blocks] ( https://spec.commonmark.org/0.29/#indented-code-blocks ) 小节。
346
329
347
330
但是通常更常用的是 fenced 代码块。不仅是 fenced 代码块更符合 Rust 惯用法,而且 indented 代码块无法使用诸如 ` ignore ` 或者 ` should_panic ` 这些属性。
348
331
349
332
### 收集文档测试时包含 item
333
+
350
334
Rustdoc 文档测试可以做到一些单元测试无法做到的事,可以扩展你的文档测试但是不出现在文档中。意味着,rustdoc 允许你有不出现在
351
335
文档中,但是会进行文档测试的 item,所以你可以利用文档测试这个功能使测试不出现在文档中,或者任意找一个私有 item 包含它。
352
336
353
- 当编译 crate 用来测试文档时(使用` --test ` ),` rustdoc ` 会设置` #[cfg(doctest)] ` 。
354
- 注意这只会在公共 item 上设置;如果你需要测试私有 item,你需要写单元测试。
337
+ 当编译 crate 用来测试文档时(使用` --test ` ),` rustdoc ` 会设置 ` #[cfg(doctest)] ` 。注意这只会在公共 item 上设置;如果你需要测试私有 item,你需要写单元测试。
355
338
356
339
在这个例子中,我们增加不会编译的文档测试,确保我们的结构体只会获取有效数据:
357
340
@@ -366,12 +349,10 @@ pub struct MyStruct(pub usize);
366
349
pub struct MyStructOnlyTakesUsize ;
367
350
```
368
351
369
- 注意结构 ` MyStructOnlyTakesUsize ` 不是你的 crate 公共 API。
370
- ` #[cfg(doctest)] ` 的使用使得这个结构体只会在` rustdoc ` 收集文档测试时存在。
371
- 这意味着当传递` --test ` 给 rustdoc 时才存在,在公共文档中是隐藏的。
352
+ 注意结构 ` MyStructOnlyTakesUsize ` 不是你的 crate 公共 API。` #[cfg(doctest)] ` 的使用使得这个结构体只会在 ` rustdoc ` 收集文档测试时存在。这意味着当传递 ` --test ` 给 rustdoc 时才存在,在公共文档中是隐藏的。
372
353
373
- 另一个可能用到` #[cfg(doctest)] ` 的是你的 README 文件中的文档测试。
374
- 比如你可以在` lib.rs ` 写下面的代码来运行 README 中的文档测试:
354
+ 另一个可能用到 ` #[cfg(doctest)] ` 的是你的 README 文件中的文档测试。
355
+ 比如你可以在 ` lib.rs ` 写下面的代码来运行 README 中的文档测试:
375
356
376
357
``` rust,no_run
377
358
#[doc = include_str!("../README.md")]
0 commit comments