forked from rust-lang/rust
-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Auto merge of rust-lang#11140 - Centri3:four_forward_slashes, r=blyxyas
New lint [`four_forward_slashes`] Closes rust-lang#9212 changelog: New lint [`four_forward_slashes`]
- Loading branch information
Showing
10 changed files
with
296 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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, | ||
); | ||
}, | ||
); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() {} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() {} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
|