#[doc]
属性
#[doc]
属性允许你控制 rustdoc
如何工作的各个方面。
#[doc]
最基本的功能是处理实际的文档文本。也就是说,///
是 #[doc]
的语法糖。这意味着这两个是相同的
#![allow(unused)] fn main() { /// This is a doc comment. #[doc = r" This is a doc comment."] fn f() {} }
(请注意属性版本中的前导空格和原始字符串字面量。)
在大多数情况下,///
比 #[doc]
更容易使用。一个后者更容易使用的情况是在宏中生成文档时;collapse-docs
传递会将多个 #[doc]
属性组合成一个文档注释,从而允许你生成这样的代码
#![allow(unused)] fn main() { #[doc = "This is"] #[doc = " a "] #[doc = "doc comment"] fn f() {} }
这会感觉更灵活。请注意,这将生成如下内容
#![allow(unused)] fn main() { #[doc = "This is\n a \ndoc comment"] fn f() {} }
但是考虑到文档是通过 Markdown 渲染的,它会删除这些换行符。
另一个用例是将外部文件作为文档包含进来
#![allow(unused)] fn main() { #[doc = include_str!("../../README.md")] fn f() {} }
doc
属性还有更多选项!这些选项不涉及输出的文本,而是涉及输出的各个呈现方面。我们将其分为以下两类:在 crate 级别有用的属性,以及在项级别有用的属性。
在 crate 级别
这些选项控制文档在 crate 级别的外观。
html_favicon_url
这种形式的 doc
属性允许你控制文档的 favicon。
#![allow(unused)] #![doc(html_favicon_url = "https://example.com/favicon.ico")] fn main() { }
这会将 <link rel="icon" href="{}">
放入你的文档中,其中属性的字符串会放入 {}
中。
如果你不使用此属性,则不会有 favicon。
html_logo_url
这种形式的 doc
属性允许你控制文档左上角的徽标。
#![allow(unused)] #![doc(html_logo_url = "https://example.com/logo.jpg")] fn main() { }
这会将 <a href='../index.html'><img src='{}' alt='logo' width='100'></a>
放入你的文档中,其中属性的字符串会放入 {}
中。
如果你不使用此属性,则不会有徽标。
html_playground_url
这种形式的 doc
属性允许你控制文档示例上的“运行”按钮向何处发出请求。
#![allow(unused)] #![doc(html_playground_url = "https://playground.example.com/")] fn main() { }
现在,当你按下“运行”时,该按钮将向此域发出请求。请求 URL 将包含 2 个查询参数:code
和 edition
,分别对应于文档中的代码和 Rust 版本。
如果你不使用此属性,则不会有运行按钮。
issue_tracker_base_url
这种形式的 doc
属性主要仅对标准库有用;当某个功能不稳定时,必须给出用于跟踪该功能的 issue 编号。rustdoc
使用此编号,加上此处给出的基本 URL,来链接到跟踪 issue。
#![allow(unused)] #![doc(issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")] fn main() { }
html_root_url
#[doc(html_root_url = "…")]
属性值指示用于生成指向外部 crate 的链接的 URL。当 rustdoc 需要生成指向外部 crate 中某个项的链接时,它将首先检查 extern crate 是否已在本地磁盘上记录,如果是,则直接链接到它。如果失败,它将使用 --extern-html-root-url
命令行标志(如果可用)给出的 URL。如果不可用,它将使用 extern crate 中的 html_root_url
值(如果可用)。如果不可用,则外部项将不会被链接。
#![allow(unused)] #![doc(html_root_url = "https://docs.rs/serde/1.0")] fn main() { }
html_no_source
默认情况下,rustdoc
将包含你的程序的源代码,并在文档中包含指向它的链接。但是,如果你包含这个
#![allow(unused)] #![doc(html_no_source)] fn main() { }
它将不会包含。
test(no_crate_inject)
默认情况下,rustdoc
将自动在每个 doctest 中添加一行 extern crate my_crate;
。但是,如果你包含这个
#![allow(unused)] #![doc(test(no_crate_inject))] fn main() { }
它将不会包含。
test(attr(...))
这种形式的 doc
属性允许你向所有 doctest 添加任意属性。例如,如果你希望 doctest 在存在死代码时失败,你可以添加这个
#![allow(unused)] #![doc(test(attr(deny(dead_code))))] fn main() { }
在项级别
这些形式的 #[doc]
属性用于单个项,以控制它们如何被记录。
inline
和 no_inline
这些属性用于 use
语句,并控制文档的显示位置。例如,考虑以下 Rust 代码
pub use bar::Bar; /// bar docs pub mod bar { /// the docs for Bar pub struct Bar; } fn main() {}
文档将生成一个“重新导出”部分,并显示 pub use bar::Bar;
,其中 Bar
是指向其页面的链接。
如果我们像这样更改 use
行
#[doc(inline)] pub use bar::Bar; pub mod bar { pub struct Bar; } fn main() {}
相反,Bar
将出现在 Structs
部分中,就像 Bar
在顶层定义一样,而不是 pub use
'd。
让我们通过使 bar
私有来更改原始示例
pub use bar::Bar; /// bar docs mod bar { /// the docs for Bar pub struct Bar; } fn main() {}
在这里,因为 bar
不是公共的,所以 bar
不会有自己的页面,因此没有链接到的位置。rustdoc
将内联这些定义,因此我们最终会得到与上面的 #[doc(inline)]
相同的情况;Bar
位于 Structs
部分中,就像它在顶层定义一样。如果我们添加属性的 no_inline
形式
#[doc(no_inline)] pub use bar::Bar; /// bar docs mod bar { /// the docs for Bar pub struct Bar; } fn main() {}
现在我们将有一行 Re-exports
,并且 Bar
将不会链接到任何地方。
一个特殊情况:在 Rust 2018 及更高版本中,如果你 pub use
你的依赖项之一,则除非你添加 #[doc(inline)]
,否则 rustdoc
不会急切地将其作为模块内联。
如果你想了解有关内联规则的更多信息,请查看 re-exports
章节。
hidden
任何使用 #[doc(hidden)]
注释的项都不会出现在文档中,除非删除了 strip-hidden
传递。重新导出的项,如果其祖先之一具有 #[doc(hidden)]
,则将被视为与私有项相同。
你可以在 re-exports
章节中找到更多信息。
alias
此属性在搜索索引中添加别名。
让我们看一个例子
#![allow(unused)] fn main() { #[doc(alias = "TheAlias")] pub struct SomeType; }
因此,现在,如果你在搜索中输入“TheAlias”,它将显示 SomeType
。当然,如果你输入 SomeType
,它将按预期返回 SomeType
!
FFI 示例
此文档属性在为 C 库编写绑定时特别有用。例如,假设我们有一个 C 函数,如下所示
int lib_name_do_something(Obj *obj);
它接受指向 Obj
类型的指针并返回一个整数。在 Rust 中,它可能像这样编写
pub struct Obj {
inner: *mut ffi::Obj,
}
impl Obj {
pub fn do_something(&mut self) -> i32 {
unsafe { ffi::lib_name_do_something(self.inner) }
}
}
该函数已转换为方法,以使其更方便使用。但是,如果你想查找 lib_name_do_something
的 Rust 等价物,你将无法做到这一点。
为了解决此限制,我们只需在 do_something
方法上添加 #[doc(alias = "lib_name_do_something")]
,然后一切都很好!现在,用户可以直接在我们的 crate 中查找 lib_name_do_something
并找到 Obj::do_something
。