注释和文档

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

注释

  1. 🌟🌟

/* 只使用注释让下面代码工作! */
fn main() {
    todo!();
    unimplemented!();

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

文档注释

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

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

行文档注释 ///

add_one 函数添加文档

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

/// Add one to the given value and return the value
///
/// # Examples
///
/// ```
/// let arg = 5;
/// let answer = my_crate::add_one(arg);
///
/// assert_eq!(6, answer);
/// ```
pub fn add_one(x: i32) -> i32 {
    x + 1
}
}

Cargo doc

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

块文档注释 /** ... */

为函数 add_two 添加文档:

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

Examples

let arg = 5;
let answer = my_crate::add_two(arg);

assert_eq!(7, answer);

*/
pub fn add_two(x: i32) -> i32 {
    x + 2
}
}

为包和模块创建文档注释

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

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

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

#![allow(unused)]
fn main() {
//! # 文档注释
//! 
//! 该库用于文档注释的教学

// in lib.rs
pub mod compute;
}

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

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

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

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

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

// in compute.rs
}

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

文档测试

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

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

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

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

   Doc-tests doc-comments

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

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

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

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

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

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

// in src/compute.rs

/// ```
/// # fn try_main() -> Result<(), String> {
/// let res = doc_comments::compute::try_div(10, 0)?;
/// # Ok(()) // returning from try_main
/// # }
/// # fn main() { 
/// #    try_main().unwrap();
/// #
/// # }
/// ```
pub fn try_div(a: i32, b: i32) -> Result<i32, String> {
    if b == 0 {
        Err(String::from("Divide-by-zero"))
    } else {
        Ok(a / b)
    }
}

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

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

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

   Doc-tests doc-comments

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

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

代码跳转

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

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

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

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

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

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

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

struct MySpecialFormatter;
}

文档属性

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

inline

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

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

/// bar docs
mod bar {
    /// the docs for Bar
    pub struct Bar;
}

no_inline

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

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

hidden

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

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

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

完整的代码

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