Skip to content

Commit 167f249

Browse files
committed
Auto merge of #10760 - NanthR:almost_standard_formulation, r=xFrednet
Standard lint formulations A WIP that fixes #10660. Fix lints that don't conform to the standard formulation. changelog: none
2 parents fdb0b04 + 50c93bb commit 167f249

File tree

11 files changed

+174
-7
lines changed

11 files changed

+174
-7
lines changed

clippy_lints/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ serde = { version = "1.0", features = ["derive"] }
2222
serde_json = { version = "1.0", optional = true }
2323
tempfile = { version = "3.3.0", optional = true }
2424
toml = "0.7.3"
25+
regex = { version = "1.5", optional = true }
2526
unicode-normalization = "0.1"
2627
unicode-script = { version = "0.5", default-features = false }
2728
semver = "1.0"
@@ -31,7 +32,7 @@ url = "2.2"
3132
[features]
3233
deny-warnings = ["clippy_utils/deny-warnings"]
3334
# build clippy with internal lints enabled, off by default
34-
internal = ["clippy_utils/internal", "serde_json", "tempfile"]
35+
internal = ["clippy_utils/internal", "serde_json", "tempfile", "regex"]
3536

3637
[package.metadata.rust-analyzer]
3738
# This crate uses #[feature(rustc_private)]

clippy_lints/src/casts/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,7 @@ declare_clippy_lint! {
522522

523523
declare_clippy_lint! {
524524
/// ### What it does
525-
/// Check for the usage of `as _` conversion using inferred type.
525+
/// Checks for the usage of `as _` conversion using inferred type.
526526
///
527527
/// ### Why is this bad?
528528
/// The conversion might include lossy conversion and dangerous cast that might go

clippy_lints/src/declared_lints.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
// Manual edits will be overwritten.
44

55
pub(crate) static LINTS: &[&crate::LintInfo] = &[
6+
#[cfg(feature = "internal")]
7+
crate::utils::internal_lints::almost_standard_lint_formulation::ALMOST_STANDARD_LINT_FORMULATION_INFO,
68
#[cfg(feature = "internal")]
79
crate::utils::internal_lints::clippy_lints_internal::CLIPPY_LINTS_INTERNAL_INFO,
810
#[cfg(feature = "internal")]

clippy_lints/src/default_constructed_unit_structs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_session::{declare_lint_pass, declare_tool_lint};
88

99
declare_clippy_lint! {
1010
/// ### What it does
11-
/// Check for construction on unit struct using `default`.
11+
/// Checks for construction on unit struct using `default`.
1212
///
1313
/// ### Why is this bad?
1414
/// This adds code complexity and an unnecessary function call.

clippy_lints/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,9 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
564564
store.register_late_pass(|_| Box::<utils::internal_lints::unnecessary_def_path::UnnecessaryDefPath>::default());
565565
store.register_late_pass(|_| Box::new(utils::internal_lints::outer_expn_data_pass::OuterExpnDataPass));
566566
store.register_late_pass(|_| Box::new(utils::internal_lints::msrv_attr_impl::MsrvAttrImpl));
567+
store.register_late_pass(|_| {
568+
Box::new(utils::internal_lints::almost_standard_lint_formulation::AlmostStandardFormulation::new())
569+
});
567570
}
568571

569572
let arithmetic_side_effects_allowed = conf.arithmetic_side_effects_allowed.clone();

clippy_lints/src/loops/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,7 @@ declare_clippy_lint! {
479479

480480
declare_clippy_lint! {
481481
/// ### What it does
482-
/// Check for unnecessary `if let` usage in a for loop
482+
/// Checks for unnecessary `if let` usage in a for loop
483483
/// where only the `Some` or `Ok` variant of the iterator element is used.
484484
///
485485
/// ### Why is this bad?
@@ -511,7 +511,7 @@ declare_clippy_lint! {
511511

512512
declare_clippy_lint! {
513513
/// ### What it does
514-
/// Check for empty spin loops
514+
/// Checks for empty spin loops
515515
///
516516
/// ### Why is this bad?
517517
/// The loop body should have something like `thread::park()` or at least
@@ -547,7 +547,7 @@ declare_clippy_lint! {
547547

548548
declare_clippy_lint! {
549549
/// ### What it does
550-
/// Check for manual implementations of Iterator::find
550+
/// Checks for manual implementations of Iterator::find
551551
///
552552
/// ### Why is this bad?
553553
/// It doesn't affect performance, but using `find` is shorter and easier to read.

clippy_lints/src/matches/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -777,7 +777,7 @@ declare_clippy_lint! {
777777

778778
declare_clippy_lint! {
779779
/// ### What it does
780-
/// Check for temporaries returned from function calls in a match scrutinee that have the
780+
/// Checks for temporaries returned from function calls in a match scrutinee that have the
781781
/// `clippy::has_significant_drop` attribute.
782782
///
783783
/// ### Why is this bad?

clippy_lints/src/utils/internal_lints.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
pub mod almost_standard_lint_formulation;
12
pub mod clippy_lints_internal;
23
pub mod collapsible_calls;
34
pub mod compiler_lint_functions;
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
use crate::utils::internal_lints::lint_without_lint_pass::is_lint_ref_type;
2+
use clippy_utils::diagnostics::span_lint_and_help;
3+
use regex::Regex;
4+
use rustc_ast as ast;
5+
use rustc_hir::{Item, ItemKind, Mutability};
6+
use rustc_lint::{LateContext, LateLintPass};
7+
use rustc_session::{declare_tool_lint, impl_lint_pass};
8+
9+
declare_clippy_lint! {
10+
/// ### What it does
11+
/// Checks if lint formulations have a standardized format.
12+
///
13+
/// ### Why is this bad?
14+
/// It's not neccessarily bad, but we try to enforce a standard in Clippy.
15+
///
16+
/// ### Example
17+
/// `Checks for use...` can be written as `Checks for usage...` .
18+
pub ALMOST_STANDARD_LINT_FORMULATION,
19+
internal,
20+
"lint formulations must have a standardized format."
21+
}
22+
23+
impl_lint_pass!(AlmostStandardFormulation => [ALMOST_STANDARD_LINT_FORMULATION]);
24+
25+
pub struct AlmostStandardFormulation {
26+
standard_formulations: Vec<StandardFormulations<'static>>,
27+
}
28+
29+
#[derive(Debug)]
30+
struct StandardFormulations<'a> {
31+
wrong_pattern: Regex,
32+
correction: &'a str,
33+
}
34+
35+
impl AlmostStandardFormulation {
36+
pub fn new() -> Self {
37+
let standard_formulations = vec![StandardFormulations {
38+
wrong_pattern: Regex::new(r"^(Check for|Detects? uses?)").unwrap(),
39+
correction: "Checks for",
40+
}];
41+
Self { standard_formulations }
42+
}
43+
}
44+
45+
impl<'tcx> LateLintPass<'tcx> for AlmostStandardFormulation {
46+
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
47+
let mut check_next = false;
48+
if let ItemKind::Static(ty, Mutability::Not, _) = item.kind {
49+
let lines = cx
50+
.tcx
51+
.hir()
52+
.attrs(item.hir_id())
53+
.iter()
54+
.filter_map(|attr| ast::Attribute::doc_str(attr).map(|sym| (sym, attr)));
55+
if is_lint_ref_type(cx, ty) {
56+
for (line, attr) in lines {
57+
let cur_line = line.as_str().trim();
58+
if check_next && !cur_line.is_empty() {
59+
for formulation in &self.standard_formulations {
60+
let starts_with_correct_formulation = cur_line.starts_with(formulation.correction);
61+
if !starts_with_correct_formulation && formulation.wrong_pattern.is_match(cur_line) {
62+
if let Some(ident) = attr.ident() {
63+
span_lint_and_help(
64+
cx,
65+
ALMOST_STANDARD_LINT_FORMULATION,
66+
ident.span,
67+
"non-standard lint formulation",
68+
None,
69+
&format!("try using `{}` instead", formulation.correction),
70+
);
71+
}
72+
return;
73+
}
74+
}
75+
return;
76+
} else if cur_line.contains("What it does") {
77+
check_next = true;
78+
} else if cur_line.contains("Why is this bad") {
79+
// Formulation documentation is done. Can add check to ensure that missing formulation is added
80+
// and add a check if it matches no accepted formulation
81+
return;
82+
}
83+
}
84+
}
85+
}
86+
}
87+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#![warn(clippy::almost_standard_lint_formulation)]
2+
#![feature(rustc_private)]
3+
4+
#[macro_use]
5+
extern crate rustc_middle;
6+
#[macro_use]
7+
extern crate rustc_session;
8+
extern crate rustc_lint;
9+
10+
declare_tool_lint! {
11+
/// # What it does
12+
///
13+
/// Checks for usage of correct lint formulations
14+
#[clippy::version = "pre 1.29.0"]
15+
pub clippy::VALID,
16+
Warn,
17+
"One",
18+
report_in_external_macro: true
19+
}
20+
21+
declare_tool_lint! {
22+
/// # What it does
23+
/// Check for lint formulations that are correct
24+
#[clippy::version = "pre 1.29.0"]
25+
pub clippy::INVALID1,
26+
Warn,
27+
"One",
28+
report_in_external_macro: true
29+
}
30+
31+
declare_tool_lint! {
32+
/// # What it does
33+
/// Detects uses of incorrect formulations
34+
#[clippy::version = "pre 1.29.0"]
35+
pub clippy::INVALID2,
36+
Warn,
37+
"One",
38+
report_in_external_macro: true
39+
}
40+
41+
declare_tool_lint! {
42+
/// # What it does
43+
/// Detects uses of incorrect formulations (allowed with attribute)
44+
#[allow(clippy::almost_standard_lint_formulation)]
45+
#[clippy::version = "pre 1.29.0"]
46+
pub clippy::ALLOWED_INVALID,
47+
Warn,
48+
"One",
49+
report_in_external_macro: true
50+
}
51+
52+
declare_lint_pass!(Pass => [VALID, INVALID1, INVALID2]);
53+
54+
fn main() {}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error: non-standard lint formulation
2+
--> $DIR/check_formulation.rs:23:5
3+
|
4+
LL | /// Check for lint formulations that are correct
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= help: try using `Checks for` instead
8+
= note: `-D clippy::almost-standard-lint-formulation` implied by `-D warnings`
9+
10+
error: non-standard lint formulation
11+
--> $DIR/check_formulation.rs:33:5
12+
|
13+
LL | /// Detects uses of incorrect formulations
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
15+
|
16+
= help: try using `Checks for` instead
17+
18+
error: aborting due to 2 previous errors
19+

0 commit comments

Comments
 (0)