summaryrefslogtreecommitdiffstats
path: root/src/tools/clippy/clippy_lints/src/doc/suspicious_doc_comments.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/clippy/clippy_lints/src/doc/suspicious_doc_comments.rs')
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/suspicious_doc_comments.rs48
1 files changed, 48 insertions, 0 deletions
diff --git a/src/tools/clippy/clippy_lints/src/doc/suspicious_doc_comments.rs b/src/tools/clippy/clippy_lints/src/doc/suspicious_doc_comments.rs
new file mode 100644
index 000000000..d7ad30efe
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/doc/suspicious_doc_comments.rs
@@ -0,0 +1,48 @@
+use clippy_utils::diagnostics::span_lint_and_then;
+use rustc_ast::token::CommentKind;
+use rustc_ast::{AttrKind, AttrStyle, Attribute};
+use rustc_errors::Applicability;
+use rustc_lint::LateContext;
+use rustc_span::Span;
+
+use super::SUSPICIOUS_DOC_COMMENTS;
+
+pub fn check(cx: &LateContext<'_>, attrs: &[Attribute]) {
+ let replacements: Vec<_> = collect_doc_replacements(attrs);
+
+ if let Some((&(lo_span, _), &(hi_span, _))) = replacements.first().zip(replacements.last()) {
+ span_lint_and_then(
+ cx,
+ SUSPICIOUS_DOC_COMMENTS,
+ lo_span.to(hi_span),
+ "this is an outer doc comment and does not apply to the parent module or crate",
+ |diag| {
+ diag.multipart_suggestion(
+ "use an inner doc comment to document the parent module or crate",
+ replacements,
+ Applicability::MaybeIncorrect,
+ );
+ },
+ );
+ }
+}
+
+fn collect_doc_replacements(attrs: &[Attribute]) -> Vec<(Span, String)> {
+ attrs
+ .iter()
+ .filter_map(|attr| {
+ if let AttrKind::DocComment(com_kind, sym) = attr.kind
+ && let AttrStyle::Outer = attr.style
+ && let Some(com) = sym.as_str().strip_prefix('!')
+ {
+ let sugg = match com_kind {
+ CommentKind::Line => format!("//!{com}"),
+ CommentKind::Block => format!("/*!{com}*/"),
+ };
+ Some((attr.span, sugg))
+ } else {
+ None
+ }
+ })
+ .collect()
+}