rust-clippy icon indicating copy to clipboard operation
rust-clippy copied to clipboard

Add new style lint: Warn if first paragraph in docstring is too long.

Open emilk opened this issue 1 year ago • 1 comments

What it does

Warn when the first paragraph of a docstring is overly long.

cargo doc will show the first paragraph of the doscstring in the summary page on a crate and module, so having a nice, short summary in the first paragraph is part of writing good docs.

A very long first paragraph can be easily created by mistake. That's because cargo doc (and most markdown viewers) ignores single newlines and requires a double newline to register as a new paragraph. So this is one paragraph:

/// A very short summary.
/// A much longer explanation that goes into a lot more detail about
/// how the thing works, possibly with doclinks and so one,
/// and probably spanning a many rows.
struct Foo { … }

while this is two paragraphs:

/// A very short summary.
///
/// A much longer explanation that goes into a lot more detail about
/// how the thing works, possibly with doclinks and so one,
/// and probably spanning a many rows.
struct Foo { … }

Advantage

An overly long first paragraph makes for a bad summary, and a bad overview in a docs page for a crate:

Screenshot 2024-06-23 at 22 44 27

Here's how it looks with an added ///: Screenshot 2024-06-23 at 22 52 57

Drawbacks

It might be annoying if the length limit is set too low.

I suggest a default of 80 chars, but configurable in clippy.toml.

Example

/// A rectangular region of space.
/// Usually a [`Rect`] has a positive (or zero) size,
/// and then [`Self::min`] `<=` [`Self::max`].
/// In these cases [`Self::min`] is the left-top corner
/// and [`Self::max`] is the right-bottom corner.
/// A rectangle is allowed to have a negative size, which happens when the order
/// of `min` and `max` are swapped. These are usually a sign of an error.
/// Normally the unit is points (logical pixels) in screen space coordinates.
/// `Rect` does NOT implement `Default`, because there is no obvious default value.
/// [`Rect::ZERO`] may seem reasonable, but when used as a bounding box, [`Rect::NOTHING`]
/// is a better default - so be explicit instead!
#[derive(Clone, Copy, Eq, PartialEq)]
struct Rect { … }

Could be written as:

/// A rectangular region of space.
/// 
/// Usually a [`Rect`] has a positive (or zero) size,
/// and then [`Self::min`] `<=` [`Self::max`].
/// In these cases [`Self::min`] is the left-top corner
/// and [`Self::max`] is the right-bottom corner.
/// A rectangle is allowed to have a negative size, which happens when the order
/// of `min` and `max` are swapped. These are usually a sign of an error.
/// Normally the unit is points (logical pixels) in screen space coordinates.
/// `Rect` does NOT implement `Default`, because there is no obvious default value.
/// [`Rect::ZERO`] may seem reasonable, but when used as a bounding box, [`Rect::NOTHING`]
/// is a better default - so be explicit instead!
#[derive(Clone, Copy, Eq, PartialEq)]
pub struct Rect {

Note that we should suggest the added extra newline, as no doubt a lot of programmers aren't aware of this.

emilk avatar Jun 23 '24 20:06 emilk

This is a good point. Gonna take a look.

GuillaumeGomez avatar Jun 23 '24 21:06 GuillaumeGomez