rfcs/text/1574-more-api-documentation...

663 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

- Feature Name: More API Documentation Conventions
- Start Date: 2016-03-31
- RFC PR: [rust-lang/rfcs#1574](https://github.com/rust-lang/rfcs/pull/1574)
- Rust Issue: N/A
# Summary
[summary]: #summary
[RFC 505] introduced certain conventions around documenting Rust projects. This
RFC augments that one, and a full text of the older one combined with these
modfications is provided below.
[RFC 505]: https://github.com/rust-lang/rfcs/blob/master/text/0505-api-comment-conventions.md
# Motivation
[motivation]: #motivation
Documentation is an extremely important part of any project. Its important
that we have consistency in our documentation.
For the most part, the RFC proposes guidelines that are already followed today,
but it tries to motivate and clarify them.
# Detailed design
[design]: #detailed-design
### English
[english]: #english
This section applies to `rustc` and the standard library.
### Using Markdown
[using-markdown]: #using-markdown
The updated list of common headings is:
* Examples
* Panics
* Errors
* Safety
* Aborts
* Undefined Behavior
RFC 505 suggests that one should always use the `rust` formatting directive:
```rust
println!("Hello, world!");
```
```ruby
puts "Hello"
```
But, in API documentation, feel free to rely on the default being rust:
/// For example:
///
/// ```
/// let x = 5;
/// ```
Other places do not know how to highlight this anyway, so it's not important to
be explicit.
RFC 505 suggests that references and citation should be linked reference
style. This is still recommended, but prefer to leave off the second `[]`:
```
[Rust website]
[Rust website]: http://www.rust-lang.org
```
to
```
[Rust website][website]
[website]: http://www.rust-lang.org
```
But, if the text is very long, it is okay to use this form.
### Examples in API docs
[examples-in-api-docs]: #examples-in-api-docs
Everything should have examples. Here is an example of how to do examples:
```
/// # Examples
///
/// ```
/// use op;
///
/// let s = "foo";
/// let answer = op::compare(s, "bar");
/// ```
///
/// Passing a closure to compare with, rather than a string:
///
/// ```
/// use op;
///
/// let s = "foo";
/// let answer = op::compare(s, |a| a.chars().is_whitespace().all());
/// ```
```
### Referring to types
[referring-to-types]: #referring-to-types
When talking about a type, use its full name. In other words, if the type is generic,
say `Option<T>`, not `Option`. An exception to this is bounds. Write `Cow<'a, B>`
rather than `Cow<'a, B> where B: 'a + ToOwned + ?Sized`.
Another possibility is to write in lower case using a more generic term. In other words,
string can refer to a `String` or an `&str`, and an option can be an `Option<T>`.
### Link all the things
[link-all-the-things]: #link-all-the-things
A major drawback of Markdown is that it cannot automatically link types in API documentation.
Do this yourself with the reference-style syntax, for ease of reading:
```
/// The [`String`] passed in lorum ipsum...
///
/// [`String`]: ../string/struct.String.html
```
### Module-level vs type-level docs
[module-level-vs-type-level-docs]: #module-level-vs-type-level-docs
There has often been a tension between module-level and type-level
documentation. For example, in today's standard library, the various
`*Cell` docs say, in the pages for each type, to "refer to the module-level
documentation for more details."
Instead, module-level documentation should show a high-level summary of
everything in the module, and each type should document itself fully. It is
okay if there is some small amount of duplication here. Module-level
documentation should be broad and not go into a lot of detail. That is left
to the type's documentation.
## Example
[example]: #example
Below is a full crate, with documentation following these rules. I am loosely basing
this off of my [ref_slice] crate, because its small, but Im not claiming the code
is good here. Its about the docs, not the code.
[ref_slice]: https://crates.io/crates/ref_slice
In lib.rs:
```rust
//! Turning references into slices
//!
//! This crate contains several utility functions for taking various kinds
//! of references and producing slices out of them. In this case, only full
//! slices, not ranges for sub-slices.
//!
//! # Layout
//!
//! At the top level, we have functions for working with references, `&T`.
//! There are two submodules for dealing with other types: `option`, for
//! &[`Option<T>`], and `mut`, for `&mut T`.
//!
//! [`Option<T>`]: http://doc.rust-lang.org/std/option/enum.Option.html
pub mod option;
/// Converts a reference to `T` into a slice of length 1.
///
/// This will not copy the data, only create the new slice.
///
/// # Panics
///
/// In this case, the code wont panic, but if it did, the circumstances
/// in which it would would be included here.
///
/// # Examples
///
/// ```
/// extern crate ref_slice;
/// use ref_slice::ref_slice;
///
/// let x = &5;
///
/// let slice = ref_slice(x);
///
/// assert_eq!(&[5], slice);
/// ```
///
/// A more compelx example. In this case, its the same example, because this
/// is a pretty trivial function, but use your imagination.
///
/// ```
/// extern crate ref_slice;
/// use ref_slice::ref_slice;
///
/// let x = &5;
///
/// let slice = ref_slice(x);
///
/// assert_eq!(&[5], slice);
/// ```
pub fn ref_slice<T>(s: &T) -> &[T] {
unimplemented!()
}
/// Functions that operate on mutable references.
///
/// This submodule mirrors the parent module, but instead of dealing with `&T`,
/// theyre for `&mut T`.
mod mut {
/// Converts a reference to `&mut T` into a mutable slice of length 1.
///
/// This will not copy the data, only create the new slice.
///
/// # Safety
///
/// In this case, the code doesnt need to be marked as unsafe, but if it
/// did, the invariants youre expected to uphold would be documented here.
///
/// # Examples
///
/// ```
/// extern crate ref_slice;
/// use ref_slice::mut;
///
/// let x = &mut 5;
///
/// let slice = mut::ref_slice(x);
///
/// assert_eq!(&mut [5], slice);
/// ```
pub fn ref_slice<T>(s: &mut T) -> &mut [T] {
unimplemented!()
}
}
```
in `option.rs`:
```rust
//! Functions that operate on references to [`Option<T>`]s.
//!
//! This submodule mirrors the parent module, but instead of dealing with `&T`,
//! theyre for `&`[`Option<T>`].
//!
//! [`Option<T>`]: http://doc.rust-lang.org/std/option/enum.Option.html
/// Converts a reference to `Option<T>` into a slice of length 0 or 1.
///
/// [`Option<T>`]: http://doc.rust-lang.org/std/option/enum.Option.html
///
/// This will not copy the data, only create the new slice.
///
/// # Examples
///
/// ```
/// extern crate ref_slice;
/// use ref_slice::option;
///
/// let x = &Some(5);
///
/// let slice = option::ref_slice(x);
///
/// assert_eq!(&[5], slice);
/// ```
///
/// `None` will result in an empty slice:
///
/// ```
/// extern crate ref_slice;
/// use ref_slice::option;
///
/// let x: &Option<i32> = &None;
///
/// let slice = option::ref_slice(x);
///
/// assert_eq!(&[], slice);
/// ```
pub fn ref_slice<T>(opt: &Option<T>) -> &[T] {
unimplemented!()
}
```
# Drawbacks
[drawbacks]: #drawbacks
Its possible that RFC 505 went far enough, and something this detailed is inappropriate.
# Alternatives
[alternatives]: #alternatives
We could stick with the more minimal conventions of the previous RFC.
# Unresolved questions
[unresolved]: #unresolved-questions
None.
# Appendix A: Full conventions text
Below is a combination of RFC 505 + this RFCs modifications, for convenience.
### Summary sentence
[summary-sentence]: #summary-sentence
In API documentation, the first line should be a single-line short sentence
providing a summary of the code. This line is used as a summary description
throughout Rustdocs output, so its a good idea to keep it short.
The summary line should be written in third person singular present indicative
form. Basically, this means write Returns instead of Return.
### English
[english]: #english
This section applies to `rustc` and the standard library.
All documentation for the standard library is standardized on American English,
with regards to spelling, grammar, and punctuation conventions. Language
changes over time, so this doesnt mean that there is always a correct answer
to every grammar question, but there is often some kind of formal consensus.
### Use line comments
[use-line-comments]: #use-line-comments
Avoid block comments. Use line comments instead:
```rust
// Wait for the main task to return, and set the process error code
// appropriately.
```
Instead of:
```rust
/*
* Wait for the main task to return, and set the process error code
* appropriately.
*/
```
Only use inner doc comments `//!` to write crate and module-level documentation,
nothing else. When using `mod` blocks, prefer `///` outside of the block:
```rust
/// This module contains tests
mod test {
// ...
}
```
over
```rust
mod test {
//! This module contains tests
// ...
}
```
### Using Markdown
[using-markdown]: #using-markdown
Within doc comments, use Markdown to format your documentation.
Use top level headings (`#`) to indicate sections within your comment. Common headings:
* Examples
* Panics
* Errors
* Safety
* Aborts
* Undefined Behavior
An example:
```rust
/// # Examples
```
Even if you only include one example, use the plural form: Examples rather
than Example. Future tooling is easier this way.
Use backticks (`) to denote a code fragment within a sentence.
Use triple backticks (```) to write longer examples, like this:
This code does something cool.
```rust
let x = foo();
x.bar();
```
When appropriate, make use of Rustdocs modifiers. Annotate triple backtick blocks with
the appropriate formatting directive.
```rust
println!("Hello, world!");
```
```ruby
puts "Hello"
```
In API documentation, feel free to rely on the default being rust:
/// For example:
///
/// ```
/// let x = 5;
/// ```
In long-form documentation, always be explicit:
For example:
```rust
let x = 5;
```
This will highlight syntax in places that do not default to rust, like GitHub.
Rustdoc is able to test all Rust examples embedded inside of documentation, so
its important to mark what is not Rust so your tests dont fail.
References and citation should be linked reference style. Prefer
```
[Rust website]
[Rust website]: http://www.rust-lang.org
```
to
```
[Rust website](http://www.rust-lang.org)
```
If the text is very long, feel free to use the shortened form:
```
This link [is very long and links to the Rust website][website].
[website]: http://www.rust-lang.org
```
### Examples in API docs
[examples-in-api-docs]: #examples-in-api-docs
Everything should have examples. Here is an example of how to do examples:
```
/// # Examples
///
/// ```
/// use op;
///
/// let s = "foo";
/// let answer = op::compare(s, "bar");
/// ```
///
/// Passing a closure to compare with, rather than a string:
///
/// ```
/// use op;
///
/// let s = "foo";
/// let answer = op::compare(s, |a| a.chars().is_whitespace().all());
/// ```
```
### Referring to types
[referring-to-types]: #referring-to-types
When talking about a type, use its full name. In other words, if the type is generic,
say `Option<T>`, not `Option`. An exception to this is bounds. Write `Cow<'a, B>`
rather than `Cow<'a, B> where B: 'a + ToOwned + ?Sized`.
Another possibility is to write in lower case using a more generic term. In other words,
string can refer to a `String` or an `&str`, and an option can be an `Option<T>`.
### Link all the things
[link-all-the-things]: #link-all-the-things
A major drawback of Markdown is that it cannot automatically link types in API documentation.
Do this yourself with the reference-style syntax, for ease of reading:
```
/// The [`String`] passed in lorum ipsum...
///
/// [`String`]: ../string/struct.String.html
```
### Module-level vs type-level docs
[module-level-vs-type-level-docs]: #module-level-vs-type-level-docs
There has often been a tension between module-level and type-level
documentation. For example, in today's standard library, the various
`*Cell` docs say, in the pages for each type, to "refer to the module-level
documentation for more details."
Instead, module-level documentation should show a high-level summary of
everything in the module, and each type should document itself fully. It is
okay if there is some small amount of duplication here. Module-level
documentation should be broad, and not go into a lot of detail, which is left
to the type's documentation.
## Example
[example]: #example
Below is a full crate, with documentation following these rules. I am loosely basing
this off of my [ref_slice] crate, because its small, but Im not claiming the code
is good here. Its about the docs, not the code.
[ref_slice]: https://crates.io/crates/ref_slice
In lib.rs:
```rust
//! Turning references into slices
//!
//! This crate contains several utility functions for taking various kinds
//! of references and producing slices out of them. In this case, only full
//! slices, not ranges for sub-slices.
//!
//! # Layout
//!
//! At the top level, we have functions for working with references, `&T`.
//! There are two submodules for dealing with other types: `option`, for
//! &[`Option<T>`], and `mut`, for `&mut T`.
//!
//! [`Option<T>`]: http://doc.rust-lang.org/std/option/enum.Option.html
pub mod option;
/// Converts a reference to `T` into a slice of length 1.
///
/// This will not copy the data, only create the new slice.
///
/// # Panics
///
/// In this case, the code wont panic, but if it did, the circumstances
/// in which it would would be included here.
///
/// # Examples
///
/// ```
/// extern crate ref_slice;
/// use ref_slice::ref_slice;
///
/// let x = &5;
///
/// let slice = ref_slice(x);
///
/// assert_eq!(&[5], slice);
/// ```
///
/// A more complex example. In this case, its the same example, because this
/// is a pretty trivial function, but use your imagination.
///
/// ```
/// extern crate ref_slice;
/// use ref_slice::ref_slice;
///
/// let x = &5;
///
/// let slice = ref_slice(x);
///
/// assert_eq!(&[5], slice);
/// ```
pub fn ref_slice<T>(s: &T) -> &[T] {
unimplemented!()
}
/// Functions that operate on mutable references.
///
/// This submodule mirrors the parent module, but instead of dealing with `&T`,
/// theyre for `&mut T`.
mod mut {
/// Converts a reference to `&mut T` into a mutable slice of length 1.
///
/// This will not copy the data, only create the new slice.
///
/// # Safety
///
/// In this case, the code doesnt need to be marked as unsafe, but if it
/// did, the invariants youre expected to uphold would be documented here.
///
/// # Examples
///
/// ```
/// extern crate ref_slice;
/// use ref_slice::mut;
///
/// let x = &mut 5;
///
/// let slice = mut::ref_slice(x);
///
/// assert_eq!(&mut [5], slice);
/// ```
pub fn ref_slice<T>(s: &mut T) -> &mut [T] {
unimplemented!()
}
}
```
in `option.rs`:
```rust
//! Functions that operate on references to [`Option<T>`]s.
//!
//! This submodule mirrors the parent module, but instead of dealing with `&T`,
//! theyre for `&`[`Option<T>`].
//!
//! [`Option<T>`]: http://doc.rust-lang.org/std/option/enum.Option.html
/// Converts a reference to `Option<T>` into a slice of length 0 or 1.
///
/// [`Option<T>`]: http://doc.rust-lang.org/std/option/enum.Option.html
///
/// This will not copy the data, only create the new slice.
///
/// # Examples
///
/// ```
/// extern crate ref_slice;
/// use ref_slice::option;
///
/// let x = &Some(5);
///
/// let slice = option::ref_slice(x);
///
/// assert_eq!(&[5], slice);
/// ```
///
/// `None` will result in an empty slice:
///
/// ```
/// extern crate ref_slice;
/// use ref_slice::option;
///
/// let x: &Option<i32> = &None;
///
/// let slice = option::ref_slice(x);
///
/// assert_eq!(&[], slice);
/// ```
pub fn ref_slice<T>(opt: &Option<T>) -> &[T] {
unimplemented!()
}
```