@@ -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 ;
77use clippy_utils:: source:: snippet_opt;
88use if_chain:: if_chain;
99use rustc_ast:: ast;
1010use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
11+ use rustc_errors:: Applicability ;
1112use rustc_hir:: def_id:: DefId ;
1213use rustc_lint:: { EarlyContext , EarlyLintPass } ;
1314use rustc_session:: { declare_tool_lint, impl_lint_pass} ;
1415use rustc_span:: hygiene:: { ExpnKind , MacroKind } ;
15- use rustc_span:: { Span , Symbol } ;
16+ use rustc_span:: Span ;
1617use serde:: { de, Deserialize } ;
1718
1819declare_clippy_lint ! {
@@ -39,8 +40,8 @@ declare_clippy_lint! {
3940
4041const 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 ) ]
4647pub struct MacroBraces {
@@ -62,33 +63,29 @@ impl_lint_pass!(MacroBraces => [NONSTANDARD_MACRO_BRACES]);
6263
6364impl 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
149142fn macro_braces ( conf : FxHashSet < MacroMatcher > ) -> FxHashMap < String , ( String , String ) > {
0 commit comments