3 Documentation is an important part of any software project, and it's
4 first-class in Rust. Let's talk about the tooling Rust gives you to
9 The Rust distribution includes a tool, `rustdoc`, that generates documentation.
10 `rustdoc` is also used by Cargo through `cargo doc`.
12 Documentation can be generated in two ways: from source code, and from
13 standalone Markdown files.
15 ## Documenting source code
17 The primary way of documenting a Rust project is through annotating the source
18 code. You can use documentation comments for this purpose:
21 /// Constructs a new `Rc<T>`.
28 /// let five = Rc::new(5);
30 pub fn new(value: T) -> Rc<T> {
31 // implementation goes here
35 This code generates documentation that looks [like this][rc-new]. I've left the
36 implementation out, with a regular comment in its place.
38 The first thing to notice about this annotation is that it uses
39 `///` instead of `//`. The triple slash
40 indicates a documentation comment.
42 Documentation comments are written in Markdown.
44 Rust keeps track of these comments, and uses them when generating
45 documentation. This is important when documenting things like enums:
48 /// The `Option` type. See [the module level documentation](../) for more.
57 The above works, but this does not:
60 /// The `Option` type. See [the module level documentation](../) for more.
63 Some(T), /// Some value `T`
70 hello.rs:4:1: 4:2 error: expected ident, found `}`
75 This [unfortunate error](https://github.com/rust-lang/rust/issues/22547) is
76 correct: documentation comments apply to the thing after them, and there's no
77 thing after that last comment.
79 [rc-new]: http://doc.rust-lang.org/nightly/std/rc/struct.Rc.html#method.new
81 ### Writing documentation comments
83 Anyway, let's cover each part of this comment in detail:
86 /// Constructs a new `Rc<T>`.
90 The first line of a documentation comment should be a short summary of its
91 functionality. One sentence. Just the basics. High level.
95 /// Other details about constructing `Rc<T>`s, maybe describing complicated
96 /// semantics, maybe additional options, all kinds of stuff.
101 Our original example had just a summary line, but if we had more things to say,
102 we could have added more explanation in a new paragraph.
104 #### Special sections
106 Next, are special sections. These are indicated with a header, `#`. There
107 are four kinds of headers that are commonly used. They aren't special syntax,
108 just convention, for now.
115 Unrecoverable misuses of a function (i.e. programming errors) in Rust are
116 usually indicated by panics, which kill the whole current thread at the very
117 least. If your function has a non-trivial contract like this, that is
118 detected/enforced by panics, documenting it is very important.
125 If your function or method returns a `Result<T, E>`, then describing the
126 conditions under which it returns `Err(E)` is a nice thing to do. This is
127 slightly less important than `Panics`, because failure is encoded into the type
128 system, but it's still a good thing to do.
135 If your function is `unsafe`, you should explain which invariants the caller is
136 responsible for upholding.
144 /// let five = Rc::new(5);
149 Fourth, `Examples`. Include one or more examples of using your function or
150 method, and your users will love you for it. These examples go inside of
151 code block annotations, which we'll talk about in a moment, and can have
152 more than one section:
157 /// Simple `&str` patterns:
160 /// let v: Vec<&str> = "Mary had a little lamb".split(' ').collect();
161 /// assert_eq!(v, vec!["Mary", "had", "a", "little", "lamb"]);
164 /// More complex patterns with a lambda:
167 /// let v: Vec<&str> = "abc1def2ghi".split(|c: char| c.is_numeric()).collect();
168 /// assert_eq!(v, vec!["abc", "def", "ghi"]);
173 Let's discuss the details of these code blocks.
175 #### Code block annotations
177 To write some Rust code in a comment, use the triple graves:
181 /// println!("Hello, world");
186 If you want something that's not Rust code, you can add an annotation:
190 /// printf("Hello, world\n");
195 This will highlight according to whatever language you're showing off.
196 If you're just showing plain text, choose `text`.
198 It's important to choose the correct annotation here, because `rustdoc` uses it
199 in an interesting way: It can be used to actually test your examples, so that
200 they don't get out of date. If you have some C code but `rustdoc` thinks it's
201 Rust because you left off the annotation, `rustdoc` will complain when trying to
202 generate the documentation.
204 ## Documentation as tests
206 Let's discuss our sample example documentation:
210 /// println!("Hello, world");
215 You'll notice that you don't need a `fn main()` or anything here. `rustdoc` will
216 automatically add a main() wrapper around your code, and in the right place.
223 /// let five = Rc::new(5);
228 This will end up testing:
233 let five = Rc::new(5);
237 Here's the full algorithm rustdoc uses to postprocess examples:
239 1. Any leading `#![foo]` attributes are left intact as crate attributes.
240 2. Some common `allow` attributes are inserted, including
241 `unused_variables`, `unused_assignments`, `unused_mut`,
242 `unused_attributes`, and `dead_code`. Small examples often trigger
244 3. If the example does not contain `extern crate`, then `extern crate
245 <mycrate>;` is inserted.
246 2. Finally, if the example does not contain `fn main`, the remainder of the
247 text is wrapped in `fn main() { your_code }`
249 Sometimes, this isn't enough, though. For example, all of these code samples
250 with `///` we've been talking about? The raw text:
253 /// Some documentation.
257 looks different than the output:
260 /// Some documentation.
264 Yes, that's right: you can add lines that start with `# `, and they will
265 be hidden from the output, but will be used when compiling your code. You
266 can use this to your advantage. In this case, documentation comments need
267 to apply to some kind of function, so if I want to show you just a
268 documentation comment, I need to add a little function definition below
269 it. At the same time, it's just there to satisfy the compiler, so hiding
270 it makes the example more clear. You can use this technique to explain
271 longer examples in detail, while still preserving the testability of your
272 documentation. For example, this code:
277 println!("{}", x + y);
280 Here's an explanation, rendered:
282 First, we set `x` to five:
287 # println!("{}", x + y);
290 Next, we set `y` to six:
295 # println!("{}", x + y);
298 Finally, we print the sum of `x` and `y`:
303 println!("{}", x + y);
306 Here's the same explanation, in raw text:
308 > First, we set `x` to five:
313 > # println!("{}", x + y);
316 > Next, we set `y` to six:
321 > # println!("{}", x + y);
324 > Finally, we print the sum of `x` and `y`:
329 > println!("{}", x + y);
332 By repeating all parts of the example, you can ensure that your example still
333 compiles, while only showing the parts that are relevant to that part of your
336 ### Documenting macros
338 Here’s an example of documenting a macro:
341 /// Panic with a given message unless an expression evaluates to true.
346 /// # #[macro_use] extern crate foo;
348 /// panic_unless!(1 + 1 == 2, “Math is broken.”);
353 /// # #[macro_use] extern crate foo;
355 /// panic_unless!(true == false, “I’m broken.”);
359 macro_rules! panic_unless {
360 ($condition:expr, $($rest:expr),+) => ({ if ! $condition { panic!($($rest),+); } });
365 You’ll note three things: we need to add our own `extern crate` line, so that
366 we can add the `#[macro_use]` attribute. Second, we’ll need to add our own
367 `main()` as well. Finally, a judicious use of `#` to comment out those two
368 things, so they don’t show up in the output.
370 ### Running documentation tests
372 To run the tests, either
375 $ rustdoc --test path/to/my/crate/root.rs
380 That's right, `cargo test` tests embedded documentation too. However,
381 `cargo test` will not test binary crates, only library ones. This is
382 due to the way `rustdoc` works: it links against the library to be tested,
383 but with a binary, there’s nothing to link to.
385 There are a few more annotations that are useful to help `rustdoc` do the right
386 thing when testing your code:
395 The `ignore` directive tells Rust to ignore your code. This is almost never
396 what you want, as it's the most generic. Instead, consider annotating it
397 with `text` if it's not code, or using `#`s to get a working example that
398 only shows the part you care about.
407 `should_panic` tells `rustdoc` that the code should compile correctly, but
408 not actually pass as a test.
413 /// println!("Hello, world");
419 The `no_run` attribute will compile your code, but not run it. This is
420 important for examples such as "Here's how to start up a network service,"
421 which you would want to make sure compile, but might run in an infinite loop!
423 ### Documenting modules
425 Rust has another kind of doc comment, `//!`. This comment doesn't document the next item, but the enclosing item. In other words:
429 //! This is documentation for the `foo` module.
437 This is where you'll see `//!` used most often: for module documentation. If
438 you have a module in `foo.rs`, you'll often open its code and see this:
441 //! A module for using `foo`s.
443 //! The `foo` module contains a lot of useful functionality blah blah blah
446 ### Documentation comment style
448 Check out [RFC 505][rfc505] for full conventions around the style and format of
451 [rfc505]: https://github.com/rust-lang/rfcs/blob/master/text/0505-api-comment-conventions.md
453 ## Other documentation
455 All of this behavior works in non-Rust source files too. Because comments
456 are written in Markdown, they're often `.md` files.
458 When you write documentation in Markdown files, you don't need to prefix
459 the documentation with comments. For example:
467 /// let five = Rc::new(5);
480 let five = Rc::new(5);
484 when it's in a Markdown file. There is one wrinkle though: Markdown files need
485 to have a title like this:
490 This is the example documentation.
493 This `%` line needs to be the very first line of the file.
497 At a deeper level, documentation comments are sugar for documentation attributes:
507 are the same, as are these:
515 You won't often see this attribute used for writing documentation, but it
516 can be useful when changing some options, or when writing a macro.
520 `rustdoc` will show the documentation for a public re-export in both places:
528 This will create documentation for bar both inside the documentation for the
529 crate `foo`, as well as the documentation for your crate. It will use the same
530 documentation in both places.
532 This behavior can be suppressed with `no_inline`:
543 You can control a few aspects of the HTML that `rustdoc` generates through the
544 `#![doc]` version of the attribute:
547 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
548 html_favicon_url = "http://www.rust-lang.org/favicon.ico",
549 html_root_url = "http://doc.rust-lang.org/")]
552 This sets a few different options, with a logo, favicon, and a root URL.
554 ## Generation options
556 `rustdoc` also contains a few other options on the command line, for further customization:
558 - `--html-in-header FILE`: includes the contents of FILE at the end of the
559 `<head>...</head>` section.
560 - `--html-before-content FILE`: includes the contents of FILE directly after
561 `<body>`, before the rendered content (including the search bar).
562 - `--html-after-content FILE`: includes the contents of FILE after all the rendered content.
566 The Markdown in documentation comments is placed without processing into
567 the final webpage. Be careful with literal HTML:
570 /// <script>alert(document.cookie)</script>