Support user format-like macros
Add support for `#[clippy::format_args]` attribute that can be attached to any macro to indicate that it functions the same as the built-in format macros like `format!`, `println!` and `write!`
This commit is contained in:
parent
627363e811
commit
81dceed8ba
13 changed files with 406 additions and 9 deletions
|
|
@ -119,3 +119,32 @@ fn test2() {
|
|||
format!("something failed at {}", Location::caller())
|
||||
);
|
||||
}
|
||||
|
||||
#[clippy::format_args]
|
||||
macro_rules! usr_println {
|
||||
($target:expr, $($args:tt)*) => {{
|
||||
if $target {
|
||||
println!($($args)*)
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
fn user_format() {
|
||||
let error = Error::new(ErrorKind::Other, "bad thing");
|
||||
let x = 'x';
|
||||
|
||||
usr_println!(true, "error: {}", format!("boom at {}", Location::caller()));
|
||||
//~^ ERROR: `format!` in `usr_println!` args
|
||||
usr_println!(true, "{}: {}", error, format!("boom at {}", Location::caller()));
|
||||
//~^ ERROR: `format!` in `usr_println!` args
|
||||
usr_println!(true, "{:?}: {}", error, format!("boom at {}", Location::caller()));
|
||||
//~^ ERROR: `format!` in `usr_println!` args
|
||||
usr_println!(true, "{{}}: {}", format!("boom at {}", Location::caller()));
|
||||
//~^ ERROR: `format!` in `usr_println!` args
|
||||
usr_println!(true, r#"error: "{}""#, format!("boom at {}", Location::caller()));
|
||||
//~^ ERROR: `format!` in `usr_println!` args
|
||||
usr_println!(true, "error: {}", format!(r#"boom at "{}""#, Location::caller()));
|
||||
//~^ ERROR: `format!` in `usr_println!` args
|
||||
usr_println!(true, "error: {}", format!("boom at {} {0}", Location::caller()));
|
||||
//~^ ERROR: `format!` in `usr_println!` args
|
||||
}
|
||||
|
|
|
|||
|
|
@ -174,5 +174,68 @@ LL | panic!("error: {}", format!("something failed at {}", Location::caller(
|
|||
= help: combine the `format!(..)` arguments with the outer `panic!(..)` call
|
||||
= help: or consider changing `format!` to `format_args!`
|
||||
|
||||
error: aborting due to 18 previous errors
|
||||
error: `format!` in `usr_println!` args
|
||||
--> tests/ui/format_args_unfixable.rs:136:5
|
||||
|
|
||||
LL | usr_println!(true, "error: {}", format!("boom at {}", Location::caller()));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: combine the `format!(..)` arguments with the outer `usr_println!(..)` call
|
||||
= help: or consider changing `format!` to `format_args!`
|
||||
|
||||
error: `format!` in `usr_println!` args
|
||||
--> tests/ui/format_args_unfixable.rs:138:5
|
||||
|
|
||||
LL | usr_println!(true, "{}: {}", error, format!("boom at {}", Location::caller()));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: combine the `format!(..)` arguments with the outer `usr_println!(..)` call
|
||||
= help: or consider changing `format!` to `format_args!`
|
||||
|
||||
error: `format!` in `usr_println!` args
|
||||
--> tests/ui/format_args_unfixable.rs:140:5
|
||||
|
|
||||
LL | usr_println!(true, "{:?}: {}", error, format!("boom at {}", Location::caller()));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: combine the `format!(..)` arguments with the outer `usr_println!(..)` call
|
||||
= help: or consider changing `format!` to `format_args!`
|
||||
|
||||
error: `format!` in `usr_println!` args
|
||||
--> tests/ui/format_args_unfixable.rs:142:5
|
||||
|
|
||||
LL | usr_println!(true, "{{}}: {}", format!("boom at {}", Location::caller()));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: combine the `format!(..)` arguments with the outer `usr_println!(..)` call
|
||||
= help: or consider changing `format!` to `format_args!`
|
||||
|
||||
error: `format!` in `usr_println!` args
|
||||
--> tests/ui/format_args_unfixable.rs:144:5
|
||||
|
|
||||
LL | usr_println!(true, r#"error: "{}""#, format!("boom at {}", Location::caller()));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: combine the `format!(..)` arguments with the outer `usr_println!(..)` call
|
||||
= help: or consider changing `format!` to `format_args!`
|
||||
|
||||
error: `format!` in `usr_println!` args
|
||||
--> tests/ui/format_args_unfixable.rs:146:5
|
||||
|
|
||||
LL | usr_println!(true, "error: {}", format!(r#"boom at "{}""#, Location::caller()));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: combine the `format!(..)` arguments with the outer `usr_println!(..)` call
|
||||
= help: or consider changing `format!` to `format_args!`
|
||||
|
||||
error: `format!` in `usr_println!` args
|
||||
--> tests/ui/format_args_unfixable.rs:148:5
|
||||
|
|
||||
LL | usr_println!(true, "error: {}", format!("boom at {} {0}", Location::caller()));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: combine the `format!(..)` arguments with the outer `usr_println!(..)` call
|
||||
= help: or consider changing `format!` to `format_args!`
|
||||
|
||||
error: aborting due to 25 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -257,8 +257,6 @@ fn tester2() {
|
|||
my_concat!("{}", local_i32);
|
||||
my_good_macro!("{}", local_i32);
|
||||
my_good_macro!("{}", local_i32,);
|
||||
|
||||
// FIXME: Broken false positives, currently unhandled
|
||||
my_bad_macro!("{}", local_i32);
|
||||
my_bad_macro2!("{}", local_i32);
|
||||
used_twice! {
|
||||
|
|
@ -267,3 +265,22 @@ fn tester2() {
|
|||
local_i32,
|
||||
};
|
||||
}
|
||||
|
||||
#[clippy::format_args]
|
||||
macro_rules! usr_println {
|
||||
($target:expr, $($args:tt)*) => {{
|
||||
if $target {
|
||||
println!($($args)*)
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
fn user_format() {
|
||||
let local_i32 = 1;
|
||||
let local_f64 = 2.0;
|
||||
|
||||
usr_println!(true, "val='{local_i32}'");
|
||||
usr_println!(true, "{local_i32}");
|
||||
usr_println!(true, "{local_i32:#010x}");
|
||||
usr_println!(true, "{local_f64:.1}");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -262,8 +262,6 @@ fn tester2() {
|
|||
my_concat!("{}", local_i32);
|
||||
my_good_macro!("{}", local_i32);
|
||||
my_good_macro!("{}", local_i32,);
|
||||
|
||||
// FIXME: Broken false positives, currently unhandled
|
||||
my_bad_macro!("{}", local_i32);
|
||||
my_bad_macro2!("{}", local_i32);
|
||||
used_twice! {
|
||||
|
|
@ -272,3 +270,22 @@ fn tester2() {
|
|||
local_i32,
|
||||
};
|
||||
}
|
||||
|
||||
#[clippy::format_args]
|
||||
macro_rules! usr_println {
|
||||
($target:expr, $($args:tt)*) => {{
|
||||
if $target {
|
||||
println!($($args)*)
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
fn user_format() {
|
||||
let local_i32 = 1;
|
||||
let local_f64 = 2.0;
|
||||
|
||||
usr_println!(true, "val='{}'", local_i32);
|
||||
usr_println!(true, "{}", local_i32);
|
||||
usr_println!(true, "{:#010x}", local_i32);
|
||||
usr_println!(true, "{:.1}", local_f64);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -845,5 +845,53 @@ LL - println!("expand='{}'", local_i32);
|
|||
LL + println!("expand='{local_i32}'");
|
||||
|
|
||||
|
||||
error: aborting due to 71 previous errors
|
||||
error: variables can be used directly in the `format!` string
|
||||
--> tests/ui/uninlined_format_args.rs:287:5
|
||||
|
|
||||
LL | usr_println!(true, "val='{}'", local_i32);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: change this to
|
||||
|
|
||||
LL - usr_println!(true, "val='{}'", local_i32);
|
||||
LL + usr_println!(true, "val='{local_i32}'");
|
||||
|
|
||||
|
||||
error: variables can be used directly in the `format!` string
|
||||
--> tests/ui/uninlined_format_args.rs:288:5
|
||||
|
|
||||
LL | usr_println!(true, "{}", local_i32);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: change this to
|
||||
|
|
||||
LL - usr_println!(true, "{}", local_i32);
|
||||
LL + usr_println!(true, "{local_i32}");
|
||||
|
|
||||
|
||||
error: variables can be used directly in the `format!` string
|
||||
--> tests/ui/uninlined_format_args.rs:289:5
|
||||
|
|
||||
LL | usr_println!(true, "{:#010x}", local_i32);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: change this to
|
||||
|
|
||||
LL - usr_println!(true, "{:#010x}", local_i32);
|
||||
LL + usr_println!(true, "{local_i32:#010x}");
|
||||
|
|
||||
|
||||
error: variables can be used directly in the `format!` string
|
||||
--> tests/ui/uninlined_format_args.rs:290:5
|
||||
|
|
||||
LL | usr_println!(true, "{:.1}", local_f64);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: change this to
|
||||
|
|
||||
LL - usr_println!(true, "{:.1}", local_f64);
|
||||
LL + usr_println!(true, "{local_f64:.1}");
|
||||
|
|
||||
|
||||
error: aborting due to 75 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -33,3 +33,38 @@ fn should_not_lint() {
|
|||
let args = format_args!("");
|
||||
println!("{args}");
|
||||
}
|
||||
|
||||
#[clippy::format_args]
|
||||
macro_rules! usr_println {
|
||||
($target:expr, $($args:tt)*) => {{
|
||||
if $target {
|
||||
println!($($args)*)
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
fn should_lint_user() {
|
||||
// prints `.`, not ` .`
|
||||
usr_println!(true, "{:5}.", format!(""));
|
||||
//~^ ERROR: format specifiers have no effect on `format_args!()`
|
||||
//prints `abcde`, not `abc`
|
||||
usr_println!(true, "{:.3}", format!("abcde"));
|
||||
//~^ ERROR: format specifiers have no effect on `format_args!()`
|
||||
|
||||
usr_println!(true, "{}.", format_args_from_macro!());
|
||||
//~^ ERROR: format specifiers have no effect on `format_args!()`
|
||||
|
||||
let args = format_args!("");
|
||||
usr_println!(true, "{args}");
|
||||
//~^ ERROR: format specifiers have no effect on `format_args!()`
|
||||
}
|
||||
|
||||
fn should_not_lint_user() {
|
||||
usr_println!(true, "{}", format_args!(""));
|
||||
// Technically the same as `{}`, but the `format_args` docs specifically mention that you can use
|
||||
// debug formatting so allow it
|
||||
usr_println!(true, "{:?}", format_args!(""));
|
||||
|
||||
let args = format_args!("");
|
||||
usr_println!(true, "{args}");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,3 +33,38 @@ fn should_not_lint() {
|
|||
let args = format_args!("");
|
||||
println!("{args}");
|
||||
}
|
||||
|
||||
#[clippy::format_args]
|
||||
macro_rules! usr_println {
|
||||
($target:expr, $($args:tt)*) => {{
|
||||
if $target {
|
||||
println!($($args)*)
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
fn should_lint_user() {
|
||||
// prints `.`, not ` .`
|
||||
usr_println!(true, "{}.", format_args!(""));
|
||||
//~^ ERROR: format specifiers have no effect on `format_args!()`
|
||||
//prints `abcde`, not `abc`
|
||||
usr_println!(true, "{}", format_args!("abcde"));
|
||||
//~^ ERROR: format specifiers have no effect on `format_args!()`
|
||||
|
||||
usr_println!(true, "{}.", format_args_from_macro!());
|
||||
//~^ ERROR: format specifiers have no effect on `format_args!()`
|
||||
|
||||
let args = format_args!("");
|
||||
usr_println!(true, "{args}");
|
||||
//~^ ERROR: format specifiers have no effect on `format_args!()`
|
||||
}
|
||||
|
||||
fn should_not_lint_user() {
|
||||
usr_println!(true, "{}", format_args!(""));
|
||||
// Technically the same as `{}`, but the `format_args` docs specifically mention that you can use
|
||||
// debug formatting so allow it
|
||||
usr_println!(true, "{:?}", format_args!(""));
|
||||
|
||||
let args = format_args!("");
|
||||
usr_println!(true, "{args}");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,3 +33,38 @@ fn should_not_lint() {
|
|||
let args = format_args!("");
|
||||
println!("{args}");
|
||||
}
|
||||
|
||||
#[clippy::format_args]
|
||||
macro_rules! usr_println {
|
||||
($target:expr, $($args:tt)*) => {{
|
||||
if $target {
|
||||
println!($($args)*)
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
fn should_lint_user() {
|
||||
// prints `.`, not ` .`
|
||||
usr_println!(true, "{:5}.", format_args!(""));
|
||||
//~^ ERROR: format specifiers have no effect on `format_args!()`
|
||||
//prints `abcde`, not `abc`
|
||||
usr_println!(true, "{:.3}", format_args!("abcde"));
|
||||
//~^ ERROR: format specifiers have no effect on `format_args!()`
|
||||
|
||||
usr_println!(true, "{:5}.", format_args_from_macro!());
|
||||
//~^ ERROR: format specifiers have no effect on `format_args!()`
|
||||
|
||||
let args = format_args!("");
|
||||
usr_println!(true, "{args:5}");
|
||||
//~^ ERROR: format specifiers have no effect on `format_args!()`
|
||||
}
|
||||
|
||||
fn should_not_lint_user() {
|
||||
usr_println!(true, "{}", format_args!(""));
|
||||
// Technically the same as `{}`, but the `format_args` docs specifically mention that you can use
|
||||
// debug formatting so allow it
|
||||
usr_println!(true, "{:?}", format_args!(""));
|
||||
|
||||
let args = format_args!("");
|
||||
usr_println!(true, "{args}");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,5 +58,63 @@ LL - println!("{args:5}");
|
|||
LL + println!("{args}");
|
||||
|
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: format specifiers have no effect on `format_args!()`
|
||||
--> tests/ui/unused_format_specs.rs:48:25
|
||||
|
|
||||
LL | usr_println!(true, "{:5}.", format_args!(""));
|
||||
| ^^^^
|
||||
|
|
||||
help: for the width to apply consider using `format!()`
|
||||
|
|
||||
LL | usr_println!(true, "{:5}.", format!(""));
|
||||
| ~~~~~~
|
||||
help: if the current behavior is intentional, remove the format specifiers
|
||||
|
|
||||
LL - usr_println!(true, "{:5}.", format_args!(""));
|
||||
LL + usr_println!(true, "{}.", format_args!(""));
|
||||
|
|
||||
|
||||
error: format specifiers have no effect on `format_args!()`
|
||||
--> tests/ui/unused_format_specs.rs:51:25
|
||||
|
|
||||
LL | usr_println!(true, "{:.3}", format_args!("abcde"));
|
||||
| ^^^^^
|
||||
|
|
||||
help: for the precision to apply consider using `format!()`
|
||||
|
|
||||
LL | usr_println!(true, "{:.3}", format!("abcde"));
|
||||
| ~~~~~~
|
||||
help: if the current behavior is intentional, remove the format specifiers
|
||||
|
|
||||
LL - usr_println!(true, "{:.3}", format_args!("abcde"));
|
||||
LL + usr_println!(true, "{}", format_args!("abcde"));
|
||||
|
|
||||
|
||||
error: format specifiers have no effect on `format_args!()`
|
||||
--> tests/ui/unused_format_specs.rs:54:25
|
||||
|
|
||||
LL | usr_println!(true, "{:5}.", format_args_from_macro!());
|
||||
| ^^^^
|
||||
|
|
||||
= help: for the width to apply consider using `format!()`
|
||||
help: if the current behavior is intentional, remove the format specifiers
|
||||
|
|
||||
LL - usr_println!(true, "{:5}.", format_args_from_macro!());
|
||||
LL + usr_println!(true, "{}.", format_args_from_macro!());
|
||||
|
|
||||
|
||||
error: format specifiers have no effect on `format_args!()`
|
||||
--> tests/ui/unused_format_specs.rs:58:25
|
||||
|
|
||||
LL | usr_println!(true, "{args:5}");
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= help: for the width to apply consider using `format!()`
|
||||
help: if the current behavior is intentional, remove the format specifiers
|
||||
|
|
||||
LL - usr_println!(true, "{args:5}");
|
||||
LL + usr_println!(true, "{args}");
|
||||
|
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue