注释和文档

本章的学习资料在这里,大家可以先行学习后再来做题。

注释

  1. 🌟🌟
2. /* 只使用注释让下面代码工作! */
3. fn main() {
4. todo!();
5. unimplemented!();

7. assert_eq!(6, 5 + 3 + 2 + 1 )
8. }

文档注释

文档注释会被解析为 HTML 文件,并支持 Markdown 语法。

在开始之前,我们需要创建一个新的项目用于后面的练习: cargo new --lib doc-comments.

行文档注释 ///

为 add_one 函数添加文档

1. #![allow(unused)]
2. fn main() {
3. // in lib.rs

5. /// Add one to the given value and return the value
6. ///
7. /// # Examples
8. ///
9. /// ```
10. /// let arg = 5;
11. /// let answer = my_crate::add_one(arg);
12. ///
13. /// assert_eq!(6, answer);
14. /// ```
15. pub fn add_one(x: i32) -> i32 {
16. x + 1
17. }
18. }

Cargo doc

我们可以使用 cargo doc --open 来生成 HTML 文件,并自动在浏览器中打开网页。

块文档注释 /** … */

为函数 add_two 添加文档:

1. #![allow(unused)]
2. fn main() {
3. /** Add two to the given value and return a new value

5. Examples

7. let arg = 5;
8. let answer = my_crate::add_two(arg);

10. assert_eq!(7, answer);

12. */
13. pub fn add_two(x: i32) -> i32 {
14. x + 2
15. }
16. }

为包和模块创建文档注释

我们还可以创建包和模块的注释,用于描述它们的功能。

首先,来为我们的库包添加一些文档注释:

注意: 必须要将包、模块注释放置在包根或模块文件的最顶部

1. #![allow(unused)]
2. fn main() {
3. //! # 文档注释
4. //!
5. //! 该库用于文档注释的教学

7. // in lib.rs
8. pub mod compute;
9. }

同样的,我们还可以使用块注释来达成目的:

1. #![allow(unused)]
2. fn main() {
3. /*! # 文档注释

5. 该库用于文档注释的教学 */
6. }

下一步,创建一个新的模块文件 src/compute.rs, 然后在其中添加以下注释:

1. #![allow(unused)]
2. fn main() {
3. //! 本模块用于处理一些复杂计算

5. // in compute.rs
6. }

然后运行 cargo doc --open 查看下结果。

文档测试

细心的同学可能会发现之前的 add_one 和 add_tow 的文档注释中,包含了两个示例代码块.

以上示例不仅仅是作为文档用于演示你的函数该如何使用,它的另一个作用就是用于文档测试 cargo test。

  1. 🌟🌟 但是在这两个函数的示例中,存在错误,请修复它们并使用 cargo test 获取以下输出结果:
1. running 0 tests

3. test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

5. Doc-tests doc-comments

7. running 2 tests
8. test src/lib.rs - add_one (line 11) ... ok
9. test src/lib.rs - add_two (line 26) ... ok

11. test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.55s
  1. 🌟🌟 有时我们会期望示例的结果是一个 panic。将以下代码添加到 src/compute.rs ,并且让 cargo test 成功运行.

你只能修改注释,不要修改 fn div

1. #![allow(unused)]
2. fn main() {
3. // in src/compute.rs

5. /// # Panics
6. ///
7. /// The function panics if the second argument is zero.
8. ///
9. /// ```rust,should_panic
10. /// // panics on division by zero
11. /// doc_comments::compute::div(10, 0);
12. /// ```
13. pub fn div(a: i32, b: i32) -> i32 {
14. if b == 0 {
15. panic!("Divide-by-zero error");
16. }

18. a / b
19. }
20. }
  1. 🌟🌟 有时我们会想要隐藏文档,但是保留文档测试

将以下代码添加到 src/compute.rs ,

1. // in src/compute.rs

3. /// ```
4. /// # fn try_main() -> Result<(), String> {
5. /// let res = doc_comments::compute::try_div(10, 0)?;
6. /// # Ok(()) // returning from try_main
7. /// # }
8. /// # fn main() {
9. /// #    try_main().unwrap();
10. /// #
11. /// # }
12. /// ```
13. pub fn try_div(a: i32, b: i32) -> Result<i32, String> {
14. if b == 0 {
15. Err(String::from("Divide-by-zero"))
16. } else {
17. Ok(a / b)
18. }
19. }

然后修改以上代码已实现两个目标:

  • 文档注释不能出现在 cargo doc --open 生成的网页中
  • 运行测试,并成功看到以下结果:
1. running 0 tests

3. test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

5. Doc-tests doc-comments

7. running 4 tests
8. test src/compute.rs - compute::div (line 7) ... ok
9. test src/lib.rs - add_two (line 27) ... ok
10. test src/lib.rs - add_one (line 11) ... ok
11. test src/compute.rs - compute::try_div (line 20) ... ok

13. test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.51s

代码跳转

Rust 为我们提供一个非常强大的特性:可以在文档注释中实现代码跳转。

将以下代码添加到 src/lib.rs:

1. #![allow(unused)]
2. fn main() {
3. // in lib.rs

5. /// Add one to the given value and return a [`Option`] type
6. pub fn add_three(x: i32) -> Option<i32> {
7. Some(x + 3)
8. }
9. }

除了跳转到标准库中,我们还能跳转到项目中的其它模块。

1. #![allow(unused)]
2. fn main() {
3. // in lib.rs

5. mod a {
6. /// Add four to the given value and return a [`Option`] type
7. /// [`crate::MySpecialFormatter`]
8. pub fn add_four(x: i32) -> Option<i32> {
9. Some(x + 4)
10. }
11. }

13. struct MySpecialFormatter;
14. }

文档属性

下面是很常用的 #[doc] 属性,该属性可以被 rustdoc 所使用。

inline

可以用于内联文档, 而不是链接到一个单独的页面。

1. #[doc(inline)]
2. pub use bar::Bar;

4. /// bar docs
5. mod bar {
6. /// the docs for Bar
7. pub struct Bar;
8. }

no_inline

用于防止链接到单独的页面或其它地方。

1. // Example from libcore/prelude
2. #[doc(no_inline)]
3. pub use crate::mem::drop;

hidden

通过这个属性让 rustdoc 不要将下面的项包含在文档中:

1. // Example from the futures-rs library
2. #[doc(hidden)]
3. pub use self::async_await::*;

对文档来说,rustdoc 被社区广泛采用,大家所看到的标准库文档也是基于此生成的。

完整的代码

doc-comments 的完整代码可以在这里找到.