Auto merge of #11140 - Centri3:four_forward_slashes, r=blyxyas
New lint [`four_forward_slashes`] Closes #9212 changelog: New lint [`four_forward_slashes`]
This commit is contained in:
commit
9f0cbfd7df
@ -4868,6 +4868,7 @@ Released 2018-09-13
|
||||
[`format_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#format_collect
|
||||
[`format_in_format_args`]: https://rust-lang.github.io/rust-clippy/master/index.html#format_in_format_args
|
||||
[`format_push_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#format_push_string
|
||||
[`four_forward_slashes`]: https://rust-lang.github.io/rust-clippy/master/index.html#four_forward_slashes
|
||||
[`from_iter_instead_of_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#from_iter_instead_of_collect
|
||||
[`from_over_into`]: https://rust-lang.github.io/rust-clippy/master/index.html#from_over_into
|
||||
[`from_raw_with_void_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#from_raw_with_void_ptr
|
||||
|
@ -183,6 +183,7 @@
|
||||
crate::formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING_INFO,
|
||||
crate::formatting::SUSPICIOUS_ELSE_FORMATTING_INFO,
|
||||
crate::formatting::SUSPICIOUS_UNARY_OP_FORMATTING_INFO,
|
||||
crate::four_forward_slashes::FOUR_FORWARD_SLASHES_INFO,
|
||||
crate::from_over_into::FROM_OVER_INTO_INFO,
|
||||
crate::from_raw_with_void_ptr::FROM_RAW_WITH_VOID_PTR_INFO,
|
||||
crate::from_str_radix_10::FROM_STR_RADIX_10_INFO,
|
||||
|
99
clippy_lints/src/four_forward_slashes.rs
Normal file
99
clippy_lints/src/four_forward_slashes.rs
Normal file
@ -0,0 +1,99 @@
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::Item;
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::Span;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Checks for outer doc comments written with 4 forward slashes (`////`).
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// This is (probably) a typo, and results in it not being a doc comment; just a regular
|
||||
/// comment.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```rust
|
||||
/// //// My amazing data structure
|
||||
/// pub struct Foo {
|
||||
/// // ...
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```rust
|
||||
/// /// My amazing data structure
|
||||
/// pub struct Foo {
|
||||
/// // ...
|
||||
/// }
|
||||
/// ```
|
||||
#[clippy::version = "1.72.0"]
|
||||
pub FOUR_FORWARD_SLASHES,
|
||||
suspicious,
|
||||
"comments with 4 forward slashes (`////`) likely intended to be doc comments (`///`)"
|
||||
}
|
||||
declare_lint_pass!(FourForwardSlashes => [FOUR_FORWARD_SLASHES]);
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for FourForwardSlashes {
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
||||
if item.span.from_expansion() {
|
||||
return;
|
||||
}
|
||||
let sm = cx.sess().source_map();
|
||||
let mut span = cx
|
||||
.tcx
|
||||
.hir()
|
||||
.attrs(item.hir_id())
|
||||
.iter()
|
||||
.fold(item.span.shrink_to_lo(), |span, attr| span.to(attr.span));
|
||||
let (Some(file), _, _, end_line, _) = sm.span_to_location_info(span) else {
|
||||
return;
|
||||
};
|
||||
let mut bad_comments = vec![];
|
||||
for line in (0..end_line.saturating_sub(1)).rev() {
|
||||
let Some(contents) = file.get_line(line).map(|c| c.trim().to_owned()) else {
|
||||
return;
|
||||
};
|
||||
// Keep searching until we find the next item
|
||||
if !contents.is_empty() && !contents.starts_with("//") && !contents.starts_with("#[") {
|
||||
break;
|
||||
}
|
||||
|
||||
if contents.starts_with("////") && !matches!(contents.chars().nth(4), Some('/' | '!')) {
|
||||
let bounds = file.line_bounds(line);
|
||||
let line_span = Span::with_root_ctxt(bounds.start, bounds.end);
|
||||
span = line_span.to(span);
|
||||
bad_comments.push((line_span, contents));
|
||||
}
|
||||
}
|
||||
|
||||
if !bad_comments.is_empty() {
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
FOUR_FORWARD_SLASHES,
|
||||
span,
|
||||
"this item has comments with 4 forward slashes (`////`). These look like doc comments, but they aren't",
|
||||
|diag| {
|
||||
let msg = if bad_comments.len() == 1 {
|
||||
"make this a doc comment by removing one `/`"
|
||||
} else {
|
||||
"turn these into doc comments by removing one `/`"
|
||||
};
|
||||
|
||||
diag.multipart_suggestion(
|
||||
msg,
|
||||
bad_comments
|
||||
.into_iter()
|
||||
// It's a little unfortunate but the span includes the `\n` yet the contents
|
||||
// do not, so we must add it back. If some codebase uses `\r\n` instead they
|
||||
// will need normalization but it should be fine
|
||||
.map(|(span, c)| (span, c.replacen("////", "///", 1) + "\n"))
|
||||
.collect(),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -136,6 +136,7 @@
|
||||
mod format_impl;
|
||||
mod format_push_string;
|
||||
mod formatting;
|
||||
mod four_forward_slashes;
|
||||
mod from_over_into;
|
||||
mod from_raw_with_void_ptr;
|
||||
mod from_str_radix_10;
|
||||
@ -1078,6 +1079,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
||||
store.register_early_pass(|| Box::new(visibility::Visibility));
|
||||
store.register_late_pass(move |_| Box::new(tuple_array_conversions::TupleArrayConversions { msrv: msrv() }));
|
||||
store.register_late_pass(|_| Box::new(manual_float_methods::ManualFloatMethods));
|
||||
store.register_late_pass(|_| Box::new(four_forward_slashes::FourForwardSlashes));
|
||||
// add lints here, do not remove this comment, it's used in `new_lint`
|
||||
}
|
||||
|
||||
|
48
tests/ui/four_forward_slashes.fixed
Normal file
48
tests/ui/four_forward_slashes.fixed
Normal file
@ -0,0 +1,48 @@
|
||||
//@run-rustfix
|
||||
//@aux-build:proc_macros.rs:proc-macro
|
||||
#![feature(custom_inner_attributes)]
|
||||
#![allow(unused)]
|
||||
#![warn(clippy::four_forward_slashes)]
|
||||
#![no_main]
|
||||
#![rustfmt::skip]
|
||||
|
||||
#[macro_use]
|
||||
extern crate proc_macros;
|
||||
|
||||
/// whoops
|
||||
fn a() {}
|
||||
|
||||
/// whoops
|
||||
#[allow(dead_code)]
|
||||
fn b() {}
|
||||
|
||||
/// whoops
|
||||
/// two borked comments!
|
||||
#[track_caller]
|
||||
fn c() {}
|
||||
|
||||
fn d() {}
|
||||
|
||||
#[test]
|
||||
/// between attributes
|
||||
#[allow(dead_code)]
|
||||
fn g() {}
|
||||
|
||||
/// not very start of contents
|
||||
fn h() {}
|
||||
|
||||
fn i() {
|
||||
//// don't lint me bozo
|
||||
todo!()
|
||||
}
|
||||
|
||||
external! {
|
||||
//// don't lint me bozo
|
||||
fn e() {}
|
||||
}
|
||||
|
||||
with_span! {
|
||||
span
|
||||
//// don't lint me bozo
|
||||
fn f() {}
|
||||
}
|
48
tests/ui/four_forward_slashes.rs
Normal file
48
tests/ui/four_forward_slashes.rs
Normal file
@ -0,0 +1,48 @@
|
||||
//@run-rustfix
|
||||
//@aux-build:proc_macros.rs:proc-macro
|
||||
#![feature(custom_inner_attributes)]
|
||||
#![allow(unused)]
|
||||
#![warn(clippy::four_forward_slashes)]
|
||||
#![no_main]
|
||||
#![rustfmt::skip]
|
||||
|
||||
#[macro_use]
|
||||
extern crate proc_macros;
|
||||
|
||||
//// whoops
|
||||
fn a() {}
|
||||
|
||||
//// whoops
|
||||
#[allow(dead_code)]
|
||||
fn b() {}
|
||||
|
||||
//// whoops
|
||||
//// two borked comments!
|
||||
#[track_caller]
|
||||
fn c() {}
|
||||
|
||||
fn d() {}
|
||||
|
||||
#[test]
|
||||
//// between attributes
|
||||
#[allow(dead_code)]
|
||||
fn g() {}
|
||||
|
||||
//// not very start of contents
|
||||
fn h() {}
|
||||
|
||||
fn i() {
|
||||
//// don't lint me bozo
|
||||
todo!()
|
||||
}
|
||||
|
||||
external! {
|
||||
//// don't lint me bozo
|
||||
fn e() {}
|
||||
}
|
||||
|
||||
with_span! {
|
||||
span
|
||||
//// don't lint me bozo
|
||||
fn f() {}
|
||||
}
|
68
tests/ui/four_forward_slashes.stderr
Normal file
68
tests/ui/four_forward_slashes.stderr
Normal file
@ -0,0 +1,68 @@
|
||||
error: this item has comments with 4 forward slashes (`////`). These look like doc comments, but they aren't
|
||||
--> $DIR/four_forward_slashes.rs:12:1
|
||||
|
|
||||
LL | / //// whoops
|
||||
LL | | fn a() {}
|
||||
| |_
|
||||
|
|
||||
= note: `-D clippy::four-forward-slashes` implied by `-D warnings`
|
||||
help: make this a doc comment by removing one `/`
|
||||
|
|
||||
LL + /// whoops
|
||||
|
|
||||
|
||||
error: this item has comments with 4 forward slashes (`////`). These look like doc comments, but they aren't
|
||||
--> $DIR/four_forward_slashes.rs:15:1
|
||||
|
|
||||
LL | / //// whoops
|
||||
LL | | #[allow(dead_code)]
|
||||
LL | | fn b() {}
|
||||
| |_
|
||||
|
|
||||
help: make this a doc comment by removing one `/`
|
||||
|
|
||||
LL + /// whoops
|
||||
|
|
||||
|
||||
error: this item has comments with 4 forward slashes (`////`). These look like doc comments, but they aren't
|
||||
--> $DIR/four_forward_slashes.rs:19:1
|
||||
|
|
||||
LL | / //// whoops
|
||||
LL | | //// two borked comments!
|
||||
LL | | #[track_caller]
|
||||
LL | | fn c() {}
|
||||
| |_
|
||||
|
|
||||
help: turn these into doc comments by removing one `/`
|
||||
|
|
||||
LL + /// whoops
|
||||
LL ~ /// two borked comments!
|
||||
|
|
||||
|
||||
error: this item has comments with 4 forward slashes (`////`). These look like doc comments, but they aren't
|
||||
--> $DIR/four_forward_slashes.rs:27:1
|
||||
|
|
||||
LL | / //// between attributes
|
||||
LL | | #[allow(dead_code)]
|
||||
LL | | fn g() {}
|
||||
| |_
|
||||
|
|
||||
help: make this a doc comment by removing one `/`
|
||||
|
|
||||
LL + /// between attributes
|
||||
|
|
||||
|
||||
error: this item has comments with 4 forward slashes (`////`). These look like doc comments, but they aren't
|
||||
--> $DIR/four_forward_slashes.rs:31:1
|
||||
|
|
||||
LL | / //// not very start of contents
|
||||
LL | | fn h() {}
|
||||
| |_
|
||||
|
|
||||
help: make this a doc comment by removing one `/`
|
||||
|
|
||||
LL + /// not very start of contents
|
||||
|
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
7
tests/ui/four_forward_slashes_first_line.fixed
Normal file
7
tests/ui/four_forward_slashes_first_line.fixed
Normal file
@ -0,0 +1,7 @@
|
||||
/// borked doc comment on the first line. doesn't combust!
|
||||
fn a() {}
|
||||
|
||||
//@run-rustfix
|
||||
// This test's entire purpose is to make sure we don't panic if the comment with four slashes
|
||||
// extends to the first line of the file. This is likely pretty rare in production, but an ICE is an
|
||||
// ICE.
|
7
tests/ui/four_forward_slashes_first_line.rs
Normal file
7
tests/ui/four_forward_slashes_first_line.rs
Normal file
@ -0,0 +1,7 @@
|
||||
//// borked doc comment on the first line. doesn't combust!
|
||||
fn a() {}
|
||||
|
||||
//@run-rustfix
|
||||
// This test's entire purpose is to make sure we don't panic if the comment with four slashes
|
||||
// extends to the first line of the file. This is likely pretty rare in production, but an ICE is an
|
||||
// ICE.
|
15
tests/ui/four_forward_slashes_first_line.stderr
Normal file
15
tests/ui/four_forward_slashes_first_line.stderr
Normal file
@ -0,0 +1,15 @@
|
||||
error: this item has comments with 4 forward slashes (`////`). These look like doc comments, but they aren't
|
||||
--> $DIR/four_forward_slashes_first_line.rs:1:1
|
||||
|
|
||||
LL | / //// borked doc comment on the first line. doesn't combust!
|
||||
LL | | fn a() {}
|
||||
| |_
|
||||
|
|
||||
= note: `-D clippy::four-forward-slashes` implied by `-D warnings`
|
||||
help: make this a doc comment by removing one `/`
|
||||
|
|
||||
LL + /// borked doc comment on the first line. doesn't combust!
|
||||
|
|
||||
|
||||
error: aborting due to previous error
|
||||
|
Loading…
Reference in New Issue
Block a user