Skip to content

Commit a601302

Browse files
committedNov 6, 2020
Auto merge of #75778 - AndyGauge:75521-rustdoc-book-improvements, r=jyn514
75521 rustdoc book improvements Added some guidelines about documenting with rustdoc Fixes #75521
2 parents 7e9a36f + 881820a commit a601302

File tree

6 files changed

+283
-31
lines changed

6 files changed

+283
-31
lines changed
 

‎src/doc/rustdoc/src/SUMMARY.md

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
- [What is rustdoc?](what-is-rustdoc.md)
44
- [How to write documentation](how-to-write-documentation.md)
5+
- [What to include (and exclude)](what-to-include.md)
56
- [Command-line arguments](command-line-arguments.md)
67
- [The `#[doc]` attribute](the-doc-attribute.md)
78
- [Documentation tests](documentation-tests.md)
@@ -10,3 +11,4 @@
1011
- [Passes](passes.md)
1112
- [Advanced features](advanced-features.md)
1213
- [Unstable features](unstable-features.md)
14+
- [References](references.md)

‎src/doc/rustdoc/src/how-to-write-documentation.md

+105-15
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,85 @@
11
# How to write documentation
22

3+
Good documentation is not natural. There are opposing goals that make writing
4+
good documentation difficult. It requires expertise in the subject but also
5+
writing to a novice perspective. Documentation therefore often glazes over
6+
implementation detail, or leaves readers with unanswered questions.
7+
8+
There are a few tenets to Rust documentation that can help guide anyone through
9+
the process of documenting libraries so that everyone has an ample opportunity
10+
to use the code.
11+
312
This chapter covers not only how to write documentation but specifically
4-
how to write **good** documentation. Something to keep in mind when
5-
writing documentation is that your audience is not just yourself but others
6-
who simply don't have the context you do. It is important to be as clear
13+
how to write **good** documentation. It is important to be as clear
714
as you can, and as complete as possible. As a rule of thumb: the more
815
documentation you write for your crate the better. If an item is public
916
then it should be documented.
1017

11-
## Basic structure
18+
## Getting Started
19+
20+
Documenting a crate should begin with front-page documentation. As an
21+
example, the [`hashbrown`] crate level documentation summarizes the role of
22+
the crate, provides links to explain technical details, and explains why you
23+
would want to use the crate.
24+
25+
After introducing the crate, it is important that the front-page gives
26+
an example of how to use the crate in a real world setting. Stick to the
27+
library's role in the example, but do so without shortcuts to benefit users who
28+
may copy and paste the example to get started.
29+
30+
[`futures`] uses inline comments to explain line by line
31+
the complexities of using a [`Future`], because a person's first exposure to
32+
rust's [`Future`] may be this example.
33+
34+
The [`backtrace`] documentation walks through the whole process, explaining
35+
changes made to the `Cargo.toml` file, passing command line arguments to the
36+
compiler, and shows a quick example of backtrace in the wild.
37+
38+
Finally, the front-page can eventually become a comprehensive reference
39+
how to use a crate, like [`regex`]. In this front page, all
40+
requirements are outlined, the edge cases shown, and practical examples
41+
provided. The front page goes on to show how to use regular expressions
42+
then concludes with crate features.
43+
44+
Don't worry about comparing your crate, which is just beginning, to other more
45+
developed crates. To get the documentation to something more polished, start
46+
incrementally and put in an introduction, example, and features. Rome was not
47+
built in a day!
48+
49+
The first lines within the `lib.rs` will compose the front-page, and they
50+
use a different convention than the rest of the rustdocs. Lines should
51+
start with `//!` which indicate module-level or crate-level documentation.
52+
Here's a quick example of the difference:
53+
54+
```rust,ignore
55+
//! Fast and easy queue abstraction.
56+
//!
57+
//! Provides an abstraction over a queue. When the abstraction is used
58+
//! there are these advantages:
59+
//! - Fast
60+
//! - [`Easy`]
61+
//!
62+
//! [`Easy`]: http://thatwaseasy.example.com
63+
64+
/// This module makes it easy.
65+
pub mod easy {
66+
67+
/// Use the abstract function to do this specific thing.
68+
pub fn abstract() {}
69+
70+
}
71+
```
72+
73+
Ideally, this first line of documentation is a sentence without highly
74+
technical details, but with a good description of where this crate fits
75+
within the rust ecosystem. Users should know whether this crate meets their use
76+
case after reading this line.
77+
78+
## Documenting components
79+
80+
Whether it is modules, structs, functions, or macros: the public
81+
API of all code should have documentation. Rarely does anyone
82+
complain about too much documentation!
1283

1384
It is recommended that each item's documentation follows this basic structure:
1485

@@ -23,9 +94,9 @@ It is recommended that each item's documentation follows this basic structure:
2394
```
2495

2596
This basic structure should be straightforward to follow when writing your
26-
documentation and, while you might think that a code example is trivial,
27-
the examples are really important because they can help your users to
28-
understand what an item is, how it is used, and for what purpose it exists.
97+
documentation; while you might think that a code example is trivial,
98+
the examples are really important because they can help users understand
99+
what an item is, how it is used, and for what purpose it exists.
29100

30101
Let's see an example coming from the [standard library] by taking a look at the
31102
[`std::env::args()`][env::args] function:
@@ -62,21 +133,40 @@ for argument in env::args() {
62133
[`args_os`]: ./fn.args_os.html
63134
``````
64135

136+
Everything before the first empty line will be reused to describe the component
137+
in searches and module overviews. For example, the function `std::env::args()`
138+
above will be shown on the [`std::env`] module documentation. It is good
139+
practice to keep the summary to one line: concise writing is a goal of good
140+
documentation.
141+
142+
Because the type system does a good job of defining what types a function
143+
passes and returns, there is no benefit of explicitly writing it
144+
into the documentation, especially since `rustdoc` adds hyper links to all types in the function signature.
145+
146+
In the example above, a 'Panics' section explains when the code might abruptly exit,
147+
which can help the reader prevent reaching a panic. A panic section is recommended
148+
every time edge cases in your code can be reached if known.
149+
65150
As you can see, it follows the structure detailed above: it starts with a short
66151
sentence explaining what the functions does, then it provides more information
67152
and finally provides a code example.
68153

69154
## Markdown
70155

71-
`rustdoc` is using the [commonmark markdown specification]. You might be
156+
`rustdoc` uses the [commonmark markdown specification]. You might be
72157
interested into taking a look at their website to see what's possible to do.
158+
- [commonmark quick reference]
159+
- [current spec]
73160

74-
## Lints
75-
76-
To be sure that you didn't miss any item without documentation or code examples,
77-
you can take a look at the rustdoc lints [here][rustdoc-lints].
78161

79-
[standard library]: https://doc.rust-lang.org/stable/std/index.html
80-
[env::args]: https://doc.rust-lang.org/stable/std/env/fn.args.html
162+
[`backtrace`]: https://docs.rs/backtrace/0.3.50/backtrace/
81163
[commonmark markdown specification]: https://commonmark.org/
82-
[rustdoc-lints]: lints.md
164+
[commonmark quick reference]: https://commonmark.org/help/
165+
[env::args]: https://doc.rust-lang.org/stable/std/env/fn.args.html
166+
[`Future`]: https://doc.rust-lang.org/std/future/trait.Future.html
167+
[`futures`]: https://docs.rs/futures/0.3.5/futures/
168+
[`hashbrown`]: https://docs.rs/hashbrown/0.8.2/hashbrown/
169+
[`regex`]: https://docs.rs/regex/1.3.9/regex/
170+
[standard library]: https://doc.rust-lang.org/stable/std/index.html
171+
[current spec]: https://spec.commonmark.org/current/
172+
[`std::env`]: https://doc.rust-lang.org/stable/std/env/index.html#functions

‎src/doc/rustdoc/src/references.md

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# References
2+
3+
There are many great `rustdoc` references out there.
4+
If you know of other great resources, please submit a pull request!
5+
6+
## Official
7+
8+
- [Learn Rust]
9+
- [Rust By Example]
10+
- [Rust Reference]
11+
- [RFC 1574: More API Documentation Conventions]
12+
- [RFC 1946: Intra Rustdoc Links]
13+
14+
## Community
15+
- [API Guidelines]
16+
- [Github tagged RFCs]
17+
- [Github tagged issues]
18+
- [RFC (stalled) front page styleguide]
19+
- [Guide on how to write documenation for a Rust crate]
20+
21+
22+
[API Guidelines]: https://rust-lang.github.io/api-guidelines/documentation.html
23+
[Github tagged RFCs]: https://github.com/rust-lang/rfcs/issues?q=label%3AT-rustdoc
24+
[Github tagged issues]: https://github.com/rust-lang/rust/issues?q=is%3Aissue+is%3Aopen+label%3AT-rustdoc
25+
[Guide on how to write documenation for a Rust crate]: https://blog.guillaume-gomez.fr/articles/2020-03-12+Guide+on+how+to+write+documentation+for+a+Rust+crate
26+
[Learn Rust]: https://doc.rust-lang.org/book/ch14-02-publishing-to-crates-io.html#making-useful-documentation-comments
27+
[RFC 1574: More API Documentation Conventions]: https://rust-lang.github.io/rfcs/1574-more-api-documentation-conventions.html
28+
[RFC 1946: Intra Rustdoc Links]: https://rust-lang.github.io/rfcs/1946-intra-rustdoc-links.html
29+
[RFC (stalled) front page styleguide]: https://github.com/rust-lang/rfcs/pull/1687
30+
[Rust By Example]: https://doc.rust-lang.org/stable/rust-by-example/meta/doc.html
31+
[Rust Reference]: https://doc.rust-lang.org/stable/reference/comments.html#doc-comments

‎src/doc/rustdoc/src/what-is-rustdoc.md

+19-16
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ CSS, and JavaScript.
77

88
## Basic usage
99

10-
Let's give it a try! Let's create a new project with Cargo:
10+
Let's give it a try! Create a new project with Cargo:
1111

1212
```bash
1313
$ cargo new docs
1414
$ cd docs
1515
```
1616

17-
In `src/lib.rs`, you'll find that Cargo has generated some sample code. Delete
17+
In `src/lib.rs`, Cargo has generated some sample code. Delete
1818
it and replace it with this:
1919

2020
```rust
@@ -31,8 +31,12 @@ $ rustdoc src/lib.rs
3131

3232
This will create a new directory, `doc`, with a website inside! In our case,
3333
the main page is located in `doc/lib/index.html`. If you open that up in
34-
a web browser, you'll see a page with a search bar, and "Crate lib" at the
35-
top, with no contents. There's two problems with this: first, why does it
34+
a web browser, you will see a page with a search bar, and "Crate lib" at the
35+
top, with no contents.
36+
37+
## Configuring rustdoc
38+
39+
There are two problems with this: first, why does it
3640
think that our package is named "lib"? Second, why does it not have any
3741
contents?
3842

@@ -46,7 +50,7 @@ $ rustdoc src/lib.rs --crate-name docs
4650

4751
Now, `doc/docs/index.html` will be generated, and the page says "Crate docs."
4852

49-
For the second issue, it's because our function `foo` is not public; `rustdoc`
53+
For the second issue, it is because our function `foo` is not public; `rustdoc`
5054
defaults to generating documentation for only public functions. If we change
5155
our code...
5256

@@ -61,7 +65,7 @@ pub fn foo() {}
6165
$ rustdoc src/lib.rs --crate-name docs
6266
```
6367

64-
We'll have some generated documentation. Open up `doc/docs/index.html` and
68+
We now have some generated documentation. Open up `doc/docs/index.html` and
6569
check it out! It should show a link to the `foo` function's page, which
6670
is located at `doc/docs/fn.foo.html`. On that page, you'll see the "foo is
6771
a function" we put inside the documentation comment in our crate.
@@ -85,13 +89,12 @@ dependency=<path>/docs/target/debug/deps
8589
You can see this with `cargo doc --verbose`.
8690

8791
It generates the correct `--crate-name` for us, as well as pointing to
88-
`src/lib.rs` But what about those other arguments? `-o` controls the
89-
*o*utput of our docs. Instead of a top-level `doc` directory, you'll
90-
notice that Cargo puts generated documentation under `target`. That's
91-
the idiomatic place for generated files in Cargo projects. Also, it
92-
passes `-L`, a flag that helps rustdoc find the dependencies
93-
your code relies on. If our project used dependencies, we'd get
94-
documentation for them as well!
92+
`src/lib.rs`. But what about those other arguments?
93+
- `-o` controls the *o*utput of our docs. Instead of a top-level
94+
`doc` directory, notice that Cargo puts generated documentation under
95+
`target`. That is the idiomatic place for generated files in Cargo projects.
96+
- `-L` flag helps rustdoc find the dependencies your code relies on.
97+
If our project used dependencies, we would get documentation for them as well!
9598

9699
## Outer and inner documentation
97100

@@ -118,7 +121,7 @@ For more information about the `//!` syntax, see [the Book].
118121

119122
## Using standalone Markdown files
120123

121-
`rustdoc` can also generate HTML from standalone Markdown files. Let's
124+
`rustdoc` can also generate HTML from standalone Markdown files. Let' s
122125
give it a try: create a `README.md` file with these contents:
123126

124127
````text
@@ -128,7 +131,7 @@ This is a project to test out `rustdoc`.
128131
129132
[Here is a link!](https://www.rust-lang.org)
130133
131-
## Subheading
134+
## Example
132135
133136
```rust
134137
fn foo() -> i32 {
@@ -143,7 +146,7 @@ And call `rustdoc` on it:
143146
$ rustdoc README.md
144147
```
145148

146-
You'll find an HTML file in `docs/doc/README.html` generated from its
149+
You will find an HTML file in `docs/doc/README.html` generated from its
147150
Markdown contents.
148151

149152
Cargo currently does not understand standalone Markdown files, unfortunately.
+125
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# What to include (and exclude)
2+
3+
It is easy to say everything must be documented in a project and often times
4+
that is correct, but how can we get there, and are there things that don't
5+
belong?
6+
7+
At the top of the `src/lib.rs` or `main.rs` file in your binary project, include
8+
the following attribute:
9+
10+
```rust
11+
#![warn(missing_docs)]
12+
```
13+
14+
Now run `cargo doc` and examine the output. Here's a sample:
15+
16+
```text
17+
Documenting docdemo v0.1.0 (/Users/username/docdemo)
18+
warning: missing documentation for the crate
19+
--> src/main.rs:1:1
20+
|
21+
1 | / #![warn(missing_docs)]
22+
2 | |
23+
3 | | fn main() {
24+
4 | | println!("Hello, world!");
25+
5 | | }
26+
| |_^
27+
|
28+
note: the lint level is defined here
29+
--> src/main.rs:1:9
30+
|
31+
1 | #![warn(missing_docs)]
32+
| ^^^^^^^^^^^^
33+
34+
warning: 1 warning emitted
35+
36+
Finished dev [unoptimized + debuginfo] target(s) in 2.96s
37+
```
38+
39+
As a library author, adding the lint `#![deny(missing_docs)]` is a great way to
40+
ensure the project does not drift away from being documented well, and
41+
`#![warn(missing_docs)]` is a good way to move towards comprehensive
42+
documentation. In addition to docs, `#![deny(missing_doc_code_examples)]`
43+
ensures each function contains a usage example. In our example above, the
44+
warning is resolved by adding crate level documentation.
45+
46+
There are more lints in the upcoming chapter [Lints][rustdoc-lints].
47+
48+
## Examples
49+
50+
Of course this is contrived to be simple, but part of the power of documentation
51+
is showing code that is easy to follow, rather than being realistic. Docs often
52+
take shortcuts with error handling because examples can become complicated to
53+
follow with all the necessary set up required for a simple example.
54+
55+
`Async` is a good example of this. In order to execute an `async` example, an
56+
executor needs to be available. Examples will often shortcut this, and leave
57+
users to figure out how to put the `async` code into their own runtime.
58+
59+
It is preferred that `unwrap()` not be used inside an example, and some of the
60+
error handling components be hidden if they make the example too difficult to
61+
follow.
62+
63+
``````text
64+
/// Example
65+
/// ```rust
66+
/// let fourtytwo = "42".parse::<u32>()?;
67+
/// println!("{} + 10 = {}", fourtytwo, fourtytwo+10);
68+
/// ```
69+
``````
70+
71+
When rustdoc wraps that in a main function, it will fail to compile because the
72+
`ParseIntError` trait is not implemented. In order to help both your audience
73+
and your test suite, this example needs some additional code:
74+
75+
``````text
76+
/// Example
77+
/// ```rust
78+
/// # main() -> Result<(), std::num::ParseIntError> {
79+
/// let fortytwo = "42".parse::<u32>()?;
80+
/// println!("{} + 10 = {}", fortytwo, fortytwo+10);
81+
/// # Ok(())
82+
/// # }
83+
/// ```
84+
``````
85+
86+
The example is the same on the doc page, but has that extra information
87+
available to anyone trying to use your crate. More about tests in the
88+
upcoming [Documentation tests] chapter.
89+
90+
## What to Exclude
91+
92+
Certain parts of your public interface may be included by default in the output
93+
of rustdoc. The attribute `#[doc(hidden)]` can hide implementation details
94+
to encourage idiomatic use of the crate.
95+
96+
For example, an internal `macro!` that makes the crate easier to implement can
97+
become a footgun for users when it appears in the public documentation. An
98+
internal `Error` type may exist, and `impl` details should be hidden, as
99+
detailed in the [API Guidelines].
100+
101+
## Customizing the output
102+
103+
It is possible to pass a custom css file to `rustdoc` and style the
104+
documentation.
105+
106+
```bash
107+
rustdoc --extend-css custom.css src/lib.rs
108+
```
109+
110+
A good example of using this feature to create a dark theme is documented [on
111+
this blog]. Just remember, dark theme is already included in the rustdoc output
112+
by clicking on the paintbrush. Adding additional options to the themes are
113+
as easy as creating a custom theme `.css` file and using the following syntax:
114+
115+
```bash
116+
rustdoc --theme awesome.css src/lib.rs
117+
```
118+
119+
Here is an example of a new theme, [Ayu].
120+
121+
[Ayu]: https://github.com/rust-lang/rust/blob/master/src/librustdoc/html/static/themes/ayu.css
122+
[API Guidelines]: https://rust-lang.github.io/api-guidelines/documentation.html#rustdoc-does-not-show-unhelpful-implementation-details-c-hidden
123+
[Documentation tests]: documentation-tests.md
124+
[on this blog]: https://blog.guillaume-gomez.fr/articles/2016-09-16+Generating+doc+with+rustdoc+and+a+custom+theme
125+
[rustdoc-lints]: lints.md

‎src/librustdoc/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,7 @@ fn usage(argv0: &str) {
432432
(option.apply)(&mut options);
433433
}
434434
println!("{}", options.usage(&format!("{} [options] <input>", argv0)));
435+
println!("More information available at https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html")
435436
}
436437

437438
/// A result type used by several functions under `main()`.

0 commit comments

Comments
 (0)
Please sign in to comment.