From 91a8611b4426c7da8c72317516626affb812d20b Mon Sep 17 00:00:00 2001 From: Takayuki Date: Tue, 4 May 2021 16:38:34 +0900 Subject: [PATCH 01/11] move misc_early to misc_early/mod.rs --- clippy_lints/src/{misc_early.rs => misc_early/mod.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename clippy_lints/src/{misc_early.rs => misc_early/mod.rs} (100%) diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early/mod.rs similarity index 100% rename from clippy_lints/src/misc_early.rs rename to clippy_lints/src/misc_early/mod.rs From 64eb18e6759f4375d01d7e3352447ff6b4305184 Mon Sep 17 00:00:00 2001 From: Takayuki Date: Tue, 4 May 2021 17:04:10 +0900 Subject: [PATCH 02/11] move builtin_type_shadow to its own module --- .../src/misc_early/builtin_type_shadow.rs | 19 +++++++++++++++++++ clippy_lints/src/misc_early/mod.rs | 18 +++++------------- ...-type-shadow.rs => builtin_type_shadow.rs} | 0 ...adow.stderr => builtin_type_shadow.stderr} | 4 ++-- 4 files changed, 26 insertions(+), 15 deletions(-) create mode 100644 clippy_lints/src/misc_early/builtin_type_shadow.rs rename tests/ui/{builtin-type-shadow.rs => builtin_type_shadow.rs} (100%) rename tests/ui/{builtin-type-shadow.stderr => builtin_type_shadow.stderr} (89%) diff --git a/clippy_lints/src/misc_early/builtin_type_shadow.rs b/clippy_lints/src/misc_early/builtin_type_shadow.rs new file mode 100644 index 00000000000..9f6b0bdc7a4 --- /dev/null +++ b/clippy_lints/src/misc_early/builtin_type_shadow.rs @@ -0,0 +1,19 @@ +use clippy_utils::diagnostics::span_lint; +use rustc_ast::ast::{GenericParam, GenericParamKind}; +use rustc_hir::PrimTy; +use rustc_lint::EarlyContext; + +use super::BUILTIN_TYPE_SHADOW; + +pub(super) fn check(cx: &EarlyContext<'_>, param: &GenericParam) { + if let GenericParamKind::Type { .. } = param.kind { + if let Some(prim_ty) = PrimTy::from_name(param.ident.name) { + span_lint( + cx, + BUILTIN_TYPE_SHADOW, + param.ident.span, + &format!("this generic shadows the built-in type `{}`", prim_ty.name()), + ); + } + } +} diff --git a/clippy_lints/src/misc_early/mod.rs b/clippy_lints/src/misc_early/mod.rs index 3c6a7071c24..94740093d3b 100644 --- a/clippy_lints/src/misc_early/mod.rs +++ b/clippy_lints/src/misc_early/mod.rs @@ -1,13 +1,14 @@ +mod builtin_type_shadow; + use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::snippet_opt; use rustc_ast::ast::{ - BindingMode, Expr, ExprKind, GenericParamKind, Generics, Lit, LitFloatType, LitIntType, LitKind, Mutability, - NodeId, Pat, PatKind, UnOp, + BindingMode, Expr, ExprKind, Generics, Lit, LitFloatType, LitIntType, LitKind, Mutability, NodeId, Pat, PatKind, + UnOp, }; use rustc_ast::visit::FnKind; use rustc_data_structures::fx::FxHashMap; use rustc_errors::Applicability; -use rustc_hir::PrimTy; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -265,16 +266,7 @@ impl EarlyLintPass for MiscEarlyLints { fn check_generics(&mut self, cx: &EarlyContext<'_>, gen: &Generics) { for param in &gen.params { - if let GenericParamKind::Type { .. } = param.kind { - if let Some(prim_ty) = PrimTy::from_name(param.ident.name) { - span_lint( - cx, - BUILTIN_TYPE_SHADOW, - param.ident.span, - &format!("this generic shadows the built-in type `{}`", prim_ty.name()), - ); - } - } + builtin_type_shadow::check(cx, param); } } diff --git a/tests/ui/builtin-type-shadow.rs b/tests/ui/builtin_type_shadow.rs similarity index 100% rename from tests/ui/builtin-type-shadow.rs rename to tests/ui/builtin_type_shadow.rs diff --git a/tests/ui/builtin-type-shadow.stderr b/tests/ui/builtin_type_shadow.stderr similarity index 89% rename from tests/ui/builtin-type-shadow.stderr rename to tests/ui/builtin_type_shadow.stderr index f42b246afd2..47a8a1e623e 100644 --- a/tests/ui/builtin-type-shadow.stderr +++ b/tests/ui/builtin_type_shadow.stderr @@ -1,5 +1,5 @@ error: this generic shadows the built-in type `u32` - --> $DIR/builtin-type-shadow.rs:4:8 + --> $DIR/builtin_type_shadow.rs:4:8 | LL | fn foo(a: u32) -> u32 { | ^^^ @@ -7,7 +7,7 @@ LL | fn foo(a: u32) -> u32 { = note: `-D clippy::builtin-type-shadow` implied by `-D warnings` error[E0308]: mismatched types - --> $DIR/builtin-type-shadow.rs:5:5 + --> $DIR/builtin_type_shadow.rs:5:5 | LL | fn foo(a: u32) -> u32 { | --- --- expected `u32` because of return type From 55af0cee15cf5c85cbb50ef41eafb4498bde24e3 Mon Sep 17 00:00:00 2001 From: Takayuki Date: Tue, 4 May 2021 17:20:22 +0900 Subject: [PATCH 03/11] move double_neg to its own module --- clippy_lints/src/misc_early/double_neg.rs | 23 +++++++++++++++++++++++ clippy_lints/src/misc_early/mod.rs | 19 +++---------------- 2 files changed, 26 insertions(+), 16 deletions(-) create mode 100644 clippy_lints/src/misc_early/double_neg.rs diff --git a/clippy_lints/src/misc_early/double_neg.rs b/clippy_lints/src/misc_early/double_neg.rs new file mode 100644 index 00000000000..6f65778e119 --- /dev/null +++ b/clippy_lints/src/misc_early/double_neg.rs @@ -0,0 +1,23 @@ +use super::MiscEarlyLints; +use clippy_utils::diagnostics::span_lint; +use rustc_ast::ast::{Expr, ExprKind, UnOp}; +use rustc_lint::EarlyContext; + +use super::DOUBLE_NEG; + +pub(super) fn check(cx: &EarlyContext<'_>, expr: &Expr) { + match expr.kind { + ExprKind::Unary(UnOp::Neg, ref inner) => { + if let ExprKind::Unary(UnOp::Neg, _) = inner.kind { + span_lint( + cx, + DOUBLE_NEG, + expr.span, + "`--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op", + ); + } + }, + ExprKind::Lit(ref lit) => MiscEarlyLints::check_lit(cx, lit), + _ => (), + } +} diff --git a/clippy_lints/src/misc_early/mod.rs b/clippy_lints/src/misc_early/mod.rs index 94740093d3b..47cc87dfffb 100644 --- a/clippy_lints/src/misc_early/mod.rs +++ b/clippy_lints/src/misc_early/mod.rs @@ -1,10 +1,10 @@ mod builtin_type_shadow; +mod double_neg; use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::snippet_opt; use rustc_ast::ast::{ - BindingMode, Expr, ExprKind, Generics, Lit, LitFloatType, LitIntType, LitKind, Mutability, NodeId, Pat, PatKind, - UnOp, + BindingMode, Expr, Generics, Lit, LitFloatType, LitIntType, LitKind, Mutability, NodeId, Pat, PatKind, }; use rustc_ast::visit::FnKind; use rustc_data_structures::fx::FxHashMap; @@ -393,20 +393,7 @@ fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { if in_external_macro(cx.sess(), expr.span) { return; } - match expr.kind { - ExprKind::Unary(UnOp::Neg, ref inner) => { - if let ExprKind::Unary(UnOp::Neg, _) = inner.kind { - span_lint( - cx, - DOUBLE_NEG, - expr.span, - "`--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op", - ); - } - }, - ExprKind::Lit(ref lit) => Self::check_lit(cx, lit), - _ => (), - } + double_neg::check(cx, expr) } } From 52cfde058668ddce3a191c0c608ac07603175d04 Mon Sep 17 00:00:00 2001 From: Takayuki Date: Tue, 4 May 2021 17:28:32 +0900 Subject: [PATCH 04/11] move redundant_pattern to its own module --- clippy_lints/src/misc_early/mod.rs | 29 ++--------------- .../src/misc_early/redundant_pattern.rs | 31 +++++++++++++++++++ 2 files changed, 34 insertions(+), 26 deletions(-) create mode 100644 clippy_lints/src/misc_early/redundant_pattern.rs diff --git a/clippy_lints/src/misc_early/mod.rs b/clippy_lints/src/misc_early/mod.rs index 47cc87dfffb..564afdb7f8d 100644 --- a/clippy_lints/src/misc_early/mod.rs +++ b/clippy_lints/src/misc_early/mod.rs @@ -1,11 +1,10 @@ mod builtin_type_shadow; mod double_neg; +mod redundant_pattern; use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::snippet_opt; -use rustc_ast::ast::{ - BindingMode, Expr, Generics, Lit, LitFloatType, LitIntType, LitKind, Mutability, NodeId, Pat, PatKind, -}; +use rustc_ast::ast::{Expr, Generics, Lit, LitFloatType, LitIntType, LitKind, NodeId, Pat, PatKind}; use rustc_ast::visit::FnKind; use rustc_data_structures::fx::FxHashMap; use rustc_errors::Applicability; @@ -336,29 +335,7 @@ fn check_pat(&mut self, cx: &EarlyContext<'_>, pat: &Pat) { } } - if let PatKind::Ident(left, ident, Some(ref right)) = pat.kind { - let left_binding = match left { - BindingMode::ByRef(Mutability::Mut) => "ref mut ", - BindingMode::ByRef(Mutability::Not) => "ref ", - BindingMode::ByValue(..) => "", - }; - - if let PatKind::Wild = right.kind { - span_lint_and_sugg( - cx, - REDUNDANT_PATTERN, - pat.span, - &format!( - "the `{} @ _` pattern can be written as just `{}`", - ident.name, ident.name, - ), - "try", - format!("{}{}", left_binding, ident.name), - Applicability::MachineApplicable, - ); - } - } - + redundant_pattern::check(cx, pat); check_unneeded_wildcard_pattern(cx, pat); } diff --git a/clippy_lints/src/misc_early/redundant_pattern.rs b/clippy_lints/src/misc_early/redundant_pattern.rs new file mode 100644 index 00000000000..525dbf7757c --- /dev/null +++ b/clippy_lints/src/misc_early/redundant_pattern.rs @@ -0,0 +1,31 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use rustc_ast::ast::{BindingMode, Mutability, Pat, PatKind}; +use rustc_errors::Applicability; +use rustc_lint::EarlyContext; + +use super::REDUNDANT_PATTERN; + +pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) { + if let PatKind::Ident(left, ident, Some(ref right)) = pat.kind { + let left_binding = match left { + BindingMode::ByRef(Mutability::Mut) => "ref mut ", + BindingMode::ByRef(Mutability::Not) => "ref ", + BindingMode::ByValue(..) => "", + }; + + if let PatKind::Wild = right.kind { + span_lint_and_sugg( + cx, + REDUNDANT_PATTERN, + pat.span, + &format!( + "the `{} @ _` pattern can be written as just `{}`", + ident.name, ident.name, + ), + "try", + format!("{}{}", left_binding, ident.name), + Applicability::MachineApplicable, + ); + } + } +} From c0a106e25214a16cb01c87f7f01fd7c95d3534c2 Mon Sep 17 00:00:00 2001 From: Takayuki Date: Tue, 4 May 2021 19:50:48 +0900 Subject: [PATCH 05/11] move unneeded_wildcard_pattern to its own module --- clippy_lints/src/misc_early/mod.rs | 48 +---------------- .../misc_early/unneeded_wildcard_pattern.rs | 52 +++++++++++++++++++ 2 files changed, 54 insertions(+), 46 deletions(-) create mode 100644 clippy_lints/src/misc_early/unneeded_wildcard_pattern.rs diff --git a/clippy_lints/src/misc_early/mod.rs b/clippy_lints/src/misc_early/mod.rs index 564afdb7f8d..7d1cd81f49f 100644 --- a/clippy_lints/src/misc_early/mod.rs +++ b/clippy_lints/src/misc_early/mod.rs @@ -1,6 +1,7 @@ mod builtin_type_shadow; mod double_neg; mod redundant_pattern; +mod unneeded_wildcard_pattern; use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::snippet_opt; @@ -336,7 +337,7 @@ fn check_pat(&mut self, cx: &EarlyContext<'_>, pat: &Pat) { } redundant_pattern::check(cx, pat); - check_unneeded_wildcard_pattern(cx, pat); + unneeded_wildcard_pattern::check(cx, pat); } fn check_fn(&mut self, cx: &EarlyContext<'_>, fn_kind: FnKind<'_>, _: Span, _: NodeId) { @@ -478,48 +479,3 @@ fn check_lit(cx: &EarlyContext<'_>, lit: &Lit) { } } } - -fn check_unneeded_wildcard_pattern(cx: &EarlyContext<'_>, pat: &Pat) { - if let PatKind::TupleStruct(_, ref patterns) | PatKind::Tuple(ref patterns) = pat.kind { - fn span_lint(cx: &EarlyContext<'_>, span: Span, only_one: bool) { - span_lint_and_sugg( - cx, - UNNEEDED_WILDCARD_PATTERN, - span, - if only_one { - "this pattern is unneeded as the `..` pattern can match that element" - } else { - "these patterns are unneeded as the `..` pattern can match those elements" - }, - if only_one { "remove it" } else { "remove them" }, - "".to_string(), - Applicability::MachineApplicable, - ); - } - - if let Some(rest_index) = patterns.iter().position(|pat| pat.is_rest()) { - if let Some((left_index, left_pat)) = patterns[..rest_index] - .iter() - .rev() - .take_while(|pat| matches!(pat.kind, PatKind::Wild)) - .enumerate() - .last() - { - span_lint(cx, left_pat.span.until(patterns[rest_index].span), left_index == 0); - } - - if let Some((right_index, right_pat)) = patterns[rest_index + 1..] - .iter() - .take_while(|pat| matches!(pat.kind, PatKind::Wild)) - .enumerate() - .last() - { - span_lint( - cx, - patterns[rest_index].span.shrink_to_hi().to(right_pat.span), - right_index == 0, - ); - } - } - } -} diff --git a/clippy_lints/src/misc_early/unneeded_wildcard_pattern.rs b/clippy_lints/src/misc_early/unneeded_wildcard_pattern.rs new file mode 100644 index 00000000000..4dd032d78f1 --- /dev/null +++ b/clippy_lints/src/misc_early/unneeded_wildcard_pattern.rs @@ -0,0 +1,52 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use rustc_ast::ast::{Pat, PatKind}; +use rustc_errors::Applicability; +use rustc_lint::EarlyContext; +use rustc_span::source_map::Span; + +use super::UNNEEDED_WILDCARD_PATTERN; + +pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) { + if let PatKind::TupleStruct(_, ref patterns) | PatKind::Tuple(ref patterns) = pat.kind { + if let Some(rest_index) = patterns.iter().position(|pat| pat.is_rest()) { + if let Some((left_index, left_pat)) = patterns[..rest_index] + .iter() + .rev() + .take_while(|pat| matches!(pat.kind, PatKind::Wild)) + .enumerate() + .last() + { + span_lint(cx, left_pat.span.until(patterns[rest_index].span), left_index == 0); + } + + if let Some((right_index, right_pat)) = patterns[rest_index + 1..] + .iter() + .take_while(|pat| matches!(pat.kind, PatKind::Wild)) + .enumerate() + .last() + { + span_lint( + cx, + patterns[rest_index].span.shrink_to_hi().to(right_pat.span), + right_index == 0, + ); + } + } + } +} + +fn span_lint(cx: &EarlyContext<'_>, span: Span, only_one: bool) { + span_lint_and_sugg( + cx, + UNNEEDED_WILDCARD_PATTERN, + span, + if only_one { + "this pattern is unneeded as the `..` pattern can match that element" + } else { + "these patterns are unneeded as the `..` pattern can match those elements" + }, + if only_one { "remove it" } else { "remove them" }, + "".to_string(), + Applicability::MachineApplicable, + ); +} From 829fde5e1f1163b3218409244863ce64d8c7dd19 Mon Sep 17 00:00:00 2001 From: Takayuki Date: Wed, 5 May 2021 01:44:38 +0900 Subject: [PATCH 06/11] move unneeded_field_pattern to its own module --- clippy_lints/src/misc_early/mod.rs | 69 +----------------- .../src/misc_early/unneeded_field_pattern.rs | 72 +++++++++++++++++++ 2 files changed, 75 insertions(+), 66 deletions(-) create mode 100644 clippy_lints/src/misc_early/unneeded_field_pattern.rs diff --git a/clippy_lints/src/misc_early/mod.rs b/clippy_lints/src/misc_early/mod.rs index 7d1cd81f49f..ee1bff8bf8a 100644 --- a/clippy_lints/src/misc_early/mod.rs +++ b/clippy_lints/src/misc_early/mod.rs @@ -1,9 +1,10 @@ mod builtin_type_shadow; mod double_neg; mod redundant_pattern; +mod unneeded_field_pattern; mod unneeded_wildcard_pattern; -use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::snippet_opt; use rustc_ast::ast::{Expr, Generics, Lit, LitFloatType, LitIntType, LitKind, NodeId, Pat, PatKind}; use rustc_ast::visit::FnKind; @@ -271,71 +272,7 @@ fn check_generics(&mut self, cx: &EarlyContext<'_>, gen: &Generics) { } fn check_pat(&mut self, cx: &EarlyContext<'_>, pat: &Pat) { - if let PatKind::Struct(ref npat, ref pfields, _) = pat.kind { - let mut wilds = 0; - let type_name = npat - .segments - .last() - .expect("A path must have at least one segment") - .ident - .name; - - for field in pfields { - if let PatKind::Wild = field.pat.kind { - wilds += 1; - } - } - if !pfields.is_empty() && wilds == pfields.len() { - span_lint_and_help( - cx, - UNNEEDED_FIELD_PATTERN, - pat.span, - "all the struct fields are matched to a wildcard pattern, consider using `..`", - None, - &format!("try with `{} {{ .. }}` instead", type_name), - ); - return; - } - if wilds > 0 { - for field in pfields { - if let PatKind::Wild = field.pat.kind { - wilds -= 1; - if wilds > 0 { - span_lint( - cx, - UNNEEDED_FIELD_PATTERN, - field.span, - "you matched a field with a wildcard pattern, consider using `..` instead", - ); - } else { - let mut normal = vec![]; - - for field in pfields { - match field.pat.kind { - PatKind::Wild => {}, - _ => { - if let Ok(n) = cx.sess().source_map().span_to_snippet(field.span) { - normal.push(n); - } - }, - } - } - - span_lint_and_help( - cx, - UNNEEDED_FIELD_PATTERN, - field.span, - "you matched a field with a wildcard pattern, consider using `..` \ - instead", - None, - &format!("try with `{} {{ {}, .. }}`", type_name, normal[..].join(", ")), - ); - } - } - } - } - } - + unneeded_field_pattern::check(cx, pat); redundant_pattern::check(cx, pat); unneeded_wildcard_pattern::check(cx, pat); } diff --git a/clippy_lints/src/misc_early/unneeded_field_pattern.rs b/clippy_lints/src/misc_early/unneeded_field_pattern.rs new file mode 100644 index 00000000000..329a0009a3e --- /dev/null +++ b/clippy_lints/src/misc_early/unneeded_field_pattern.rs @@ -0,0 +1,72 @@ +use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; +use rustc_ast::ast::{Pat, PatKind}; +use rustc_lint::{EarlyContext, LintContext}; + +use super::UNNEEDED_FIELD_PATTERN; + +pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) { + if let PatKind::Struct(ref npat, ref pfields, _) = pat.kind { + let mut wilds = 0; + let type_name = npat + .segments + .last() + .expect("A path must have at least one segment") + .ident + .name; + + for field in pfields { + if let PatKind::Wild = field.pat.kind { + wilds += 1; + } + } + if !pfields.is_empty() && wilds == pfields.len() { + span_lint_and_help( + cx, + UNNEEDED_FIELD_PATTERN, + pat.span, + "all the struct fields are matched to a wildcard pattern, consider using `..`", + None, + &format!("try with `{} {{ .. }}` instead", type_name), + ); + return; + } + if wilds > 0 { + for field in pfields { + if let PatKind::Wild = field.pat.kind { + wilds -= 1; + if wilds > 0 { + span_lint( + cx, + UNNEEDED_FIELD_PATTERN, + field.span, + "you matched a field with a wildcard pattern, consider using `..` instead", + ); + } else { + let mut normal = vec![]; + + for field in pfields { + match field.pat.kind { + PatKind::Wild => {}, + _ => { + if let Ok(n) = cx.sess().source_map().span_to_snippet(field.span) { + normal.push(n); + } + }, + } + } + + span_lint_and_help( + cx, + UNNEEDED_FIELD_PATTERN, + field.span, + "you matched a field with a wildcard pattern, consider using `..` \ + instead", + None, + &format!("try with `{} {{ {}, .. }}`", type_name, normal[..].join(", ")), + ); + } + } + } + } + } +} From f012e0e3de04ca5b8022a0b8856a12d47d746b5b Mon Sep 17 00:00:00 2001 From: Takayuki Date: Wed, 5 May 2021 02:10:24 +0900 Subject: [PATCH 07/11] move unseparated_literal_suffix to its own module --- clippy_lints/src/misc_early/mod.rs | 19 ++----------- .../misc_early/unseparated_literal_suffix.rs | 27 +++++++++++++++++++ 2 files changed, 29 insertions(+), 17 deletions(-) create mode 100644 clippy_lints/src/misc_early/unseparated_literal_suffix.rs diff --git a/clippy_lints/src/misc_early/mod.rs b/clippy_lints/src/misc_early/mod.rs index ee1bff8bf8a..182218e77f6 100644 --- a/clippy_lints/src/misc_early/mod.rs +++ b/clippy_lints/src/misc_early/mod.rs @@ -3,6 +3,7 @@ mod redundant_pattern; mod unneeded_field_pattern; mod unneeded_wildcard_pattern; +mod unseparated_literal_suffix; use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::snippet_opt; @@ -396,23 +397,7 @@ fn check_lit(cx: &EarlyContext<'_>, lit: &Lit) { ); } } else if let LitKind::Float(_, LitFloatType::Suffixed(float_ty)) = lit.kind { - let suffix = float_ty.name_str(); - let maybe_last_sep_idx = if let Some(val) = lit_snip.len().checked_sub(suffix.len() + 1) { - val - } else { - return; // It's useless so shouldn't lint. - }; - if lit_snip.as_bytes()[maybe_last_sep_idx] != b'_' { - span_lint_and_sugg( - cx, - UNSEPARATED_LITERAL_SUFFIX, - lit.span, - "float type suffix should be separated by an underscore", - "add an underscore", - format!("{}_{}", &lit_snip[..=maybe_last_sep_idx], suffix), - Applicability::MachineApplicable, - ); - } + unseparated_literal_suffix::check(cx, lit, float_ty, lit_snip) } } } diff --git a/clippy_lints/src/misc_early/unseparated_literal_suffix.rs b/clippy_lints/src/misc_early/unseparated_literal_suffix.rs new file mode 100644 index 00000000000..ffdd5d93a38 --- /dev/null +++ b/clippy_lints/src/misc_early/unseparated_literal_suffix.rs @@ -0,0 +1,27 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use rustc_ast::ast::FloatTy; +use rustc_ast::ast::Lit; +use rustc_errors::Applicability; +use rustc_lint::EarlyContext; + +use super::UNSEPARATED_LITERAL_SUFFIX; + +pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, float_ty: FloatTy, lit_snip: String) { + let suffix = float_ty.name_str(); + let maybe_last_sep_idx = if let Some(val) = lit_snip.len().checked_sub(suffix.len() + 1) { + val + } else { + return; // It's useless so shouldn't lint. + }; + if lit_snip.as_bytes()[maybe_last_sep_idx] != b'_' { + span_lint_and_sugg( + cx, + UNSEPARATED_LITERAL_SUFFIX, + lit.span, + "float type suffix should be separated by an underscore", + "add an underscore", + format!("{}_{}", &lit_snip[..=maybe_last_sep_idx], suffix), + Applicability::MachineApplicable, + ); + } +} From 0773d8afdb792a3147de53ad590b620be9eef006 Mon Sep 17 00:00:00 2001 From: Takayuki Date: Wed, 5 May 2021 02:21:26 +0900 Subject: [PATCH 08/11] move mixed_case_hex_literals to its own module --- .../src/misc_early/mixed_case_hex_literals.rs | 29 +++++++++++++++++++ clippy_lints/src/misc_early/mod.rs | 23 ++------------- 2 files changed, 31 insertions(+), 21 deletions(-) create mode 100644 clippy_lints/src/misc_early/mixed_case_hex_literals.rs diff --git a/clippy_lints/src/misc_early/mixed_case_hex_literals.rs b/clippy_lints/src/misc_early/mixed_case_hex_literals.rs new file mode 100644 index 00000000000..fbcbfa2556f --- /dev/null +++ b/clippy_lints/src/misc_early/mixed_case_hex_literals.rs @@ -0,0 +1,29 @@ +use clippy_utils::diagnostics::span_lint; +use rustc_ast::ast::Lit; +use rustc_lint::EarlyContext; + +use super::MIXED_CASE_HEX_LITERALS; + +pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, maybe_last_sep_idx: usize, lit_snip: String) { + if maybe_last_sep_idx <= 2 { + // It's meaningless or causes range error. + return; + } + let mut seen = (false, false); + for ch in lit_snip.as_bytes()[2..=maybe_last_sep_idx].iter() { + match ch { + b'a'..=b'f' => seen.0 = true, + b'A'..=b'F' => seen.1 = true, + _ => {}, + } + if seen.0 && seen.1 { + span_lint( + cx, + MIXED_CASE_HEX_LITERALS, + lit.span, + "inconsistent casing in hexadecimal literal", + ); + break; + } + } +} diff --git a/clippy_lints/src/misc_early/mod.rs b/clippy_lints/src/misc_early/mod.rs index 182218e77f6..0bfa6833aac 100644 --- a/clippy_lints/src/misc_early/mod.rs +++ b/clippy_lints/src/misc_early/mod.rs @@ -1,5 +1,6 @@ mod builtin_type_shadow; mod double_neg; +mod mixed_case_hex_literals; mod redundant_pattern; mod unneeded_field_pattern; mod unneeded_wildcard_pattern; @@ -351,27 +352,7 @@ fn check_lit(cx: &EarlyContext<'_>, lit: &Lit) { } if lit_snip.starts_with("0x") { - if maybe_last_sep_idx <= 2 { - // It's meaningless or causes range error. - return; - } - let mut seen = (false, false); - for ch in lit_snip.as_bytes()[2..=maybe_last_sep_idx].iter() { - match ch { - b'a'..=b'f' => seen.0 = true, - b'A'..=b'F' => seen.1 = true, - _ => {}, - } - if seen.0 && seen.1 { - span_lint( - cx, - MIXED_CASE_HEX_LITERALS, - lit.span, - "inconsistent casing in hexadecimal literal", - ); - break; - } - } + mixed_case_hex_literals::check(cx, lit, maybe_last_sep_idx, lit_snip) } else if lit_snip.starts_with("0b") || lit_snip.starts_with("0o") { /* nothing to do */ } else if value != 0 && lit_snip.starts_with('0') { From b1567f4466388df8377512580d72513e1e4e0e48 Mon Sep 17 00:00:00 2001 From: Takayuki Date: Wed, 5 May 2021 06:18:58 +0900 Subject: [PATCH 09/11] move zero_prefixed_literal to its own module --- clippy_lints/src/misc_early/mod.rs | 24 ++------------- .../src/misc_early/zero_prefixed_literal.rs | 29 +++++++++++++++++++ 2 files changed, 32 insertions(+), 21 deletions(-) create mode 100644 clippy_lints/src/misc_early/zero_prefixed_literal.rs diff --git a/clippy_lints/src/misc_early/mod.rs b/clippy_lints/src/misc_early/mod.rs index 0bfa6833aac..4b1d55beca8 100644 --- a/clippy_lints/src/misc_early/mod.rs +++ b/clippy_lints/src/misc_early/mod.rs @@ -5,8 +5,9 @@ mod unneeded_field_pattern; mod unneeded_wildcard_pattern; mod unseparated_literal_suffix; +mod zero_prefixed_literal; -use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; use clippy_utils::source::snippet_opt; use rustc_ast::ast::{Expr, Generics, Lit, LitFloatType, LitIntType, LitKind, NodeId, Pat, PatKind}; use rustc_ast::visit::FnKind; @@ -356,26 +357,7 @@ fn check_lit(cx: &EarlyContext<'_>, lit: &Lit) { } else if lit_snip.starts_with("0b") || lit_snip.starts_with("0o") { /* nothing to do */ } else if value != 0 && lit_snip.starts_with('0') { - span_lint_and_then( - cx, - ZERO_PREFIXED_LITERAL, - lit.span, - "this is a decimal constant", - |diag| { - diag.span_suggestion( - lit.span, - "if you mean to use a decimal constant, remove the `0` to avoid confusion", - lit_snip.trim_start_matches(|c| c == '_' || c == '0').to_string(), - Applicability::MaybeIncorrect, - ); - diag.span_suggestion( - lit.span, - "if you mean to use an octal constant, use `0o`", - format!("0o{}", lit_snip.trim_start_matches(|c| c == '_' || c == '0')), - Applicability::MaybeIncorrect, - ); - }, - ); + zero_prefixed_literal::check(cx, lit, lit_snip) } } else if let LitKind::Float(_, LitFloatType::Suffixed(float_ty)) = lit.kind { unseparated_literal_suffix::check(cx, lit, float_ty, lit_snip) diff --git a/clippy_lints/src/misc_early/zero_prefixed_literal.rs b/clippy_lints/src/misc_early/zero_prefixed_literal.rs new file mode 100644 index 00000000000..16add0fa1b4 --- /dev/null +++ b/clippy_lints/src/misc_early/zero_prefixed_literal.rs @@ -0,0 +1,29 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use rustc_ast::ast::Lit; +use rustc_errors::Applicability; +use rustc_lint::EarlyContext; + +use super::ZERO_PREFIXED_LITERAL; + +pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, lit_snip: String) { + span_lint_and_then( + cx, + ZERO_PREFIXED_LITERAL, + lit.span, + "this is a decimal constant", + |diag| { + diag.span_suggestion( + lit.span, + "if you mean to use a decimal constant, remove the `0` to avoid confusion", + lit_snip.trim_start_matches(|c| c == '_' || c == '0').to_string(), + Applicability::MaybeIncorrect, + ); + diag.span_suggestion( + lit.span, + "if you mean to use an octal constant, use `0o`", + format!("0o{}", lit_snip.trim_start_matches(|c| c == '_' || c == '0')), + Applicability::MaybeIncorrect, + ); + }, + ); +} From 2dfb246d8e8db3280326330b9ca67aee5d3214e9 Mon Sep 17 00:00:00 2001 From: Takayuki Date: Wed, 5 May 2021 06:39:38 +0900 Subject: [PATCH 10/11] refactor unseparated_literal_suffix --- .../src/misc_early/mixed_case_hex_literals.rs | 7 ++++- clippy_lints/src/misc_early/mod.rs | 28 ++++--------------- .../misc_early/unseparated_literal_suffix.rs | 9 +++--- 3 files changed, 15 insertions(+), 29 deletions(-) diff --git a/clippy_lints/src/misc_early/mixed_case_hex_literals.rs b/clippy_lints/src/misc_early/mixed_case_hex_literals.rs index fbcbfa2556f..98b0f7b5664 100644 --- a/clippy_lints/src/misc_early/mixed_case_hex_literals.rs +++ b/clippy_lints/src/misc_early/mixed_case_hex_literals.rs @@ -4,7 +4,12 @@ use super::MIXED_CASE_HEX_LITERALS; -pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, maybe_last_sep_idx: usize, lit_snip: String) { +pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, suffix: &str, lit_snip: String) { + let maybe_last_sep_idx = if let Some(val) = lit_snip.len().checked_sub(suffix.len() + 1) { + val + } else { + return; // It's useless so shouldn't lint. + }; if maybe_last_sep_idx <= 2 { // It's meaningless or causes range error. return; diff --git a/clippy_lints/src/misc_early/mod.rs b/clippy_lints/src/misc_early/mod.rs index 4b1d55beca8..146d0c367a8 100644 --- a/clippy_lints/src/misc_early/mod.rs +++ b/clippy_lints/src/misc_early/mod.rs @@ -7,12 +7,11 @@ mod unseparated_literal_suffix; mod zero_prefixed_literal; -use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint; use clippy_utils::source::snippet_opt; use rustc_ast::ast::{Expr, Generics, Lit, LitFloatType, LitIntType, LitKind, NodeId, Pat, PatKind}; use rustc_ast::visit::FnKind; use rustc_data_structures::fx::FxHashMap; -use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -333,34 +332,17 @@ fn check_lit(cx: &EarlyContext<'_>, lit: &Lit) { LitIntType::Unsigned(ty) => ty.name_str(), LitIntType::Unsuffixed => "", }; - - let maybe_last_sep_idx = if let Some(val) = lit_snip.len().checked_sub(suffix.len() + 1) { - val - } else { - return; // It's useless so shouldn't lint. - }; - // Do not lint when literal is unsuffixed. - if !suffix.is_empty() && lit_snip.as_bytes()[maybe_last_sep_idx] != b'_' { - span_lint_and_sugg( - cx, - UNSEPARATED_LITERAL_SUFFIX, - lit.span, - "integer type suffix should be separated by an underscore", - "add an underscore", - format!("{}_{}", &lit_snip[..=maybe_last_sep_idx], suffix), - Applicability::MachineApplicable, - ); - } - + unseparated_literal_suffix::check(cx, lit, &lit_snip, suffix, "integer"); if lit_snip.starts_with("0x") { - mixed_case_hex_literals::check(cx, lit, maybe_last_sep_idx, lit_snip) + mixed_case_hex_literals::check(cx, lit, suffix, lit_snip) } else if lit_snip.starts_with("0b") || lit_snip.starts_with("0o") { /* nothing to do */ } else if value != 0 && lit_snip.starts_with('0') { zero_prefixed_literal::check(cx, lit, lit_snip) } } else if let LitKind::Float(_, LitFloatType::Suffixed(float_ty)) = lit.kind { - unseparated_literal_suffix::check(cx, lit, float_ty, lit_snip) + let suffix = float_ty.name_str(); + unseparated_literal_suffix::check(cx, lit, &lit_snip, suffix, "float") } } } diff --git a/clippy_lints/src/misc_early/unseparated_literal_suffix.rs b/clippy_lints/src/misc_early/unseparated_literal_suffix.rs index ffdd5d93a38..1ffdd4cf676 100644 --- a/clippy_lints/src/misc_early/unseparated_literal_suffix.rs +++ b/clippy_lints/src/misc_early/unseparated_literal_suffix.rs @@ -1,24 +1,23 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use rustc_ast::ast::FloatTy; use rustc_ast::ast::Lit; use rustc_errors::Applicability; use rustc_lint::EarlyContext; use super::UNSEPARATED_LITERAL_SUFFIX; -pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, float_ty: FloatTy, lit_snip: String) { - let suffix = float_ty.name_str(); +pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, lit_snip: &String, suffix: &str, sugg_type: &str) { let maybe_last_sep_idx = if let Some(val) = lit_snip.len().checked_sub(suffix.len() + 1) { val } else { return; // It's useless so shouldn't lint. }; - if lit_snip.as_bytes()[maybe_last_sep_idx] != b'_' { + // Do not lint when literal is unsuffixed. + if !suffix.is_empty() && lit_snip.as_bytes()[maybe_last_sep_idx] != b'_' { span_lint_and_sugg( cx, UNSEPARATED_LITERAL_SUFFIX, lit.span, - "float type suffix should be separated by an underscore", + &format!("{} type suffix should be separated by an underscore", sugg_type), "add an underscore", format!("{}_{}", &lit_snip[..=maybe_last_sep_idx], suffix), Applicability::MachineApplicable, From 3fbb060379485605fc8649ba5e749b141fbb9335 Mon Sep 17 00:00:00 2001 From: Takayuki Date: Wed, 5 May 2021 06:53:04 +0900 Subject: [PATCH 11/11] replace lit_snip type with &str --- clippy_lints/src/misc_early/mixed_case_hex_literals.rs | 2 +- clippy_lints/src/misc_early/mod.rs | 4 ++-- clippy_lints/src/misc_early/unseparated_literal_suffix.rs | 2 +- clippy_lints/src/misc_early/zero_prefixed_literal.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/misc_early/mixed_case_hex_literals.rs b/clippy_lints/src/misc_early/mixed_case_hex_literals.rs index 98b0f7b5664..80e24213100 100644 --- a/clippy_lints/src/misc_early/mixed_case_hex_literals.rs +++ b/clippy_lints/src/misc_early/mixed_case_hex_literals.rs @@ -4,7 +4,7 @@ use super::MIXED_CASE_HEX_LITERALS; -pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, suffix: &str, lit_snip: String) { +pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, suffix: &str, lit_snip: &str) { let maybe_last_sep_idx = if let Some(val) = lit_snip.len().checked_sub(suffix.len() + 1) { val } else { diff --git a/clippy_lints/src/misc_early/mod.rs b/clippy_lints/src/misc_early/mod.rs index 146d0c367a8..dd38316fa25 100644 --- a/clippy_lints/src/misc_early/mod.rs +++ b/clippy_lints/src/misc_early/mod.rs @@ -334,11 +334,11 @@ fn check_lit(cx: &EarlyContext<'_>, lit: &Lit) { }; unseparated_literal_suffix::check(cx, lit, &lit_snip, suffix, "integer"); if lit_snip.starts_with("0x") { - mixed_case_hex_literals::check(cx, lit, suffix, lit_snip) + mixed_case_hex_literals::check(cx, lit, suffix, &lit_snip) } else if lit_snip.starts_with("0b") || lit_snip.starts_with("0o") { /* nothing to do */ } else if value != 0 && lit_snip.starts_with('0') { - zero_prefixed_literal::check(cx, lit, lit_snip) + zero_prefixed_literal::check(cx, lit, &lit_snip) } } else if let LitKind::Float(_, LitFloatType::Suffixed(float_ty)) = lit.kind { let suffix = float_ty.name_str(); diff --git a/clippy_lints/src/misc_early/unseparated_literal_suffix.rs b/clippy_lints/src/misc_early/unseparated_literal_suffix.rs index 1ffdd4cf676..2018aa6184a 100644 --- a/clippy_lints/src/misc_early/unseparated_literal_suffix.rs +++ b/clippy_lints/src/misc_early/unseparated_literal_suffix.rs @@ -5,7 +5,7 @@ use super::UNSEPARATED_LITERAL_SUFFIX; -pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, lit_snip: &String, suffix: &str, sugg_type: &str) { +pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, lit_snip: &str, suffix: &str, sugg_type: &str) { let maybe_last_sep_idx = if let Some(val) = lit_snip.len().checked_sub(suffix.len() + 1) { val } else { diff --git a/clippy_lints/src/misc_early/zero_prefixed_literal.rs b/clippy_lints/src/misc_early/zero_prefixed_literal.rs index 16add0fa1b4..4963bba82f2 100644 --- a/clippy_lints/src/misc_early/zero_prefixed_literal.rs +++ b/clippy_lints/src/misc_early/zero_prefixed_literal.rs @@ -5,7 +5,7 @@ use super::ZERO_PREFIXED_LITERAL; -pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, lit_snip: String) { +pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, lit_snip: &str) { span_lint_and_then( cx, ZERO_PREFIXED_LITERAL,