文档编写
crate 级别的文档应该详实有例
Crate level docs are thorough and include examples (C-CRATE-DOC)
参考 RFC 1687 。
每个条目都应该有例子
All items have a rustdoc example (C-EXAMPLE)
每个公有的 模块、 trait 、结构体、枚举体、函数、方法、宏、类型定义 , 都应该有展示其功能和使用方法的例子。
这条原则应该在合理的地方使用。
以链接的形式关联另一个条目的使用例子可能就足够了。 比如一个函数用到一个具体的类型,合适的做法是: 给这个函数或者类型写一个例子,然后链接这个例子到另一个。
写例子的目的不一定仅仅是展示 如何使用 这个条目。 阅读它的人可以理解怎样调用函数、匹配枚举体 和 其他基础的用法。 但更多时候,例子通常用来展示 为什么 使用者愿意去使用这个条目。
// 这就是一个关于 `.clone()` 的不好的例子。
// 它死板地展示如何调用 clone() ,而完全没有表明 *为什么* 需要这样做。
fn main() {
let hello = "hello";
hello.clone();
}
例子应该使用 ?
而不使用 try!
或者 unwrap
Examples use
?
, nottry!
, notunwrap
(C-QUESTION-MARK)
不管你喜不喜欢这样做,例子里的代码通常会被使用者一字不落地复制下来。 使用者应该慎重地决定怎样处理每个错误。
一个容易出错的代码示例通常是按照下面的方式来写:
由 cargo test
编译测试代码块,
/// ```rust
/// # use std::error::Error;
/// #
/// # fn main() -> Result<(), Box<dyn Error>> {
/// your;
/// example?;
/// code;
/// #
/// # Ok(())
/// # }
/// ```
但以 #
开头的每行代码不会出现在读者可见的 rustdoc 里。
use std::error::Error;
fn main() -> Result<(), Box<dyn Error>> {
your;
example?;
code;
Ok(())
}
函数涉及错误、 panic、安全性时 应该加以说明
Function docs include error, panic, and safety considerations (C-FAILURE)
引发错误的条件应该在 "Errors" 标题下说明。 这也适用于 trait 方法 —— 可以或者可能返回错误的方法都应该在 "Errors" 小节进行说明。
比如以下标准库里的例子,
std::io::Read::read
trait 里某个方法可能会返回一个错误。
/// Pull some bytes from this source into the specified buffer, returning
/// how many bytes were read.
///
/// ... lots more info ...
///
/// # Errors
///
/// If this function encounters any form of I/O or other error, an error
/// variant will be returned. If an error is returned then it must be
/// guaranteed that no bytes were read.
引发 panic 的条件应该在 "Panics" 标题下说明。 这也适用于 trait 方法 —— 可以或者可能导致 panic 的方法都应该在 "Panics" 小节进行说明。
标准库里的 Vec::insert
方法可能会 panic :
/// Inserts an element at position `index` within the vector, shifting all
/// elements after it to the right.
///
/// # Panics
///
/// Panics if `index` is out of bounds.
没必要把所有可能想到的 panic 情况都进行说明,
尤其是如果 panic 发生在调用期间有逻辑错误的时候。
以如下的方式说明 Display
会 panic 就显得多余了。
/// # Panics
///
/// This function panics if `T`'s implementation of `Display` panics.
pub fn print<T: Display>(t: T) {
println!("{}", t.to_string());
}
unsafe 的函数应该放在 "Safety" 小节,用来解释如何正确使用这个函数。
例如,不安全的 std::ptr::read
方法必须在以下情况才能被调用:
/// Reads the value from `src` without moving it. This leaves the
/// memory in `src` unchanged.
///
/// # Safety
///
/// Beyond accepting a raw pointer, this is unsafe because it semantically
/// moves the value out of `src` without preventing further usage of `src`.
/// If `T` is not `Copy`, then care must be taken to ensure that the value at
/// `src` is not used before the data is overwritten again (e.g. with `write`,
/// `zero_memory`, or `copy_memory`). Note that `*src = foo` counts as a use
/// because it will attempt to drop the value previously at `*src`.
///
/// The pointer must be aligned; use `read_unaligned` if that is not the case.
给相关的内容添加超链接
Prose contains hyperlinks to relevant things (C-LINK)
一般使用 markdown 超链接语法 [text](url)
来设置超链接。
链接到某个类型则可以使用 [`text`]
语法来标注,
在 docstring 底部另起一行,使用 [`text`]: <target>
来添加链接地址,
下面谈谈这里的 <target>
。
通常这样做来链接到这个类型的方法:
[`serialize_struct`]: #method.serialize_struct
通常这样做来链接到其他类型:
[`Deserialize`]: trait.Deserialize.html
也可以链接到父模块或者子模块:
[`Value`]: ../enum.Value.html
[`DeserializeOwned`]: de/trait.DeserializeOwned.html
这条原则由 RFC 1574 正式推荐,可参考其 "Link all the things" 部分。
Cargo.toml 应包含所有常见的配置数据
Cargo.toml includes all common metadata (C-METADATA)
在 Cargo.toml
的 [package]
部分应该要有以下内容:
authors
description
license
repository
readme
keywords
categories
此外,这两个配置字段可选填:
documentation
homepage
crates.io 默认会把已发布的 crate 文档链接到 docs.rs 。
documentation
配置信息在文档发布到 docs.rs 之外的地方时才需要填写。
比如这个 crate 链接了不在 docs.rs 上构建的共享库。
homepage
配置信息只填写除源码仓库或 API 文档网址之外的单独网站。
不要让 homepage
和 documentation
或者 repository
的值重复。
比如 serde 设置其 homepage
为 https://serde.rs 。
设置 html_root_url 属性 "https://docs.rs/CRATE/X.Y.Z"
Crate sets html_root_url attribute (C-HTML-ROOT)
加入 crate 使用 docs.rs 作为其主要的 API 文档平台,
那么 html_root_url
应该指向 "https://docs.rs/CRATE/MAJOR.MINOR.PATCH"
地址。1
在编译下游 crates 时, html_root_url
属性告诉 rustdoc
如何生成指向条目的 URLs 。
如果没有这个属性,依赖于这个 crate 的其他 crates 里的文档链接地址就不正确。
#![doc(html_root_url = "https://docs.rs/log/0.3.8")]
因为这个 URL 包含确定的版本号,所以这个版本号必须和 Cargo.toml
里的版本号同步。
version-sync
crate 能帮助你做集成测试,当 html_root_url
里的版本号落后于 crate 的版本号时,测试不通过。
如果你不喜欢使用 version-sync
提供的测试机制,那么建议你在 Cargo.toml
里 version 一行添加注释来 提醒你 保持这两者同步,就像:
version = "0.3.8" # remember to update html_root_url
对于发布在 docs.rs 之外的文档, html_root_url
得设置成一个增加
crate 名 + index.html 之后能访问到 crate 根目录文档的地址。
比如 crate 的根目录文档地址是 "https://api.rocket.rs/rocket/index.html"
,
那么 html_root_url
的值应该填成 "https://api.rocket.rs"
。
译者注:当 rustdoc 支持不设置 html_root_url
默认就指向 docs.rs
的功能之后,这条原则就可以删除。见
issue 42301 。
此外,你还可以看看文档 rustdoc: html_root_url 和 cargo doc 。
发布时 记录该版本的重大变化
Release notes document all significant changes (C-RELNOTES)
crate 的使用者能从版本说明 (release note) 中找到每个发布版本的更改概要。 这些版本说明或者其链接应该在 crate 根文档 以及/或者 Cargo.toml 填写的仓库说明 里有介绍。
不兼容的变更 (正如 RFC 1105 所定义) 应该清楚地写在版本说明里。
如果使用 Git 来追踪 crate 源代码,那么每个发布到 crates.io 上的版本 应该有对应的标签 (tag) 来标记这次已发布的提交记录。 不使用 Git 的版本控制工具也应该用类似的方式进行处理。 参考以下 Git 命令:
# Tag the current commit
GIT_COMMITTER_DATE=$(git log -n1 --pretty=%aD) git tag -a -m "Release 0.3.0" 0.3.0
git push --tags
有注释的 tag 会更好,因为一些 Git 命令会在有注释 tag 存在的情况下 忽略不带注释的 tag 。
例子:
文档不应该展示无太大帮助的实现细节
Rustdoc does not show unhelpful implementation details (C-HIDDEN)
rustdoc 应该包含帮助使用者充分使用该 crate 的所有信息。 解释相关的实现细节是可以的, 但是不应该在文档里展开论述这些细节。
尤其应该挑选哪些条目可以在 rustdoc 展示出来 ——
展示那些让使用者完全掌握使用这个 crate 的内容,
其他的内容不展示。
下面代码中给 PublicError
实现 From<PrivateError>
的 rustdoc 文档会默认展示出来,
使用 #[doc(hidden)]
来隐藏它,因为用户不会在代码里面用到私有的 PrivateError
,
所以这个 impl 块对用户来说完全无关。
// This error type is returned to users.
pub struct PublicError { /* ... */ }
// This error type is returned by some private helper functions.
struct PrivateError { /* ... */ }
// Enable use of `?` operator.
#[doc(hidden)]
impl From<PrivateError> for PublicError {
fn from(err: PrivateError) -> PublicError {
/* ... */
}
}
pub(crate)
是一个很棒的工具,它从公有 API 移除掉实现的细节:
让条目于 定义所在的模块之外 被使用,但 定义所在的 crate 之外 无法被使用。
(仅让条目在 crate 内可见,在 crate 之外不可见)