49 lines
1.6 KiB
Rust
49 lines
1.6 KiB
Rust
|
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()
|
||
|
}
|