1
1
use clippy_utils:: diagnostics:: span_lint_and_sugg;
2
2
use clippy_utils:: source:: snippet;
3
- use clippy_utils:: ty:: implements_trait;
4
3
use rustc_ast:: ast:: LitKind ;
5
4
use rustc_errors:: Applicability ;
6
5
use rustc_hir:: { Expr , ExprKind } ;
7
6
use rustc_lint:: { LateContext , LateLintPass } ;
8
7
use rustc_session:: declare_lint_pass;
9
8
10
- use rustc_span:: symbol:: sym;
11
-
12
9
declare_clippy_lint ! {
13
10
/// ### What it does
14
11
///
@@ -34,40 +31,25 @@ declare_clippy_lint! {
34
31
35
32
declare_lint_pass ! ( SplittingStringsAtNewlines => [ SPLITTING_STRINGS_AT_NEWLINES ] ) ;
36
33
37
- // Check if an expr is of a type that implements `Deref` with `Target = str`
38
- fn derefs_into_str ( cx : & LateContext < ' _ > , expr : & ' _ Expr < ' _ > ) -> bool {
39
- matches ! (
40
- cx. tcx. get_diagnostic_item( sym:: Deref ) ,
41
- Some ( def_id) if (
42
- implements_trait( cx, cx. typeck_results( ) . expr_ty( expr) , def_id, & [ ] )
43
- && matches!(
44
- cx. get_associated_type( cx. typeck_results( ) . expr_ty_adjusted( expr) , def_id, "Target" ) ,
45
- Some ( target) if target. is_str( )
46
- )
47
- )
48
- )
49
- }
50
-
51
34
impl LateLintPass < ' _ > for SplittingStringsAtNewlines {
52
35
fn check_expr ( & mut self , cx : & LateContext < ' _ > , expr : & ' _ Expr < ' _ > ) {
53
- // We're looking for `A.trim().split(B)`, where the type of `A` implements `Deref` with `Target =
54
- // str` (e.g. a `str` literal or an expression returning `String`), and `B` is a `Pattern`
55
- // that hard-codes a newline (either `"\n"` or `"\r\n"`). There are a lot of ways to specify a
56
- // pattern, and this lint only checks the most basic ones: a `'\n'`, `"\n"`, and `"\r\n"`.
36
+ // We're looking for `A.trim().split(B)`, where the adjusted type of `A` is `&str` (e.g. a `str`
37
+ // literal or an expression returning `String`), and `B` is a `Pattern` that hard-codes a
38
+ // newline (either `"\n"` or `"\r\n"`). There are a lot of ways to specify a pattern, and
39
+ // this lint only checks the most basic ones: a `'\n'`, `"\n"`, and `"\r\n"`.
57
40
58
41
if expr. span . from_expansion ( ) {
59
42
// Don't generate lints in code expanded from macros
60
43
return ;
61
44
}
62
45
63
- if let ExprKind :: MethodCall ( split_method_name, split_receiver, split_args , _) = expr. kind
46
+ if let ExprKind :: MethodCall ( split_method_name, split_receiver, [ split_arg ] , _) = expr. kind
64
47
&& split_method_name. ident . as_str ( ) == "split"
65
- && split_args. len ( ) == 1
66
48
&& let ExprKind :: MethodCall ( trim_method_name, trim_receiver, trim_args, _) = split_receiver. kind
67
49
&& trim_method_name. ident . as_str ( ) == "trim"
68
50
&& trim_args. is_empty ( )
69
- && derefs_into_str ( cx , trim_receiver)
70
- && let ExprKind :: Lit ( split_lit) = split_args [ 0 ] . kind
51
+ && cx . typeck_results ( ) . expr_ty_adjusted ( trim_receiver) . peel_refs ( ) . is_str ( )
52
+ && let ExprKind :: Lit ( split_lit) = split_arg . kind
71
53
{
72
54
let char_n = matches ! ( split_lit. node, LitKind :: Char ( '\n' ) ) ;
73
55
let str_n_or_rn =
0 commit comments