Skip to content

Commit b83678b

Browse files
Improve code and apply suggestions
1 parent 7b06d2b commit b83678b

File tree

5 files changed

+116
-12
lines changed

5 files changed

+116
-12
lines changed

clippy_lints/src/useless_concat.rs

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
22
use clippy_utils::macros::macro_backtrace;
33
use clippy_utils::paths::CONCAT;
44
use clippy_utils::source::snippet_opt;
5-
use clippy_utils::{match_def_path, tokenize_with_text};
5+
use clippy_utils::tokenize_with_text;
66
use rustc_ast::LitKind;
77
use rustc_errors::Applicability;
88
use rustc_hir::{Expr, ExprKind};
@@ -43,7 +43,7 @@ impl LateLintPass<'_> for UselessConcat {
4343
// Get the direct parent of the expression.
4444
&& let Some(macro_call) = macro_backtrace(expr.span).next()
4545
// Check if the `concat` macro from the `core` library.
46-
&& match_def_path(cx, macro_call.def_id, &CONCAT)
46+
&& CONCAT.matches(cx, macro_call.def_id)
4747
// We get the original code to parse it.
4848
&& let Some(original_code) = snippet_opt(cx, macro_call.span)
4949
// This check allows us to ensure that the code snippet:
@@ -68,7 +68,13 @@ impl LateLintPass<'_> for UselessConcat {
6868
}
6969
literal = Some(token_s);
7070
},
71-
TokenKind::Ident => nb_idents += 1,
71+
TokenKind::Ident => {
72+
if token_s == "true" || token_s == "false" {
73+
literal = Some(token_s);
74+
} else {
75+
nb_idents += 1;
76+
}
77+
},
7278
TokenKind::Comma => {
7379
nb_commas += 1;
7480
if nb_commas > 1 {
@@ -82,12 +88,46 @@ impl LateLintPass<'_> for UselessConcat {
8288
}
8389
}
8490
let literal = match literal {
85-
Some(lit) => {
91+
Some(original_lit) => {
8692
// Literals can also be number, so we need to check this case too.
93+
let lit = original_lit.strip_prefix("r").unwrap_or(original_lit);
94+
let lit = lit.trim_start_matches('#');
8795
if lit.starts_with('"') {
88-
lit.to_string()
96+
// It's a string, nothing to be done.
97+
original_lit.to_string()
98+
} else if original_lit.starts_with('\'') {
99+
format!(
100+
"\"{}\"",
101+
original_lit
102+
.strip_prefix('\'')
103+
.and_then(|l| l.strip_suffix('\''))
104+
.unwrap_or(original_lit)
105+
)
106+
} else if original_lit == "true" || original_lit == "false" {
107+
// It's a boolean so nothing else to be done.
108+
format!("\"{original_lit}\"")
89109
} else {
90-
format!("\"{lit}\"")
110+
format!(
111+
"\"{}\"",
112+
original_lit
113+
.strip_suffix("f16")
114+
.or_else(|| original_lit.strip_suffix("f32"))
115+
.or_else(|| original_lit.strip_suffix("f64"))
116+
.or_else(|| original_lit.strip_suffix("128")) // We never know?
117+
.or_else(|| original_lit.strip_suffix("u8"))
118+
.or_else(|| original_lit.strip_suffix("u16"))
119+
.or_else(|| original_lit.strip_suffix("u32"))
120+
.or_else(|| original_lit.strip_suffix("u64"))
121+
.or_else(|| original_lit.strip_suffix("u128"))
122+
.or_else(|| original_lit.strip_suffix("usize"))
123+
.or_else(|| original_lit.strip_suffix("i8"))
124+
.or_else(|| original_lit.strip_suffix("i16"))
125+
.or_else(|| original_lit.strip_suffix("i32"))
126+
.or_else(|| original_lit.strip_suffix("i64"))
127+
.or_else(|| original_lit.strip_suffix("i128"))
128+
.or_else(|| original_lit.strip_suffix("isize"))
129+
.unwrap_or(original_lit)
130+
)
91131
}
92132
},
93133
None => "\"\"".to_string(),

clippy_utils/src/paths.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,12 +129,14 @@ path_macros! {
129129
// Paths in `core`/`alloc`/`std`. This should be avoided and cleaned up by adding diagnostic items.
130130
pub static ALIGN_OF: PathLookup = value_path!(core::mem::align_of);
131131
pub static CHAR_TO_DIGIT: PathLookup = value_path!(char::to_digit);
132-
pub static CONCAT: PathLookup = value_path!(core::macros::builtin::concat);
133132
pub static IO_ERROR_NEW: PathLookup = value_path!(std::io::Error::new);
134133
pub static IO_ERRORKIND_OTHER_CTOR: PathLookup = value_path!(std::io::ErrorKind::Other);
135134
pub static ITER_STEP: PathLookup = type_path!(core::iter::Step);
136135
pub static SLICE_FROM_REF: PathLookup = value_path!(core::slice::from_ref);
137136

137+
// This path is wrongly computed when using `PathLookup`.
138+
pub static CONCAT: PathLookup = macro_path!(core::concat);
139+
138140
// Paths in external crates
139141
pub static FUTURES_IO_ASYNCREADEXT: PathLookup = type_path!(futures_util::AsyncReadExt);
140142
pub static FUTURES_IO_ASYNCWRITEEXT: PathLookup = type_path!(futures_util::AsyncWriteExt);

tests/ui/useless_concat.fixed

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1+
//@aux-build:proc_macros.rs
2+
13
#![warn(clippy::useless_concat)]
24
#![allow(clippy::print_literal)]
35

6+
extern crate proc_macros;
7+
use proc_macros::{external, with_span};
8+
49
macro_rules! my_concat {
510
($fmt:literal $(, $e:expr)*) => {
611
println!(concat!("ERROR: ", $fmt), $($e,)*);
@@ -9,12 +14,23 @@ macro_rules! my_concat {
914

1015
fn main() {
1116
let x = ""; //~ useless_concat
17+
let x = "c"; //~ useless_concat
18+
let x = "true"; //~ useless_concat
19+
let x = "1"; //~ useless_concat
20+
let x = "1.0000"; //~ useless_concat
1221
let x = "a"; //~ useless_concat
22+
let x = r##"a"##; //~ useless_concat
1323
let x = "1"; //~ useless_concat
1424
println!("b: {}", "a"); //~ useless_concat
1525
// Should not lint.
1626
let x = concat!("a", "b");
1727
let local_i32 = 1;
1828
my_concat!("{}", local_i32);
1929
let x = concat!(file!(), "#L", line!());
30+
31+
external! { concat!(); }
32+
with_span! {
33+
span
34+
concat!();
35+
}
2036
}

tests/ui/useless_concat.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1+
//@aux-build:proc_macros.rs
2+
13
#![warn(clippy::useless_concat)]
24
#![allow(clippy::print_literal)]
35

6+
extern crate proc_macros;
7+
use proc_macros::{external, with_span};
8+
49
macro_rules! my_concat {
510
($fmt:literal $(, $e:expr)*) => {
611
println!(concat!("ERROR: ", $fmt), $($e,)*);
@@ -9,12 +14,23 @@ macro_rules! my_concat {
914

1015
fn main() {
1116
let x = concat!(); //~ useless_concat
17+
let x = concat!('c'); //~ useless_concat
18+
let x = concat!(true); //~ useless_concat
19+
let x = concat!(1f32); //~ useless_concat
20+
let x = concat!(1.0000f32); //~ useless_concat
1221
let x = concat!("a"); //~ useless_concat
22+
let x = concat!(r##"a"##); //~ useless_concat
1323
let x = concat!(1); //~ useless_concat
1424
println!("b: {}", concat!("a")); //~ useless_concat
1525
// Should not lint.
1626
let x = concat!("a", "b");
1727
let local_i32 = 1;
1828
my_concat!("{}", local_i32);
1929
let x = concat!(file!(), "#L", line!());
30+
31+
external! { concat!(); }
32+
with_span! {
33+
span
34+
concat!();
35+
}
2036
}

tests/ui/useless_concat.stderr

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: unneeded use of `concat!` macro
2-
--> tests/ui/useless_concat.rs:11:13
2+
--> tests/ui/useless_concat.rs:16:13
33
|
44
LL | let x = concat!();
55
| ^^^^^^^^^ help: replace with: `""`
@@ -8,22 +8,52 @@ LL | let x = concat!();
88
= help: to override `-D warnings` add `#[allow(clippy::useless_concat)]`
99

1010
error: unneeded use of `concat!` macro
11-
--> tests/ui/useless_concat.rs:12:13
11+
--> tests/ui/useless_concat.rs:17:13
12+
|
13+
LL | let x = concat!('c');
14+
| ^^^^^^^^^^^^ help: replace with: `"c"`
15+
16+
error: unneeded use of `concat!` macro
17+
--> tests/ui/useless_concat.rs:18:13
18+
|
19+
LL | let x = concat!(true);
20+
| ^^^^^^^^^^^^^ help: replace with: `"true"`
21+
22+
error: unneeded use of `concat!` macro
23+
--> tests/ui/useless_concat.rs:19:13
24+
|
25+
LL | let x = concat!(1f32);
26+
| ^^^^^^^^^^^^^ help: replace with: `"1"`
27+
28+
error: unneeded use of `concat!` macro
29+
--> tests/ui/useless_concat.rs:20:13
30+
|
31+
LL | let x = concat!(1.0000f32);
32+
| ^^^^^^^^^^^^^^^^^^ help: replace with: `"1.0000"`
33+
34+
error: unneeded use of `concat!` macro
35+
--> tests/ui/useless_concat.rs:21:13
1236
|
1337
LL | let x = concat!("a");
1438
| ^^^^^^^^^^^^ help: replace with: `"a"`
1539

1640
error: unneeded use of `concat!` macro
17-
--> tests/ui/useless_concat.rs:13:13
41+
--> tests/ui/useless_concat.rs:22:13
42+
|
43+
LL | let x = concat!(r##"a"##);
44+
| ^^^^^^^^^^^^^^^^^ help: replace with: `r##"a"##`
45+
46+
error: unneeded use of `concat!` macro
47+
--> tests/ui/useless_concat.rs:23:13
1848
|
1949
LL | let x = concat!(1);
2050
| ^^^^^^^^^^ help: replace with: `"1"`
2151

2252
error: unneeded use of `concat!` macro
23-
--> tests/ui/useless_concat.rs:14:23
53+
--> tests/ui/useless_concat.rs:24:23
2454
|
2555
LL | println!("b: {}", concat!("a"));
2656
| ^^^^^^^^^^^^ help: replace with: `"a"`
2757

28-
error: aborting due to 4 previous errors
58+
error: aborting due to 9 previous errors
2959

0 commit comments

Comments
 (0)