Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More api documentation conventions #1574

Merged
merged 14 commits into from
Jul 14, 2016
266 changes: 266 additions & 0 deletions text/0000-more-api-documentation-conventions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
- Feature Name: More API Documentation Conventions
- Start Date: 2016-03-31
- RFC PR: (leave this empty)
- Rust Issue: (leave this empty)

# Summary
[summary]: #summary

[RFC 505] introduced certain conventions around documenting Rust projects. This RFC supersedes
that one, thought it has the same aims: to describe how the Rust project should be documented,
and provide guidance for other Rust projects as well.

This RFC will contain some similar text as RFC 505, so that we can have one RFC with the full
conventions.

[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. It’s 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

This RFC is large. Here’s a table of contents:

* [Content](#content)
* [Summary sentence](#summary-sentence)
* [English](#english)
* [Form](#form)
* [Use line comments](#use-line-comments)
* [Using Markdown](#using-markdown)
* [Example](#example)

## Content
[content]: #content

These conventions relate to the contents of the documentation, the words themselves.

### 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 Rustdoc’s output, so it’s 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.”

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might be a little off-topic—and maybe nit-picky—but here goes.

One thing that bugs me about Rust documentation—including the documentation I write for my crate—is that the summary line looks ugly. In a module's documentation page, where the types, functions, methods, etc. are neatly aligned in tables, the summary line looks best as a fragment. E.g.,

FooManages a foobar thingamabob.
QuxWraps a blah blah blah.

But when I navigate to the documentation page for Foo , the same fragment looks abrupt because it's in prose. Instead, I would like the summary to be a complete sentence starting with a noun. E.g., Foo manages a foobar thingamabob.

I wish Rust automatically formatted this for me. That is, I wish I could write a complete sentence for the summary line and have rustdoc leave out the noun when generating the one-liner for the module-level table. I suspect rustdoc wouldn't need to be very smart to do this. It could recognize that the sentence starts with Foo and, because Foo is the thing being documented, elide it from the output and capitalize the following word. E.g., Foo manages becomes Manages.

In addition to looking prettier, I think this would also encourage documentation authors to write better summary lines.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe follow the style guide also in this RFC and use ‘Return’. instead of “Return.”?


### English
[english]: #english

This section applies to `rustc` and the standard library.

All documentation is standardized on American English, with regards to
spelling, grammar, and punctuation conventions. Language changes over time,
so this doesn’t mean that there is always a correct answer to every grammar
question, but there is often some kind of formal consensus.

One specific rule that comes up often: when quoting something for emphasis,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is quoting for emphasis something that people do deliberately? I thought it was a mistake. Maybe an english/american thing. Anyway, can we recommend using markdown punctuation for emphasis? Or are we targeting an ascii world? I.e., *foo*. And then just quotes for quoting?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it is something that's done deliberately, though I am not aware if it's a regionalism or not.

I've often seemed bolding used when showing off a term for the first time, or to highlight things for other reasons. Maybe this is too specific, though. Right now, all the docs use quoting for emphasis, and use bold very sparingly.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Anecdotally, I can't recall ever seeing single quotes used for emphasis except in Rust documentation. I don't think it's standard or common.

Copy link

@codyps codyps May 17, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for what it's worth, asciidoc uses single quotes to emit emphasized (italicized and differently colored) text. Perhaps rustdoc simply needs to use a similar rule & emphasize single quoted text? Or just convert the existing single-quote-to-emphasize into some other markup that actually applies an emphasis style?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use a single quote, and put punctuation outside the quotes, ‘this’. When
quoting something at length, “use double quotes and put the punctuation
inside of the quote.” Most documentation will end up using single quotes,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think code documentation conventions should recommend putting punctuation inside the quotes unless the punctuation itself is part of the quote. Quoting the Jargon File, chapter 5, "Hacker Writing Style":

This is incorrect according to standard American usage (which would put the continuation commas and the final period inside the string quotes); however, it is counter-intuitive to hackers to mutilate literal strings with characters that don't belong in them.'

This case will come up often in documentation, and a style guideline should not make a recommendation that on balance will reduce precision in favor of an arbitrary English formatting/typesetting convention that isn't even universal in English text. (Convention varies: as I understand it, some style conventions for British English also put the punctuation outside the quotes.)

I realize that a style guide is the ultimate example of a bikeshed topic, and for the vast majority of items an arbitrary convention for consistency improves on having no convention at all. But in this particular case, I think this guideline does more harm than good.

so if you’re not sure, just stick with them.

## Form
[form]: #form

These conventions relate to the formatting of the documentation, how they
appear in source code.

### Use line comments
[use-line-comments]: #use-line-comments

Avoid block comments. Use line comments instead:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You got that one wrong.

It should be preferable to avoid line comments, and use block comments whenever possible.

Case: line comments aren't that easy to work with for blind people, like block comments are.
#1373 (comment)

Also note that block comments should be

/*
    Some
    multiline
    comment.
*/

with no unnecessary asterisks.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This particular convention has already been in place for years, and is in the original RFC. (I am interested in the a18n bit though)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This particular convention has already been in place for years, and is in the original RFC.

Yes, I know. Just because something has been in place "for years" doesn't mean that it's right.

I just wanted to highlight that this RFC makes same mistake as the original one – hopefully there'll be interest to make corrections :)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, accessibility should be enough motivation to change the standard here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also note that block comments should be

/*
    Some
    multiline
    comment.
*/

with no unnecessary asterisks.

I disagree. I guess it's a personal opinion but I really don't like this writing.

/*
 * Some
 * multiline
 * comment.
 */

Is more pleasant to read. Or:

// Some
// multiline
// comment

(which is my favourite).

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@GuillaumeGomez That just revives the exact reason @camlorn gave for preferring block comments for a11y reasons - specifically, that screen readers then pepper their output with meaningless noise, obscuring the comment itself.

It may be more pleasant to read for you, but I find the two about equal, and for people with a11y concerns your proposal is just as bad as line comments.


```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:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the # be in the middle of this line? If it is there to give an example of headers, we should do something to make it stand out more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, a rewording might be needed.


* Examples
* Panics
* Errors
* Safety
* Aborts
* Undefined Behavior

Even if you only include one example, use the plural form: ‘Examples’ rather
than ‘Example’. Future tooling is easier this way.

Use graves (`) to denote a code fragment within a sentence.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think referring to ` as "backticks" is more common than "graves", and also matches the terminology that both Markdown and CommonMark use.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed.


Use triple graves (```) to write longer examples, like this:

This code does something cool.

```rust
let x = foo();

x.bar();
```

When appropriate, make use of Rustdoc’s modifiers. Annotate triple grave blocks with
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

grave → backtick here too?

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
it’s important to mark what is not Rust so your tests don’t fail.

References and citation should be linked ‘reference style.’ Prefer

```
[Rust website]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I would recommend [Rust website][], since this avoids ambiguity in the case of two consecutive comments (like, [Rust][] [website][]).

One question that I had was whether this was intentionally recommending against using a shortened thunk like [Rust website][rw]? (I don't think we should take a stance about that; let people decide for themselves based on how long the link text is.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally feel that it looks much uglier, but you're right that it can remove ambiguity. However, I don't think that putting two links side by side like that is generally a good idea, because then it looks visually ambiguous when rendered; it all looks like one big link.

And yeah, my intention wasn't to ever say never. I'll modify it to make this clearer.


[Rust website]: http://www.rust-lang.org
```

to

```
[Rust 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
///
/// Basic usage:
///
/// ```
/// 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());
/// ```
```

For particularly simple APIs, still say “Examples” and “Basic usage:” for
consistency’s sake.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not like this practice for it adds noise. Including "Basic usage" is sensible only when there is another example showing some other usage. Also, most of the examples (at least in the stdlib) are simple, so the consistency argument falls away.

Copy link

@nixpulvis nixpulvis Apr 20, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do think it should be a convention to give descriptions to each example if there is more than one.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tshepang: It's for consistency. I don't mind having to write it every time, even if there is only one example. People will know the pattern and just get faster to what they're looking for.

Copy link
Member

@tshepang tshepang May 27, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If someone new sees "Basic usage", they will expect to see something like "Advanced usage", which they won't in most examples.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see why they'd expect an "Advanced usage". The goal of the doc is to help you understand how you can use the API. It's not supposed to cover every case.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you intend to add "Advanced usage", it's then that you may add "Basic usage". And those aren't so common, so rather leave it out.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hum, I see your point. But then it wouldn't be uniformized. :-/

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I myself would not go as far as placing "Basic usage" text. I'd just:

  1. present the (basic example) code block,
  2. then describe the (more advanced) example,
  3. and then its code block.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It leaves a lot of places to do whatever you want in here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with @tshepang that the "Basic usage" detracts more than it adds.

It is not currently used consistently in the standard library. And when I look at examples that include it, and examples that don't, I prefer the latter. For example, str::len() vs. Vec::len().

Now, if there is any prose discussion needed for an example, it makes sense to have some introductory text, or text describing each example in turn. But the string "Basic usage" just takes up vertical space, without adding much. The # Examples heading already sets this off as an example, and most examples can be fairly basic, so it seems like doing this just for the sake of consistency will waste a lot of space.

Even for those examples that do have some introductory text for more specific examples later, I don't think the "Basic usage" adds much. The str::chars() example would read just as well without it.

I decided to look to see if other style guides addressed examples in doc comments. Not many do; the JavaDoc style guide does not, nor does Python's PEP-257. The Python doctest documentation does not separate examples into a separate section, but intersperses them with the rest of the documentation. The Ruby on Rails API Documentation Guide recommends putting examples at the end, and makes an "Examples" heading optional.

I think that there are good arguments both ways for the "Examples" heading being optional or mandatory for consistency; I don't see a problem with requiring that. But requiring both an "Examples" heading and "Basic usage" seems like overkill.


### 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 lengthy bounds. Write `Cow<'a, B>`
rather than `Cow<'a, B> where B: 'a + ToOwned + ?Sized`.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where exactly do you draw the line for lengthy?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it'll be "on case".

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Lengthy" would be, for me, when absolute correctness gets in the way of communicating clearly. This goes along with why we frequently unwrap() in documentation, even though we all why we shouldn't do it in production.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait, would you expect to ever write bounds? I would not.


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
```

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Manual linking is a lot of work that the computer could be automating for me. I understand that automatic linking is tricky, but manual linking leads to inconsistencies, broken links, omissions, etc. Are there any plans to use automatic linking in the future?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue is that Markdown has no automatic linking. If we can get rustdoc to use commonmark, and commonmark has a way of doing extensions, then that's a path forward, but it's unclear when that will happen.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about rustdoc doing some kind of pre-processing on the Markdown to look for things that can be linked? Everyone ends up inventing their own Markdown flavor :).

Another question: Is it possible to define all link targets in one place in my crate and reference those links from different source files? E.g., with src/lib.rs:

[`Foo`]: struct.Foo.html

And then in src/bar.rs:

Here's my link to [`Foo`], even from another file.

I ask this because I don't see myself providing manual links if I must redefine the same links in many different source files. But if I can list all my links in one place, it's at least tractable.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another question: Is it possible to define all link targets in one place in my crate and reference those links from different source files? E.g., with src/lib.rs:

No, the references need to be in the same Markdown block as they're used in.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be solved in rustdoc tool rather than manually. For instance, it should be trivial in a preprocessing step, assuming there's an index of symbols, to find all [] links that do not have a corresponding reference link and look them up in the symbol index for the proper URL.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So for now, let's continue this way and maybe add a processus to check if urls are valid as a test while waiting for rustdoc to generate such urls by himself.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new rustbuild process does check links, so this is done :)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's something that we can hopefully do someday, but I don't want future rustdoc features blocking useful work today

But this is not about blocking useful work. It is about adding work that will be useless when the features are implemented.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is unclear, if ever, when that is landing. In the meantime, we need to improve the docs today.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The best way to improve the docs is to give that feature priority. Adding the references manually is unqualified work, unlike implementing the feature, but it is a lot of work. And not just for the standard library maintainers, but for maintainers of all the crates out there, if they want to have good documentation.


## Example
[example]: #example

Below is a full crate, with documentation following these rules:

```rust
```

## Formatting

# Drawbacks
[drawbacks]: #drawbacks

It’s 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.