Auto merge of #75778 - AndyGauge:75521-rustdoc-book-improvements, r=jyn514
75521 rustdoc book improvements Added some guidelines about documenting with rustdoc Fixes #75521
This commit is contained in:
commit
a601302ff0
@ -2,6 +2,7 @@
|
||||
|
||||
- [What is rustdoc?](what-is-rustdoc.md)
|
||||
- [How to write documentation](how-to-write-documentation.md)
|
||||
- [What to include (and exclude)](what-to-include.md)
|
||||
- [Command-line arguments](command-line-arguments.md)
|
||||
- [The `#[doc]` attribute](the-doc-attribute.md)
|
||||
- [Documentation tests](documentation-tests.md)
|
||||
@ -10,3 +11,4 @@
|
||||
- [Passes](passes.md)
|
||||
- [Advanced features](advanced-features.md)
|
||||
- [Unstable features](unstable-features.md)
|
||||
- [References](references.md)
|
||||
|
@ -1,14 +1,85 @@
|
||||
# How to write documentation
|
||||
|
||||
Good documentation is not natural. There are opposing goals that make writing
|
||||
good documentation difficult. It requires expertise in the subject but also
|
||||
writing to a novice perspective. Documentation therefore often glazes over
|
||||
implementation detail, or leaves readers with unanswered questions.
|
||||
|
||||
There are a few tenets to Rust documentation that can help guide anyone through
|
||||
the process of documenting libraries so that everyone has an ample opportunity
|
||||
to use the code.
|
||||
|
||||
This chapter covers not only how to write documentation but specifically
|
||||
how to write **good** documentation. Something to keep in mind when
|
||||
writing documentation is that your audience is not just yourself but others
|
||||
who simply don't have the context you do. It is important to be as clear
|
||||
how to write **good** documentation. It is important to be as clear
|
||||
as you can, and as complete as possible. As a rule of thumb: the more
|
||||
documentation you write for your crate the better. If an item is public
|
||||
then it should be documented.
|
||||
|
||||
## Basic structure
|
||||
## Getting Started
|
||||
|
||||
Documenting a crate should begin with front-page documentation. As an
|
||||
example, the [`hashbrown`] crate level documentation summarizes the role of
|
||||
the crate, provides links to explain technical details, and explains why you
|
||||
would want to use the crate.
|
||||
|
||||
After introducing the crate, it is important that the front-page gives
|
||||
an example of how to use the crate in a real world setting. Stick to the
|
||||
library's role in the example, but do so without shortcuts to benefit users who
|
||||
may copy and paste the example to get started.
|
||||
|
||||
[`futures`] uses inline comments to explain line by line
|
||||
the complexities of using a [`Future`], because a person's first exposure to
|
||||
rust's [`Future`] may be this example.
|
||||
|
||||
The [`backtrace`] documentation walks through the whole process, explaining
|
||||
changes made to the `Cargo.toml` file, passing command line arguments to the
|
||||
compiler, and shows a quick example of backtrace in the wild.
|
||||
|
||||
Finally, the front-page can eventually become a comprehensive reference
|
||||
how to use a crate, like [`regex`]. In this front page, all
|
||||
requirements are outlined, the edge cases shown, and practical examples
|
||||
provided. The front page goes on to show how to use regular expressions
|
||||
then concludes with crate features.
|
||||
|
||||
Don't worry about comparing your crate, which is just beginning, to other more
|
||||
developed crates. To get the documentation to something more polished, start
|
||||
incrementally and put in an introduction, example, and features. Rome was not
|
||||
built in a day!
|
||||
|
||||
The first lines within the `lib.rs` will compose the front-page, and they
|
||||
use a different convention than the rest of the rustdocs. Lines should
|
||||
start with `//!` which indicate module-level or crate-level documentation.
|
||||
Here's a quick example of the difference:
|
||||
|
||||
```rust,ignore
|
||||
//! Fast and easy queue abstraction.
|
||||
//!
|
||||
//! Provides an abstraction over a queue. When the abstraction is used
|
||||
//! there are these advantages:
|
||||
//! - Fast
|
||||
//! - [`Easy`]
|
||||
//!
|
||||
//! [`Easy`]: http://thatwaseasy.example.com
|
||||
|
||||
/// This module makes it easy.
|
||||
pub mod easy {
|
||||
|
||||
/// Use the abstract function to do this specific thing.
|
||||
pub fn abstract() {}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Ideally, this first line of documentation is a sentence without highly
|
||||
technical details, but with a good description of where this crate fits
|
||||
within the rust ecosystem. Users should know whether this crate meets their use
|
||||
case after reading this line.
|
||||
|
||||
## Documenting components
|
||||
|
||||
Whether it is modules, structs, functions, or macros: the public
|
||||
API of all code should have documentation. Rarely does anyone
|
||||
complain about too much documentation!
|
||||
|
||||
It is recommended that each item's documentation follows this basic structure:
|
||||
|
||||
@ -23,9 +94,9 @@ It is recommended that each item's documentation follows this basic structure:
|
||||
```
|
||||
|
||||
This basic structure should be straightforward to follow when writing your
|
||||
documentation and, while you might think that a code example is trivial,
|
||||
the examples are really important because they can help your users to
|
||||
understand what an item is, how it is used, and for what purpose it exists.
|
||||
documentation; while you might think that a code example is trivial,
|
||||
the examples are really important because they can help users understand
|
||||
what an item is, how it is used, and for what purpose it exists.
|
||||
|
||||
Let's see an example coming from the [standard library] by taking a look at the
|
||||
[`std::env::args()`][env::args] function:
|
||||
@ -62,21 +133,40 @@ for argument in env::args() {
|
||||
[`args_os`]: ./fn.args_os.html
|
||||
``````
|
||||
|
||||
Everything before the first empty line will be reused to describe the component
|
||||
in searches and module overviews. For example, the function `std::env::args()`
|
||||
above will be shown on the [`std::env`] module documentation. It is good
|
||||
practice to keep the summary to one line: concise writing is a goal of good
|
||||
documentation.
|
||||
|
||||
Because the type system does a good job of defining what types a function
|
||||
passes and returns, there is no benefit of explicitly writing it
|
||||
into the documentation, especially since `rustdoc` adds hyper links to all types in the function signature.
|
||||
|
||||
In the example above, a 'Panics' section explains when the code might abruptly exit,
|
||||
which can help the reader prevent reaching a panic. A panic section is recommended
|
||||
every time edge cases in your code can be reached if known.
|
||||
|
||||
As you can see, it follows the structure detailed above: it starts with a short
|
||||
sentence explaining what the functions does, then it provides more information
|
||||
and finally provides a code example.
|
||||
|
||||
## Markdown
|
||||
|
||||
`rustdoc` is using the [commonmark markdown specification]. You might be
|
||||
`rustdoc` uses the [commonmark markdown specification]. You might be
|
||||
interested into taking a look at their website to see what's possible to do.
|
||||
- [commonmark quick reference]
|
||||
- [current spec]
|
||||
|
||||
## Lints
|
||||
|
||||
To be sure that you didn't miss any item without documentation or code examples,
|
||||
you can take a look at the rustdoc lints [here][rustdoc-lints].
|
||||
|
||||
[standard library]: https://doc.rust-lang.org/stable/std/index.html
|
||||
[env::args]: https://doc.rust-lang.org/stable/std/env/fn.args.html
|
||||
[`backtrace`]: https://docs.rs/backtrace/0.3.50/backtrace/
|
||||
[commonmark markdown specification]: https://commonmark.org/
|
||||
[rustdoc-lints]: lints.md
|
||||
[commonmark quick reference]: https://commonmark.org/help/
|
||||
[env::args]: https://doc.rust-lang.org/stable/std/env/fn.args.html
|
||||
[`Future`]: https://doc.rust-lang.org/std/future/trait.Future.html
|
||||
[`futures`]: https://docs.rs/futures/0.3.5/futures/
|
||||
[`hashbrown`]: https://docs.rs/hashbrown/0.8.2/hashbrown/
|
||||
[`regex`]: https://docs.rs/regex/1.3.9/regex/
|
||||
[standard library]: https://doc.rust-lang.org/stable/std/index.html
|
||||
[current spec]: https://spec.commonmark.org/current/
|
||||
[`std::env`]: https://doc.rust-lang.org/stable/std/env/index.html#functions
|
||||
|
31
src/doc/rustdoc/src/references.md
Normal file
31
src/doc/rustdoc/src/references.md
Normal file
@ -0,0 +1,31 @@
|
||||
# References
|
||||
|
||||
There are many great `rustdoc` references out there.
|
||||
If you know of other great resources, please submit a pull request!
|
||||
|
||||
## Official
|
||||
|
||||
- [Learn Rust]
|
||||
- [Rust By Example]
|
||||
- [Rust Reference]
|
||||
- [RFC 1574: More API Documentation Conventions]
|
||||
- [RFC 1946: Intra Rustdoc Links]
|
||||
|
||||
## Community
|
||||
- [API Guidelines]
|
||||
- [Github tagged RFCs]
|
||||
- [Github tagged issues]
|
||||
- [RFC (stalled) front page styleguide]
|
||||
- [Guide on how to write documenation for a Rust crate]
|
||||
|
||||
|
||||
[API Guidelines]: https://rust-lang.github.io/api-guidelines/documentation.html
|
||||
[Github tagged RFCs]: https://github.com/rust-lang/rfcs/issues?q=label%3AT-rustdoc
|
||||
[Github tagged issues]: https://github.com/rust-lang/rust/issues?q=is%3Aissue+is%3Aopen+label%3AT-rustdoc
|
||||
[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
|
||||
[Learn Rust]: https://doc.rust-lang.org/book/ch14-02-publishing-to-crates-io.html#making-useful-documentation-comments
|
||||
[RFC 1574: More API Documentation Conventions]: https://rust-lang.github.io/rfcs/1574-more-api-documentation-conventions.html
|
||||
[RFC 1946: Intra Rustdoc Links]: https://rust-lang.github.io/rfcs/1946-intra-rustdoc-links.html
|
||||
[RFC (stalled) front page styleguide]: https://github.com/rust-lang/rfcs/pull/1687
|
||||
[Rust By Example]: https://doc.rust-lang.org/stable/rust-by-example/meta/doc.html
|
||||
[Rust Reference]: https://doc.rust-lang.org/stable/reference/comments.html#doc-comments
|
@ -7,14 +7,14 @@ CSS, and JavaScript.
|
||||
|
||||
## Basic usage
|
||||
|
||||
Let's give it a try! Let's create a new project with Cargo:
|
||||
Let's give it a try! Create a new project with Cargo:
|
||||
|
||||
```bash
|
||||
$ cargo new docs
|
||||
$ cd docs
|
||||
```
|
||||
|
||||
In `src/lib.rs`, you'll find that Cargo has generated some sample code. Delete
|
||||
In `src/lib.rs`, Cargo has generated some sample code. Delete
|
||||
it and replace it with this:
|
||||
|
||||
```rust
|
||||
@ -31,8 +31,12 @@ $ rustdoc src/lib.rs
|
||||
|
||||
This will create a new directory, `doc`, with a website inside! In our case,
|
||||
the main page is located in `doc/lib/index.html`. If you open that up in
|
||||
a web browser, you'll see a page with a search bar, and "Crate lib" at the
|
||||
top, with no contents. There's two problems with this: first, why does it
|
||||
a web browser, you will see a page with a search bar, and "Crate lib" at the
|
||||
top, with no contents.
|
||||
|
||||
## Configuring rustdoc
|
||||
|
||||
There are two problems with this: first, why does it
|
||||
think that our package is named "lib"? Second, why does it not have any
|
||||
contents?
|
||||
|
||||
@ -46,7 +50,7 @@ $ rustdoc src/lib.rs --crate-name docs
|
||||
|
||||
Now, `doc/docs/index.html` will be generated, and the page says "Crate docs."
|
||||
|
||||
For the second issue, it's because our function `foo` is not public; `rustdoc`
|
||||
For the second issue, it is because our function `foo` is not public; `rustdoc`
|
||||
defaults to generating documentation for only public functions. If we change
|
||||
our code...
|
||||
|
||||
@ -61,7 +65,7 @@ pub fn foo() {}
|
||||
$ rustdoc src/lib.rs --crate-name docs
|
||||
```
|
||||
|
||||
We'll have some generated documentation. Open up `doc/docs/index.html` and
|
||||
We now have some generated documentation. Open up `doc/docs/index.html` and
|
||||
check it out! It should show a link to the `foo` function's page, which
|
||||
is located at `doc/docs/fn.foo.html`. On that page, you'll see the "foo is
|
||||
a function" we put inside the documentation comment in our crate.
|
||||
@ -85,13 +89,12 @@ dependency=<path>/docs/target/debug/deps
|
||||
You can see this with `cargo doc --verbose`.
|
||||
|
||||
It generates the correct `--crate-name` for us, as well as pointing to
|
||||
`src/lib.rs` But what about those other arguments? `-o` controls the
|
||||
*o*utput of our docs. Instead of a top-level `doc` directory, you'll
|
||||
notice that Cargo puts generated documentation under `target`. That's
|
||||
the idiomatic place for generated files in Cargo projects. Also, it
|
||||
passes `-L`, a flag that helps rustdoc find the dependencies
|
||||
your code relies on. If our project used dependencies, we'd get
|
||||
documentation for them as well!
|
||||
`src/lib.rs`. But what about those other arguments?
|
||||
- `-o` controls the *o*utput of our docs. Instead of a top-level
|
||||
`doc` directory, notice that Cargo puts generated documentation under
|
||||
`target`. That is the idiomatic place for generated files in Cargo projects.
|
||||
- `-L` flag helps rustdoc find the dependencies your code relies on.
|
||||
If our project used dependencies, we would get documentation for them as well!
|
||||
|
||||
## Outer and inner documentation
|
||||
|
||||
@ -118,7 +121,7 @@ For more information about the `//!` syntax, see [the Book].
|
||||
|
||||
## Using standalone Markdown files
|
||||
|
||||
`rustdoc` can also generate HTML from standalone Markdown files. Let's
|
||||
`rustdoc` can also generate HTML from standalone Markdown files. Let' s
|
||||
give it a try: create a `README.md` file with these contents:
|
||||
|
||||
````text
|
||||
@ -128,7 +131,7 @@ This is a project to test out `rustdoc`.
|
||||
|
||||
[Here is a link!](https://www.rust-lang.org)
|
||||
|
||||
## Subheading
|
||||
## Example
|
||||
|
||||
```rust
|
||||
fn foo() -> i32 {
|
||||
@ -143,7 +146,7 @@ And call `rustdoc` on it:
|
||||
$ rustdoc README.md
|
||||
```
|
||||
|
||||
You'll find an HTML file in `docs/doc/README.html` generated from its
|
||||
You will find an HTML file in `docs/doc/README.html` generated from its
|
||||
Markdown contents.
|
||||
|
||||
Cargo currently does not understand standalone Markdown files, unfortunately.
|
||||
|
125
src/doc/rustdoc/src/what-to-include.md
Normal file
125
src/doc/rustdoc/src/what-to-include.md
Normal file
@ -0,0 +1,125 @@
|
||||
# What to include (and exclude)
|
||||
|
||||
It is easy to say everything must be documented in a project and often times
|
||||
that is correct, but how can we get there, and are there things that don't
|
||||
belong?
|
||||
|
||||
At the top of the `src/lib.rs` or `main.rs` file in your binary project, include
|
||||
the following attribute:
|
||||
|
||||
```rust
|
||||
#![warn(missing_docs)]
|
||||
```
|
||||
|
||||
Now run `cargo doc` and examine the output. Here's a sample:
|
||||
|
||||
```text
|
||||
Documenting docdemo v0.1.0 (/Users/username/docdemo)
|
||||
warning: missing documentation for the crate
|
||||
--> src/main.rs:1:1
|
||||
|
|
||||
1 | / #![warn(missing_docs)]
|
||||
2 | |
|
||||
3 | | fn main() {
|
||||
4 | | println!("Hello, world!");
|
||||
5 | | }
|
||||
| |_^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> src/main.rs:1:9
|
||||
|
|
||||
1 | #![warn(missing_docs)]
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 2.96s
|
||||
```
|
||||
|
||||
As a library author, adding the lint `#![deny(missing_docs)]` is a great way to
|
||||
ensure the project does not drift away from being documented well, and
|
||||
`#![warn(missing_docs)]` is a good way to move towards comprehensive
|
||||
documentation. In addition to docs, `#![deny(missing_doc_code_examples)]`
|
||||
ensures each function contains a usage example. In our example above, the
|
||||
warning is resolved by adding crate level documentation.
|
||||
|
||||
There are more lints in the upcoming chapter [Lints][rustdoc-lints].
|
||||
|
||||
## Examples
|
||||
|
||||
Of course this is contrived to be simple, but part of the power of documentation
|
||||
is showing code that is easy to follow, rather than being realistic. Docs often
|
||||
take shortcuts with error handling because examples can become complicated to
|
||||
follow with all the necessary set up required for a simple example.
|
||||
|
||||
`Async` is a good example of this. In order to execute an `async` example, an
|
||||
executor needs to be available. Examples will often shortcut this, and leave
|
||||
users to figure out how to put the `async` code into their own runtime.
|
||||
|
||||
It is preferred that `unwrap()` not be used inside an example, and some of the
|
||||
error handling components be hidden if they make the example too difficult to
|
||||
follow.
|
||||
|
||||
``````text
|
||||
/// Example
|
||||
/// ```rust
|
||||
/// let fourtytwo = "42".parse::<u32>()?;
|
||||
/// println!("{} + 10 = {}", fourtytwo, fourtytwo+10);
|
||||
/// ```
|
||||
``````
|
||||
|
||||
When rustdoc wraps that in a main function, it will fail to compile because the
|
||||
`ParseIntError` trait is not implemented. In order to help both your audience
|
||||
and your test suite, this example needs some additional code:
|
||||
|
||||
``````text
|
||||
/// Example
|
||||
/// ```rust
|
||||
/// # main() -> Result<(), std::num::ParseIntError> {
|
||||
/// let fortytwo = "42".parse::<u32>()?;
|
||||
/// println!("{} + 10 = {}", fortytwo, fortytwo+10);
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
``````
|
||||
|
||||
The example is the same on the doc page, but has that extra information
|
||||
available to anyone trying to use your crate. More about tests in the
|
||||
upcoming [Documentation tests] chapter.
|
||||
|
||||
## What to Exclude
|
||||
|
||||
Certain parts of your public interface may be included by default in the output
|
||||
of rustdoc. The attribute `#[doc(hidden)]` can hide implementation details
|
||||
to encourage idiomatic use of the crate.
|
||||
|
||||
For example, an internal `macro!` that makes the crate easier to implement can
|
||||
become a footgun for users when it appears in the public documentation. An
|
||||
internal `Error` type may exist, and `impl` details should be hidden, as
|
||||
detailed in the [API Guidelines].
|
||||
|
||||
## Customizing the output
|
||||
|
||||
It is possible to pass a custom css file to `rustdoc` and style the
|
||||
documentation.
|
||||
|
||||
```bash
|
||||
rustdoc --extend-css custom.css src/lib.rs
|
||||
```
|
||||
|
||||
A good example of using this feature to create a dark theme is documented [on
|
||||
this blog]. Just remember, dark theme is already included in the rustdoc output
|
||||
by clicking on the paintbrush. Adding additional options to the themes are
|
||||
as easy as creating a custom theme `.css` file and using the following syntax:
|
||||
|
||||
```bash
|
||||
rustdoc --theme awesome.css src/lib.rs
|
||||
```
|
||||
|
||||
Here is an example of a new theme, [Ayu].
|
||||
|
||||
[Ayu]: https://github.com/rust-lang/rust/blob/master/src/librustdoc/html/static/themes/ayu.css
|
||||
[API Guidelines]: https://rust-lang.github.io/api-guidelines/documentation.html#rustdoc-does-not-show-unhelpful-implementation-details-c-hidden
|
||||
[Documentation tests]: documentation-tests.md
|
||||
[on this blog]: https://blog.guillaume-gomez.fr/articles/2016-09-16+Generating+doc+with+rustdoc+and+a+custom+theme
|
||||
[rustdoc-lints]: lints.md
|
@ -432,6 +432,7 @@ fn usage(argv0: &str) {
|
||||
(option.apply)(&mut options);
|
||||
}
|
||||
println!("{}", options.usage(&format!("{} [options] <input>", argv0)));
|
||||
println!("More information available at https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html")
|
||||
}
|
||||
|
||||
/// A result type used by several functions under `main()`.
|
||||
|
Loading…
Reference in New Issue
Block a user