summaryrefslogtreecommitdiffstats
path: root/src/tools/clippy/clippy_lints/src/manual_strip.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/clippy/clippy_lints/src/manual_strip.rs')
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_strip.rs171
1 files changed, 88 insertions, 83 deletions
diff --git a/src/tools/clippy/clippy_lints/src/manual_strip.rs b/src/tools/clippy/clippy_lints/src/manual_strip.rs
index 9a9e6af50..7b04fd28b 100644
--- a/src/tools/clippy/clippy_lints/src/manual_strip.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_strip.rs
@@ -4,14 +4,13 @@ use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
use clippy_utils::source::snippet;
use clippy_utils::usage::mutated_variables;
use clippy_utils::{eq_expr_value, higher, match_def_path, paths};
-use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_hir::def::Res;
use rustc_hir::intravisit::{walk_expr, Visitor};
use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
-use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_session::impl_lint_pass;
use rustc_span::source_map::Spanned;
use rustc_span::Span;
@@ -71,55 +70,61 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip {
return;
}
- if_chain! {
- if let Some(higher::If { cond, then, .. }) = higher::If::hir(expr);
- if let ExprKind::MethodCall(_, target_arg, [pattern], _) = cond.kind;
- if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(cond.hir_id);
- if let ExprKind::Path(target_path) = &target_arg.kind;
- then {
- let strip_kind = if match_def_path(cx, method_def_id, &paths::STR_STARTS_WITH) {
- StripKind::Prefix
- } else if match_def_path(cx, method_def_id, &paths::STR_ENDS_WITH) {
- StripKind::Suffix
- } else {
- return;
- };
- let target_res = cx.qpath_res(target_path, target_arg.hir_id);
- if target_res == Res::Err {
- return;
- };
-
- if_chain! {
- if let Res::Local(hir_id) = target_res;
- if let Some(used_mutably) = mutated_variables(then, cx);
- if used_mutably.contains(&hir_id);
- then {
- return;
- }
- }
-
- let strippings = find_stripping(cx, strip_kind, target_res, pattern, then);
- if !strippings.is_empty() {
+ if let Some(higher::If { cond, then, .. }) = higher::If::hir(expr)
+ && let ExprKind::MethodCall(_, target_arg, [pattern], _) = cond.kind
+ && let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(cond.hir_id)
+ && let ExprKind::Path(target_path) = &target_arg.kind
+ {
+ let strip_kind = if match_def_path(cx, method_def_id, &paths::STR_STARTS_WITH) {
+ StripKind::Prefix
+ } else if match_def_path(cx, method_def_id, &paths::STR_ENDS_WITH) {
+ StripKind::Suffix
+ } else {
+ return;
+ };
+ let target_res = cx.qpath_res(target_path, target_arg.hir_id);
+ if target_res == Res::Err {
+ return;
+ };
+
+ if let Res::Local(hir_id) = target_res
+ && let Some(used_mutably) = mutated_variables(then, cx)
+ && used_mutably.contains(&hir_id)
+ {
+ return;
+ }
- let kind_word = match strip_kind {
- StripKind::Prefix => "prefix",
- StripKind::Suffix => "suffix",
- };
+ let strippings = find_stripping(cx, strip_kind, target_res, pattern, then);
+ if !strippings.is_empty() {
+ let kind_word = match strip_kind {
+ StripKind::Prefix => "prefix",
+ StripKind::Suffix => "suffix",
+ };
- let test_span = expr.span.until(then.span);
- span_lint_and_then(cx, MANUAL_STRIP, strippings[0], &format!("stripping a {kind_word} manually"), |diag| {
+ let test_span = expr.span.until(then.span);
+ span_lint_and_then(
+ cx,
+ MANUAL_STRIP,
+ strippings[0],
+ &format!("stripping a {kind_word} manually"),
+ |diag| {
diag.span_note(test_span, format!("the {kind_word} was tested here"));
multispan_sugg(
diag,
&format!("try using the `strip_{kind_word}` method"),
- vec![(test_span,
- format!("if let Some(<stripped>) = {}.strip_{kind_word}({}) ",
- snippet(cx, target_arg.span, ".."),
- snippet(cx, pattern.span, "..")))]
- .into_iter().chain(strippings.into_iter().map(|span| (span, "<stripped>".into()))),
+ vec![(
+ test_span,
+ format!(
+ "if let Some(<stripped>) = {}.strip_{kind_word}({}) ",
+ snippet(cx, target_arg.span, ".."),
+ snippet(cx, pattern.span, "..")
+ ),
+ )]
+ .into_iter()
+ .chain(strippings.into_iter().map(|span| (span, "<stripped>".into()))),
);
- });
- }
+ },
+ );
}
}
}
@@ -129,15 +134,13 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip {
// Returns `Some(arg)` if `expr` matches `arg.len()` and `None` otherwise.
fn len_arg<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
- if_chain! {
- if let ExprKind::MethodCall(_, arg, [], _) = expr.kind;
- if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
- if match_def_path(cx, method_def_id, &paths::STR_LEN);
- then {
- Some(arg)
- } else {
- None
- }
+ if let ExprKind::MethodCall(_, arg, [], _) = expr.kind
+ && let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
+ && match_def_path(cx, method_def_id, &paths::STR_LEN)
+ {
+ Some(arg)
+ } else {
+ None
}
}
@@ -201,36 +204,38 @@ fn find_stripping<'tcx>(
impl<'a, 'tcx> Visitor<'tcx> for StrippingFinder<'a, 'tcx> {
fn visit_expr(&mut self, ex: &'tcx Expr<'_>) {
- if_chain! {
- if is_ref_str(self.cx, ex);
- let unref = peel_ref(ex);
- if let ExprKind::Index(indexed, index, _) = &unref.kind;
- if let Some(higher::Range { start, end, .. }) = higher::Range::hir(index);
- if let ExprKind::Path(path) = &indexed.kind;
- if self.cx.qpath_res(path, ex.hir_id) == self.target;
- then {
- match (self.strip_kind, start, end) {
- (StripKind::Prefix, Some(start), None) => {
- if eq_pattern_length(self.cx, self.pattern, start) {
- self.results.push(ex.span);
- return;
- }
- },
- (StripKind::Suffix, None, Some(end)) => {
- if_chain! {
- if let ExprKind::Binary(Spanned { node: BinOpKind::Sub, .. }, left, right) = end.kind;
- if let Some(left_arg) = len_arg(self.cx, left);
- if let ExprKind::Path(left_path) = &left_arg.kind;
- if self.cx.qpath_res(left_path, left_arg.hir_id) == self.target;
- if eq_pattern_length(self.cx, self.pattern, right);
- then {
- self.results.push(ex.span);
- return;
- }
- }
- },
- _ => {}
- }
+ if is_ref_str(self.cx, ex)
+ && let unref = peel_ref(ex)
+ && let ExprKind::Index(indexed, index, _) = &unref.kind
+ && let Some(higher::Range { start, end, .. }) = higher::Range::hir(index)
+ && let ExprKind::Path(path) = &indexed.kind
+ && self.cx.qpath_res(path, ex.hir_id) == self.target
+ {
+ match (self.strip_kind, start, end) {
+ (StripKind::Prefix, Some(start), None) => {
+ if eq_pattern_length(self.cx, self.pattern, start) {
+ self.results.push(ex.span);
+ return;
+ }
+ },
+ (StripKind::Suffix, None, Some(end)) => {
+ if let ExprKind::Binary(
+ Spanned {
+ node: BinOpKind::Sub, ..
+ },
+ left,
+ right,
+ ) = end.kind
+ && let Some(left_arg) = len_arg(self.cx, left)
+ && let ExprKind::Path(left_path) = &left_arg.kind
+ && self.cx.qpath_res(left_path, left_arg.hir_id) == self.target
+ && eq_pattern_length(self.cx, self.pattern, right)
+ {
+ self.results.push(ex.span);
+ return;
+ }
+ },
+ _ => {},
}
}