Skip to content

Commit a4b2864

Browse files
committed
Auto merge of #11798 - y21:move_sus_doc_comments, r=flip1995
move `suspicious_doc_comments` to doc pass This was my first lint. I've been meaning to move it over to `doc.rs` since that's a better place. There weren't any changes made to the lint logic itself. I guess this can be considered part of #11493 changelog: none
2 parents 07bc130 + d89890d commit a4b2864

File tree

4 files changed

+90
-95
lines changed

4 files changed

+90
-95
lines changed

clippy_lints/src/declared_lints.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
139139
crate::doc::MISSING_PANICS_DOC_INFO,
140140
crate::doc::MISSING_SAFETY_DOC_INFO,
141141
crate::doc::NEEDLESS_DOCTEST_MAIN_INFO,
142+
crate::doc::SUSPICIOUS_DOC_COMMENTS_INFO,
142143
crate::doc::UNNECESSARY_SAFETY_DOC_INFO,
143144
crate::double_parens::DOUBLE_PARENS_INFO,
144145
crate::drop_forget_ref::DROP_NON_DROP_INFO,
@@ -626,7 +627,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
626627
crate::strings::STR_TO_STRING_INFO,
627628
crate::strings::TRIM_SPLIT_WHITESPACE_INFO,
628629
crate::strlen_on_c_strings::STRLEN_ON_C_STRINGS_INFO,
629-
crate::suspicious_doc_comments::SUSPICIOUS_DOC_COMMENTS_INFO,
630630
crate::suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS_INFO,
631631
crate::suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL_INFO,
632632
crate::suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL_INFO,

clippy_lints/src/doc.rs

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ use pulldown_cmark::Event::{
1010
use pulldown_cmark::Tag::{CodeBlock, Heading, Item, Link, Paragraph};
1111
use pulldown_cmark::{BrokenLink, CodeBlockKind, CowStr, Options};
1212
use rustc_ast::ast::{Async, Attribute, Fn, FnRetTy, ItemKind};
13+
use rustc_ast::token::CommentKind;
14+
use rustc_ast::{AttrKind, AttrStyle};
1315
use rustc_data_structures::fx::FxHashSet;
1416
use rustc_data_structures::sync::Lrc;
1517
use rustc_errors::emitter::EmitterWriter;
@@ -260,6 +262,53 @@ declare_clippy_lint! {
260262
"`pub fn` or `pub trait` with `# Safety` docs"
261263
}
262264

265+
declare_clippy_lint! {
266+
/// ### What it does
267+
/// Detects the use of outer doc comments (`///`, `/**`) followed by a bang (`!`): `///!`
268+
///
269+
/// ### Why is this bad?
270+
/// Triple-slash comments (known as "outer doc comments") apply to items that follow it.
271+
/// An outer doc comment followed by a bang (i.e. `///!`) has no specific meaning.
272+
///
273+
/// The user most likely meant to write an inner doc comment (`//!`, `/*!`), which
274+
/// applies to the parent item (i.e. the item that the comment is contained in,
275+
/// usually a module or crate).
276+
///
277+
/// ### Known problems
278+
/// Inner doc comments can only appear before items, so there are certain cases where the suggestion
279+
/// made by this lint is not valid code. For example:
280+
/// ```rs
281+
/// fn foo() {}
282+
/// ///!
283+
/// fn bar() {}
284+
/// ```
285+
/// This lint detects the doc comment and suggests changing it to `//!`, but an inner doc comment
286+
/// is not valid at that position.
287+
///
288+
/// ### Example
289+
/// In this example, the doc comment is attached to the *function*, rather than the *module*.
290+
/// ```no_run
291+
/// pub mod util {
292+
/// ///! This module contains utility functions.
293+
///
294+
/// pub fn dummy() {}
295+
/// }
296+
/// ```
297+
///
298+
/// Use instead:
299+
/// ```no_run
300+
/// pub mod util {
301+
/// //! This module contains utility functions.
302+
///
303+
/// pub fn dummy() {}
304+
/// }
305+
/// ```
306+
#[clippy::version = "1.70.0"]
307+
pub SUSPICIOUS_DOC_COMMENTS,
308+
suspicious,
309+
"suspicious usage of (outer) doc comments"
310+
}
311+
263312
#[expect(clippy::module_name_repetitions)]
264313
#[derive(Clone)]
265314
pub struct DocMarkdown {
@@ -284,6 +333,7 @@ impl_lint_pass!(DocMarkdown => [
284333
MISSING_PANICS_DOC,
285334
NEEDLESS_DOCTEST_MAIN,
286335
UNNECESSARY_SAFETY_DOC,
336+
SUSPICIOUS_DOC_COMMENTS
287337
]);
288338

289339
impl<'tcx> LateLintPass<'tcx> for DocMarkdown {
@@ -478,6 +528,8 @@ fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs: &[
478528
return None;
479529
}
480530

531+
check_almost_inner_doc(cx, attrs);
532+
481533
let (fragments, _) = attrs_to_doc_fragments(attrs.iter().map(|attr| (attr, None)), true);
482534
let mut doc = String::new();
483535
for fragment in &fragments {
@@ -506,6 +558,43 @@ fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs: &[
506558
))
507559
}
508560

561+
/// Looks for `///!` and `/**!` comments, which were probably meant to be `//!` and `/*!`
562+
fn check_almost_inner_doc(cx: &LateContext<'_>, attrs: &[Attribute]) {
563+
let replacements: Vec<_> = attrs
564+
.iter()
565+
.filter_map(|attr| {
566+
if let AttrKind::DocComment(com_kind, sym) = attr.kind
567+
&& let AttrStyle::Outer = attr.style
568+
&& let Some(com) = sym.as_str().strip_prefix('!')
569+
{
570+
let sugg = match com_kind {
571+
CommentKind::Line => format!("//!{com}"),
572+
CommentKind::Block => format!("/*!{com}*/"),
573+
};
574+
Some((attr.span, sugg))
575+
} else {
576+
None
577+
}
578+
})
579+
.collect();
580+
581+
if let Some((&(lo_span, _), &(hi_span, _))) = replacements.first().zip(replacements.last()) {
582+
span_lint_and_then(
583+
cx,
584+
SUSPICIOUS_DOC_COMMENTS,
585+
lo_span.to(hi_span),
586+
"this is an outer doc comment and does not apply to the parent module or crate",
587+
|diag| {
588+
diag.multipart_suggestion(
589+
"use an inner doc comment to document the parent module or crate",
590+
replacements,
591+
Applicability::MaybeIncorrect,
592+
);
593+
},
594+
);
595+
}
596+
}
597+
509598
const RUST_CODE: &[&str] = &["rust", "no_run", "should_panic", "compile_fail"];
510599

511600
#[allow(clippy::too_many_lines)] // Only a big match statement

clippy_lints/src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,6 @@ mod slow_vector_initialization;
307307
mod std_instead_of_core;
308308
mod strings;
309309
mod strlen_on_c_strings;
310-
mod suspicious_doc_comments;
311310
mod suspicious_operation_groupings;
312311
mod suspicious_trait_impl;
313312
mod suspicious_xor_used_as_pow;
@@ -1000,7 +999,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
1000999
store.register_late_pass(|_| Box::new(lines_filter_map_ok::LinesFilterMapOk));
10011000
store.register_late_pass(|_| Box::new(tests_outside_test_module::TestsOutsideTestModule));
10021001
store.register_late_pass(|_| Box::new(manual_slice_size_calculation::ManualSliceSizeCalculation));
1003-
store.register_early_pass(|| Box::new(suspicious_doc_comments::SuspiciousDocComments));
10041002
store.register_early_pass(move || {
10051003
Box::new(excessive_nesting::ExcessiveNesting {
10061004
excessive_nesting_threshold,

clippy_lints/src/suspicious_doc_comments.rs

Lines changed: 0 additions & 92 deletions
This file was deleted.

0 commit comments

Comments
 (0)