Skip to content

Commit bcb0b51

Browse files
committed
8733: Move lint to methods type
1 parent 4153141 commit bcb0b51

File tree

9 files changed

+89
-96
lines changed

9 files changed

+89
-96
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5576,10 +5576,10 @@ Released 2018-09-13
55765576
[`size_of_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#size_of_ref
55775577
[`skip_while_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#skip_while_next
55785578
[`slow_vector_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#slow_vector_initialization
5579-
[`splitting_strings_at_newlines`]: https://rust-lang.github.io/rust-clippy/master/index.html#splitting_strings_at_newlines
55805579
[`stable_sort_primitive`]: https://rust-lang.github.io/rust-clippy/master/index.html#stable_sort_primitive
55815580
[`std_instead_of_alloc`]: https://rust-lang.github.io/rust-clippy/master/index.html#std_instead_of_alloc
55825581
[`std_instead_of_core`]: https://rust-lang.github.io/rust-clippy/master/index.html#std_instead_of_core
5582+
[`str_split_at_newline`]: https://rust-lang.github.io/rust-clippy/master/index.html#str_split_at_newline
55835583
[`str_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#str_to_string
55845584
[`string_add`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_add
55855585
[`string_add_assign`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_add_assign

clippy_lints/src/declared_lints.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
433433
crate::methods::STABLE_SORT_PRIMITIVE_INFO,
434434
crate::methods::STRING_EXTEND_CHARS_INFO,
435435
crate::methods::STRING_LIT_CHARS_ANY_INFO,
436+
crate::methods::STR_SPLIT_AT_NEWLINE_INFO,
436437
crate::methods::SUSPICIOUS_COMMAND_ARG_SPACE_INFO,
437438
crate::methods::SUSPICIOUS_MAP_INFO,
438439
crate::methods::SUSPICIOUS_SPLITN_INFO,
@@ -626,7 +627,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
626627
crate::size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT_INFO,
627628
crate::size_of_ref::SIZE_OF_REF_INFO,
628629
crate::slow_vector_initialization::SLOW_VECTOR_INITIALIZATION_INFO,
629-
crate::splitting_strings_at_newlines::SPLITTING_STRINGS_AT_NEWLINES_INFO,
630630
crate::std_instead_of_core::ALLOC_INSTEAD_OF_CORE_INFO,
631631
crate::std_instead_of_core::STD_INSTEAD_OF_ALLOC_INFO,
632632
crate::std_instead_of_core::STD_INSTEAD_OF_CORE_INFO,

clippy_lints/src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,6 @@ mod single_range_in_vec_init;
310310
mod size_of_in_element_count;
311311
mod size_of_ref;
312312
mod slow_vector_initialization;
313-
mod splitting_strings_at_newlines;
314313
mod std_instead_of_core;
315314
mod strings;
316315
mod strlen_on_c_strings;
@@ -1081,7 +1080,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
10811080
store.register_late_pass(|_| Box::new(uninhabited_references::UninhabitedReferences));
10821081
store.register_late_pass(|_| Box::new(ineffective_open_options::IneffectiveOpenOptions));
10831082
store.register_late_pass(|_| Box::new(unconditional_recursion::UnconditionalRecursion));
1084-
store.register_late_pass(|_| Box::new(splitting_strings_at_newlines::SplittingStringsAtNewlines));
10851083
// add lints here, do not remove this comment, it's used in `new_lint`
10861084
}
10871085

clippy_lints/src/methods/mod.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ mod single_char_pattern;
9393
mod single_char_push_string;
9494
mod skip_while_next;
9595
mod stable_sort_primitive;
96+
mod str_split;
9697
mod str_splitn;
9798
mod string_extend_chars;
9899
mod string_lit_chars_any;
@@ -3829,6 +3830,29 @@ declare_clippy_lint! {
38293830
"filtering an iterator over `Result`s for `Ok` can be achieved with `flatten`"
38303831
}
38313832

3833+
declare_clippy_lint! {
3834+
/// ### What it does
3835+
///
3836+
/// Checks for usages of `str.trim().split("\n")` and `str.trim().split("\r\n")`.
3837+
///
3838+
/// ### Why is this bad?
3839+
///
3840+
/// Hard-coding the line endings makes the code less portable. `str.lines` should be used instead.
3841+
///
3842+
/// ### Example
3843+
/// ```no_run
3844+
/// "some\ntext\nwith\nnewlines\n".trim().split('\n');
3845+
/// ```
3846+
/// Use instead:
3847+
/// ```no_run
3848+
/// "some\ntext\nwith\nnewlines\n".lines();
3849+
/// ```
3850+
#[clippy::version = "1.76.0"]
3851+
pub STR_SPLIT_AT_NEWLINE,
3852+
suspicious,
3853+
"splitting a trimmed string at hard-coded newlines"
3854+
}
3855+
38323856
pub struct Methods {
38333857
avoid_breaking_exported_api: bool,
38343858
msrv: Msrv,
@@ -3983,6 +4007,7 @@ impl_lint_pass!(Methods => [
39834007
RESULT_FILTER_MAP,
39844008
ITER_FILTER_IS_SOME,
39854009
ITER_FILTER_IS_OK,
4010+
STR_SPLIT_AT_NEWLINE,
39864011
]);
39874012

39884013
/// Extracts a method call name, args, and `Span` of the method name.
@@ -4569,6 +4594,9 @@ impl Methods {
45694594
("sort_unstable_by", [arg]) => {
45704595
unnecessary_sort_by::check(cx, expr, recv, arg, true);
45714596
},
4597+
("split", [arg]) => {
4598+
str_split::check(cx, expr, recv, arg);
4599+
},
45724600
("splitn" | "rsplitn", [count_arg, pat_arg]) => {
45734601
if let Some(Constant::Int(count)) = constant(cx, cx.typeck_results(), count_arg) {
45744602
suspicious_splitn::check(cx, name, expr, recv, count);

clippy_lints/src/methods/str_split.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
use clippy_utils::diagnostics::span_lint_and_sugg;
2+
use clippy_utils::source::snippet_with_context;
3+
use rustc_ast::ast::LitKind;
4+
use rustc_errors::Applicability;
5+
use rustc_hir::{Expr, ExprKind};
6+
use rustc_lint::LateContext;
7+
8+
use super::STR_SPLIT_AT_NEWLINE;
9+
10+
pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, split_recv: &'_ Expr<'_>, split_arg: &'_ Expr<'_>) {
11+
// We're looking for `A.trim().split(B)`, where the adjusted type of `A` is `&str` (e.g. a `str`
12+
// literal or an expression returning `String`), and `B` is a `Pattern` that hard-codes a
13+
// newline (either `"\n"` or `"\r\n"`). There are a lot of ways to specify a pattern, and
14+
// this lint only checks the most basic ones: a `'\n'`, `"\n"`, and `"\r\n"`.
15+
16+
if let ExprKind::MethodCall(trim_method_name, trim_recv, trim_args, _) = split_recv.kind
17+
&& trim_method_name.ident.as_str() == "trim"
18+
&& trim_args.is_empty()
19+
&& cx.typeck_results().expr_ty_adjusted(trim_recv).peel_refs().is_str()
20+
&& let ExprKind::Lit(split_lit) = split_arg.kind
21+
{
22+
let char_n = matches!(split_lit.node, LitKind::Char('\n'));
23+
let str_n_or_rn =
24+
matches!(split_lit.node, LitKind::Str(sym, _) if (sym.as_str() == "\n" || sym.as_str() == "\r\n"));
25+
26+
if char_n || str_n_or_rn {
27+
let mut app = Applicability::MachineApplicable;
28+
span_lint_and_sugg(
29+
cx,
30+
STR_SPLIT_AT_NEWLINE,
31+
expr.span,
32+
"using `str.trim().split()` with hard-coded newlines is not portable",
33+
"use `str.lines()` instead",
34+
format!(
35+
"{}.lines()",
36+
snippet_with_context(cx, trim_recv.span, expr.span.ctxt(), "..", &mut app).0
37+
),
38+
app,
39+
);
40+
}
41+
}
42+
}

clippy_lints/src/splitting_strings_at_newlines.rs

Lines changed: 0 additions & 75 deletions
This file was deleted.

tests/ui/splitting_strings_at_newlines.fixed renamed to tests/ui/str_split.fixed

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![warn(clippy::splitting_strings_at_newlines)]
1+
#![warn(clippy::str_split_at_newline)]
22

33
use core::str::Split;
44
use std::ops::Deref;

tests/ui/splitting_strings_at_newlines.rs renamed to tests/ui/str_split.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![warn(clippy::splitting_strings_at_newlines)]
1+
#![warn(clippy::str_split_at_newline)]
22

33
use core::str::Split;
44
use std::ops::Deref;

tests/ui/splitting_strings_at_newlines.stderr renamed to tests/ui/str_split.stderr

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,80 @@
11
error: using `str.trim().split()` with hard-coded newlines is not portable
2-
--> $DIR/splitting_strings_at_newlines.rs:59:13
2+
--> $DIR/str_split.rs:59:13
33
|
44
LL | let _ = s1.trim().split('\n');
55
| ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s1.lines()`
66
|
7-
= note: `-D clippy::splitting-strings-at-newlines` implied by `-D warnings`
8-
= help: to override `-D warnings` add `#[allow(clippy::splitting_strings_at_newlines)]`
7+
= note: `-D clippy::str-split-at-newline` implied by `-D warnings`
8+
= help: to override `-D warnings` add `#[allow(clippy::str_split_at_newline)]`
99

1010
error: using `str.trim().split()` with hard-coded newlines is not portable
11-
--> $DIR/splitting_strings_at_newlines.rs:61:13
11+
--> $DIR/str_split.rs:61:13
1212
|
1313
LL | let _ = s1.trim().split("\n");
1414
| ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s1.lines()`
1515

1616
error: using `str.trim().split()` with hard-coded newlines is not portable
17-
--> $DIR/splitting_strings_at_newlines.rs:62:13
17+
--> $DIR/str_split.rs:62:13
1818
|
1919
LL | let _ = s1.trim().split("\r\n");
2020
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s1.lines()`
2121

2222
error: using `str.trim().split()` with hard-coded newlines is not portable
23-
--> $DIR/splitting_strings_at_newlines.rs:65:13
23+
--> $DIR/str_split.rs:65:13
2424
|
2525
LL | let _ = "hello\nworld\n".trim().split('\n');
2626
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `"hello\nworld\n".lines()`
2727

2828
error: using `str.trim().split()` with hard-coded newlines is not portable
29-
--> $DIR/splitting_strings_at_newlines.rs:67:13
29+
--> $DIR/str_split.rs:67:13
3030
|
3131
LL | let _ = "hello\nworld\n".trim().split("\n");
3232
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `"hello\nworld\n".lines()`
3333

3434
error: using `str.trim().split()` with hard-coded newlines is not portable
35-
--> $DIR/splitting_strings_at_newlines.rs:68:13
35+
--> $DIR/str_split.rs:68:13
3636
|
3737
LL | let _ = "hello\nworld\n".trim().split("\r\n");
3838
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `"hello\nworld\n".lines()`
3939

4040
error: using `str.trim().split()` with hard-coded newlines is not portable
41-
--> $DIR/splitting_strings_at_newlines.rs:71:13
41+
--> $DIR/str_split.rs:71:13
4242
|
4343
LL | let _ = s2.trim().split('\n');
4444
| ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s2.lines()`
4545

4646
error: using `str.trim().split()` with hard-coded newlines is not portable
47-
--> $DIR/splitting_strings_at_newlines.rs:73:13
47+
--> $DIR/str_split.rs:73:13
4848
|
4949
LL | let _ = s2.trim().split("\n");
5050
| ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s2.lines()`
5151

5252
error: using `str.trim().split()` with hard-coded newlines is not portable
53-
--> $DIR/splitting_strings_at_newlines.rs:74:13
53+
--> $DIR/str_split.rs:74:13
5454
|
5555
LL | let _ = s2.trim().split("\r\n");
5656
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s2.lines()`
5757

5858
error: using `str.trim().split()` with hard-coded newlines is not portable
59-
--> $DIR/splitting_strings_at_newlines.rs:78:13
59+
--> $DIR/str_split.rs:78:13
6060
|
6161
LL | let _ = s3.trim().split('\n');
6262
| ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s3.lines()`
6363

6464
error: using `str.trim().split()` with hard-coded newlines is not portable
65-
--> $DIR/splitting_strings_at_newlines.rs:80:13
65+
--> $DIR/str_split.rs:80:13
6666
|
6767
LL | let _ = s3.trim().split("\n");
6868
| ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s3.lines()`
6969

7070
error: using `str.trim().split()` with hard-coded newlines is not portable
71-
--> $DIR/splitting_strings_at_newlines.rs:81:13
71+
--> $DIR/str_split.rs:81:13
7272
|
7373
LL | let _ = s3.trim().split("\r\n");
7474
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s3.lines()`
7575

7676
error: using `str.trim().split()` with hard-coded newlines is not portable
77-
--> $DIR/splitting_strings_at_newlines.rs:84:13
77+
--> $DIR/str_split.rs:84:13
7878
|
7979
LL | let _ = make_str!().trim().split('\n');
8080
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `make_str!().lines()`

0 commit comments

Comments
 (0)