blob: 11e9862da14babdc939d411249b85c7904a68362 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
#![warn(clippy::str_split_at_newline)]
#![allow(clippy::needless_lifetimes)]
use core::str::Split;
use std::ops::Deref;
struct NotStr<'a> {
s: &'a str,
}
impl<'a> NotStr<'a> {
fn trim(&'a self) -> &'a str {
self.s
}
}
struct DerefsIntoNotStr<'a> {
not_str: &'a NotStr<'a>,
}
impl<'a> Deref for DerefsIntoNotStr<'a> {
type Target = NotStr<'a>;
fn deref(&self) -> &Self::Target {
self.not_str
}
}
struct DerefsIntoStr<'a> {
s: &'a str,
}
impl<'a> Deref for DerefsIntoStr<'a> {
type Target = str;
fn deref(&self) -> &Self::Target {
self.s
}
}
macro_rules! trim_split {
( $x:expr, $y:expr ) => {
$x.trim().split($y);
};
}
macro_rules! make_str {
( $x: expr ) => {
format!("x={}", $x)
};
}
fn main() {
let s1 = "hello\nworld\n";
let s2 = s1.to_owned();
// CASES THAT SHOULD EMIT A LINT
// Splitting a `str` variable at "\n" or "\r\n" after trimming should warn
let _ = s1.trim().split('\n');
//~^ str_split_at_newline
#[allow(clippy::single_char_pattern)]
let _ = s1.trim().split("\n");
//~^ str_split_at_newline
let _ = s1.trim().split("\r\n");
//~^ str_split_at_newline
// Splitting a `String` variable at "\n" or "\r\n" after trimming should warn
let _ = s2.trim().split('\n');
//~^ str_split_at_newline
#[allow(clippy::single_char_pattern)]
let _ = s2.trim().split("\n");
//~^ str_split_at_newline
let _ = s2.trim().split("\r\n");
//~^ str_split_at_newline
// Splitting a variable that derefs into `str` at "\n" or "\r\n" after trimming should warn.
let s3 = DerefsIntoStr { s: s1 };
let _ = s3.trim().split('\n');
//~^ str_split_at_newline
#[allow(clippy::single_char_pattern)]
let _ = s3.trim().split("\n");
//~^ str_split_at_newline
let _ = s3.trim().split("\r\n");
//~^ str_split_at_newline
// If the `&str` is generated by a macro then the macro should not be expanded in the suggested fix.
let _ = make_str!(s1).trim().split('\n');
//~^ str_split_at_newline
// CASES THAT SHOULD NOT EMIT A LINT
// Splitting a `str` constant at "\n" or "\r\n" after trimming should not warn
let _ = "hello\nworld\n".trim().split('\n');
#[allow(clippy::single_char_pattern)]
let _ = "hello\nworld\n".trim().split("\n");
let _ = "hello\nworld\n".trim().split("\r\n");
// Splitting a `str` variable at "\n" or "\r\n" without trimming should not warn, since it is not
// equivalent
let _ = s1.split('\n');
#[allow(clippy::single_char_pattern)]
let _ = s1.split("\n");
let _ = s1.split("\r\n");
// Splitting a `String` variable at "\n" or "\r\n" without trimming should not warn.
let _ = s2.split('\n');
#[allow(clippy::single_char_pattern)]
let _ = s2.split("\n");
// Splitting a variable that derefs into `str` at "\n" or "\r\n" without trimming should not warn.
let _ = s3.split('\n');
#[allow(clippy::single_char_pattern)]
let _ = s3.split("\n");
let _ = s3.split("\r\n");
let _ = s2.split("\r\n");
// Splitting a `str` variable at other separators should not warn
let _ = s1.trim().split('\r');
#[allow(clippy::single_char_pattern)]
let _ = s1.trim().split("\r");
let _ = s1.trim().split("\n\r");
let _ = s1.trim().split("\r \n");
// Splitting a `String` variable at other separators should not warn
let _ = s2.trim().split('\r');
#[allow(clippy::single_char_pattern)]
let _ = s2.trim().split("\r");
let _ = s2.trim().split("\n\r");
// Splitting a variable that derefs into `str` at other separators should not warn
let _ = s3.trim().split('\r');
#[allow(clippy::single_char_pattern)]
let _ = s3.trim().split("\r");
let _ = s3.trim().split("\n\r");
let _ = s3.trim().split("\r \n");
let _ = s2.trim().split("\r \n");
// Using `trim` and `split` on other types should not warn
let not_str = NotStr { s: s1 };
let _ = not_str.trim().split('\n');
#[allow(clippy::single_char_pattern)]
let _ = not_str.trim().split("\n");
let _ = not_str.trim().split("\r\n");
let derefs_into_not_str = DerefsIntoNotStr { not_str: ¬_str };
let _ = derefs_into_not_str.trim().split('\n');
#[allow(clippy::single_char_pattern)]
let _ = derefs_into_not_str.trim().split("\n");
let _ = derefs_into_not_str.trim().split("\r\n");
// Code generated by macros should not create a warning
trim_split!(s1, "\r\n");
trim_split!("hello\nworld\n", "\r\n");
trim_split!(s2, "\r\n");
trim_split!(s3, "\r\n");
}
|