Skip to content

Commit 61fd2a8

Browse files
committed
Auto merge of #9499 - kraktus:nonstandard_macro_braces, r=xFrednet
[`nonstandard_macro_braces`] Do not modify macro arguments fix #9498 based on top of #9471 Also simplify the lint by not caring about code format which should be `rustfmt` job, and turn the lint into machine Applicable changelog: Suggestion: [`nonstandard_macro_braces`]: The suggestion is now machine applicable and will no longer replace brackets inside the macro argument. [#9499](#9499)
2 parents c2c170a + a390115 commit 61fd2a8

File tree

4 files changed

+111
-104
lines changed

4 files changed

+111
-104
lines changed

clippy_lints/src/nonstandard_macro_braces.rs

Lines changed: 32 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,17 @@ use std::{
33
hash::{Hash, Hasher},
44
};
55

6-
use clippy_utils::diagnostics::span_lint_and_help;
6+
use clippy_utils::diagnostics::span_lint_and_sugg;
77
use clippy_utils::source::snippet_opt;
88
use if_chain::if_chain;
99
use rustc_ast::ast;
1010
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
11+
use rustc_errors::Applicability;
1112
use rustc_hir::def_id::DefId;
1213
use rustc_lint::{EarlyContext, EarlyLintPass};
1314
use rustc_session::{declare_tool_lint, impl_lint_pass};
1415
use rustc_span::hygiene::{ExpnKind, MacroKind};
15-
use rustc_span::{Span, Symbol};
16+
use rustc_span::Span;
1617
use serde::{de, Deserialize};
1718

1819
declare_clippy_lint! {
@@ -39,8 +40,8 @@ declare_clippy_lint! {
3940

4041
const BRACES: &[(&str, &str)] = &[("(", ")"), ("{", "}"), ("[", "]")];
4142

42-
/// The (name, (open brace, close brace), source snippet)
43-
type MacroInfo<'a> = (Symbol, &'a (String, String), String);
43+
/// The (callsite span, (open brace, close brace), source snippet)
44+
type MacroInfo<'a> = (Span, &'a (String, String), String);
4445

4546
#[derive(Clone, Debug, Default)]
4647
pub struct MacroBraces {
@@ -62,33 +63,29 @@ impl_lint_pass!(MacroBraces => [NONSTANDARD_MACRO_BRACES]);
6263

6364
impl EarlyLintPass for MacroBraces {
6465
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
65-
if let Some((name, braces, snip)) = is_offending_macro(cx, item.span, self) {
66-
let span = item.span.ctxt().outer_expn_data().call_site;
67-
emit_help(cx, snip, braces, name, span);
66+
if let Some((span, braces, snip)) = is_offending_macro(cx, item.span, self) {
67+
emit_help(cx, &snip, braces, span);
6868
self.done.insert(span);
6969
}
7070
}
7171

7272
fn check_stmt(&mut self, cx: &EarlyContext<'_>, stmt: &ast::Stmt) {
73-
if let Some((name, braces, snip)) = is_offending_macro(cx, stmt.span, self) {
74-
let span = stmt.span.ctxt().outer_expn_data().call_site;
75-
emit_help(cx, snip, braces, name, span);
73+
if let Some((span, braces, snip)) = is_offending_macro(cx, stmt.span, self) {
74+
emit_help(cx, &snip, braces, span);
7675
self.done.insert(span);
7776
}
7877
}
7978

8079
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
81-
if let Some((name, braces, snip)) = is_offending_macro(cx, expr.span, self) {
82-
let span = expr.span.ctxt().outer_expn_data().call_site;
83-
emit_help(cx, snip, braces, name, span);
80+
if let Some((span, braces, snip)) = is_offending_macro(cx, expr.span, self) {
81+
emit_help(cx, &snip, braces, span);
8482
self.done.insert(span);
8583
}
8684
}
8785

8886
fn check_ty(&mut self, cx: &EarlyContext<'_>, ty: &ast::Ty) {
89-
if let Some((name, braces, snip)) = is_offending_macro(cx, ty.span, self) {
90-
let span = ty.span.ctxt().outer_expn_data().call_site;
91-
emit_help(cx, snip, braces, name, span);
87+
if let Some((span, braces, snip)) = is_offending_macro(cx, ty.span, self) {
88+
emit_help(cx, &snip, braces, span);
9289
self.done.insert(span);
9390
}
9491
}
@@ -102,48 +99,44 @@ fn is_offending_macro<'a>(cx: &EarlyContext<'_>, span: Span, mac_braces: &'a Mac
10299
.last()
103100
.map_or(false, |e| e.macro_def_id.map_or(false, DefId::is_local))
104101
};
102+
let span_call_site = span.ctxt().outer_expn_data().call_site;
105103
if_chain! {
106104
if let ExpnKind::Macro(MacroKind::Bang, mac_name) = span.ctxt().outer_expn_data().kind;
107105
let name = mac_name.as_str();
108106
if let Some(braces) = mac_braces.macro_braces.get(name);
109-
if let Some(snip) = snippet_opt(cx, span.ctxt().outer_expn_data().call_site);
107+
if let Some(snip) = snippet_opt(cx, span_call_site);
110108
// we must check only invocation sites
111109
// https://github.com/rust-lang/rust-clippy/issues/7422
112110
if snip.starts_with(&format!("{}!", name));
113111
if unnested_or_local();
114112
// make formatting consistent
115113
let c = snip.replace(' ', "");
116114
if !c.starts_with(&format!("{}!{}", name, braces.0));
117-
if !mac_braces.done.contains(&span.ctxt().outer_expn_data().call_site);
115+
if !mac_braces.done.contains(&span_call_site);
118116
then {
119-
Some((mac_name, braces, snip))
117+
Some((span_call_site, braces, snip))
120118
} else {
121119
None
122120
}
123121
}
124122
}
125123

126-
fn emit_help(cx: &EarlyContext<'_>, snip: String, braces: &(String, String), name: Symbol, span: Span) {
127-
let with_space = &format!("! {}", braces.0);
128-
let without_space = &format!("!{}", braces.0);
129-
let mut help = snip;
130-
for b in BRACES.iter().filter(|b| b.0 != braces.0) {
131-
help = help.replace(b.0, &braces.0).replace(b.1, &braces.1);
132-
// Only `{` traditionally has space before the brace
133-
if braces.0 != "{" && help.contains(with_space) {
134-
help = help.replace(with_space, without_space);
135-
} else if braces.0 == "{" && help.contains(without_space) {
136-
help = help.replace(without_space, with_space);
137-
}
124+
fn emit_help(cx: &EarlyContext<'_>, snip: &str, braces: &(String, String), span: Span) {
125+
if let Some((macro_name, macro_args_str)) = snip.split_once('!') {
126+
let mut macro_args = macro_args_str.trim().to_string();
127+
// now remove the wrong braces
128+
macro_args.remove(0);
129+
macro_args.pop();
130+
span_lint_and_sugg(
131+
cx,
132+
NONSTANDARD_MACRO_BRACES,
133+
span,
134+
&format!("use of irregular braces for `{}!` macro", macro_name),
135+
"consider writing",
136+
format!("{}!{}{}{}", macro_name, braces.0, macro_args, braces.1),
137+
Applicability::MachineApplicable,
138+
);
138139
}
139-
span_lint_and_help(
140-
cx,
141-
NONSTANDARD_MACRO_BRACES,
142-
span,
143-
&format!("use of irregular braces for `{}!` macro", name),
144-
Some(span),
145-
&format!("consider writing `{}`", help),
146-
);
147140
}
148141

149142
fn macro_braces(conf: FxHashSet<MacroMatcher>) -> FxHashMap<String, (String, String)> {
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// aux-build:proc_macro_derive.rs
2+
// run-rustfix
3+
4+
#![warn(clippy::nonstandard_macro_braces)]
5+
6+
extern crate proc_macro_derive;
7+
extern crate quote;
8+
9+
use quote::quote;
10+
11+
#[derive(proc_macro_derive::DeriveSomething)]
12+
pub struct S;
13+
14+
proc_macro_derive::foo_bar!();
15+
16+
#[rustfmt::skip]
17+
macro_rules! test {
18+
() => {
19+
vec![0, 0, 0]
20+
};
21+
}
22+
23+
#[rustfmt::skip]
24+
macro_rules! test2 {
25+
($($arg:tt)*) => {
26+
format_args!($($arg)*)
27+
};
28+
}
29+
30+
macro_rules! type_pos {
31+
($what:ty) => {
32+
Vec<$what>
33+
};
34+
}
35+
36+
macro_rules! printlnfoo {
37+
($thing:expr) => {
38+
println!("{}", $thing)
39+
};
40+
}
41+
42+
#[rustfmt::skip]
43+
fn main() {
44+
let _ = vec![1, 2, 3];
45+
let _ = format!("ugh {} stop being such a good compiler", "hello");
46+
let _ = matches!({}, ());
47+
let _ = quote!{let x = 1;};
48+
let _ = quote::quote!{match match match};
49+
let _ = test!(); // trigger when macro def is inside our own crate
50+
let _ = vec![1,2,3];
51+
52+
let _ = quote::quote! {true || false};
53+
let _ = vec! [0 ,0 ,0];
54+
let _ = format!("fds{}fds", 10);
55+
let _ = test2!["{}{}{}", 1, 2, 3];
56+
57+
let _: type_pos![usize] = vec![];
58+
59+
eprint!["test if user config overrides defaults"];
60+
61+
printlnfoo!["test if printlnfoo is triggered by println"];
62+
}

tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// aux-build:proc_macro_derive.rs
2+
// run-rustfix
23

34
#![warn(clippy::nonstandard_macro_braces)]
45

Lines changed: 16 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,106 +1,57 @@
11
error: use of irregular braces for `vec!` macro
2-
--> $DIR/conf_nonstandard_macro_braces.rs:43:13
2+
--> $DIR/conf_nonstandard_macro_braces.rs:44:13
33
|
44
LL | let _ = vec! {1, 2, 3};
5-
| ^^^^^^^^^^^^^^
5+
| ^^^^^^^^^^^^^^ help: consider writing: `vec![1, 2, 3]`
66
|
77
= note: `-D clippy::nonstandard-macro-braces` implied by `-D warnings`
8-
help: consider writing `vec![1, 2, 3]`
9-
--> $DIR/conf_nonstandard_macro_braces.rs:43:13
10-
|
11-
LL | let _ = vec! {1, 2, 3};
12-
| ^^^^^^^^^^^^^^
138

149
error: use of irregular braces for `format!` macro
15-
--> $DIR/conf_nonstandard_macro_braces.rs:44:13
16-
|
17-
LL | let _ = format!["ugh {} stop being such a good compiler", "hello"];
18-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
19-
|
20-
help: consider writing `format!("ugh () stop being such a good compiler", "hello")`
21-
--> $DIR/conf_nonstandard_macro_braces.rs:44:13
10+
--> $DIR/conf_nonstandard_macro_braces.rs:45:13
2211
|
2312
LL | let _ = format!["ugh {} stop being such a good compiler", "hello"];
24-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `format!("ugh {} stop being such a good compiler", "hello")`
2514

2615
error: use of irregular braces for `matches!` macro
27-
--> $DIR/conf_nonstandard_macro_braces.rs:45:13
28-
|
29-
LL | let _ = matches!{{}, ()};
30-
| ^^^^^^^^^^^^^^^^
31-
|
32-
help: consider writing `matches!((), ())`
33-
--> $DIR/conf_nonstandard_macro_braces.rs:45:13
16+
--> $DIR/conf_nonstandard_macro_braces.rs:46:13
3417
|
3518
LL | let _ = matches!{{}, ()};
36-
| ^^^^^^^^^^^^^^^^
19+
| ^^^^^^^^^^^^^^^^ help: consider writing: `matches!({}, ())`
3720

3821
error: use of irregular braces for `quote!` macro
39-
--> $DIR/conf_nonstandard_macro_braces.rs:46:13
40-
|
41-
LL | let _ = quote!(let x = 1;);
42-
| ^^^^^^^^^^^^^^^^^^
43-
|
44-
help: consider writing `quote! {let x = 1;}`
45-
--> $DIR/conf_nonstandard_macro_braces.rs:46:13
22+
--> $DIR/conf_nonstandard_macro_braces.rs:47:13
4623
|
4724
LL | let _ = quote!(let x = 1;);
48-
| ^^^^^^^^^^^^^^^^^^
25+
| ^^^^^^^^^^^^^^^^^^ help: consider writing: `quote!{let x = 1;}`
4926

5027
error: use of irregular braces for `quote::quote!` macro
51-
--> $DIR/conf_nonstandard_macro_braces.rs:47:13
28+
--> $DIR/conf_nonstandard_macro_braces.rs:48:13
5229
|
5330
LL | let _ = quote::quote!(match match match);
54-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
55-
|
56-
help: consider writing `quote::quote! {match match match}`
57-
--> $DIR/conf_nonstandard_macro_braces.rs:47:13
58-
|
59-
LL | let _ = quote::quote!(match match match);
60-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
31+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `quote::quote!{match match match}`
6132

6233
error: use of irregular braces for `vec!` macro
63-
--> $DIR/conf_nonstandard_macro_braces.rs:18:9
34+
--> $DIR/conf_nonstandard_macro_braces.rs:19:9
6435
|
6536
LL | vec!{0, 0, 0}
66-
| ^^^^^^^^^^^^^
37+
| ^^^^^^^^^^^^^ help: consider writing: `vec![0, 0, 0]`
6738
...
6839
LL | let _ = test!(); // trigger when macro def is inside our own crate
6940
| ------- in this macro invocation
7041
|
71-
help: consider writing `vec![0, 0, 0]`
72-
--> $DIR/conf_nonstandard_macro_braces.rs:18:9
73-
|
74-
LL | vec!{0, 0, 0}
75-
| ^^^^^^^^^^^^^
76-
...
77-
LL | let _ = test!(); // trigger when macro def is inside our own crate
78-
| ------- in this macro invocation
7942
= note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
8043

8144
error: use of irregular braces for `type_pos!` macro
82-
--> $DIR/conf_nonstandard_macro_braces.rs:56:12
45+
--> $DIR/conf_nonstandard_macro_braces.rs:57:12
8346
|
8447
LL | let _: type_pos!(usize) = vec![];
85-
| ^^^^^^^^^^^^^^^^
86-
|
87-
help: consider writing `type_pos![usize]`
88-
--> $DIR/conf_nonstandard_macro_braces.rs:56:12
89-
|
90-
LL | let _: type_pos!(usize) = vec![];
91-
| ^^^^^^^^^^^^^^^^
48+
| ^^^^^^^^^^^^^^^^ help: consider writing: `type_pos![usize]`
9249

9350
error: use of irregular braces for `eprint!` macro
94-
--> $DIR/conf_nonstandard_macro_braces.rs:58:5
95-
|
96-
LL | eprint!("test if user config overrides defaults");
97-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
98-
|
99-
help: consider writing `eprint!["test if user config overrides defaults"]`
100-
--> $DIR/conf_nonstandard_macro_braces.rs:58:5
51+
--> $DIR/conf_nonstandard_macro_braces.rs:59:5
10152
|
10253
LL | eprint!("test if user config overrides defaults");
103-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
54+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `eprint!["test if user config overrides defaults"]`
10455

10556
error: aborting due to 8 previous errors
10657

0 commit comments

Comments
 (0)