-
Notifications
You must be signed in to change notification settings - Fork 1.7k
changelog: new lint: [split_with_space
]
#13059
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,7 @@ use clippy_utils::{ | |
get_expr_use_or_unification_node, get_parent_expr, is_lint_allowed, is_path_diagnostic_item, method_calls, | ||
peel_blocks, SpanlessEq, | ||
}; | ||
use rustc_ast::ast::LitKind; | ||
use rustc_errors::Applicability; | ||
use rustc_hir::def_id::DefId; | ||
use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, LangItem, Node, QPath}; | ||
|
@@ -467,6 +468,49 @@ impl<'tcx> LateLintPass<'tcx> for StringToString { | |
} | ||
} | ||
|
||
declare_clippy_lint! { | ||
/// ### What it does | ||
/// Checks for calling `str::split` with the ASCII space character instead of `str::split_whitespace`. | ||
/// | ||
/// ### Why is this bad? | ||
/// `split` using the ASCII space character does not handle cases where there is a different space character used. `split_whitespace` handles all whitespace characters. | ||
/// | ||
/// ### Example | ||
/// ```no_run | ||
/// "A B C".split(' '); | ||
/// ``` | ||
/// Use instead: | ||
/// ```no_run | ||
/// "A B C".split_whitespace(); | ||
/// ``` | ||
#[clippy::version = "1.81.0"] | ||
pub SPLIT_WITH_SPACE, | ||
pedantic, | ||
"using `str::split` with the ASCII space character instead of `str::split_whitespace`" | ||
} | ||
declare_lint_pass!(SplitWithSpace => [SPLIT_WITH_SPACE]); | ||
|
||
impl<'tcx> LateLintPass<'tcx> for SplitWithSpace { | ||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) { | ||
if let ExprKind::MethodCall(path, _split_recv, [arg], split_ws_span) = expr.kind | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should check that the receiver is really a |
||
&& path.ident.name == sym!(split) | ||
&& let ExprKind::Lit(lit) = arg.kind | ||
&& (matches!(lit.node, LitKind::Char(' ')) | ||
|| matches!(lit.node, LitKind::Str(str, _) if str.as_str() == " ")) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There should be a check here that this isn't from a macro, (or at least, not from an external macro since the user can't change that, can use |
||
{ | ||
span_lint_and_sugg( | ||
cx, | ||
SPLIT_WITH_SPACE, | ||
split_ws_span.with_hi(split_ws_span.lo()), | ||
"found call to `str::split` that uses the ASCII space character as an argument".to_string(), | ||
"replace the use of `str::split` with `str::split_whitespace`".to_string(), | ||
String::new(), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The current span & suggestion seems to replace nothing? I think it would be good to use
|
||
Applicability::MachineApplicable, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ...It should probably not be MachineApplicable though. Although in the majority of cases I imagine this is strictly more correct, there might be weird edge cases where people do want to split by exactly that, and rely on |
||
); | ||
} | ||
} | ||
} | ||
|
||
declare_clippy_lint! { | ||
/// ### What it does | ||
/// Warns about calling `str::trim` (or variants) before `str::split_whitespace`. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
//@aux-build:proc_macros.rs | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This test links proc_macros.rs but never actually uses it. It probably should, though, so this is a good idea. Can you add a test with proc macros? You can look at e.g. this file to see how to write a test that uses this. |
||
//@no-rustfix | ||
|
||
#[deny(clippy::split_with_space)] | ||
#[allow(unused)] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think |
||
fn main() { | ||
let some_space_delimtetered_string = "Hello everyone! How are you doing?"; | ||
|
||
for substr in some_space_delimtetered_string.split(' ') { | ||
println!("{substr}"); | ||
} | ||
|
||
for substr in some_space_delimtetered_string.split(" ") { | ||
println!("{substr}"); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There should be some negative tests, e.g. splitting by something that isn't a space. |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
error: found call to `str::split` that uses the ASCII space character as an argument | ||
--> tests/ui/split_with_space.rs:9:50 | ||
| | ||
LL | for substr in some_space_delimtetered_string.split(' ') { | ||
| ^ help: replace the use of `str::split` with `str::split_whitespace` | ||
| | ||
note: the lint level is defined here | ||
--> tests/ui/split_with_space.rs:4:8 | ||
| | ||
LL | #[deny(clippy::split_with_space)] | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
error: found call to `str::split` that uses the ASCII space character as an argument | ||
--> tests/ui/split_with_space.rs:13:50 | ||
| | ||
LL | for substr in some_space_delimtetered_string.split(" ") { | ||
| ^ help: replace the use of `str::split` with `str::split_whitespace` | ||
|
||
error: aborting due to 2 previous errors | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be good to mention that split_whitespace also handles multiple consecutive spaces