Skip to content

Commit

Permalink
8733: Simplify code
Browse files Browse the repository at this point in the history
Following the suggestions of @y21 in rust-lang#11987.
  • Loading branch information
torfsen committed Dec 21, 2023
1 parent ee170c1 commit c05c79e
Showing 1 changed file with 7 additions and 25 deletions.
32 changes: 7 additions & 25 deletions clippy_lints/src/splitting_strings_at_newlines.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet;
use clippy_utils::ty::implements_trait;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;

use rustc_span::symbol::sym;

declare_clippy_lint! {
/// ### What it does
///
Expand All @@ -34,40 +31,25 @@ declare_clippy_lint! {

declare_lint_pass!(SplittingStringsAtNewlines => [SPLITTING_STRINGS_AT_NEWLINES]);

// Check if an expr is of a type that implements `Deref` with `Target = str`
fn derefs_into_str(cx: &LateContext<'_>, expr: &'_ Expr<'_>) -> bool {
matches!(
cx.tcx.get_diagnostic_item(sym::Deref),
Some(def_id) if (
implements_trait(cx, cx.typeck_results().expr_ty(expr), def_id, &[])
&& matches!(
cx.get_associated_type(cx.typeck_results().expr_ty_adjusted(expr), def_id, "Target"),
Some(target) if target.is_str()
)
)
)
}

impl LateLintPass<'_> for SplittingStringsAtNewlines {
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) {
// We're looking for `A.trim().split(B)`, where the type of `A` implements `Deref` with `Target =
// str` (e.g. a `str` literal or an expression returning `String`), and `B` is a `Pattern`
// that hard-codes a newline (either `"\n"` or `"\r\n"`). There are a lot of ways to specify a
// pattern, and this lint only checks the most basic ones: a `'\n'`, `"\n"`, and `"\r\n"`.
// We're looking for `A.trim().split(B)`, where the adjusted type of `A` is `&str` (e.g. a `str`
// literal or an expression returning `String`), and `B` is a `Pattern` that hard-codes a
// newline (either `"\n"` or `"\r\n"`). There are a lot of ways to specify a pattern, and
// this lint only checks the most basic ones: a `'\n'`, `"\n"`, and `"\r\n"`.

if expr.span.from_expansion() {
// Don't generate lints in code expanded from macros
return;
}

if let ExprKind::MethodCall(split_method_name, split_receiver, split_args, _) = expr.kind
if let ExprKind::MethodCall(split_method_name, split_receiver, [split_arg], _) = expr.kind
&& split_method_name.ident.as_str() == "split"
&& split_args.len() == 1
&& let ExprKind::MethodCall(trim_method_name, trim_receiver, trim_args, _) = split_receiver.kind
&& trim_method_name.ident.as_str() == "trim"
&& trim_args.is_empty()
&& derefs_into_str(cx, trim_receiver)
&& let ExprKind::Lit(split_lit) = split_args[0].kind
&& cx.typeck_results().expr_ty_adjusted(trim_receiver).peel_refs().is_str()
&& let ExprKind::Lit(split_lit) = split_arg.kind
{
let char_n = matches!(split_lit.node, LitKind::Char('\n'));
let str_n_or_rn =
Expand Down

0 comments on commit c05c79e

Please sign in to comment.