From 7fc38a76936950b4ce6aa10c21e544ea09688f54 Mon Sep 17 00:00:00 2001 From: AudaciousAxiom <179637270+AudaciousAxiom@users.noreply.github.com> Date: Thu, 28 Aug 2025 22:03:10 +0200 Subject: [PATCH 01/12] feat: introduce a `doc_comments_missing_terminal_punctuation` lint --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + ...c_comments_missing_terminal_punctuation.rs | 211 ++++++++++++++++++ clippy_lints/src/doc/mod.rs | 25 +++ ...omments_missing_terminal_punctuation.fixed | 142 ++++++++++++ ...c_comments_missing_terminal_punctuation.rs | 142 ++++++++++++ ...mments_missing_terminal_punctuation.stderr | 83 +++++++ ..._missing_terminal_punctuation_unfixable.rs | 12 + ...sing_terminal_punctuation_unfixable.stderr | 15 ++ 9 files changed, 632 insertions(+) create mode 100644 clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs create mode 100644 tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed create mode 100644 tests/ui/doc/doc_comments_missing_terminal_punctuation.rs create mode 100644 tests/ui/doc/doc_comments_missing_terminal_punctuation.stderr create mode 100644 tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.rs create mode 100644 tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 37d46d349667..42d9b2ea60f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6224,6 +6224,7 @@ Released 2018-09-13 [`diverging_sub_expression`]: https://rust-lang.github.io/rust-clippy/master/index.html#diverging_sub_expression [`doc_broken_link`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_broken_link [`doc_comment_double_space_linebreaks`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_comment_double_space_linebreaks +[`doc_comments_missing_terminal_punctuation`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_comments_missing_terminal_punctuation [`doc_include_without_cfg`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_include_without_cfg [`doc_lazy_continuation`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_lazy_continuation [`doc_link_code`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_link_code diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 375d179681da..fbeafef2e455 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -110,6 +110,7 @@ pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[ crate::disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS_INFO, crate::disallowed_types::DISALLOWED_TYPES_INFO, crate::doc::DOC_BROKEN_LINK_INFO, + crate::doc::DOC_COMMENTS_MISSING_TERMINAL_PUNCTUATION_INFO, crate::doc::DOC_COMMENT_DOUBLE_SPACE_LINEBREAKS_INFO, crate::doc::DOC_INCLUDE_WITHOUT_CFG_INFO, crate::doc::DOC_LAZY_CONTINUATION_INFO, diff --git a/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs b/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs new file mode 100644 index 000000000000..47a721ce76a1 --- /dev/null +++ b/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs @@ -0,0 +1,211 @@ +use rustc_ast::ast::{AttrKind, AttrStyle, Attribute}; +use rustc_errors::Applicability; +use rustc_lint::EarlyContext; + +use super::DOC_COMMENTS_MISSING_TERMINAL_PUNCTUATION; + +const MSG: &str = "doc comments should end with a terminal punctuation mark"; +const PUNCTUATION_SUGGESTION: char = '.'; + +pub fn check(cx: &EarlyContext<'_>, attrs: &[Attribute]) { + let mut doc_comment_attrs = attrs.iter().enumerate().filter(|(_, a)| is_doc_comment(a)); + + let Some((i, mut last_doc_attr)) = doc_comment_attrs.next_back() else { + return; + }; + + // Check that the next attribute is not a `#[doc]` attribute. + if let Some(next_attr) = attrs.get(i + 1) + && is_doc_attr(next_attr) + { + return; + } + + // Find the last, non-blank, non-refdef line of multiline doc comments: this is enough to check that + // the doc comment ends with proper punctuation. + while is_doc_comment_trailer(last_doc_attr) { + if let Some(doc_attr) = doc_comment_attrs.next_back() { + (_, last_doc_attr) = doc_attr; + } else { + // The doc comment looks (functionally) empty. + return; + } + } + + if let Some(doc_string) = is_missing_punctuation(last_doc_attr) { + let span = last_doc_attr.span; + + if is_line_doc_comment(last_doc_attr) { + let suggestion = generate_suggestion(last_doc_attr, doc_string); + + clippy_utils::diagnostics::span_lint_and_sugg( + cx, + DOC_COMMENTS_MISSING_TERMINAL_PUNCTUATION, + span, + MSG, + "end the doc comment with some punctuation", + suggestion, + Applicability::MaybeIncorrect, + ); + } else { + // Seems more difficult to preserve the formatting of block doc comments, so we do not provide + // suggestions for them; they are much rarer anyway. + clippy_utils::diagnostics::span_lint(cx, DOC_COMMENTS_MISSING_TERMINAL_PUNCTUATION, span, MSG); + } + } +} + +#[must_use] +fn is_missing_punctuation(attr: &Attribute) -> Option<&str> { + const TERMINAL_PUNCTUATION_MARKS: &[char] = &['.', '?', '!', '…']; + const EXCEPTIONS: &[char] = &[ + '>', // Raw HTML or (unfortunately) Markdown autolinks. + '|', // Markdown tables. + ]; + + let doc_string = get_doc_string(attr)?; + + // Doc comments could have some trailing whitespace, but that is not this lint's job. + let trimmed = doc_string.trim_end(); + + // Doc comments are also allowed to end with fenced code blocks. + if trimmed.ends_with(TERMINAL_PUNCTUATION_MARKS) || trimmed.ends_with(EXCEPTIONS) || trimmed.ends_with("```") { + return None; + } + + // Ignore single-line list items: they may not require any terminal punctuation. + if looks_like_list_item(trimmed) { + return None; + } + + if let Some(stripped) = strip_sentence_trailers(trimmed) + && stripped.ends_with(TERMINAL_PUNCTUATION_MARKS) + { + return None; + } + + Some(doc_string) +} + +#[must_use] +fn generate_suggestion(doc_attr: &Attribute, doc_string: &str) -> String { + let doc_comment_prefix = match doc_attr.style { + AttrStyle::Outer => "///", + AttrStyle::Inner => "//!", + }; + + let mut original_line = format!("{doc_comment_prefix}{doc_string}"); + + if let Some(stripped) = strip_sentence_trailers(doc_string) { + // Insert the punctuation mark just before the sentence trailer. + original_line.insert(doc_comment_prefix.len() + stripped.len(), PUNCTUATION_SUGGESTION); + } else { + original_line.push(PUNCTUATION_SUGGESTION); + } + + original_line +} + +/// Strips closing parentheses and Markdown emphasis delimiters. +#[must_use] +fn strip_sentence_trailers(string: &str) -> Option<&str> { + // The std has a few occurrences of doc comments ending with a sentence in parentheses. + const TRAILERS: &[char] = &[')', '*', '_']; + + if let Some(stripped) = string.strip_suffix("**") { + return Some(stripped); + } + + if let Some(stripped) = string.strip_suffix("__") { + return Some(stripped); + } + + // Markdown inline links should not be mistaken for sentences in parentheses. + if looks_like_inline_link(string) { + return None; + } + + string.strip_suffix(TRAILERS) +} + +/// Returns whether the doc comment looks like a Markdown reference definition or a blank line. +#[must_use] +fn is_doc_comment_trailer(attr: &Attribute) -> bool { + let Some(doc_string) = get_doc_string(attr) else { + return false; + }; + + super::looks_like_refdef(doc_string, 0..doc_string.len()).is_some() || doc_string.trim_end().is_empty() +} + +/// Returns whether the string looks like it ends with a Markdown inline link. +#[must_use] +fn looks_like_inline_link(string: &str) -> bool { + let Some(sub) = string.strip_suffix(')') else { + return false; + }; + let Some((sub, _)) = sub.rsplit_once('(') else { + return false; + }; + + // Check whether there is closing bracket just before the opening parenthesis. + sub.ends_with(']') +} + +/// Returns whether the string looks like a Markdown list item. +#[must_use] +fn looks_like_list_item(string: &str) -> bool { + const BULLET_LIST_MARKERS: &[char] = &['-', '+', '*']; + const ORDERED_LIST_MARKER_SYMBOL: &[char] = &['.', ')']; + + let trimmed = string.trim_start(); + + if let Some(sub) = trimmed.strip_prefix(BULLET_LIST_MARKERS) + && sub.starts_with(char::is_whitespace) + { + return true; + } + + let mut stripped = trimmed; + while let Some(sub) = stripped.strip_prefix(|c| char::is_digit(c, 10)) { + stripped = sub; + } + if let Some(sub) = stripped.strip_prefix(ORDERED_LIST_MARKER_SYMBOL) + && sub.starts_with(char::is_whitespace) + { + return true; + } + + false +} + +#[must_use] +fn is_doc_attr(attr: &Attribute) -> bool { + if let AttrKind::Normal(normal_attr) = &attr.kind + && let Some(segment) = &normal_attr.item.path.segments.first() + && segment.ident.name == clippy_utils::sym::doc + { + true + } else { + false + } +} + +#[must_use] +fn get_doc_string(attr: &Attribute) -> Option<&str> { + if let AttrKind::DocComment(_, symbol) = &attr.kind { + Some(symbol.as_str()) + } else { + None + } +} + +#[must_use] +fn is_doc_comment(attr: &Attribute) -> bool { + matches!(attr.kind, AttrKind::DocComment(_, _)) +} + +#[must_use] +fn is_line_doc_comment(attr: &Attribute) -> bool { + matches!(attr.kind, AttrKind::DocComment(rustc_ast::token::CommentKind::Line, _)) +} diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs index 2a3fb8294611..97a0fb714339 100644 --- a/clippy_lints/src/doc/mod.rs +++ b/clippy_lints/src/doc/mod.rs @@ -28,6 +28,7 @@ use url::Url; mod broken_link; mod doc_comment_double_space_linebreaks; +mod doc_comments_missing_terminal_punctuation; mod doc_suspicious_footnotes; mod include_in_doc_without_cfg; mod lazy_continuation; @@ -670,6 +671,28 @@ declare_clippy_lint! { "looks like a link or footnote ref, but with no definition" } +declare_clippy_lint! { + /// ### What it does + /// Checks for doc comments that do not end with a period or another punctuation mark. + /// Various Markdowns constructs are taken into account to avoid false positives. + /// + /// ### Why is this bad? + /// A project may wish to enforce consistent doc comments by making sure they end with a punctuation mark. + /// + /// ### Example + /// ```no_run + /// /// Returns the Answer to the Ultimate Question of Life, the Universe, and Everything + /// ``` + /// Use instead: + /// ```no_run + /// /// Returns the Answer to the Ultimate Question of Life, the Universe, and Everything. + /// ``` + #[clippy::version = "1.92.0"] + pub DOC_COMMENTS_MISSING_TERMINAL_PUNCTUATION, + nursery, + "missing terminal punctuation in doc comments" +} + pub struct Documentation { valid_idents: FxHashSet, check_private_items: bool, @@ -704,11 +727,13 @@ impl_lint_pass!(Documentation => [ DOC_INCLUDE_WITHOUT_CFG, DOC_COMMENT_DOUBLE_SPACE_LINEBREAKS, DOC_SUSPICIOUS_FOOTNOTES, + DOC_COMMENTS_MISSING_TERMINAL_PUNCTUATION, ]); impl EarlyLintPass for Documentation { fn check_attributes(&mut self, cx: &EarlyContext<'_>, attrs: &[rustc_ast::Attribute]) { include_in_doc_without_cfg::check(cx, attrs); + doc_comments_missing_terminal_punctuation::check(cx, attrs); } } diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed b/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed new file mode 100644 index 000000000000..555b16d7022b --- /dev/null +++ b/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed @@ -0,0 +1,142 @@ +#![feature(custom_inner_attributes)] +#![rustfmt::skip] +#![warn(clippy::doc_comments_missing_terminal_punctuation)] + +/// Returns the Answer to the Ultimate Question of Life, the Universe, and Everything. +//~^ doc_comments_missing_terminal_punctuation +fn answer() -> i32 { + 42 +} + +/// The `Option` type. +//~^ doc_comments_missing_terminal_punctuation +// Triggers even in the presence of another attribute. +#[derive(Debug)] +enum MyOption { + /// No value. + //~^ doc_comments_missing_terminal_punctuation + None, + /// Some value of type `T`. + Some(T), +} + +// Triggers correctly even when interleaved with other attributes. +/// A multiline +#[derive(Debug)] +/// doc comment: +/// only the last line triggers the lint. +//~^ doc_comments_missing_terminal_punctuation +enum Exceptions { + /// Question marks are fine? + QuestionMark, + /// Exclamation marks are fine! + ExclamationMark, + /// Ellipses are ok too… + Ellipsis, + /// HTML content is however not checked: + /// Raw HTML is allowed as well + RawHtml, + /// The raw HTML exception also unfortunately results in ignoring autolinks too: + /// + MarkdownAutolink, + /// | Exception | Note | + /// | -------------- | ----- | + /// | Markdown table | A-ok | + MarkdownTable, + /// ``` + /// // Code blocks are no issues. + /// ``` + CodeBlock, +} + +// Check the lint can be expected on a whole enum at once. +#[expect(clippy::doc_comments_missing_terminal_punctuation)] +enum Char { + /// U+0000 + Null, + /// U+0001 + StartOfHeading, +} + +// Check the lint can be expected on a single variant without affecting others. +enum Char2 { + #[expect(clippy::doc_comments_missing_terminal_punctuation)] + /// U+0000 + Null, + /// U+0001. + //~^ doc_comments_missing_terminal_punctuation + StartOfHeading, +} + +mod module { + //! Works on + //! inner attributes too. + //~^ doc_comments_missing_terminal_punctuation +} + +enum Trailers { + /// (Sometimes the last sentence is in parentheses, and that's ok.) + ParensPassing, + /// (But sometimes it is missing a period.) + //~^ doc_comments_missing_terminal_punctuation + ParensFailing, + /// **Sometimes the last sentence is in bold, and that's ok.** + DoubleStarPassing, + /// **But sometimes it is missing a period.** + //~^ doc_comments_missing_terminal_punctuation + DoubleStarFailing, + /// _Sometimes the last sentence is in italics, and that's ok._ + UnderscorePassing, + /// _But sometimes it is missing a period._ + //~^ doc_comments_missing_terminal_punctuation + UnderscoreFailing, +} + +/// Doc comments can end with an [inline link](#anchor). +//~^ doc_comments_missing_terminal_punctuation +struct InlineLink; + +/// Some doc comments contain [link reference definitions][spec]. +//~^ doc_comments_missing_terminal_punctuation +/// +/// [spec]: https://spec.commonmark.org/0.31.2/#link-reference-definitions +struct LinkRefDefinition; + +// List items do not always need to end with a period. +enum UnorderedLists { + /// - A list item + Dash, + /// + A list item + Plus, + /// * A list item + Star, +} + +enum OrderedLists { + /// 1. A list item + Dot, + /// 42) A list item + Paren, +} + +/// Doc comments with trailing blank lines are supported. +//~^ doc_comments_missing_terminal_punctuation +/// +struct TrailingBlankLine; + +/// The first paragraph is not checked +/// +/// Other sentences are not either +/// Only the last sentence is. +//~^ doc_comments_missing_terminal_punctuation +struct OnlyLastSentence; + +/// Sometimes a doc attribute is used for concatenation: +/// ``` +#[doc = ""] +/// ``` +struct DocAttribute; + +#[expect(clippy::empty_docs)] +/// +struct EmptyDocComment; diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs b/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs new file mode 100644 index 000000000000..f2c6f0d610e9 --- /dev/null +++ b/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs @@ -0,0 +1,142 @@ +#![feature(custom_inner_attributes)] +#![rustfmt::skip] +#![warn(clippy::doc_comments_missing_terminal_punctuation)] + +/// Returns the Answer to the Ultimate Question of Life, the Universe, and Everything +//~^ doc_comments_missing_terminal_punctuation +fn answer() -> i32 { + 42 +} + +/// The `Option` type +//~^ doc_comments_missing_terminal_punctuation +// Triggers even in the presence of another attribute. +#[derive(Debug)] +enum MyOption { + /// No value + //~^ doc_comments_missing_terminal_punctuation + None, + /// Some value of type `T`. + Some(T), +} + +// Triggers correctly even when interleaved with other attributes. +/// A multiline +#[derive(Debug)] +/// doc comment: +/// only the last line triggers the lint +//~^ doc_comments_missing_terminal_punctuation +enum Exceptions { + /// Question marks are fine? + QuestionMark, + /// Exclamation marks are fine! + ExclamationMark, + /// Ellipses are ok too… + Ellipsis, + /// HTML content is however not checked: + /// Raw HTML is allowed as well + RawHtml, + /// The raw HTML exception also unfortunately results in ignoring autolinks too: + /// + MarkdownAutolink, + /// | Exception | Note | + /// | -------------- | ----- | + /// | Markdown table | A-ok | + MarkdownTable, + /// ``` + /// // Code blocks are no issues. + /// ``` + CodeBlock, +} + +// Check the lint can be expected on a whole enum at once. +#[expect(clippy::doc_comments_missing_terminal_punctuation)] +enum Char { + /// U+0000 + Null, + /// U+0001 + StartOfHeading, +} + +// Check the lint can be expected on a single variant without affecting others. +enum Char2 { + #[expect(clippy::doc_comments_missing_terminal_punctuation)] + /// U+0000 + Null, + /// U+0001 + //~^ doc_comments_missing_terminal_punctuation + StartOfHeading, +} + +mod module { + //! Works on + //! inner attributes too + //~^ doc_comments_missing_terminal_punctuation +} + +enum Trailers { + /// (Sometimes the last sentence is in parentheses, and that's ok.) + ParensPassing, + /// (But sometimes it is missing a period) + //~^ doc_comments_missing_terminal_punctuation + ParensFailing, + /// **Sometimes the last sentence is in bold, and that's ok.** + DoubleStarPassing, + /// **But sometimes it is missing a period** + //~^ doc_comments_missing_terminal_punctuation + DoubleStarFailing, + /// _Sometimes the last sentence is in italics, and that's ok._ + UnderscorePassing, + /// _But sometimes it is missing a period_ + //~^ doc_comments_missing_terminal_punctuation + UnderscoreFailing, +} + +/// Doc comments can end with an [inline link](#anchor) +//~^ doc_comments_missing_terminal_punctuation +struct InlineLink; + +/// Some doc comments contain [link reference definitions][spec] +//~^ doc_comments_missing_terminal_punctuation +/// +/// [spec]: https://spec.commonmark.org/0.31.2/#link-reference-definitions +struct LinkRefDefinition; + +// List items do not always need to end with a period. +enum UnorderedLists { + /// - A list item + Dash, + /// + A list item + Plus, + /// * A list item + Star, +} + +enum OrderedLists { + /// 1. A list item + Dot, + /// 42) A list item + Paren, +} + +/// Doc comments with trailing blank lines are supported +//~^ doc_comments_missing_terminal_punctuation +/// +struct TrailingBlankLine; + +/// The first paragraph is not checked +/// +/// Other sentences are not either +/// Only the last sentence is +//~^ doc_comments_missing_terminal_punctuation +struct OnlyLastSentence; + +/// Sometimes a doc attribute is used for concatenation: +/// ``` +#[doc = ""] +/// ``` +struct DocAttribute; + +#[expect(clippy::empty_docs)] +/// +struct EmptyDocComment; diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation.stderr b/tests/ui/doc/doc_comments_missing_terminal_punctuation.stderr new file mode 100644 index 000000000000..b3fccdd186c7 --- /dev/null +++ b/tests/ui/doc/doc_comments_missing_terminal_punctuation.stderr @@ -0,0 +1,83 @@ +error: doc comments should end with a terminal punctuation mark + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:5:1 + | +LL | /// Returns the Answer to the Ultimate Question of Life, the Universe, and Everything + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: end the doc comment with some punctuation: `/// Returns the Answer to the Ultimate Question of Life, the Universe, and Everything.` + | + = note: `-D clippy::doc-comments-missing-terminal-punctuation` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::doc_comments_missing_terminal_punctuation)]` + +error: doc comments should end with a terminal punctuation mark + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:11:1 + | +LL | /// The `Option` type + | ^^^^^^^^^^^^^^^^^^^^^ help: end the doc comment with some punctuation: `/// The `Option` type.` + +error: doc comments should end with a terminal punctuation mark + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:16:5 + | +LL | /// No value + | ^^^^^^^^^^^^ help: end the doc comment with some punctuation: `/// No value.` + +error: doc comments should end with a terminal punctuation mark + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:27:1 + | +LL | /// only the last line triggers the lint + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: end the doc comment with some punctuation: `/// only the last line triggers the lint.` + +error: doc comments should end with a terminal punctuation mark + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:66:5 + | +LL | /// U+0001 + | ^^^^^^^^^^ help: end the doc comment with some punctuation: `/// U+0001.` + +error: doc comments should end with a terminal punctuation mark + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:73:5 + | +LL | //! inner attributes too + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: end the doc comment with some punctuation: `//! inner attributes too.` + +error: doc comments should end with a terminal punctuation mark + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:80:5 + | +LL | /// (But sometimes it is missing a period) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: end the doc comment with some punctuation: `/// (But sometimes it is missing a period.)` + +error: doc comments should end with a terminal punctuation mark + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:85:5 + | +LL | /// **But sometimes it is missing a period** + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: end the doc comment with some punctuation: `/// **But sometimes it is missing a period.**` + +error: doc comments should end with a terminal punctuation mark + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:90:5 + | +LL | /// _But sometimes it is missing a period_ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: end the doc comment with some punctuation: `/// _But sometimes it is missing a period._` + +error: doc comments should end with a terminal punctuation mark + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:95:1 + | +LL | /// Doc comments can end with an [inline link](#anchor) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: end the doc comment with some punctuation: `/// Doc comments can end with an [inline link](#anchor).` + +error: doc comments should end with a terminal punctuation mark + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:99:1 + | +LL | /// Some doc comments contain [link reference definitions][spec] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: end the doc comment with some punctuation: `/// Some doc comments contain [link reference definitions][spec].` + +error: doc comments should end with a terminal punctuation mark + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:122:1 + | +LL | /// Doc comments with trailing blank lines are supported + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: end the doc comment with some punctuation: `/// Doc comments with trailing blank lines are supported.` + +error: doc comments should end with a terminal punctuation mark + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:130:1 + | +LL | /// Only the last sentence is + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: end the doc comment with some punctuation: `/// Only the last sentence is.` + +error: aborting due to 13 previous errors + diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.rs b/tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.rs new file mode 100644 index 000000000000..8db089250cce --- /dev/null +++ b/tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.rs @@ -0,0 +1,12 @@ +#![feature(custom_inner_attributes)] +#![rustfmt::skip] +#![warn(clippy::doc_comments_missing_terminal_punctuation)] +// Only line doc comments are provided with suggestions. +//@no-rustfix + +/** +//~^ doc_comments_missing_terminal_punctuation + * Block doc comments work + * + */ +struct BlockDocComment; diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.stderr b/tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.stderr new file mode 100644 index 000000000000..f2b2601f3079 --- /dev/null +++ b/tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.stderr @@ -0,0 +1,15 @@ +error: doc comments should end with a terminal punctuation mark + --> tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.rs:7:1 + | +LL | / /** +LL | | +LL | | * Block doc comments work +LL | | * +LL | | */ + | |___^ + | + = note: `-D clippy::doc-comments-missing-terminal-punctuation` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::doc_comments_missing_terminal_punctuation)]` + +error: aborting due to 1 previous error + From abdedec18b2e4fb923077cc269d2dd4140c2c047 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 26 Sep 2025 13:16:46 -0700 Subject: [PATCH 02/12] doc_comments_missing_terminal_punctuation: real md parser --- ...c_comments_missing_terminal_punctuation.rs | 235 ++++-------------- clippy_lints/src/doc/mod.rs | 10 +- ...omments_missing_terminal_punctuation.fixed | 19 +- ...c_comments_missing_terminal_punctuation.rs | 15 +- ...mments_missing_terminal_punctuation.stderr | 66 +++-- ..._missing_terminal_punctuation_unfixable.rs | 11 +- ...sing_terminal_punctuation_unfixable.stderr | 10 +- 7 files changed, 134 insertions(+), 232 deletions(-) diff --git a/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs b/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs index 47a721ce76a1..cb8022caa1fd 100644 --- a/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs +++ b/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs @@ -1,54 +1,29 @@ -use rustc_ast::ast::{AttrKind, AttrStyle, Attribute}; use rustc_errors::Applicability; -use rustc_lint::EarlyContext; +use rustc_lint::LateContext; +use rustc_resolve::rustdoc::main_body_opts; -use super::DOC_COMMENTS_MISSING_TERMINAL_PUNCTUATION; +use rustc_resolve::rustdoc::pulldown_cmark::{Event, Options, Parser, Tag, TagEnd}; + +use super::{DOC_COMMENTS_MISSING_TERMINAL_PUNCTUATION, Fragments}; const MSG: &str = "doc comments should end with a terminal punctuation mark"; const PUNCTUATION_SUGGESTION: char = '.'; -pub fn check(cx: &EarlyContext<'_>, attrs: &[Attribute]) { - let mut doc_comment_attrs = attrs.iter().enumerate().filter(|(_, a)| is_doc_comment(a)); - - let Some((i, mut last_doc_attr)) = doc_comment_attrs.next_back() else { - return; - }; - - // Check that the next attribute is not a `#[doc]` attribute. - if let Some(next_attr) = attrs.get(i + 1) - && is_doc_attr(next_attr) - { - return; - } - - // Find the last, non-blank, non-refdef line of multiline doc comments: this is enough to check that - // the doc comment ends with proper punctuation. - while is_doc_comment_trailer(last_doc_attr) { - if let Some(doc_attr) = doc_comment_attrs.next_back() { - (_, last_doc_attr) = doc_attr; - } else { - // The doc comment looks (functionally) empty. - return; - } - } - - if let Some(doc_string) = is_missing_punctuation(last_doc_attr) { - let span = last_doc_attr.span; - - if is_line_doc_comment(last_doc_attr) { - let suggestion = generate_suggestion(last_doc_attr, doc_string); - +pub fn check(cx: &LateContext<'_>, doc: &str, fragments: Fragments<'_>) { + if let Some(offset) = is_missing_punctuation(doc) { + if let Some(span) = fragments.span(cx, offset..offset) { clippy_utils::diagnostics::span_lint_and_sugg( cx, DOC_COMMENTS_MISSING_TERMINAL_PUNCTUATION, span, MSG, "end the doc comment with some punctuation", - suggestion, + PUNCTUATION_SUGGESTION.to_string(), Applicability::MaybeIncorrect, ); } else { - // Seems more difficult to preserve the formatting of block doc comments, so we do not provide + let span = fragments.fragments.last().unwrap().span; + // Seems more difficult to preserve the formatting of `#[doc]` attrs, so we do not provide // suggestions for them; they are much rarer anyway. clippy_utils::diagnostics::span_lint(cx, DOC_COMMENTS_MISSING_TERMINAL_PUNCTUATION, span, MSG); } @@ -56,156 +31,56 @@ pub fn check(cx: &EarlyContext<'_>, attrs: &[Attribute]) { } #[must_use] -fn is_missing_punctuation(attr: &Attribute) -> Option<&str> { +/// If punctuation is missing, returns the docstring and the offset +/// where new punctuation should be inserted. +fn is_missing_punctuation(doc_string: &str) -> Option { const TERMINAL_PUNCTUATION_MARKS: &[char] = &['.', '?', '!', '…']; - const EXCEPTIONS: &[char] = &[ - '>', // Raw HTML or (unfortunately) Markdown autolinks. - '|', // Markdown tables. - ]; - - let doc_string = get_doc_string(attr)?; - // Doc comments could have some trailing whitespace, but that is not this lint's job. - let trimmed = doc_string.trim_end(); - - // Doc comments are also allowed to end with fenced code blocks. - if trimmed.ends_with(TERMINAL_PUNCTUATION_MARKS) || trimmed.ends_with(EXCEPTIONS) || trimmed.ends_with("```") { - return None; - } - - // Ignore single-line list items: they may not require any terminal punctuation. - if looks_like_list_item(trimmed) { - return None; - } - - if let Some(stripped) = strip_sentence_trailers(trimmed) - && stripped.ends_with(TERMINAL_PUNCTUATION_MARKS) + let mut no_report_depth = 0; + let mut text_offset = None; + for (event, offset) in + Parser::new_ext(doc_string, main_body_opts() - Options::ENABLE_SMART_PUNCTUATION).into_offset_iter() { - return None; - } - - Some(doc_string) -} - -#[must_use] -fn generate_suggestion(doc_attr: &Attribute, doc_string: &str) -> String { - let doc_comment_prefix = match doc_attr.style { - AttrStyle::Outer => "///", - AttrStyle::Inner => "//!", - }; - - let mut original_line = format!("{doc_comment_prefix}{doc_string}"); - - if let Some(stripped) = strip_sentence_trailers(doc_string) { - // Insert the punctuation mark just before the sentence trailer. - original_line.insert(doc_comment_prefix.len() + stripped.len(), PUNCTUATION_SUGGESTION); - } else { - original_line.push(PUNCTUATION_SUGGESTION); - } - - original_line -} - -/// Strips closing parentheses and Markdown emphasis delimiters. -#[must_use] -fn strip_sentence_trailers(string: &str) -> Option<&str> { - // The std has a few occurrences of doc comments ending with a sentence in parentheses. - const TRAILERS: &[char] = &[')', '*', '_']; - - if let Some(stripped) = string.strip_suffix("**") { - return Some(stripped); - } - - if let Some(stripped) = string.strip_suffix("__") { - return Some(stripped); - } - - // Markdown inline links should not be mistaken for sentences in parentheses. - if looks_like_inline_link(string) { - return None; - } - - string.strip_suffix(TRAILERS) -} - -/// Returns whether the doc comment looks like a Markdown reference definition or a blank line. -#[must_use] -fn is_doc_comment_trailer(attr: &Attribute) -> bool { - let Some(doc_string) = get_doc_string(attr) else { - return false; - }; - - super::looks_like_refdef(doc_string, 0..doc_string.len()).is_some() || doc_string.trim_end().is_empty() -} - -/// Returns whether the string looks like it ends with a Markdown inline link. -#[must_use] -fn looks_like_inline_link(string: &str) -> bool { - let Some(sub) = string.strip_suffix(')') else { - return false; - }; - let Some((sub, _)) = sub.rsplit_once('(') else { - return false; - }; - - // Check whether there is closing bracket just before the opening parenthesis. - sub.ends_with(']') -} - -/// Returns whether the string looks like a Markdown list item. -#[must_use] -fn looks_like_list_item(string: &str) -> bool { - const BULLET_LIST_MARKERS: &[char] = &['-', '+', '*']; - const ORDERED_LIST_MARKER_SYMBOL: &[char] = &['.', ')']; - - let trimmed = string.trim_start(); - - if let Some(sub) = trimmed.strip_prefix(BULLET_LIST_MARKERS) - && sub.starts_with(char::is_whitespace) - { - return true; - } - - let mut stripped = trimmed; - while let Some(sub) = stripped.strip_prefix(|c| char::is_digit(c, 10)) { - stripped = sub; - } - if let Some(sub) = stripped.strip_prefix(ORDERED_LIST_MARKER_SYMBOL) - && sub.starts_with(char::is_whitespace) - { - return true; + match event { + Event::Start( + Tag::CodeBlock(..) + | Tag::FootnoteDefinition(_) + | Tag::Heading { .. } + | Tag::HtmlBlock + | Tag::List(..) + | Tag::Table(_), + ) => { + no_report_depth += 1; + }, + Event::End( + TagEnd::CodeBlock + | TagEnd::FootnoteDefinition + | TagEnd::Heading(_) + | TagEnd::HtmlBlock + | TagEnd::List(_) + | TagEnd::Table, + ) => { + no_report_depth -= 1; + }, + Event::InlineHtml(_) | Event::Start(Tag::Image { .. }) | Event::End(TagEnd::Image) => { + text_offset = None; + }, + Event::Text(..) | Event::Start(Tag::Link { .. }) | Event::End(TagEnd::Link) + if no_report_depth == 0 && !offset.is_empty() => + { + text_offset = Some(offset); + }, + _ => {}, + } } - false -} - -#[must_use] -fn is_doc_attr(attr: &Attribute) -> bool { - if let AttrKind::Normal(normal_attr) = &attr.kind - && let Some(segment) = &normal_attr.item.path.segments.first() - && segment.ident.name == clippy_utils::sym::doc + let text_offset = text_offset?; + if doc_string[..text_offset.end] + .trim_end_matches(|c: char| c.is_whitespace() || c == ')' || c == ']' || c == '}') + .ends_with(TERMINAL_PUNCTUATION_MARKS) { - true - } else { - false - } -} - -#[must_use] -fn get_doc_string(attr: &Attribute) -> Option<&str> { - if let AttrKind::DocComment(_, symbol) = &attr.kind { - Some(symbol.as_str()) - } else { None + } else { + Some(text_offset.end) } } - -#[must_use] -fn is_doc_comment(attr: &Attribute) -> bool { - matches!(attr.kind, AttrKind::DocComment(_, _)) -} - -#[must_use] -fn is_line_doc_comment(attr: &Attribute) -> bool { - matches!(attr.kind, AttrKind::DocComment(rustc_ast::token::CommentKind::Line, _)) -} diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs index 97a0fb714339..a0911fccd591 100644 --- a/clippy_lints/src/doc/mod.rs +++ b/clippy_lints/src/doc/mod.rs @@ -733,7 +733,6 @@ impl_lint_pass!(Documentation => [ impl EarlyLintPass for Documentation { fn check_attributes(&mut self, cx: &EarlyContext<'_>, attrs: &[rustc_ast::Attribute]) { include_in_doc_without_cfg::check(cx, attrs); - doc_comments_missing_terminal_punctuation::check(cx, attrs); } } @@ -900,6 +899,15 @@ fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet, attrs: &[ }, ); + doc_comments_missing_terminal_punctuation::check( + cx, + &doc, + Fragments { + doc: &doc, + fragments: &fragments, + }, + ); + // NOTE: check_doc uses it own cb function, // to avoid causing duplicated diagnostics for the broken link checker. let mut full_fake_broken_link_callback = |bl: BrokenLink<'_>| -> Option<(CowStr<'_>, CowStr<'_>)> { diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed b/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed index 555b16d7022b..6a5a30954585 100644 --- a/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed +++ b/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed @@ -36,8 +36,9 @@ enum Exceptions { /// HTML content is however not checked: /// Raw HTML is allowed as well RawHtml, - /// The raw HTML exception also unfortunately results in ignoring autolinks too: - /// + /// The raw HTML exception actually does the right thing to autolinks: + /// . + //~^ doc_comments_missing_terminal_punctuation MarkdownAutolink, /// | Exception | Note | /// | -------------- | ----- | @@ -77,7 +78,7 @@ mod module { enum Trailers { /// (Sometimes the last sentence is in parentheses, and that's ok.) ParensPassing, - /// (But sometimes it is missing a period.) + /// (But sometimes it is missing a period). //~^ doc_comments_missing_terminal_punctuation ParensFailing, /// **Sometimes the last sentence is in bold, and that's ok.** @@ -131,12 +132,16 @@ struct TrailingBlankLine; //~^ doc_comments_missing_terminal_punctuation struct OnlyLastSentence; -/// Sometimes a doc attribute is used for concatenation: -/// ``` -#[doc = ""] /// ``` -struct DocAttribute; +struct IncompleteBlockCode; #[expect(clippy::empty_docs)] /// struct EmptyDocComment; + +/** + * Block doc comments work. + * + */ +//~^^^ doc_comments_missing_terminal_punctuation +struct BlockDocComment; diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs b/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs index f2c6f0d610e9..09d54b134e9d 100644 --- a/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs +++ b/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs @@ -36,8 +36,9 @@ enum Exceptions { /// HTML content is however not checked: /// Raw HTML is allowed as well RawHtml, - /// The raw HTML exception also unfortunately results in ignoring autolinks too: + /// The raw HTML exception actually does the right thing to autolinks: /// + //~^ doc_comments_missing_terminal_punctuation MarkdownAutolink, /// | Exception | Note | /// | -------------- | ----- | @@ -131,12 +132,16 @@ struct TrailingBlankLine; //~^ doc_comments_missing_terminal_punctuation struct OnlyLastSentence; -/// Sometimes a doc attribute is used for concatenation: -/// ``` -#[doc = ""] /// ``` -struct DocAttribute; +struct IncompleteBlockCode; #[expect(clippy::empty_docs)] /// struct EmptyDocComment; + +/** + * Block doc comments work + * + */ +//~^^^ doc_comments_missing_terminal_punctuation +struct BlockDocComment; diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation.stderr b/tests/ui/doc/doc_comments_missing_terminal_punctuation.stderr index b3fccdd186c7..e4f3d30cf89d 100644 --- a/tests/ui/doc/doc_comments_missing_terminal_punctuation.stderr +++ b/tests/ui/doc/doc_comments_missing_terminal_punctuation.stderr @@ -1,83 +1,95 @@ error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:5:1 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:5:86 | LL | /// Returns the Answer to the Ultimate Question of Life, the Universe, and Everything - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: end the doc comment with some punctuation: `/// Returns the Answer to the Ultimate Question of Life, the Universe, and Everything.` + | ^ help: end the doc comment with some punctuation: `.` | = note: `-D clippy::doc-comments-missing-terminal-punctuation` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::doc_comments_missing_terminal_punctuation)]` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:11:1 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:11:22 | LL | /// The `Option` type - | ^^^^^^^^^^^^^^^^^^^^^ help: end the doc comment with some punctuation: `/// The `Option` type.` + | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:16:5 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:16:17 | LL | /// No value - | ^^^^^^^^^^^^ help: end the doc comment with some punctuation: `/// No value.` + | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:27:1 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:27:41 | LL | /// only the last line triggers the lint - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: end the doc comment with some punctuation: `/// only the last line triggers the lint.` + | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:66:5 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:40:56 + | +LL | /// + | ^ help: end the doc comment with some punctuation: `.` + +error: doc comments should end with a terminal punctuation mark + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:67:15 | LL | /// U+0001 - | ^^^^^^^^^^ help: end the doc comment with some punctuation: `/// U+0001.` + | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:73:5 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:74:29 | LL | //! inner attributes too - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: end the doc comment with some punctuation: `//! inner attributes too.` + | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:80:5 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:81:47 | LL | /// (But sometimes it is missing a period) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: end the doc comment with some punctuation: `/// (But sometimes it is missing a period.)` + | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:85:5 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:86:47 | LL | /// **But sometimes it is missing a period** - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: end the doc comment with some punctuation: `/// **But sometimes it is missing a period.**` + | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:90:5 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:91:46 | LL | /// _But sometimes it is missing a period_ - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: end the doc comment with some punctuation: `/// _But sometimes it is missing a period._` + | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:95:1 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:96:56 | LL | /// Doc comments can end with an [inline link](#anchor) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: end the doc comment with some punctuation: `/// Doc comments can end with an [inline link](#anchor).` + | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:99:1 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:100:65 | LL | /// Some doc comments contain [link reference definitions][spec] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: end the doc comment with some punctuation: `/// Some doc comments contain [link reference definitions][spec].` + | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:122:1 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:123:57 | LL | /// Doc comments with trailing blank lines are supported - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: end the doc comment with some punctuation: `/// Doc comments with trailing blank lines are supported.` + | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:130:1 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:131:30 | LL | /// Only the last sentence is - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: end the doc comment with some punctuation: `/// Only the last sentence is.` + | ^ help: end the doc comment with some punctuation: `.` + +error: doc comments should end with a terminal punctuation mark + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:143:27 + | +LL | * Block doc comments work + | ^ help: end the doc comment with some punctuation: `.` -error: aborting due to 13 previous errors +error: aborting due to 15 previous errors diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.rs b/tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.rs index 8db089250cce..44d3dd693a69 100644 --- a/tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.rs +++ b/tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.rs @@ -4,9 +4,10 @@ // Only line doc comments are provided with suggestions. //@no-rustfix -/** +/// Sometimes a doc attribute is used for concatenation +/// ``` +#[doc = ""] +/// ``` //~^ doc_comments_missing_terminal_punctuation - * Block doc comments work - * - */ -struct BlockDocComment; +struct DocAttribute; + diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.stderr b/tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.stderr index f2b2601f3079..073293454296 100644 --- a/tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.stderr +++ b/tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.stderr @@ -1,12 +1,8 @@ error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.rs:7:1 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.rs:10:1 | -LL | / /** -LL | | -LL | | * Block doc comments work -LL | | * -LL | | */ - | |___^ +LL | /// ``` + | ^^^^^^^ | = note: `-D clippy::doc-comments-missing-terminal-punctuation` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::doc_comments_missing_terminal_punctuation)]` From 7678f3b65aaccd1818c0320fc14642a46186cecd Mon Sep 17 00:00:00 2001 From: AudaciousAxiom <179637270+AudaciousAxiom@users.noreply.github.com> Date: Sat, 27 Sep 2025 12:30:26 +0200 Subject: [PATCH 03/12] doc_comments_missing_terminal_punctuation: exclude doc attributes to avoid FP --- ...c_comments_missing_terminal_punctuation.rs | 30 ++++++++----------- ...omments_missing_terminal_punctuation.fixed | 6 ++++ ...c_comments_missing_terminal_punctuation.rs | 6 ++++ ..._missing_terminal_punctuation_unfixable.rs | 13 -------- ...sing_terminal_punctuation_unfixable.stderr | 11 ------- 5 files changed, 25 insertions(+), 41 deletions(-) delete mode 100644 tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.rs delete mode 100644 tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.stderr diff --git a/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs b/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs index cb8022caa1fd..ec628c2bbab4 100644 --- a/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs +++ b/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs @@ -10,23 +10,19 @@ const MSG: &str = "doc comments should end with a terminal punctuation mark"; const PUNCTUATION_SUGGESTION: char = '.'; pub fn check(cx: &LateContext<'_>, doc: &str, fragments: Fragments<'_>) { - if let Some(offset) = is_missing_punctuation(doc) { - if let Some(span) = fragments.span(cx, offset..offset) { - clippy_utils::diagnostics::span_lint_and_sugg( - cx, - DOC_COMMENTS_MISSING_TERMINAL_PUNCTUATION, - span, - MSG, - "end the doc comment with some punctuation", - PUNCTUATION_SUGGESTION.to_string(), - Applicability::MaybeIncorrect, - ); - } else { - let span = fragments.fragments.last().unwrap().span; - // Seems more difficult to preserve the formatting of `#[doc]` attrs, so we do not provide - // suggestions for them; they are much rarer anyway. - clippy_utils::diagnostics::span_lint(cx, DOC_COMMENTS_MISSING_TERMINAL_PUNCTUATION, span, MSG); - } + // This ignores `#[doc]` attributes, which we do not handle. + if let Some(offset) = is_missing_punctuation(doc) + && let Some(span) = fragments.span(cx, offset..offset) + { + clippy_utils::diagnostics::span_lint_and_sugg( + cx, + DOC_COMMENTS_MISSING_TERMINAL_PUNCTUATION, + span, + MSG, + "end the doc comment with some punctuation", + PUNCTUATION_SUGGESTION.to_string(), + Applicability::MaybeIncorrect, + ); } } diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed b/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed index 6a5a30954585..ef2f5867418b 100644 --- a/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed +++ b/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed @@ -145,3 +145,9 @@ struct EmptyDocComment; */ //~^^^ doc_comments_missing_terminal_punctuation struct BlockDocComment; + +/// Sometimes a doc attribute is used for concatenation +/// ``` +#[doc = ""] +/// ``` +struct DocAttribute; diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs b/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs index 09d54b134e9d..40a989c159c4 100644 --- a/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs +++ b/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs @@ -145,3 +145,9 @@ struct EmptyDocComment; */ //~^^^ doc_comments_missing_terminal_punctuation struct BlockDocComment; + +/// Sometimes a doc attribute is used for concatenation +/// ``` +#[doc = ""] +/// ``` +struct DocAttribute; diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.rs b/tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.rs deleted file mode 100644 index 44d3dd693a69..000000000000 --- a/tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.rs +++ /dev/null @@ -1,13 +0,0 @@ -#![feature(custom_inner_attributes)] -#![rustfmt::skip] -#![warn(clippy::doc_comments_missing_terminal_punctuation)] -// Only line doc comments are provided with suggestions. -//@no-rustfix - -/// Sometimes a doc attribute is used for concatenation -/// ``` -#[doc = ""] -/// ``` -//~^ doc_comments_missing_terminal_punctuation -struct DocAttribute; - diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.stderr b/tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.stderr deleted file mode 100644 index 073293454296..000000000000 --- a/tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.rs:10:1 - | -LL | /// ``` - | ^^^^^^^ - | - = note: `-D clippy::doc-comments-missing-terminal-punctuation` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::doc_comments_missing_terminal_punctuation)]` - -error: aborting due to 1 previous error - From e34a90b26e23e2e50d11e6f4b29302427d172587 Mon Sep 17 00:00:00 2001 From: AudaciousAxiom <179637270+AudaciousAxiom@users.noreply.github.com> Date: Sat, 27 Sep 2025 12:11:51 +0200 Subject: [PATCH 04/12] doc_comments_missing_terminal_punctuation: exclude tables and code blocks --- ...c_comments_missing_terminal_punctuation.rs | 11 +++++----- ...omments_missing_terminal_punctuation.fixed | 6 ++++++ ...c_comments_missing_terminal_punctuation.rs | 6 ++++++ ...mments_missing_terminal_punctuation.stderr | 20 +++++++++---------- 4 files changed, 27 insertions(+), 16 deletions(-) diff --git a/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs b/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs index ec628c2bbab4..d56f7500cb69 100644 --- a/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs +++ b/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs @@ -48,15 +48,14 @@ fn is_missing_punctuation(doc_string: &str) -> Option { ) => { no_report_depth += 1; }, + Event::End(TagEnd::FootnoteDefinition) => { + no_report_depth -= 1; + }, Event::End( - TagEnd::CodeBlock - | TagEnd::FootnoteDefinition - | TagEnd::Heading(_) - | TagEnd::HtmlBlock - | TagEnd::List(_) - | TagEnd::Table, + TagEnd::CodeBlock | TagEnd::Heading(_) | TagEnd::HtmlBlock | TagEnd::List(_) | TagEnd::Table, ) => { no_report_depth -= 1; + text_offset = None; }, Event::InlineHtml(_) | Event::Start(Tag::Image { .. }) | Event::End(TagEnd::Image) => { text_offset = None; diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed b/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed index ef2f5867418b..8ab134614ba7 100644 --- a/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed +++ b/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed @@ -40,10 +40,14 @@ enum Exceptions { /// . //~^ doc_comments_missing_terminal_punctuation MarkdownAutolink, + /// This table introduction ends with a colon: + /// /// | Exception | Note | /// | -------------- | ----- | /// | Markdown table | A-ok | MarkdownTable, + /// Here is a snippet + /// /// ``` /// // Code blocks are no issues. /// ``` @@ -105,6 +109,8 @@ struct LinkRefDefinition; // List items do not always need to end with a period. enum UnorderedLists { + /// This list has an introductory sentence: + /// /// - A list item Dash, /// + A list item diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs b/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs index 40a989c159c4..fa238ce8920c 100644 --- a/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs +++ b/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs @@ -40,10 +40,14 @@ enum Exceptions { /// //~^ doc_comments_missing_terminal_punctuation MarkdownAutolink, + /// This table introduction ends with a colon: + /// /// | Exception | Note | /// | -------------- | ----- | /// | Markdown table | A-ok | MarkdownTable, + /// Here is a snippet + /// /// ``` /// // Code blocks are no issues. /// ``` @@ -105,6 +109,8 @@ struct LinkRefDefinition; // List items do not always need to end with a period. enum UnorderedLists { + /// This list has an introductory sentence: + /// /// - A list item Dash, /// + A list item diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation.stderr b/tests/ui/doc/doc_comments_missing_terminal_punctuation.stderr index e4f3d30cf89d..ca4cdf66f24b 100644 --- a/tests/ui/doc/doc_comments_missing_terminal_punctuation.stderr +++ b/tests/ui/doc/doc_comments_missing_terminal_punctuation.stderr @@ -32,61 +32,61 @@ LL | /// | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:67:15 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:71:15 | LL | /// U+0001 | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:74:29 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:78:29 | LL | //! inner attributes too | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:81:47 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:85:47 | LL | /// (But sometimes it is missing a period) | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:86:47 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:90:47 | LL | /// **But sometimes it is missing a period** | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:91:46 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:95:46 | LL | /// _But sometimes it is missing a period_ | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:96:56 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:100:56 | LL | /// Doc comments can end with an [inline link](#anchor) | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:100:65 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:104:65 | LL | /// Some doc comments contain [link reference definitions][spec] | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:123:57 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:129:57 | LL | /// Doc comments with trailing blank lines are supported | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:131:30 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:137:30 | LL | /// Only the last sentence is | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:143:27 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:149:27 | LL | * Block doc comments work | ^ help: end the doc comment with some punctuation: `.` From 36df5d67219460f19b832238f228080c4ee1e82e Mon Sep 17 00:00:00 2001 From: AudaciousAxiom <179637270+AudaciousAxiom@users.noreply.github.com> Date: Sat, 27 Sep 2025 14:33:04 +0200 Subject: [PATCH 05/12] doc_comments_missing_terminal_punctuation: handle code spans properly --- .../doc/doc_comments_missing_terminal_punctuation.rs | 2 +- .../doc_comments_missing_terminal_punctuation.fixed | 4 ++++ .../doc/doc_comments_missing_terminal_punctuation.rs | 4 ++++ .../doc_comments_missing_terminal_punctuation.stderr | 10 ++++++++-- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs b/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs index d56f7500cb69..705bc3fc95d6 100644 --- a/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs +++ b/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs @@ -60,7 +60,7 @@ fn is_missing_punctuation(doc_string: &str) -> Option { Event::InlineHtml(_) | Event::Start(Tag::Image { .. }) | Event::End(TagEnd::Image) => { text_offset = None; }, - Event::Text(..) | Event::Start(Tag::Link { .. }) | Event::End(TagEnd::Link) + Event::Code(..) | Event::Text(..) | Event::Start(Tag::Link { .. }) | Event::End(TagEnd::Link) if no_report_depth == 0 && !offset.is_empty() => { text_offset = Some(offset); diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed b/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed index 8ab134614ba7..d925e895cb99 100644 --- a/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed +++ b/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed @@ -141,6 +141,10 @@ struct OnlyLastSentence; /// ``` struct IncompleteBlockCode; +/// This ends with a code `span`. +//~^ doc_comments_missing_terminal_punctuation +struct CodeSpan; + #[expect(clippy::empty_docs)] /// struct EmptyDocComment; diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs b/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs index fa238ce8920c..2d1c39e48a3d 100644 --- a/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs +++ b/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs @@ -141,6 +141,10 @@ struct OnlyLastSentence; /// ``` struct IncompleteBlockCode; +/// This ends with a code `span` +//~^ doc_comments_missing_terminal_punctuation +struct CodeSpan; + #[expect(clippy::empty_docs)] /// struct EmptyDocComment; diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation.stderr b/tests/ui/doc/doc_comments_missing_terminal_punctuation.stderr index ca4cdf66f24b..d1782ce8d33a 100644 --- a/tests/ui/doc/doc_comments_missing_terminal_punctuation.stderr +++ b/tests/ui/doc/doc_comments_missing_terminal_punctuation.stderr @@ -86,10 +86,16 @@ LL | /// Only the last sentence is | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:149:27 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:144:33 + | +LL | /// This ends with a code `span` + | ^ help: end the doc comment with some punctuation: `.` + +error: doc comments should end with a terminal punctuation mark + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:153:27 | LL | * Block doc comments work | ^ help: end the doc comment with some punctuation: `.` -error: aborting due to 15 previous errors +error: aborting due to 16 previous errors From d35076edcb9243c8f895c5dc3a6026bfbce58f8a Mon Sep 17 00:00:00 2001 From: AudaciousAxiom <179637270+AudaciousAxiom@users.noreply.github.com> Date: Tue, 30 Sep 2025 18:12:41 +0200 Subject: [PATCH 06/12] doc_comments_missing_terminal_punctuation: remove the parens special treatment --- ...c_comments_missing_terminal_punctuation.rs | 11 ++++--- ...omments_missing_terminal_punctuation.fixed | 7 +++-- ...c_comments_missing_terminal_punctuation.rs | 7 +++-- ...mments_missing_terminal_punctuation.stderr | 30 +++++++++++-------- 4 files changed, 31 insertions(+), 24 deletions(-) diff --git a/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs b/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs index 705bc3fc95d6..d26da1c1e5c0 100644 --- a/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs +++ b/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs @@ -27,8 +27,7 @@ pub fn check(cx: &LateContext<'_>, doc: &str, fragments: Fragments<'_>) { } #[must_use] -/// If punctuation is missing, returns the docstring and the offset -/// where new punctuation should be inserted. +/// If punctuation is missing, returns the offset where new punctuation should be inserted. fn is_missing_punctuation(doc_string: &str) -> Option { const TERMINAL_PUNCTUATION_MARKS: &[char] = &['.', '?', '!', '…']; @@ -63,19 +62,19 @@ fn is_missing_punctuation(doc_string: &str) -> Option { Event::Code(..) | Event::Text(..) | Event::Start(Tag::Link { .. }) | Event::End(TagEnd::Link) if no_report_depth == 0 && !offset.is_empty() => { - text_offset = Some(offset); + text_offset = Some(offset.end); }, _ => {}, } } let text_offset = text_offset?; - if doc_string[..text_offset.end] - .trim_end_matches(|c: char| c.is_whitespace() || c == ')' || c == ']' || c == '}') + if doc_string[..text_offset] + .trim_end() .ends_with(TERMINAL_PUNCTUATION_MARKS) { None } else { - Some(text_offset.end) + Some(text_offset) } } diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed b/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed index d925e895cb99..b17914250fa6 100644 --- a/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed +++ b/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed @@ -80,9 +80,10 @@ mod module { } enum Trailers { - /// (Sometimes the last sentence is in parentheses, and that's ok.) - ParensPassing, - /// (But sometimes it is missing a period). + /// Sometimes the doc comment ends with parentheses (like this). + //~^ doc_comments_missing_terminal_punctuation + EndsWithParens, + /// (Sometimes the last sentence is in parentheses, but there is no special treatment of this.). //~^ doc_comments_missing_terminal_punctuation ParensFailing, /// **Sometimes the last sentence is in bold, and that's ok.** diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs b/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs index 2d1c39e48a3d..8c599b191656 100644 --- a/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs +++ b/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs @@ -80,9 +80,10 @@ mod module { } enum Trailers { - /// (Sometimes the last sentence is in parentheses, and that's ok.) - ParensPassing, - /// (But sometimes it is missing a period) + /// Sometimes the doc comment ends with parentheses (like this) + //~^ doc_comments_missing_terminal_punctuation + EndsWithParens, + /// (Sometimes the last sentence is in parentheses, but there is no special treatment of this.) //~^ doc_comments_missing_terminal_punctuation ParensFailing, /// **Sometimes the last sentence is in bold, and that's ok.** diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation.stderr b/tests/ui/doc/doc_comments_missing_terminal_punctuation.stderr index d1782ce8d33a..4b4105155e87 100644 --- a/tests/ui/doc/doc_comments_missing_terminal_punctuation.stderr +++ b/tests/ui/doc/doc_comments_missing_terminal_punctuation.stderr @@ -44,58 +44,64 @@ LL | //! inner attributes too | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:85:47 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:83:68 | -LL | /// (But sometimes it is missing a period) - | ^ help: end the doc comment with some punctuation: `.` +LL | /// Sometimes the doc comment ends with parentheses (like this) + | ^ help: end the doc comment with some punctuation: `.` + +error: doc comments should end with a terminal punctuation mark + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:86:100 + | +LL | /// (Sometimes the last sentence is in parentheses, but there is no special treatment of this.) + | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:90:47 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:91:47 | LL | /// **But sometimes it is missing a period** | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:95:46 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:96:46 | LL | /// _But sometimes it is missing a period_ | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:100:56 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:101:56 | LL | /// Doc comments can end with an [inline link](#anchor) | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:104:65 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:105:65 | LL | /// Some doc comments contain [link reference definitions][spec] | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:129:57 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:130:57 | LL | /// Doc comments with trailing blank lines are supported | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:137:30 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:138:30 | LL | /// Only the last sentence is | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:144:33 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:145:33 | LL | /// This ends with a code `span` | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:153:27 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:154:27 | LL | * Block doc comments work | ^ help: end the doc comment with some punctuation: `.` -error: aborting due to 16 previous errors +error: aborting due to 17 previous errors From f24631329204d822021d78f169164778de64b0f3 Mon Sep 17 00:00:00 2001 From: AudaciousAxiom <179637270+AudaciousAxiom@users.noreply.github.com> Date: Thu, 2 Oct 2025 19:20:59 +0200 Subject: [PATCH 07/12] doc_comments_missing_terminal_punctuation: accept punctuation in quotes --- ...c_comments_missing_terminal_punctuation.rs | 10 +++++++++- ...omments_missing_terminal_punctuation.fixed | 5 +++++ ...c_comments_missing_terminal_punctuation.rs | 5 +++++ ...mments_missing_terminal_punctuation.stderr | 20 ++++++++++++------- 4 files changed, 32 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs b/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs index d26da1c1e5c0..5c73b747e826 100644 --- a/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs +++ b/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs @@ -59,11 +59,19 @@ fn is_missing_punctuation(doc_string: &str) -> Option { Event::InlineHtml(_) | Event::Start(Tag::Image { .. }) | Event::End(TagEnd::Image) => { text_offset = None; }, - Event::Code(..) | Event::Text(..) | Event::Start(Tag::Link { .. }) | Event::End(TagEnd::Link) + Event::Code(..) | Event::Start(Tag::Link { .. }) | Event::End(TagEnd::Link) if no_report_depth == 0 && !offset.is_empty() => { text_offset = Some(offset.end); }, + Event::Text(..) if no_report_depth == 0 && !offset.is_empty() => { + // American-style quotes require punctuation to be placed inside closing quotation marks. + if doc_string[..offset.end].trim_end().ends_with('"') { + text_offset = Some(offset.end - 1); + } else { + text_offset = Some(offset.end); + } + }, _ => {}, } } diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed b/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed index b17914250fa6..ebc9c17ea043 100644 --- a/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed +++ b/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed @@ -96,6 +96,11 @@ enum Trailers { /// _But sometimes it is missing a period._ //~^ doc_comments_missing_terminal_punctuation UnderscoreFailing, + /// This comment ends with "a quote." + QuotePassing, + /// This comment ends with "a quote." + //~^ doc_comments_missing_terminal_punctuation + QuoteFailing, } /// Doc comments can end with an [inline link](#anchor). diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs b/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs index 8c599b191656..3677dc4ffb3e 100644 --- a/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs +++ b/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs @@ -96,6 +96,11 @@ enum Trailers { /// _But sometimes it is missing a period_ //~^ doc_comments_missing_terminal_punctuation UnderscoreFailing, + /// This comment ends with "a quote." + QuotePassing, + /// This comment ends with "a quote" + //~^ doc_comments_missing_terminal_punctuation + QuoteFailing, } /// Doc comments can end with an [inline link](#anchor) diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation.stderr b/tests/ui/doc/doc_comments_missing_terminal_punctuation.stderr index 4b4105155e87..2783f8e055b6 100644 --- a/tests/ui/doc/doc_comments_missing_terminal_punctuation.stderr +++ b/tests/ui/doc/doc_comments_missing_terminal_punctuation.stderr @@ -68,40 +68,46 @@ LL | /// _But sometimes it is missing a period_ | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:101:56 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:101:40 + | +LL | /// This comment ends with "a quote" + | ^ help: end the doc comment with some punctuation: `.` + +error: doc comments should end with a terminal punctuation mark + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:106:56 | LL | /// Doc comments can end with an [inline link](#anchor) | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:105:65 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:110:65 | LL | /// Some doc comments contain [link reference definitions][spec] | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:130:57 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:135:57 | LL | /// Doc comments with trailing blank lines are supported | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:138:30 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:143:30 | LL | /// Only the last sentence is | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:145:33 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:150:33 | LL | /// This ends with a code `span` | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:154:27 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:159:27 | LL | * Block doc comments work | ^ help: end the doc comment with some punctuation: `.` -error: aborting due to 17 previous errors +error: aborting due to 18 previous errors From 2ec26719fe462c25cee88115c057d963c08a2b3a Mon Sep 17 00:00:00 2001 From: AudaciousAxiom <179637270+AudaciousAxiom@users.noreply.github.com> Date: Thu, 2 Oct 2025 22:31:01 +0200 Subject: [PATCH 08/12] doc_comments_missing_terminal_punctuation: treat some trailers as unfixable --- ...c_comments_missing_terminal_punctuation.rs | 91 ++++++++++++------- ...omments_missing_terminal_punctuation.fixed | 17 ++-- ...c_comments_missing_terminal_punctuation.rs | 17 ++-- ...mments_missing_terminal_punctuation.stderr | 36 ++------ ..._missing_terminal_punctuation_unfixable.rs | 13 +++ ...sing_terminal_punctuation_unfixable.stderr | 20 ++++ 6 files changed, 116 insertions(+), 78 deletions(-) create mode 100644 tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.rs create mode 100644 tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.stderr diff --git a/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs b/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs index 5c73b747e826..47b73999665b 100644 --- a/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs +++ b/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs @@ -10,29 +10,45 @@ const MSG: &str = "doc comments should end with a terminal punctuation mark"; const PUNCTUATION_SUGGESTION: char = '.'; pub fn check(cx: &LateContext<'_>, doc: &str, fragments: Fragments<'_>) { - // This ignores `#[doc]` attributes, which we do not handle. - if let Some(offset) = is_missing_punctuation(doc) - && let Some(span) = fragments.span(cx, offset..offset) - { - clippy_utils::diagnostics::span_lint_and_sugg( - cx, - DOC_COMMENTS_MISSING_TERMINAL_PUNCTUATION, - span, - MSG, - "end the doc comment with some punctuation", - PUNCTUATION_SUGGESTION.to_string(), - Applicability::MaybeIncorrect, - ); + match is_missing_punctuation(doc) { + IsMissingPunctuation::Fixable(offset) => { + // This ignores `#[doc]` attributes, which we do not handle. + if let Some(span) = fragments.span(cx, offset..offset) { + clippy_utils::diagnostics::span_lint_and_sugg( + cx, + DOC_COMMENTS_MISSING_TERMINAL_PUNCTUATION, + span, + MSG, + "end the doc comment with some punctuation", + PUNCTUATION_SUGGESTION.to_string(), + Applicability::MaybeIncorrect, + ); + } + }, + IsMissingPunctuation::Unfixable(offset) => { + // This ignores `#[doc]` attributes, which we do not handle. + if let Some(span) = fragments.span(cx, offset..offset) { + clippy_utils::diagnostics::span_lint_and_help( + cx, + DOC_COMMENTS_MISSING_TERMINAL_PUNCTUATION, + span, + MSG, + None, + "end the doc comment with some punctuation", + ); + } + }, + IsMissingPunctuation::No => {}, } } #[must_use] /// If punctuation is missing, returns the offset where new punctuation should be inserted. -fn is_missing_punctuation(doc_string: &str) -> Option { +fn is_missing_punctuation(doc_string: &str) -> IsMissingPunctuation { const TERMINAL_PUNCTUATION_MARKS: &[char] = &['.', '?', '!', '…']; let mut no_report_depth = 0; - let mut text_offset = None; + let mut missing_punctuation = IsMissingPunctuation::No; for (event, offset) in Parser::new_ext(doc_string, main_body_opts() - Options::ENABLE_SMART_PUNCTUATION).into_offset_iter() { @@ -54,35 +70,48 @@ fn is_missing_punctuation(doc_string: &str) -> Option { TagEnd::CodeBlock | TagEnd::Heading(_) | TagEnd::HtmlBlock | TagEnd::List(_) | TagEnd::Table, ) => { no_report_depth -= 1; - text_offset = None; + missing_punctuation = IsMissingPunctuation::No; }, Event::InlineHtml(_) | Event::Start(Tag::Image { .. }) | Event::End(TagEnd::Image) => { - text_offset = None; + missing_punctuation = IsMissingPunctuation::No; }, Event::Code(..) | Event::Start(Tag::Link { .. }) | Event::End(TagEnd::Link) if no_report_depth == 0 && !offset.is_empty() => { - text_offset = Some(offset.end); + if doc_string[..offset.end] + .trim_end() + .ends_with(TERMINAL_PUNCTUATION_MARKS) + { + missing_punctuation = IsMissingPunctuation::No; + } else { + missing_punctuation = IsMissingPunctuation::Fixable(offset.end); + } }, Event::Text(..) if no_report_depth == 0 && !offset.is_empty() => { - // American-style quotes require punctuation to be placed inside closing quotation marks. - if doc_string[..offset.end].trim_end().ends_with('"') { - text_offset = Some(offset.end - 1); + let trimmed = doc_string[..offset.end].trim_end(); + if trimmed.ends_with(TERMINAL_PUNCTUATION_MARKS) { + missing_punctuation = IsMissingPunctuation::No; + } else if let Some(t) = trimmed.strip_suffix(|c| c == ')' || c == '"') { + if t.ends_with(TERMINAL_PUNCTUATION_MARKS) { + // Avoid false positives. + missing_punctuation = IsMissingPunctuation::No; + } else { + missing_punctuation = IsMissingPunctuation::Unfixable(offset.end); + } } else { - text_offset = Some(offset.end); + missing_punctuation = IsMissingPunctuation::Fixable(offset.end); } }, _ => {}, } } - let text_offset = text_offset?; - if doc_string[..text_offset] - .trim_end() - .ends_with(TERMINAL_PUNCTUATION_MARKS) - { - None - } else { - Some(text_offset) - } + missing_punctuation +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +enum IsMissingPunctuation { + Fixable(usize), + Unfixable(usize), + No, } diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed b/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed index ebc9c17ea043..a1f1da33d806 100644 --- a/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed +++ b/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed @@ -80,12 +80,10 @@ mod module { } enum Trailers { - /// Sometimes the doc comment ends with parentheses (like this). - //~^ doc_comments_missing_terminal_punctuation - EndsWithParens, - /// (Sometimes the last sentence is in parentheses, but there is no special treatment of this.). - //~^ doc_comments_missing_terminal_punctuation - ParensFailing, + /// Sometimes the last sentence ends with parentheses (and that's ok). + ParensPassing, + /// (Sometimes the last sentence is in parentheses.) + SentenceInParensPassing, /// **Sometimes the last sentence is in bold, and that's ok.** DoubleStarPassing, /// **But sometimes it is missing a period.** @@ -97,10 +95,9 @@ enum Trailers { //~^ doc_comments_missing_terminal_punctuation UnderscoreFailing, /// This comment ends with "a quote." - QuotePassing, - /// This comment ends with "a quote." - //~^ doc_comments_missing_terminal_punctuation - QuoteFailing, + AmericanStyleQuotePassing, + /// This comment ends with "a quote". + BritishStyleQuotePassing, } /// Doc comments can end with an [inline link](#anchor). diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs b/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs index 3677dc4ffb3e..85c1b31dcd5b 100644 --- a/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs +++ b/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs @@ -80,12 +80,10 @@ mod module { } enum Trailers { - /// Sometimes the doc comment ends with parentheses (like this) - //~^ doc_comments_missing_terminal_punctuation - EndsWithParens, - /// (Sometimes the last sentence is in parentheses, but there is no special treatment of this.) - //~^ doc_comments_missing_terminal_punctuation - ParensFailing, + /// Sometimes the last sentence ends with parentheses (and that's ok). + ParensPassing, + /// (Sometimes the last sentence is in parentheses.) + SentenceInParensPassing, /// **Sometimes the last sentence is in bold, and that's ok.** DoubleStarPassing, /// **But sometimes it is missing a period** @@ -97,10 +95,9 @@ enum Trailers { //~^ doc_comments_missing_terminal_punctuation UnderscoreFailing, /// This comment ends with "a quote." - QuotePassing, - /// This comment ends with "a quote" - //~^ doc_comments_missing_terminal_punctuation - QuoteFailing, + AmericanStyleQuotePassing, + /// This comment ends with "a quote". + BritishStyleQuotePassing, } /// Doc comments can end with an [inline link](#anchor) diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation.stderr b/tests/ui/doc/doc_comments_missing_terminal_punctuation.stderr index 2783f8e055b6..bd36e7ace929 100644 --- a/tests/ui/doc/doc_comments_missing_terminal_punctuation.stderr +++ b/tests/ui/doc/doc_comments_missing_terminal_punctuation.stderr @@ -44,70 +44,52 @@ LL | //! inner attributes too | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:83:68 - | -LL | /// Sometimes the doc comment ends with parentheses (like this) - | ^ help: end the doc comment with some punctuation: `.` - -error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:86:100 - | -LL | /// (Sometimes the last sentence is in parentheses, but there is no special treatment of this.) - | ^ help: end the doc comment with some punctuation: `.` - -error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:91:47 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:89:47 | LL | /// **But sometimes it is missing a period** | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:96:46 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:94:46 | LL | /// _But sometimes it is missing a period_ | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:101:40 - | -LL | /// This comment ends with "a quote" - | ^ help: end the doc comment with some punctuation: `.` - -error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:106:56 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:103:56 | LL | /// Doc comments can end with an [inline link](#anchor) | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:110:65 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:107:65 | LL | /// Some doc comments contain [link reference definitions][spec] | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:135:57 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:132:57 | LL | /// Doc comments with trailing blank lines are supported | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:143:30 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:140:30 | LL | /// Only the last sentence is | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:150:33 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:147:33 | LL | /// This ends with a code `span` | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:159:27 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:156:27 | LL | * Block doc comments work | ^ help: end the doc comment with some punctuation: `.` -error: aborting due to 18 previous errors +error: aborting due to 15 previous errors diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.rs b/tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.rs new file mode 100644 index 000000000000..1c52441eb656 --- /dev/null +++ b/tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.rs @@ -0,0 +1,13 @@ +#![feature(custom_inner_attributes)] +#![rustfmt::skip] +#![warn(clippy::doc_comments_missing_terminal_punctuation)] +//@no-rustfix + +enum UnfixableTrailers { + /// Sometimes the doc comment ends with parentheses (like this) + //~^ doc_comments_missing_terminal_punctuation + EndsWithParens, + /// This comment ends with "a quote" + //~^ doc_comments_missing_terminal_punctuation + QuoteFailing, +} diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.stderr b/tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.stderr new file mode 100644 index 000000000000..72e10b0bff9f --- /dev/null +++ b/tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.stderr @@ -0,0 +1,20 @@ +error: doc comments should end with a terminal punctuation mark + --> tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.rs:7:68 + | +LL | /// Sometimes the doc comment ends with parentheses (like this) + | ^ + | + = help: end the doc comment with some punctuation + = note: `-D clippy::doc-comments-missing-terminal-punctuation` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::doc_comments_missing_terminal_punctuation)]` + +error: doc comments should end with a terminal punctuation mark + --> tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.rs:10:41 + | +LL | /// This comment ends with "a quote" + | ^ + | + = help: end the doc comment with some punctuation + +error: aborting due to 2 previous errors + From 53fd302ad1ca19d3a8294e02b96050df101270c9 Mon Sep 17 00:00:00 2001 From: AudaciousAxiom <179637270+AudaciousAxiom@users.noreply.github.com> Date: Sun, 5 Oct 2025 11:19:46 +0200 Subject: [PATCH 09/12] doc_comments_missing_terminal_punctuation: short-circuit to avoid parsing --- .../src/doc/doc_comments_missing_terminal_punctuation.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs b/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs index 47b73999665b..7b3f438e9067 100644 --- a/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs +++ b/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs @@ -47,6 +47,11 @@ pub fn check(cx: &LateContext<'_>, doc: &str, fragments: Fragments<'_>) { fn is_missing_punctuation(doc_string: &str) -> IsMissingPunctuation { const TERMINAL_PUNCTUATION_MARKS: &[char] = &['.', '?', '!', '…']; + // Short-circuit in simple, common cases to avoid Markdown parsing. + if doc_string.trim_end().ends_with(TERMINAL_PUNCTUATION_MARKS) { + return IsMissingPunctuation::No; + } + let mut no_report_depth = 0; let mut missing_punctuation = IsMissingPunctuation::No; for (event, offset) in From 76fb0ce3b821c50057328e8897ac6705443f1195 Mon Sep 17 00:00:00 2001 From: AudaciousAxiom <179637270+AudaciousAxiom@users.noreply.github.com> Date: Sat, 18 Oct 2025 10:45:55 +0200 Subject: [PATCH 10/12] doc_comments_missing_terminal_punctuation: check every paragraph --- ...c_comments_missing_terminal_punctuation.rs | 98 ++++++++++--------- clippy_lints/src/doc/mod.rs | 13 ++- ...omments_missing_terminal_punctuation.fixed | 16 ++- ...c_comments_missing_terminal_punctuation.rs | 14 ++- ...mments_missing_terminal_punctuation.stderr | 44 ++++++--- 5 files changed, 112 insertions(+), 73 deletions(-) diff --git a/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs b/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs index 7b3f438e9067..1a69bfaa1237 100644 --- a/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs +++ b/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs @@ -10,50 +10,50 @@ const MSG: &str = "doc comments should end with a terminal punctuation mark"; const PUNCTUATION_SUGGESTION: char = '.'; pub fn check(cx: &LateContext<'_>, doc: &str, fragments: Fragments<'_>) { - match is_missing_punctuation(doc) { - IsMissingPunctuation::Fixable(offset) => { - // This ignores `#[doc]` attributes, which we do not handle. - if let Some(span) = fragments.span(cx, offset..offset) { - clippy_utils::diagnostics::span_lint_and_sugg( - cx, - DOC_COMMENTS_MISSING_TERMINAL_PUNCTUATION, - span, - MSG, - "end the doc comment with some punctuation", - PUNCTUATION_SUGGESTION.to_string(), - Applicability::MaybeIncorrect, - ); - } - }, - IsMissingPunctuation::Unfixable(offset) => { - // This ignores `#[doc]` attributes, which we do not handle. - if let Some(span) = fragments.span(cx, offset..offset) { - clippy_utils::diagnostics::span_lint_and_help( - cx, - DOC_COMMENTS_MISSING_TERMINAL_PUNCTUATION, - span, - MSG, - None, - "end the doc comment with some punctuation", - ); - } - }, - IsMissingPunctuation::No => {}, + for missing_punctuation in is_missing_punctuation(doc) { + match missing_punctuation { + MissingPunctuation::Fixable(offset) => { + // This ignores `#[doc]` attributes, which we do not handle. + if let Some(span) = fragments.span(cx, offset..offset) { + clippy_utils::diagnostics::span_lint_and_sugg( + cx, + DOC_COMMENTS_MISSING_TERMINAL_PUNCTUATION, + span, + MSG, + "end the doc comment with some punctuation", + PUNCTUATION_SUGGESTION.to_string(), + Applicability::MaybeIncorrect, + ); + } + }, + MissingPunctuation::Unfixable(offset) => { + // This ignores `#[doc]` attributes, which we do not handle. + if let Some(span) = fragments.span(cx, offset..offset) { + clippy_utils::diagnostics::span_lint_and_help( + cx, + DOC_COMMENTS_MISSING_TERMINAL_PUNCTUATION, + span, + MSG, + None, + "end the doc comment with some punctuation", + ); + } + }, + } } } #[must_use] /// If punctuation is missing, returns the offset where new punctuation should be inserted. -fn is_missing_punctuation(doc_string: &str) -> IsMissingPunctuation { - const TERMINAL_PUNCTUATION_MARKS: &[char] = &['.', '?', '!', '…']; - - // Short-circuit in simple, common cases to avoid Markdown parsing. - if doc_string.trim_end().ends_with(TERMINAL_PUNCTUATION_MARKS) { - return IsMissingPunctuation::No; - } +fn is_missing_punctuation(doc_string: &str) -> Vec { + // The colon is not exactly a terminal punctuation mark, but this is required for paragraphs that + // introduce a table or a list for example. + const TERMINAL_PUNCTUATION_MARKS: &[char] = &['.', '?', '!', '…', ':']; let mut no_report_depth = 0; - let mut missing_punctuation = IsMissingPunctuation::No; + let mut missing_punctuation = Vec::new(); + let mut current_paragraph = None; + for (event, offset) in Parser::new_ext(doc_string, main_body_opts() - Options::ENABLE_SMART_PUNCTUATION).into_offset_iter() { @@ -75,10 +75,15 @@ fn is_missing_punctuation(doc_string: &str) -> IsMissingPunctuation { TagEnd::CodeBlock | TagEnd::Heading(_) | TagEnd::HtmlBlock | TagEnd::List(_) | TagEnd::Table, ) => { no_report_depth -= 1; - missing_punctuation = IsMissingPunctuation::No; + current_paragraph = None; }, Event::InlineHtml(_) | Event::Start(Tag::Image { .. }) | Event::End(TagEnd::Image) => { - missing_punctuation = IsMissingPunctuation::No; + current_paragraph = None; + }, + Event::End(TagEnd::Paragraph) => { + if let Some(mp) = current_paragraph { + missing_punctuation.push(mp); + } }, Event::Code(..) | Event::Start(Tag::Link { .. }) | Event::End(TagEnd::Link) if no_report_depth == 0 && !offset.is_empty() => @@ -87,24 +92,24 @@ fn is_missing_punctuation(doc_string: &str) -> IsMissingPunctuation { .trim_end() .ends_with(TERMINAL_PUNCTUATION_MARKS) { - missing_punctuation = IsMissingPunctuation::No; + current_paragraph = None; } else { - missing_punctuation = IsMissingPunctuation::Fixable(offset.end); + current_paragraph = Some(MissingPunctuation::Fixable(offset.end)); } }, Event::Text(..) if no_report_depth == 0 && !offset.is_empty() => { let trimmed = doc_string[..offset.end].trim_end(); if trimmed.ends_with(TERMINAL_PUNCTUATION_MARKS) { - missing_punctuation = IsMissingPunctuation::No; + current_paragraph = None; } else if let Some(t) = trimmed.strip_suffix(|c| c == ')' || c == '"') { if t.ends_with(TERMINAL_PUNCTUATION_MARKS) { // Avoid false positives. - missing_punctuation = IsMissingPunctuation::No; + current_paragraph = None; } else { - missing_punctuation = IsMissingPunctuation::Unfixable(offset.end); + current_paragraph = Some(MissingPunctuation::Unfixable(offset.end)); } } else { - missing_punctuation = IsMissingPunctuation::Fixable(offset.end); + current_paragraph = Some(MissingPunctuation::Fixable(offset.end)); } }, _ => {}, @@ -115,8 +120,7 @@ fn is_missing_punctuation(doc_string: &str) -> IsMissingPunctuation { } #[derive(Debug, Copy, Clone, PartialEq, Eq)] -enum IsMissingPunctuation { +enum MissingPunctuation { Fixable(usize), Unfixable(usize), - No, } diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs index a0911fccd591..90120553fff5 100644 --- a/clippy_lints/src/doc/mod.rs +++ b/clippy_lints/src/doc/mod.rs @@ -673,19 +673,24 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for doc comments that do not end with a period or another punctuation mark. + /// Checks for doc comments whose paragraphs do not end with a period or another punctuation mark. /// Various Markdowns constructs are taken into account to avoid false positives. /// /// ### Why is this bad? - /// A project may wish to enforce consistent doc comments by making sure they end with a punctuation mark. + /// A project may wish to enforce consistent doc comments by making sure paragraphs end with a + /// punctuation mark. /// /// ### Example /// ```no_run - /// /// Returns the Answer to the Ultimate Question of Life, the Universe, and Everything + /// /// Returns a random number + /// /// + /// /// It was chosen by a fair dice roll /// ``` /// Use instead: /// ```no_run - /// /// Returns the Answer to the Ultimate Question of Life, the Universe, and Everything. + /// /// Returns a random number. + /// /// + /// /// It was chosen by a fair dice roll. /// ``` #[clippy::version = "1.92.0"] pub DOC_COMMENTS_MISSING_TERMINAL_PUNCTUATION, diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed b/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed index a1f1da33d806..6961d3d0eae1 100644 --- a/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed +++ b/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed @@ -46,7 +46,8 @@ enum Exceptions { /// | -------------- | ----- | /// | Markdown table | A-ok | MarkdownTable, - /// Here is a snippet + /// Here is a snippet. + //~^ doc_comments_missing_terminal_punctuation /// /// ``` /// // Code blocks are no issues. @@ -134,12 +135,17 @@ enum OrderedLists { /// struct TrailingBlankLine; -/// The first paragraph is not checked +/// This doc comment has multiple paragraph. +/// This first paragraph is missing punctuation. +//~^ doc_comments_missing_terminal_punctuation +/// +/// The second one as well +/// And it has multiple sentences. +//~^ doc_comments_missing_terminal_punctuation /// -/// Other sentences are not either -/// Only the last sentence is. +/// Same for this third and last one. //~^ doc_comments_missing_terminal_punctuation -struct OnlyLastSentence; +struct MultiParagraphDocComment; /// ``` struct IncompleteBlockCode; diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs b/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs index 85c1b31dcd5b..1ab0b96ec719 100644 --- a/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs +++ b/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs @@ -47,6 +47,7 @@ enum Exceptions { /// | Markdown table | A-ok | MarkdownTable, /// Here is a snippet + //~^ doc_comments_missing_terminal_punctuation /// /// ``` /// // Code blocks are no issues. @@ -134,12 +135,17 @@ enum OrderedLists { /// struct TrailingBlankLine; -/// The first paragraph is not checked +/// This doc comment has multiple paragraph. +/// This first paragraph is missing punctuation +//~^ doc_comments_missing_terminal_punctuation +/// +/// The second one as well +/// And it has multiple sentences +//~^ doc_comments_missing_terminal_punctuation /// -/// Other sentences are not either -/// Only the last sentence is +/// Same for this third and last one //~^ doc_comments_missing_terminal_punctuation -struct OnlyLastSentence; +struct MultiParagraphDocComment; /// ``` struct IncompleteBlockCode; diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation.stderr b/tests/ui/doc/doc_comments_missing_terminal_punctuation.stderr index bd36e7ace929..f0617c6e9b25 100644 --- a/tests/ui/doc/doc_comments_missing_terminal_punctuation.stderr +++ b/tests/ui/doc/doc_comments_missing_terminal_punctuation.stderr @@ -32,64 +32,82 @@ LL | /// | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:71:15 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:49:26 + | +LL | /// Here is a snippet + | ^ help: end the doc comment with some punctuation: `.` + +error: doc comments should end with a terminal punctuation mark + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:72:15 | LL | /// U+0001 | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:78:29 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:79:29 | LL | //! inner attributes too | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:89:47 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:90:47 | LL | /// **But sometimes it is missing a period** | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:94:46 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:95:46 | LL | /// _But sometimes it is missing a period_ | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:103:56 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:104:56 | LL | /// Doc comments can end with an [inline link](#anchor) | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:107:65 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:108:65 | LL | /// Some doc comments contain [link reference definitions][spec] | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:132:57 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:133:57 | LL | /// Doc comments with trailing blank lines are supported | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:140:30 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:139:48 + | +LL | /// This first paragraph is missing punctuation + | ^ help: end the doc comment with some punctuation: `.` + +error: doc comments should end with a terminal punctuation mark + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:143:34 + | +LL | /// And it has multiple sentences + | ^ help: end the doc comment with some punctuation: `.` + +error: doc comments should end with a terminal punctuation mark + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:146:37 | -LL | /// Only the last sentence is - | ^ help: end the doc comment with some punctuation: `.` +LL | /// Same for this third and last one + | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:147:33 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:153:33 | LL | /// This ends with a code `span` | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:156:27 + --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:162:27 | LL | * Block doc comments work | ^ help: end the doc comment with some punctuation: `.` -error: aborting due to 15 previous errors +error: aborting due to 18 previous errors From 52aa4a5abe06cf4173fd83003b2f9f3b9d00374d Mon Sep 17 00:00:00 2001 From: AudaciousAxiom <179637270+AudaciousAxiom@users.noreply.github.com> Date: Sun, 19 Oct 2025 16:52:21 +0200 Subject: [PATCH 11/12] doc_paragraphs_missing_punctuation: rename the lint --- CHANGELOG.md | 2 +- clippy_lints/src/declared_lints.rs | 2 +- ... => doc_paragraphs_missing_punctuation.rs} | 6 +-- clippy_lints/src/doc/mod.rs | 8 ++-- ... doc_paragraphs_missing_punctuation.fixed} | 42 +++++++++---------- ... => doc_paragraphs_missing_punctuation.rs} | 42 +++++++++---------- ...doc_paragraphs_missing_punctuation.stderr} | 40 +++++++++--------- ...ragraphs_missing_punctuation_unfixable.rs} | 6 +-- ...aphs_missing_punctuation_unfixable.stderr} | 8 ++-- 9 files changed, 78 insertions(+), 78 deletions(-) rename clippy_lints/src/doc/{doc_comments_missing_terminal_punctuation.rs => doc_paragraphs_missing_punctuation.rs} (95%) rename tests/ui/doc/{doc_comments_missing_terminal_punctuation.fixed => doc_paragraphs_missing_punctuation.fixed} (76%) rename tests/ui/doc/{doc_comments_missing_terminal_punctuation.rs => doc_paragraphs_missing_punctuation.rs} (76%) rename tests/ui/doc/{doc_comments_missing_terminal_punctuation.stderr => doc_paragraphs_missing_punctuation.stderr} (72%) rename tests/ui/doc/{doc_comments_missing_terminal_punctuation_unfixable.rs => doc_paragraphs_missing_punctuation_unfixable.rs} (60%) rename tests/ui/doc/{doc_comments_missing_terminal_punctuation_unfixable.stderr => doc_paragraphs_missing_punctuation_unfixable.stderr} (60%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42d9b2ea60f2..df4346cef8b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6224,7 +6224,6 @@ Released 2018-09-13 [`diverging_sub_expression`]: https://rust-lang.github.io/rust-clippy/master/index.html#diverging_sub_expression [`doc_broken_link`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_broken_link [`doc_comment_double_space_linebreaks`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_comment_double_space_linebreaks -[`doc_comments_missing_terminal_punctuation`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_comments_missing_terminal_punctuation [`doc_include_without_cfg`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_include_without_cfg [`doc_lazy_continuation`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_lazy_continuation [`doc_link_code`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_link_code @@ -6232,6 +6231,7 @@ Released 2018-09-13 [`doc_markdown`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown [`doc_nested_refdefs`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_nested_refdefs [`doc_overindented_list_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_overindented_list_items +[`doc_paragraphs_missing_punctuation`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_paragraphs_missing_punctuation [`doc_suspicious_footnotes`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_suspicious_footnotes [`double_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_comparisons [`double_ended_iterator_last`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_ended_iterator_last diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index fbeafef2e455..e9ce87c2dd8d 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -110,7 +110,6 @@ pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[ crate::disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS_INFO, crate::disallowed_types::DISALLOWED_TYPES_INFO, crate::doc::DOC_BROKEN_LINK_INFO, - crate::doc::DOC_COMMENTS_MISSING_TERMINAL_PUNCTUATION_INFO, crate::doc::DOC_COMMENT_DOUBLE_SPACE_LINEBREAKS_INFO, crate::doc::DOC_INCLUDE_WITHOUT_CFG_INFO, crate::doc::DOC_LAZY_CONTINUATION_INFO, @@ -119,6 +118,7 @@ pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[ crate::doc::DOC_MARKDOWN_INFO, crate::doc::DOC_NESTED_REFDEFS_INFO, crate::doc::DOC_OVERINDENTED_LIST_ITEMS_INFO, + crate::doc::DOC_PARAGRAPHS_MISSING_PUNCTUATION_INFO, crate::doc::DOC_SUSPICIOUS_FOOTNOTES_INFO, crate::doc::EMPTY_DOCS_INFO, crate::doc::MISSING_ERRORS_DOC_INFO, diff --git a/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs b/clippy_lints/src/doc/doc_paragraphs_missing_punctuation.rs similarity index 95% rename from clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs rename to clippy_lints/src/doc/doc_paragraphs_missing_punctuation.rs index 1a69bfaa1237..7e8acadbd6fa 100644 --- a/clippy_lints/src/doc/doc_comments_missing_terminal_punctuation.rs +++ b/clippy_lints/src/doc/doc_paragraphs_missing_punctuation.rs @@ -4,7 +4,7 @@ use rustc_resolve::rustdoc::main_body_opts; use rustc_resolve::rustdoc::pulldown_cmark::{Event, Options, Parser, Tag, TagEnd}; -use super::{DOC_COMMENTS_MISSING_TERMINAL_PUNCTUATION, Fragments}; +use super::{DOC_PARAGRAPHS_MISSING_PUNCTUATION, Fragments}; const MSG: &str = "doc comments should end with a terminal punctuation mark"; const PUNCTUATION_SUGGESTION: char = '.'; @@ -17,7 +17,7 @@ pub fn check(cx: &LateContext<'_>, doc: &str, fragments: Fragments<'_>) { if let Some(span) = fragments.span(cx, offset..offset) { clippy_utils::diagnostics::span_lint_and_sugg( cx, - DOC_COMMENTS_MISSING_TERMINAL_PUNCTUATION, + DOC_PARAGRAPHS_MISSING_PUNCTUATION, span, MSG, "end the doc comment with some punctuation", @@ -31,7 +31,7 @@ pub fn check(cx: &LateContext<'_>, doc: &str, fragments: Fragments<'_>) { if let Some(span) = fragments.span(cx, offset..offset) { clippy_utils::diagnostics::span_lint_and_help( cx, - DOC_COMMENTS_MISSING_TERMINAL_PUNCTUATION, + DOC_PARAGRAPHS_MISSING_PUNCTUATION, span, MSG, None, diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs index 90120553fff5..45c11f8a82de 100644 --- a/clippy_lints/src/doc/mod.rs +++ b/clippy_lints/src/doc/mod.rs @@ -28,7 +28,7 @@ use url::Url; mod broken_link; mod doc_comment_double_space_linebreaks; -mod doc_comments_missing_terminal_punctuation; +mod doc_paragraphs_missing_punctuation; mod doc_suspicious_footnotes; mod include_in_doc_without_cfg; mod lazy_continuation; @@ -693,7 +693,7 @@ declare_clippy_lint! { /// /// It was chosen by a fair dice roll. /// ``` #[clippy::version = "1.92.0"] - pub DOC_COMMENTS_MISSING_TERMINAL_PUNCTUATION, + pub DOC_PARAGRAPHS_MISSING_PUNCTUATION, nursery, "missing terminal punctuation in doc comments" } @@ -732,7 +732,7 @@ impl_lint_pass!(Documentation => [ DOC_INCLUDE_WITHOUT_CFG, DOC_COMMENT_DOUBLE_SPACE_LINEBREAKS, DOC_SUSPICIOUS_FOOTNOTES, - DOC_COMMENTS_MISSING_TERMINAL_PUNCTUATION, + DOC_PARAGRAPHS_MISSING_PUNCTUATION, ]); impl EarlyLintPass for Documentation { @@ -904,7 +904,7 @@ fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet, attrs: &[ }, ); - doc_comments_missing_terminal_punctuation::check( + doc_paragraphs_missing_punctuation::check( cx, &doc, Fragments { diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed b/tests/ui/doc/doc_paragraphs_missing_punctuation.fixed similarity index 76% rename from tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed rename to tests/ui/doc/doc_paragraphs_missing_punctuation.fixed index 6961d3d0eae1..95d65039440b 100644 --- a/tests/ui/doc/doc_comments_missing_terminal_punctuation.fixed +++ b/tests/ui/doc/doc_paragraphs_missing_punctuation.fixed @@ -1,20 +1,20 @@ #![feature(custom_inner_attributes)] #![rustfmt::skip] -#![warn(clippy::doc_comments_missing_terminal_punctuation)] +#![warn(clippy::doc_paragraphs_missing_punctuation)] /// Returns the Answer to the Ultimate Question of Life, the Universe, and Everything. -//~^ doc_comments_missing_terminal_punctuation +//~^ doc_paragraphs_missing_punctuation fn answer() -> i32 { 42 } /// The `Option` type. -//~^ doc_comments_missing_terminal_punctuation +//~^ doc_paragraphs_missing_punctuation // Triggers even in the presence of another attribute. #[derive(Debug)] enum MyOption { /// No value. - //~^ doc_comments_missing_terminal_punctuation + //~^ doc_paragraphs_missing_punctuation None, /// Some value of type `T`. Some(T), @@ -25,7 +25,7 @@ enum MyOption { #[derive(Debug)] /// doc comment: /// only the last line triggers the lint. -//~^ doc_comments_missing_terminal_punctuation +//~^ doc_paragraphs_missing_punctuation enum Exceptions { /// Question marks are fine? QuestionMark, @@ -38,7 +38,7 @@ enum Exceptions { RawHtml, /// The raw HTML exception actually does the right thing to autolinks: /// . - //~^ doc_comments_missing_terminal_punctuation + //~^ doc_paragraphs_missing_punctuation MarkdownAutolink, /// This table introduction ends with a colon: /// @@ -47,7 +47,7 @@ enum Exceptions { /// | Markdown table | A-ok | MarkdownTable, /// Here is a snippet. - //~^ doc_comments_missing_terminal_punctuation + //~^ doc_paragraphs_missing_punctuation /// /// ``` /// // Code blocks are no issues. @@ -56,7 +56,7 @@ enum Exceptions { } // Check the lint can be expected on a whole enum at once. -#[expect(clippy::doc_comments_missing_terminal_punctuation)] +#[expect(clippy::doc_paragraphs_missing_punctuation)] enum Char { /// U+0000 Null, @@ -66,18 +66,18 @@ enum Char { // Check the lint can be expected on a single variant without affecting others. enum Char2 { - #[expect(clippy::doc_comments_missing_terminal_punctuation)] + #[expect(clippy::doc_paragraphs_missing_punctuation)] /// U+0000 Null, /// U+0001. - //~^ doc_comments_missing_terminal_punctuation + //~^ doc_paragraphs_missing_punctuation StartOfHeading, } mod module { //! Works on //! inner attributes too. - //~^ doc_comments_missing_terminal_punctuation + //~^ doc_paragraphs_missing_punctuation } enum Trailers { @@ -88,12 +88,12 @@ enum Trailers { /// **Sometimes the last sentence is in bold, and that's ok.** DoubleStarPassing, /// **But sometimes it is missing a period.** - //~^ doc_comments_missing_terminal_punctuation + //~^ doc_paragraphs_missing_punctuation DoubleStarFailing, /// _Sometimes the last sentence is in italics, and that's ok._ UnderscorePassing, /// _But sometimes it is missing a period._ - //~^ doc_comments_missing_terminal_punctuation + //~^ doc_paragraphs_missing_punctuation UnderscoreFailing, /// This comment ends with "a quote." AmericanStyleQuotePassing, @@ -102,11 +102,11 @@ enum Trailers { } /// Doc comments can end with an [inline link](#anchor). -//~^ doc_comments_missing_terminal_punctuation +//~^ doc_paragraphs_missing_punctuation struct InlineLink; /// Some doc comments contain [link reference definitions][spec]. -//~^ doc_comments_missing_terminal_punctuation +//~^ doc_paragraphs_missing_punctuation /// /// [spec]: https://spec.commonmark.org/0.31.2/#link-reference-definitions struct LinkRefDefinition; @@ -131,27 +131,27 @@ enum OrderedLists { } /// Doc comments with trailing blank lines are supported. -//~^ doc_comments_missing_terminal_punctuation +//~^ doc_paragraphs_missing_punctuation /// struct TrailingBlankLine; /// This doc comment has multiple paragraph. /// This first paragraph is missing punctuation. -//~^ doc_comments_missing_terminal_punctuation +//~^ doc_paragraphs_missing_punctuation /// /// The second one as well /// And it has multiple sentences. -//~^ doc_comments_missing_terminal_punctuation +//~^ doc_paragraphs_missing_punctuation /// /// Same for this third and last one. -//~^ doc_comments_missing_terminal_punctuation +//~^ doc_paragraphs_missing_punctuation struct MultiParagraphDocComment; /// ``` struct IncompleteBlockCode; /// This ends with a code `span`. -//~^ doc_comments_missing_terminal_punctuation +//~^ doc_paragraphs_missing_punctuation struct CodeSpan; #[expect(clippy::empty_docs)] @@ -162,7 +162,7 @@ struct EmptyDocComment; * Block doc comments work. * */ -//~^^^ doc_comments_missing_terminal_punctuation +//~^^^ doc_paragraphs_missing_punctuation struct BlockDocComment; /// Sometimes a doc attribute is used for concatenation diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs b/tests/ui/doc/doc_paragraphs_missing_punctuation.rs similarity index 76% rename from tests/ui/doc/doc_comments_missing_terminal_punctuation.rs rename to tests/ui/doc/doc_paragraphs_missing_punctuation.rs index 1ab0b96ec719..35b74d7d13b9 100644 --- a/tests/ui/doc/doc_comments_missing_terminal_punctuation.rs +++ b/tests/ui/doc/doc_paragraphs_missing_punctuation.rs @@ -1,20 +1,20 @@ #![feature(custom_inner_attributes)] #![rustfmt::skip] -#![warn(clippy::doc_comments_missing_terminal_punctuation)] +#![warn(clippy::doc_paragraphs_missing_punctuation)] /// Returns the Answer to the Ultimate Question of Life, the Universe, and Everything -//~^ doc_comments_missing_terminal_punctuation +//~^ doc_paragraphs_missing_punctuation fn answer() -> i32 { 42 } /// The `Option` type -//~^ doc_comments_missing_terminal_punctuation +//~^ doc_paragraphs_missing_punctuation // Triggers even in the presence of another attribute. #[derive(Debug)] enum MyOption { /// No value - //~^ doc_comments_missing_terminal_punctuation + //~^ doc_paragraphs_missing_punctuation None, /// Some value of type `T`. Some(T), @@ -25,7 +25,7 @@ enum MyOption { #[derive(Debug)] /// doc comment: /// only the last line triggers the lint -//~^ doc_comments_missing_terminal_punctuation +//~^ doc_paragraphs_missing_punctuation enum Exceptions { /// Question marks are fine? QuestionMark, @@ -38,7 +38,7 @@ enum Exceptions { RawHtml, /// The raw HTML exception actually does the right thing to autolinks: /// - //~^ doc_comments_missing_terminal_punctuation + //~^ doc_paragraphs_missing_punctuation MarkdownAutolink, /// This table introduction ends with a colon: /// @@ -47,7 +47,7 @@ enum Exceptions { /// | Markdown table | A-ok | MarkdownTable, /// Here is a snippet - //~^ doc_comments_missing_terminal_punctuation + //~^ doc_paragraphs_missing_punctuation /// /// ``` /// // Code blocks are no issues. @@ -56,7 +56,7 @@ enum Exceptions { } // Check the lint can be expected on a whole enum at once. -#[expect(clippy::doc_comments_missing_terminal_punctuation)] +#[expect(clippy::doc_paragraphs_missing_punctuation)] enum Char { /// U+0000 Null, @@ -66,18 +66,18 @@ enum Char { // Check the lint can be expected on a single variant without affecting others. enum Char2 { - #[expect(clippy::doc_comments_missing_terminal_punctuation)] + #[expect(clippy::doc_paragraphs_missing_punctuation)] /// U+0000 Null, /// U+0001 - //~^ doc_comments_missing_terminal_punctuation + //~^ doc_paragraphs_missing_punctuation StartOfHeading, } mod module { //! Works on //! inner attributes too - //~^ doc_comments_missing_terminal_punctuation + //~^ doc_paragraphs_missing_punctuation } enum Trailers { @@ -88,12 +88,12 @@ enum Trailers { /// **Sometimes the last sentence is in bold, and that's ok.** DoubleStarPassing, /// **But sometimes it is missing a period** - //~^ doc_comments_missing_terminal_punctuation + //~^ doc_paragraphs_missing_punctuation DoubleStarFailing, /// _Sometimes the last sentence is in italics, and that's ok._ UnderscorePassing, /// _But sometimes it is missing a period_ - //~^ doc_comments_missing_terminal_punctuation + //~^ doc_paragraphs_missing_punctuation UnderscoreFailing, /// This comment ends with "a quote." AmericanStyleQuotePassing, @@ -102,11 +102,11 @@ enum Trailers { } /// Doc comments can end with an [inline link](#anchor) -//~^ doc_comments_missing_terminal_punctuation +//~^ doc_paragraphs_missing_punctuation struct InlineLink; /// Some doc comments contain [link reference definitions][spec] -//~^ doc_comments_missing_terminal_punctuation +//~^ doc_paragraphs_missing_punctuation /// /// [spec]: https://spec.commonmark.org/0.31.2/#link-reference-definitions struct LinkRefDefinition; @@ -131,27 +131,27 @@ enum OrderedLists { } /// Doc comments with trailing blank lines are supported -//~^ doc_comments_missing_terminal_punctuation +//~^ doc_paragraphs_missing_punctuation /// struct TrailingBlankLine; /// This doc comment has multiple paragraph. /// This first paragraph is missing punctuation -//~^ doc_comments_missing_terminal_punctuation +//~^ doc_paragraphs_missing_punctuation /// /// The second one as well /// And it has multiple sentences -//~^ doc_comments_missing_terminal_punctuation +//~^ doc_paragraphs_missing_punctuation /// /// Same for this third and last one -//~^ doc_comments_missing_terminal_punctuation +//~^ doc_paragraphs_missing_punctuation struct MultiParagraphDocComment; /// ``` struct IncompleteBlockCode; /// This ends with a code `span` -//~^ doc_comments_missing_terminal_punctuation +//~^ doc_paragraphs_missing_punctuation struct CodeSpan; #[expect(clippy::empty_docs)] @@ -162,7 +162,7 @@ struct EmptyDocComment; * Block doc comments work * */ -//~^^^ doc_comments_missing_terminal_punctuation +//~^^^ doc_paragraphs_missing_punctuation struct BlockDocComment; /// Sometimes a doc attribute is used for concatenation diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation.stderr b/tests/ui/doc/doc_paragraphs_missing_punctuation.stderr similarity index 72% rename from tests/ui/doc/doc_comments_missing_terminal_punctuation.stderr rename to tests/ui/doc/doc_paragraphs_missing_punctuation.stderr index f0617c6e9b25..75c5edb06f99 100644 --- a/tests/ui/doc/doc_comments_missing_terminal_punctuation.stderr +++ b/tests/ui/doc/doc_paragraphs_missing_punctuation.stderr @@ -1,110 +1,110 @@ error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:5:86 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:5:86 | LL | /// Returns the Answer to the Ultimate Question of Life, the Universe, and Everything | ^ help: end the doc comment with some punctuation: `.` | - = note: `-D clippy::doc-comments-missing-terminal-punctuation` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::doc_comments_missing_terminal_punctuation)]` + = note: `-D clippy::doc-paragraphs-missing-punctuation` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::doc_paragraphs_missing_punctuation)]` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:11:22 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:11:22 | LL | /// The `Option` type | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:16:17 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:16:17 | LL | /// No value | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:27:41 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:27:41 | LL | /// only the last line triggers the lint | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:40:56 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:40:56 | LL | /// | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:49:26 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:49:26 | LL | /// Here is a snippet | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:72:15 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:72:15 | LL | /// U+0001 | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:79:29 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:79:29 | LL | //! inner attributes too | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:90:47 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:90:47 | LL | /// **But sometimes it is missing a period** | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:95:46 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:95:46 | LL | /// _But sometimes it is missing a period_ | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:104:56 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:104:56 | LL | /// Doc comments can end with an [inline link](#anchor) | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:108:65 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:108:65 | LL | /// Some doc comments contain [link reference definitions][spec] | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:133:57 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:133:57 | LL | /// Doc comments with trailing blank lines are supported | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:139:48 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:139:48 | LL | /// This first paragraph is missing punctuation | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:143:34 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:143:34 | LL | /// And it has multiple sentences | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:146:37 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:146:37 | LL | /// Same for this third and last one | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:153:33 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:153:33 | LL | /// This ends with a code `span` | ^ help: end the doc comment with some punctuation: `.` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation.rs:162:27 + --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:162:27 | LL | * Block doc comments work | ^ help: end the doc comment with some punctuation: `.` diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.rs b/tests/ui/doc/doc_paragraphs_missing_punctuation_unfixable.rs similarity index 60% rename from tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.rs rename to tests/ui/doc/doc_paragraphs_missing_punctuation_unfixable.rs index 1c52441eb656..3873f1d1edcf 100644 --- a/tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.rs +++ b/tests/ui/doc/doc_paragraphs_missing_punctuation_unfixable.rs @@ -1,13 +1,13 @@ #![feature(custom_inner_attributes)] #![rustfmt::skip] -#![warn(clippy::doc_comments_missing_terminal_punctuation)] +#![warn(clippy::doc_paragraphs_missing_punctuation)] //@no-rustfix enum UnfixableTrailers { /// Sometimes the doc comment ends with parentheses (like this) - //~^ doc_comments_missing_terminal_punctuation + //~^ doc_paragraphs_missing_punctuation EndsWithParens, /// This comment ends with "a quote" - //~^ doc_comments_missing_terminal_punctuation + //~^ doc_paragraphs_missing_punctuation QuoteFailing, } diff --git a/tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.stderr b/tests/ui/doc/doc_paragraphs_missing_punctuation_unfixable.stderr similarity index 60% rename from tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.stderr rename to tests/ui/doc/doc_paragraphs_missing_punctuation_unfixable.stderr index 72e10b0bff9f..72cce4b82594 100644 --- a/tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.stderr +++ b/tests/ui/doc/doc_paragraphs_missing_punctuation_unfixable.stderr @@ -1,15 +1,15 @@ error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.rs:7:68 + --> tests/ui/doc/doc_paragraphs_missing_punctuation_unfixable.rs:7:68 | LL | /// Sometimes the doc comment ends with parentheses (like this) | ^ | = help: end the doc comment with some punctuation - = note: `-D clippy::doc-comments-missing-terminal-punctuation` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::doc_comments_missing_terminal_punctuation)]` + = note: `-D clippy::doc-paragraphs-missing-punctuation` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::doc_paragraphs_missing_punctuation)]` error: doc comments should end with a terminal punctuation mark - --> tests/ui/doc/doc_comments_missing_terminal_punctuation_unfixable.rs:10:41 + --> tests/ui/doc/doc_paragraphs_missing_punctuation_unfixable.rs:10:41 | LL | /// This comment ends with "a quote" | ^ From 2f9342e8ff97499b4035c19b58d4e6764076aa00 Mon Sep 17 00:00:00 2001 From: AudaciousAxiom <179637270+AudaciousAxiom@users.noreply.github.com> Date: Sun, 19 Oct 2025 17:08:33 +0200 Subject: [PATCH 12/12] doc_paragraphs_missing_punctuation: update the lint message --- .../doc/doc_paragraphs_missing_punctuation.rs | 2 +- .../doc_paragraphs_missing_punctuation.stderr | 36 +++++++++---------- ...raphs_missing_punctuation_unfixable.stderr | 4 +-- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/clippy_lints/src/doc/doc_paragraphs_missing_punctuation.rs b/clippy_lints/src/doc/doc_paragraphs_missing_punctuation.rs index 7e8acadbd6fa..a5d641621103 100644 --- a/clippy_lints/src/doc/doc_paragraphs_missing_punctuation.rs +++ b/clippy_lints/src/doc/doc_paragraphs_missing_punctuation.rs @@ -6,7 +6,7 @@ use rustc_resolve::rustdoc::pulldown_cmark::{Event, Options, Parser, Tag, TagEnd use super::{DOC_PARAGRAPHS_MISSING_PUNCTUATION, Fragments}; -const MSG: &str = "doc comments should end with a terminal punctuation mark"; +const MSG: &str = "doc paragraphs should end with a terminal punctuation mark"; const PUNCTUATION_SUGGESTION: char = '.'; pub fn check(cx: &LateContext<'_>, doc: &str, fragments: Fragments<'_>) { diff --git a/tests/ui/doc/doc_paragraphs_missing_punctuation.stderr b/tests/ui/doc/doc_paragraphs_missing_punctuation.stderr index 75c5edb06f99..81805eeecfda 100644 --- a/tests/ui/doc/doc_paragraphs_missing_punctuation.stderr +++ b/tests/ui/doc/doc_paragraphs_missing_punctuation.stderr @@ -1,4 +1,4 @@ -error: doc comments should end with a terminal punctuation mark +error: doc paragraphs should end with a terminal punctuation mark --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:5:86 | LL | /// Returns the Answer to the Ultimate Question of Life, the Universe, and Everything @@ -7,103 +7,103 @@ LL | /// Returns the Answer to the Ultimate Question of Life, the Universe, and = note: `-D clippy::doc-paragraphs-missing-punctuation` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::doc_paragraphs_missing_punctuation)]` -error: doc comments should end with a terminal punctuation mark +error: doc paragraphs should end with a terminal punctuation mark --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:11:22 | LL | /// The `Option` type | ^ help: end the doc comment with some punctuation: `.` -error: doc comments should end with a terminal punctuation mark +error: doc paragraphs should end with a terminal punctuation mark --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:16:17 | LL | /// No value | ^ help: end the doc comment with some punctuation: `.` -error: doc comments should end with a terminal punctuation mark +error: doc paragraphs should end with a terminal punctuation mark --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:27:41 | LL | /// only the last line triggers the lint | ^ help: end the doc comment with some punctuation: `.` -error: doc comments should end with a terminal punctuation mark +error: doc paragraphs should end with a terminal punctuation mark --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:40:56 | LL | /// | ^ help: end the doc comment with some punctuation: `.` -error: doc comments should end with a terminal punctuation mark +error: doc paragraphs should end with a terminal punctuation mark --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:49:26 | LL | /// Here is a snippet | ^ help: end the doc comment with some punctuation: `.` -error: doc comments should end with a terminal punctuation mark +error: doc paragraphs should end with a terminal punctuation mark --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:72:15 | LL | /// U+0001 | ^ help: end the doc comment with some punctuation: `.` -error: doc comments should end with a terminal punctuation mark +error: doc paragraphs should end with a terminal punctuation mark --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:79:29 | LL | //! inner attributes too | ^ help: end the doc comment with some punctuation: `.` -error: doc comments should end with a terminal punctuation mark +error: doc paragraphs should end with a terminal punctuation mark --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:90:47 | LL | /// **But sometimes it is missing a period** | ^ help: end the doc comment with some punctuation: `.` -error: doc comments should end with a terminal punctuation mark +error: doc paragraphs should end with a terminal punctuation mark --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:95:46 | LL | /// _But sometimes it is missing a period_ | ^ help: end the doc comment with some punctuation: `.` -error: doc comments should end with a terminal punctuation mark +error: doc paragraphs should end with a terminal punctuation mark --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:104:56 | LL | /// Doc comments can end with an [inline link](#anchor) | ^ help: end the doc comment with some punctuation: `.` -error: doc comments should end with a terminal punctuation mark +error: doc paragraphs should end with a terminal punctuation mark --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:108:65 | LL | /// Some doc comments contain [link reference definitions][spec] | ^ help: end the doc comment with some punctuation: `.` -error: doc comments should end with a terminal punctuation mark +error: doc paragraphs should end with a terminal punctuation mark --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:133:57 | LL | /// Doc comments with trailing blank lines are supported | ^ help: end the doc comment with some punctuation: `.` -error: doc comments should end with a terminal punctuation mark +error: doc paragraphs should end with a terminal punctuation mark --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:139:48 | LL | /// This first paragraph is missing punctuation | ^ help: end the doc comment with some punctuation: `.` -error: doc comments should end with a terminal punctuation mark +error: doc paragraphs should end with a terminal punctuation mark --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:143:34 | LL | /// And it has multiple sentences | ^ help: end the doc comment with some punctuation: `.` -error: doc comments should end with a terminal punctuation mark +error: doc paragraphs should end with a terminal punctuation mark --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:146:37 | LL | /// Same for this third and last one | ^ help: end the doc comment with some punctuation: `.` -error: doc comments should end with a terminal punctuation mark +error: doc paragraphs should end with a terminal punctuation mark --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:153:33 | LL | /// This ends with a code `span` | ^ help: end the doc comment with some punctuation: `.` -error: doc comments should end with a terminal punctuation mark +error: doc paragraphs should end with a terminal punctuation mark --> tests/ui/doc/doc_paragraphs_missing_punctuation.rs:162:27 | LL | * Block doc comments work diff --git a/tests/ui/doc/doc_paragraphs_missing_punctuation_unfixable.stderr b/tests/ui/doc/doc_paragraphs_missing_punctuation_unfixable.stderr index 72cce4b82594..10f41ddc83b1 100644 --- a/tests/ui/doc/doc_paragraphs_missing_punctuation_unfixable.stderr +++ b/tests/ui/doc/doc_paragraphs_missing_punctuation_unfixable.stderr @@ -1,4 +1,4 @@ -error: doc comments should end with a terminal punctuation mark +error: doc paragraphs should end with a terminal punctuation mark --> tests/ui/doc/doc_paragraphs_missing_punctuation_unfixable.rs:7:68 | LL | /// Sometimes the doc comment ends with parentheses (like this) @@ -8,7 +8,7 @@ LL | /// Sometimes the doc comment ends with parentheses (like this) = note: `-D clippy::doc-paragraphs-missing-punctuation` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::doc_paragraphs_missing_punctuation)]` -error: doc comments should end with a terminal punctuation mark +error: doc paragraphs should end with a terminal punctuation mark --> tests/ui/doc/doc_paragraphs_missing_punctuation_unfixable.rs:10:41 | LL | /// This comment ends with "a quote"