about summary refs log tree commit diff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/ui/str_split.fixed145
-rw-r--r--tests/ui/str_split.rs145
-rw-r--r--tests/ui/str_split.stderr65
3 files changed, 355 insertions, 0 deletions
diff --git a/tests/ui/str_split.fixed b/tests/ui/str_split.fixed
new file mode 100644
index 00000000000..4f33241da7a
--- /dev/null
+++ b/tests/ui/str_split.fixed
@@ -0,0 +1,145 @@
+#![warn(clippy::str_split_at_newline)]
+
+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.lines();
+    #[allow(clippy::single_char_pattern)]
+    let _ = s1.lines();
+    let _ = s1.lines();
+
+    // Splitting a `String` variable at "\n" or "\r\n" after trimming should warn
+    let _ = s2.lines();
+    #[allow(clippy::single_char_pattern)]
+    let _ = s2.lines();
+    let _ = s2.lines();
+
+    // Splitting a variable that derefs into `str` at "\n" or "\r\n" after trimming should warn.
+    let s3 = DerefsIntoStr { s: s1 };
+    let _ = s3.lines();
+    #[allow(clippy::single_char_pattern)]
+    let _ = s3.lines();
+    let _ = s3.lines();
+
+    // If the `&str` is generated by a macro then the macro should not be expanded in the suggested fix.
+    let _ = make_str!(s1).lines();
+
+    // 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: &not_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");
+}
diff --git a/tests/ui/str_split.rs b/tests/ui/str_split.rs
new file mode 100644
index 00000000000..f24caa61c30
--- /dev/null
+++ b/tests/ui/str_split.rs
@@ -0,0 +1,145 @@
+#![warn(clippy::str_split_at_newline)]
+
+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');
+    #[allow(clippy::single_char_pattern)]
+    let _ = s1.trim().split("\n");
+    let _ = s1.trim().split("\r\n");
+
+    // Splitting a `String` variable at "\n" or "\r\n" after trimming should warn
+    let _ = s2.trim().split('\n');
+    #[allow(clippy::single_char_pattern)]
+    let _ = s2.trim().split("\n");
+    let _ = s2.trim().split("\r\n");
+
+    // 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');
+    #[allow(clippy::single_char_pattern)]
+    let _ = s3.trim().split("\n");
+    let _ = s3.trim().split("\r\n");
+
+    // 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');
+
+    // 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: &not_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");
+}
diff --git a/tests/ui/str_split.stderr b/tests/ui/str_split.stderr
new file mode 100644
index 00000000000..ee0a9653711
--- /dev/null
+++ b/tests/ui/str_split.stderr
@@ -0,0 +1,65 @@
+error: using `str.trim().split()` with hard-coded newlines
+  --> $DIR/str_split.rs:59:13
+   |
+LL |     let _ = s1.trim().split('\n');
+   |             ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s1.lines()`
+   |
+   = note: `-D clippy::str-split-at-newline` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::str_split_at_newline)]`
+
+error: using `str.trim().split()` with hard-coded newlines
+  --> $DIR/str_split.rs:61:13
+   |
+LL |     let _ = s1.trim().split("\n");
+   |             ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s1.lines()`
+
+error: using `str.trim().split()` with hard-coded newlines
+  --> $DIR/str_split.rs:62:13
+   |
+LL |     let _ = s1.trim().split("\r\n");
+   |             ^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s1.lines()`
+
+error: using `str.trim().split()` with hard-coded newlines
+  --> $DIR/str_split.rs:65:13
+   |
+LL |     let _ = s2.trim().split('\n');
+   |             ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s2.lines()`
+
+error: using `str.trim().split()` with hard-coded newlines
+  --> $DIR/str_split.rs:67:13
+   |
+LL |     let _ = s2.trim().split("\n");
+   |             ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s2.lines()`
+
+error: using `str.trim().split()` with hard-coded newlines
+  --> $DIR/str_split.rs:68:13
+   |
+LL |     let _ = s2.trim().split("\r\n");
+   |             ^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s2.lines()`
+
+error: using `str.trim().split()` with hard-coded newlines
+  --> $DIR/str_split.rs:72:13
+   |
+LL |     let _ = s3.trim().split('\n');
+   |             ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s3.lines()`
+
+error: using `str.trim().split()` with hard-coded newlines
+  --> $DIR/str_split.rs:74:13
+   |
+LL |     let _ = s3.trim().split("\n");
+   |             ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s3.lines()`
+
+error: using `str.trim().split()` with hard-coded newlines
+  --> $DIR/str_split.rs:75:13
+   |
+LL |     let _ = s3.trim().split("\r\n");
+   |             ^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s3.lines()`
+
+error: using `str.trim().split()` with hard-coded newlines
+  --> $DIR/str_split.rs:78:13
+   |
+LL |     let _ = make_str!(s1).trim().split('\n');
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `make_str!(s1).lines()`
+
+error: aborting due to 10 previous errors
+