<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # 文檔 > [documentation.md](https://github.com/rust-lang/rust/blob/master/src/doc/book/documentation.md) commit 6ba952020fbc91bad64be1ea0650bfba52e6aab4 文檔是任何軟件項目中重要的一部分,并且它在Rust中是一級重要的。讓我們討論下Rust提供給我們編寫項目文檔的的工具。 ### 關于`rustdoc` Rust發行版中包含了一個工具,`rustdoc`,它可以生成文檔。`rustdoc`也可以在Cargo中通過`cargo doc`使用。 文檔可以使用兩種方法生成:從源代碼,或者從單獨的Markdown文件。 ### 文檔化源代碼 文檔化Rust項目的主要方法是在源代碼中添加注釋。為了這個目標你可以這樣使用文檔注釋: ~~~ /// Constructs a new `Rc`. /// /// # Examples /// /// ``` /// use std::rc::Rc; /// /// let five = Rc::new(5); /// ``` pub fn new(value: T) -> Rc { // implementation goes here } ~~~ 這段代碼產生像[這樣](http://doc.rust-lang.org/nightly/std/rc/struct.Rc.html#method.new)的文檔。我忽略了函數的實現,而是留下了一個標準的注釋。 第一個需要注意的地方是這個注釋:它使用了`///`,而不是`//`。三斜線指示這是文檔注釋。 文檔注釋用Markdown語法編寫。 Rust會記錄這些注釋,并在生成文檔時使用它們。這在文檔化像枚舉這樣的結構時很重要: ~~~ /// The `Option` type. See [the module level documentation](../) for more. enum Option<T> { /// No value None, /// Some value `T` Some(T), } ~~~ 上面的代碼可以工作,但這個不行: ~~~ /// The `Option` type. See [the module level documentation](../) for more. enum Option<T> { None, /// No value Some(T), /// Some value `T` } ~~~ 你會得到一個錯誤: ~~~ hello.rs:4:1: 4:2 error: expected ident, found `}` hello.rs:4 } ^ ~~~ 這個[不幸的錯誤](https://github.com/rust-lang/rust/issues/22547)是有道理的:文檔注釋適用于它后面的內容,而在在最后的注釋后面沒有任何內容。 ### 編寫文檔注釋 不管怎樣,讓我們來詳細了解一下注釋的每一部分: ~~~ /// Constructs a new `Rc<T>`. # fn foo() {} ~~~ 文檔注釋的第一行應該是它功能的一個簡要總結。一句話。只包括基礎。高層次。 ~~~ /// /// Other details about constructing `Rc<T>`s, maybe describing complicated /// semantics, maybe additional options, all kinds of stuff. /// # fn foo() {} ~~~ 我們原始的例子只有一行總結,不過如果有更多東西要寫,我們在一個新的段落增加更多解釋。 ### 特殊部分 下面,是特殊部分。它由一個標頭指示,`#`。有四種經常使用的標頭。它們不是特殊的語法,只是傳統,目前為止。 ~~~ /// # Panics # fn foo() {} ~~~ 不可恢復的函數濫用(比如,程序錯誤)在Rust中通常用恐慌(panics)指示,它至少會殺死整個當前的線程。如果你的函數有被識別為或者強制為恐慌這樣的不平凡契約,記錄文檔是非常重要的。 ~~~ /// # Failures # fn foo() {} ~~~ 如果你的函數或方法返回`Result<T, E>`,那么描述何種情況下它會返回`Err(E)`是件好事。這并不如`Panics`重要,因為失敗(failure)被編碼進了類型系統,不過仍舊是件好事。 ~~~ /// # Safety # fn foo() {} ~~~ 如果你的函是`unsafe`的,你應該解釋調用者應該支持哪種不可變量。 ~~~ /// # Examples /// /// ``` /// use std::rc::Rc; /// /// let five = Rc::new(5); /// ``` # fn foo() {} ~~~ 第四個,`Examples`。包含一個或多個使用你函數的例子,這樣你的用戶會為此感(ài)謝(shàng)你的。這些例子寫在代碼塊注釋中,我們稍后會討論到,并且可以有不止一個部分: ~~~ /// # Examples /// /// Simple `&str` patterns: /// /// ``` /// let v: Vec<&str> = "Mary had a little lamb".split(' ').collect(); /// assert_eq!(v, vec!["Mary", "had", "a", "little", "lamb"]); /// ``` /// /// More complex patterns with a lambda: /// /// ``` /// let v: Vec<&str> = "abc1def2ghi".split(|c: char| c.is_numeric()).collect(); /// assert_eq!(v, vec!["abc", "def", "ghi"]); /// ``` # fn foo() {} ~~~ 讓我們聊聊這些代碼塊的細節。 ### 代碼塊注釋 在注釋中編寫Rust代碼,使用三個重音號: ~~~ /// ``` /// println!("Hello, world"); /// ``` # fn foo() {} ~~~ 如果你想要一些不是Rust的代碼,你可以加上一個注解: ~~~ /// ```c /// printf("Hello, world\n"); /// ``` # fn foo() {} ~~~ 這會根據你選擇的語言高亮代碼。如果你只是想展示普通文本,選擇`text`。 選擇正確的注釋是很重要的,因為`rustdoc`用一種有意思的方法使用它:它可以用來實際測試你的代碼,這樣你的注解就不會過時。如果你寫了些C代碼不過`rustdoc`會認為它是Rust代碼由于你忽略了注解,`rustdoc`會在你生成文檔時提示。 ### 文檔作為測試 讓我們看看我的例子文檔的樣例: ~~~ /// ``` /// println!("Hello, world"); /// ``` # fn foo() {} ~~~ 你會注意到你并不需要`fn main()`或者別的什么函數。`rustdoc`會自動一個`main()`包裝你的代碼,使用試探法試圖把它放到正確的位置。例如: ~~~ /// ``` /// use std::rc::Rc; /// /// let five = Rc::new(5); /// ``` # fn foo() {} ~~~ 這會作為測試: ~~~ fn main() { use std::rc::Rc; let five = Rc::new(5); } ~~~ 這里是`rustdoc`用來后處理例子的完整的算法: 1. 任何`#![foo]`開頭的屬性會被完整的作為包裝箱屬性 1. 一些通用的`allow`屬性被插入,包括`unused_variables`、`unused_assignments`、`unused_mut`、`unused_attributes`和`dead_code`。小的例子經常觸發這些lint檢查 1. 如果例子并未包含`extern crate`,那么`extern crate <mycrate>;`被插入(注意缺失了`#[macro_use]`) 1. 最后,如果例子不包含`fn main`,剩下的文本將被包裝到`fn main() { your_code }`中 有時,這是不夠的。例如,我們已經考慮到了所有`///`開頭的代碼樣例了嗎?普通文本: ~~~ /// Some documentation. # fn foo() {} ~~~ 與它的輸出看起來有些不同: ~~~ /// Some documentation. # fn foo() {} ~~~ 是的,你猜對了:你寫的以`#`開頭的行會在輸出中被隱藏,不過會在編譯你的代碼時被使用。你可以利用這一點。在這個例子中,文檔注釋需要適用于一些函數,所以我只想向你展示文檔注釋,我需要在下面增加一些函數定義。同時,這只是用來滿足編譯器的,所以省略它會使得例子看起來更清楚。你可以使用這個技巧來詳細的解釋較長的例子,同時保留你文檔的可測試行。 例如,想象一下我們想要為如下代碼寫文檔: ~~~ let x = 5; let y = 6; println!("{}", x + y); ~~~ 最終我們可能想要文檔變成這樣: > 首先,我們把`x`設置為`5`: ~~~ let x = 5; # let y = 6; # println!("{}", x + y); ~~~ > 接著,我們把`y`設置為`6`: ~~~ # let x = 5; let y = 6; # println!("{}", x + y); ~~~ > 最后,我們打印`x`和`y`的和: ~~~ # let x = 5; # let y = 6; println!("{}", x + y); ~~~ 為了讓每個代碼塊可以執行,我們想要每個代碼塊都有整個程序,不過我們并不想讀者每回都看到所有的行。這是我們的源代碼: ~~~ 首先,我們把`x`設置為`5`: ```text let x = 5; # let y = 6; # println!("{}", x + y); ``` 接著,我們把`y`設置為`6`: ```text # let x = 5; let y = 6; # println!("{}", x + y); ``` 最后,我們打印`x`和`y`的和: ```text # let x = 5; # let y = 6; println!("{}", x + y); ``` ~~~ 通過重復例子的所有部分,你可以確保你的例子仍能編譯,同時只顯示與你解釋相關的部分。 ### 文檔化宏 下面是一個宏的文檔例子: ~~~ /// Panic with a given message unless an expression evaluates to true. /// /// # Examples /// /// ``` /// # #[macro_use] extern crate foo; /// # fn main() { /// panic_unless!(1 + 1 == 2, “Math is broken.”); /// # } /// ``` /// /// ```should_panic /// # #[macro_use] extern crate foo; /// # fn main() { /// panic_unless!(true == false, “I’m broken.”); /// # } /// ``` #[macro_export] macro_rules! panic_unless { ($condition:expr, $($rest:expr),+) => ({ if ! $condition { panic!($($rest),+); } }); } # fn main() {} ~~~ 你會注意到3個地方:我們需要添加我們自己的`extern crate`行,這樣我們可以添加`#[macro_use]`屬性。第二,我們也需要添加我們自己的`main()`(為了上面討論過的原因)。最后,用`#`機智的注釋掉這兩個代碼,這樣它們不會出現在輸出中。 另一個`#`好用的情況是當你想要忽略錯誤處理的時候。例如你想要如下情況。 ~~~ /// use std::io; /// let mut input = String::new(); /// try!(io::stdin().read_line(&mut input)); ~~~ 問題是`try!`返回一個`Result<T, E>`而測試函數并不返回任何值所以這會產生一個類型不匹配錯誤。 ~~~ /// A doc test using try! /// /// ``` /// use std::io; /// # fn foo() -> io::Result<()> { /// let mut input = String::new(); /// try!(io::stdin().read_line(&mut input)); /// # Ok(()) /// # } /// ``` # fn foo() {} ~~~ 你可以將代碼放進函數里來解決這個問題。在運行文檔測試時它捕獲并返回`Result<T, E>`。這種模式不時出現在標準庫中。 ### 運行文檔測試 要運行測試,要么 ~~~ $ rustdoc --test path/to/my/crate/root.rs # or(或者) $ cargo test ~~~ 對了,`cargo test`也會測試內嵌的文檔。**然而,`cargo test`將不會測試二進制 crate,只測試庫 crate**。這是由于`rustdoc`的運行機制:它鏈接要測試的庫,不過對于一個二進制文件,木有什么好鏈接的。 這還有一些注釋有利于幫助`rustdoc`在測試你的代碼時正常工作: ~~~ /// ```ignore /// fn foo() { /// ``` # fn foo() {} ~~~ `ignore`指令告訴Rust忽略你的代碼。這幾乎不會是你想要的,因為這是最不受支持的。相反,如果不是代碼的話考慮注釋為`text`,或者使用`#`來形成一個可運行但只顯示你關心部分的例子。 ~~~ /// ```should_panic /// assert!(false); /// ``` # fn foo() {} ~~~ `should_panic`告訴`rustdoc`這段代碼應該正確編譯,但是作為一個測試則不能通過。 ~~~ /// ```no_run /// loop { /// println!("Hello, world"); /// } /// ``` # fn foo() {} ~~~ `no_run`屬性會編譯你的代碼,但是不運行它。這對像如“如何開始一個網絡服務”這樣的例子很重要,你會希望確保它能夠編譯,不過它可能會無限循環的執行! ### 文檔化模塊 Rust有另一種文檔注釋,`//!`。這種注釋并不文檔化接下來的內容,而是包圍它的內容。換句話說: ~~~ mod foo { //! This is documentation for the `foo` module. //! //! # Examples // ... } ~~~ 這是你會看到`//!`最常見的用法:作為模塊文檔。如果你在`foo.rs`中有一個模塊,打開它你常常會看到這些: ~~~ //! A module for using `foo`s. //! //! The `foo` module contains a lot of useful functionality blah blah blah ~~~ ### 文檔注釋風格 查看[RFC 505](https://github.com/rust-lang/rfcs/blob/master/text/0505-api-comment-conventions.md)以了解文檔風格和格式的慣例。 ### 其它文檔 所有這些行為都能在非 Rust 代碼文件中工作。因為注釋是用 Markdown 編寫的,它們通常是`.md`文件。 當你在 Markdown 文件中寫文檔時,你并不需要加上注釋前綴。例如: ~~~ /// # Examples /// /// ``` /// use std::rc::Rc; /// /// let five = Rc::new(5); /// ``` # fn foo() {} ~~~ 在一個Markdown文件中,就是: ~~~ # Examples ``` use std::rc::Rc; let five = Rc::new(5); ``` ~~~ 不過文檔寫在 Markdown 文件中要加一點:Markdown文件需要有一個像這樣的標題: ~~~ % The title This is the example documentation. ~~~ `%`行需要放在文件的第一行。 ### `doc`屬性 在更底層,文檔注釋是文檔屬性的語法糖: ~~~ /// this # fn foo() {} #[doc="this"] # fn bar() {} ~~~ 跟下面這個是相同的: ~~~ //! this #![doc="this"] ~~~ 寫文檔時你不會經常看見這些屬性,不過當你要改變一些選項,或者寫一個宏的時候比較有用。 ### 重導出(Re-exports) `rustdoc`對公有重導出部分會在兩個地方都顯式文檔: ~~~ extern crate foo; pub use foo::bar; ~~~ 這既會為`bar`在`foo`包裝箱中生成文檔,也會在你的包裝箱中生成文檔。它會在兩個地方使用相同的內容。 這種行文可以通過`no_inline`來阻止: ~~~ extern crate foo; #[doc(no_inline)] pub use foo::bar; ~~~ ### 缺失文檔 有時你想要確保你項目中每一個公開的項都有文檔,特別是當你編寫一個庫的時候。Rust 允許你為此產生警告或錯誤,當一個項缺少文檔時。為了生成警告,你需要使用`warn`: ~~~ #![warn(missing_docs)] ~~~ 而為了生成錯誤你需要使用`deny`: ~~~ #![deny(missing_docs)] ~~~ 有時你想要顯式的禁用警告/錯誤來讓一些項沒有文檔。這可以使用`allow`來搞定: ~~~ #[allow(missing_docs)] struct Undocumented; ~~~ 你可能甚至希望在文檔中完全隱藏某些項: ~~~ #[doc(hidden)] struct Hidden; ~~~ ### 控制HTML 你可以通過`#![doc]`屬性控制`rustdoc`生成的THML文檔的一些方面: ~~~ #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://www.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/")] ~~~ 這里設置了一些不同的選項,帶有一個logo,一個網站圖標,和一個根URL。 ### 配置文檔測試 你也可以通過`#![doc(test(..))]`屬性來配置`rustdoc`測試你文檔示例的方式。 ~~~ #![doc(test(attr(allow(unused_variables), deny(warnings))))] ~~~ 這允許示例中存在未使用的變量,但其他 lint 警告拋出仍會使測試失敗。 ### 生成選項 `rustdoc`也提供了一些其他命令行選項,以便進一步定制: - `--html-in-header FILE`:在`<head>...</head>`部分的末尾加上`FILE`內容 - `--html-before-content FILE`:在`<body>`之后,在渲染內容之前加上`FILE`內容 - `--html-after-content FILE`:在所有渲染內容之后加上`FILE`內容 ### 注解安全 文檔注釋中的Markdown會被不加處理的放置于最終的網頁中。注意HTML文本(XSS?): ~~~ /// <script>alert(document.cookie)</script> # fn foo() {} ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看