Move DurationSubsec
into Operators
lint pass
This commit is contained in:
parent
4ac3626f2e
commit
732d7162ab
@ -1,75 +0,0 @@
|
||||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::snippet_with_applicability;
|
||||
use clippy_utils::ty::is_type_diagnostic_item;
|
||||
use if_chain::if_chain;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{BinOpKind, Expr, ExprKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::sym;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Checks for calculation of subsecond microseconds or milliseconds
|
||||
/// from other `Duration` methods.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// It's more concise to call `Duration::subsec_micros()` or
|
||||
/// `Duration::subsec_millis()` than to calculate them.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```rust
|
||||
/// # use std::time::Duration;
|
||||
/// # let duration = Duration::new(5, 0);
|
||||
/// let micros = duration.subsec_nanos() / 1_000;
|
||||
/// let millis = duration.subsec_nanos() / 1_000_000;
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```rust
|
||||
/// # use std::time::Duration;
|
||||
/// # let duration = Duration::new(5, 0);
|
||||
/// let micros = duration.subsec_micros();
|
||||
/// let millis = duration.subsec_millis();
|
||||
/// ```
|
||||
#[clippy::version = "pre 1.29.0"]
|
||||
pub DURATION_SUBSEC,
|
||||
complexity,
|
||||
"checks for calculation of subsecond microseconds or milliseconds"
|
||||
}
|
||||
|
||||
declare_lint_pass!(DurationSubsec => [DURATION_SUBSEC]);
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for DurationSubsec {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
if_chain! {
|
||||
if let ExprKind::Binary(Spanned { node: BinOpKind::Div, .. }, left, right) = expr.kind;
|
||||
if let ExprKind::MethodCall(method_path, args, _) = left.kind;
|
||||
if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&args[0]).peel_refs(), sym::Duration);
|
||||
if let Some((Constant::Int(divisor), _)) = constant(cx, cx.typeck_results(), right);
|
||||
then {
|
||||
let suggested_fn = match (method_path.ident.as_str(), divisor) {
|
||||
("subsec_micros", 1_000) | ("subsec_nanos", 1_000_000) => "subsec_millis",
|
||||
("subsec_nanos", 1_000) => "subsec_micros",
|
||||
_ => return,
|
||||
};
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
DURATION_SUBSEC,
|
||||
expr.span,
|
||||
&format!("calling `{}()` is more concise than this calculation", suggested_fn),
|
||||
"try",
|
||||
format!(
|
||||
"{}.{}()",
|
||||
snippet_with_applicability(cx, args[0].span, "_", &mut applicability),
|
||||
suggested_fn
|
||||
),
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -57,7 +57,6 @@
|
||||
LintId::of(drop_forget_ref::FORGET_REF),
|
||||
LintId::of(drop_forget_ref::UNDROPPED_MANUALLY_DROPS),
|
||||
LintId::of(duplicate_mod::DUPLICATE_MOD),
|
||||
LintId::of(duration_subsec::DURATION_SUBSEC),
|
||||
LintId::of(entry::MAP_ENTRY),
|
||||
LintId::of(enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT),
|
||||
LintId::of(enum_variants::ENUM_VARIANT_NAMES),
|
||||
@ -258,6 +257,7 @@
|
||||
LintId::of(operators::ASSIGN_OP_PATTERN),
|
||||
LintId::of(operators::BAD_BIT_MASK),
|
||||
LintId::of(operators::DOUBLE_COMPARISONS),
|
||||
LintId::of(operators::DURATION_SUBSEC),
|
||||
LintId::of(operators::INEFFECTIVE_BIT_MASK),
|
||||
LintId::of(operators::MISREFACTORED_ASSIGN_OP),
|
||||
LintId::of(option_env_unwrap::OPTION_ENV_UNWRAP),
|
||||
|
@ -11,7 +11,6 @@
|
||||
LintId::of(casts::UNNECESSARY_CAST),
|
||||
LintId::of(derivable_impls::DERIVABLE_IMPLS),
|
||||
LintId::of(double_parens::DOUBLE_PARENS),
|
||||
LintId::of(duration_subsec::DURATION_SUBSEC),
|
||||
LintId::of(explicit_write::EXPLICIT_WRITE),
|
||||
LintId::of(format::USELESS_FORMAT),
|
||||
LintId::of(functions::TOO_MANY_ARGUMENTS),
|
||||
@ -71,6 +70,7 @@
|
||||
LintId::of(no_effect::NO_EFFECT),
|
||||
LintId::of(no_effect::UNNECESSARY_OPERATION),
|
||||
LintId::of(operators::DOUBLE_COMPARISONS),
|
||||
LintId::of(operators::DURATION_SUBSEC),
|
||||
LintId::of(overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL),
|
||||
LintId::of(partialeq_ne_impl::PARTIALEQ_NE_IMPL),
|
||||
LintId::of(precedence::PRECEDENCE),
|
||||
|
@ -131,7 +131,6 @@
|
||||
drop_forget_ref::FORGET_REF,
|
||||
drop_forget_ref::UNDROPPED_MANUALLY_DROPS,
|
||||
duplicate_mod::DUPLICATE_MOD,
|
||||
duration_subsec::DURATION_SUBSEC,
|
||||
else_if_without_else::ELSE_IF_WITHOUT_ELSE,
|
||||
empty_drop::EMPTY_DROP,
|
||||
empty_enum::EMPTY_ENUM,
|
||||
@ -432,6 +431,7 @@
|
||||
operators::ASSIGN_OP_PATTERN,
|
||||
operators::BAD_BIT_MASK,
|
||||
operators::DOUBLE_COMPARISONS,
|
||||
operators::DURATION_SUBSEC,
|
||||
operators::FLOAT_ARITHMETIC,
|
||||
operators::INEFFECTIVE_BIT_MASK,
|
||||
operators::INTEGER_ARITHMETIC,
|
||||
|
@ -212,7 +212,6 @@ macro_rules! declare_clippy_lint {
|
||||
mod double_parens;
|
||||
mod drop_forget_ref;
|
||||
mod duplicate_mod;
|
||||
mod duration_subsec;
|
||||
mod else_if_without_else;
|
||||
mod empty_drop;
|
||||
mod empty_enum;
|
||||
@ -732,7 +731,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
||||
store.register_late_pass(|| Box::new(inherent_impl::MultipleInherentImpl));
|
||||
store.register_late_pass(|| Box::new(neg_cmp_op_on_partial_ord::NoNegCompOpForPartialOrd));
|
||||
store.register_late_pass(|| Box::new(unwrap::Unwrap));
|
||||
store.register_late_pass(|| Box::new(duration_subsec::DurationSubsec));
|
||||
store.register_late_pass(|| Box::new(indexing_slicing::IndexingSlicing));
|
||||
store.register_late_pass(|| Box::new(non_copy_const::NonCopyConst));
|
||||
store.register_late_pass(|| Box::new(ptr_offset_with_cast::PtrOffsetWithCast));
|
||||
|
44
clippy_lints/src/operators/duration_subsec.rs
Normal file
44
clippy_lints/src/operators/duration_subsec.rs
Normal file
@ -0,0 +1,44 @@
|
||||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::snippet_with_applicability;
|
||||
use clippy_utils::ty::is_type_diagnostic_item;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{BinOpKind, Expr, ExprKind};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_span::sym;
|
||||
|
||||
use super::DURATION_SUBSEC;
|
||||
|
||||
pub(crate) fn check<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
expr: &'tcx Expr<'_>,
|
||||
op: BinOpKind,
|
||||
left: &'tcx Expr<'_>,
|
||||
right: &'tcx Expr<'_>,
|
||||
) {
|
||||
if op == BinOpKind::Div
|
||||
&& let ExprKind::MethodCall(method_path, [self_arg], _) = left.kind
|
||||
&& is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(self_arg).peel_refs(), sym::Duration)
|
||||
&& let Some((Constant::Int(divisor), _)) = constant(cx, cx.typeck_results(), right)
|
||||
{
|
||||
let suggested_fn = match (method_path.ident.as_str(), divisor) {
|
||||
("subsec_micros", 1_000) | ("subsec_nanos", 1_000_000) => "subsec_millis",
|
||||
("subsec_nanos", 1_000) => "subsec_micros",
|
||||
_ => return,
|
||||
};
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
DURATION_SUBSEC,
|
||||
expr.span,
|
||||
&format!("calling `{}()` is more concise than this calculation", suggested_fn),
|
||||
"try",
|
||||
format!(
|
||||
"{}.{}()",
|
||||
snippet_with_applicability(cx, self_arg.span, "_", &mut applicability),
|
||||
suggested_fn
|
||||
),
|
||||
applicability,
|
||||
);
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@
|
||||
mod assign_op_pattern;
|
||||
mod bit_mask;
|
||||
mod double_comparison;
|
||||
mod duration_subsec;
|
||||
mod misrefactored_assign_op;
|
||||
mod numeric_arithmetic;
|
||||
mod verbose_bit_mask;
|
||||
@ -271,6 +272,36 @@
|
||||
"unnecessary double comparisons that can be simplified"
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Checks for calculation of subsecond microseconds or milliseconds
|
||||
/// from other `Duration` methods.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// It's more concise to call `Duration::subsec_micros()` or
|
||||
/// `Duration::subsec_millis()` than to calculate them.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```rust
|
||||
/// # use std::time::Duration;
|
||||
/// # let duration = Duration::new(5, 0);
|
||||
/// let micros = duration.subsec_nanos() / 1_000;
|
||||
/// let millis = duration.subsec_nanos() / 1_000_000;
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```rust
|
||||
/// # use std::time::Duration;
|
||||
/// # let duration = Duration::new(5, 0);
|
||||
/// let micros = duration.subsec_micros();
|
||||
/// let millis = duration.subsec_millis();
|
||||
/// ```
|
||||
#[clippy::version = "pre 1.29.0"]
|
||||
pub DURATION_SUBSEC,
|
||||
complexity,
|
||||
"checks for calculation of subsecond microseconds or milliseconds"
|
||||
}
|
||||
|
||||
pub struct Operators {
|
||||
arithmetic_context: numeric_arithmetic::Context,
|
||||
verbose_bit_mask_threshold: u64,
|
||||
@ -285,6 +316,7 @@ pub struct Operators {
|
||||
INEFFECTIVE_BIT_MASK,
|
||||
VERBOSE_BIT_MASK,
|
||||
DOUBLE_COMPARISONS,
|
||||
DURATION_SUBSEC,
|
||||
]);
|
||||
impl Operators {
|
||||
pub fn new(verbose_bit_mask_threshold: u64) -> Self {
|
||||
@ -305,6 +337,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
|
||||
bit_mask::check(cx, e, op.node, lhs, rhs);
|
||||
verbose_bit_mask::check(cx, e, op.node, lhs, rhs, self.verbose_bit_mask_threshold);
|
||||
double_comparison::check(cx, op.node, lhs, rhs, e.span);
|
||||
duration_subsec::check(cx, e, op.node, lhs, rhs);
|
||||
},
|
||||
ExprKind::AssignOp(op, lhs, rhs) => {
|
||||
self.arithmetic_context.check_binary(cx, e, op.node, lhs, rhs);
|
||||
|
Loading…
Reference in New Issue
Block a user