| #![warn(clippy::str_split_at_newline)] | |
| 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"); | |
| } |