1
1
use core:: { cmp, fmt:: Write , mem} ;
2
- use proc_macro2:: { Delimiter , Ident , Spacing , Span , TokenStream , TokenTree as TT } ;
2
+ use proc_macro2:: { Delimiter , Group , Ident , Spacing , Span , TokenStream , TokenTree as TT } ;
3
3
use quote:: { quote, quote_spanned, ToTokens } ;
4
4
5
5
macro_rules! expr_position {
@@ -83,11 +83,6 @@ expr_precedence! {
83
83
Prefix => Unary ,
84
84
Postfix => Call ,
85
85
}
86
- impl Default for ExprPrecedence {
87
- fn default ( ) -> Self {
88
- Self :: Postfix
89
- }
90
- }
91
86
92
87
macro_rules! prec {
93
88
( $name: ident) => { {
@@ -172,30 +167,6 @@ impl Default for State {
172
167
#[ allow( clippy:: enum_glob_use) ]
173
168
use State :: * ;
174
169
175
- enum Output {
176
- String ( String ) ,
177
- Snip ( Snip ) ,
178
- Mut ( TokenStream ) ,
179
- }
180
- impl ToTokens for Output {
181
- fn to_tokens ( & self , tokens : & mut TokenStream ) {
182
- match self {
183
- Self :: String ( s) => tokens. extend ( quote ! ( sugg. push_str( #s) ; ) ) ,
184
- Self :: Snip ( s) => {
185
- let stream = & s. stream ;
186
- let position = s. position ;
187
- tokens. extend ( quote ! ( sugg. push_str( & clippy_utils:: _internal:: snip( cx, #stream, #position, & mut app) ) ; ) ) ;
188
- } ,
189
- Self :: Mut ( s) => tokens. extend ( quote ! {
190
- match #s {
191
- rustc_ast:: Mutability :: Mut => sugg. push_str( "mut " ) ,
192
- rustc_ast:: Mutability :: Not => ( ) ,
193
- }
194
- } ) ,
195
- }
196
- }
197
- }
198
-
199
170
enum Error {
200
171
UnexpectedToken ( Span ) ,
201
172
UnknownCommand ( Span ) ,
@@ -215,28 +186,42 @@ struct Snip {
215
186
position : ExprPosition ,
216
187
}
217
188
218
- #[ derive( Default ) ]
219
189
struct ExprParser {
220
190
state : State ,
221
191
next_string : String ,
222
192
precedence : ExprPrecedence ,
223
- result : Vec < Output > ,
193
+ result : TokenStream ,
224
194
}
225
195
impl ExprParser {
196
+ #[ allow( clippy:: needless_pass_by_value) ]
197
+ fn new ( cx_tokens : TT , app_tokens : TT ) -> Self {
198
+ Self {
199
+ state : State :: default ( ) ,
200
+ next_string : String :: new ( ) ,
201
+ precedence : ExprPrecedence :: Postfix ,
202
+ result : quote ! {
203
+ let cx: & rustc_lint:: LateContext <' _> = #cx_tokens;
204
+ let app: & mut rustc_errors:: Applicability = #app_tokens;
205
+ let mut sugg = String :: new( ) ;
206
+ } ,
207
+ }
208
+ }
209
+
226
210
fn push_str ( & mut self ) {
227
211
if !self . next_string . is_empty ( ) {
228
- self . result . push ( Output :: String ( self . next_string . clone ( ) ) ) ;
212
+ let s = & self . next_string ;
213
+ self . result . extend ( quote ! ( sugg. push_str( #s) ; ) ) ;
229
214
self . next_string . clear ( ) ;
230
215
}
231
216
}
232
217
233
218
fn push_snip ( & mut self , kind : ExprKind , position : ExprPosition ) {
234
219
if let ExprKind :: Snip ( s) = kind {
235
220
debug_assert ! ( self . next_string. is_empty( ) ) ;
236
- self . result . push ( Output :: Snip ( Snip {
237
- position : cmp:: max ( s. position , position) ,
238
- ..s
239
- } ) ) ;
221
+ let stream = s . stream ;
222
+ let position = cmp:: max ( s. position , position) ;
223
+ self . result
224
+ . extend ( quote ! ( sugg . push_str ( & clippy_utils :: _internal :: snip ( cx , #stream , #position , app ) ) ; ) ) ;
240
225
}
241
226
}
242
227
@@ -254,8 +239,7 @@ impl ExprParser {
254
239
}
255
240
256
241
#[ allow( clippy:: too_many_lines) ]
257
- fn parse ( & mut self , input : TokenStream ) -> Result < ( ) , Error > {
258
- let mut iter = input. into_iter ( ) ;
242
+ fn parse ( & mut self , mut iter : <TokenStream as IntoIterator >:: IntoIter ) -> Result < ( ) , Error > {
259
243
while let Some ( tt) = iter. next ( ) {
260
244
self . state = match ( tt, mem:: take ( & mut self . state ) ) {
261
245
( TT :: Punct ( p) , state @ ( Start | Prefix | PrefixRef | BinOp ( _) | PartialBinOp ( ..) ) )
@@ -293,7 +277,14 @@ impl ExprParser {
293
277
match iter. next ( ) . unwrap ( ) {
294
278
TT :: Group ( args) if args. delimiter ( ) == Delimiter :: Parenthesis => {
295
279
self . push_str ( ) ;
296
- self . result . push ( Output :: Mut ( args. stream ( ) ) ) ;
280
+ let stream = args. stream ( ) ;
281
+ self . result . extend ( quote ! {
282
+ let mutability: rustc_ast:: Mutability = #stream;
283
+ match mutability {
284
+ rustc_ast:: Mutability :: Mut => sugg. push_str( "mut " ) ,
285
+ rustc_ast:: Mutability :: Not => ( ) ,
286
+ }
287
+ } ) ;
297
288
Prefix
298
289
} ,
299
290
tt => return Err ( Error :: UnexpectedToken ( tt. span ( ) ) ) ,
@@ -313,7 +304,7 @@ impl ExprParser {
313
304
let precedence = self . precedence ;
314
305
self . next_string . push ( '[' ) ;
315
306
self . state = Start ;
316
- self . parse ( g. stream ( ) ) ?;
307
+ self . parse ( g. stream ( ) . into_iter ( ) ) ?;
317
308
self . next_string . push ( ']' ) ;
318
309
self . precedence = precedence;
319
310
Expr ( ExprKind :: Normal )
@@ -527,7 +518,7 @@ impl ExprParser {
527
518
let precedence = self . precedence ;
528
519
self . next_string . push ( '(' ) ;
529
520
self . state = Start ;
530
- self . parse ( g. stream ( ) ) ?;
521
+ self . parse ( g. stream ( ) . into_iter ( ) ) ?;
531
522
self . next_string . push ( ')' ) ;
532
523
self . precedence = precedence;
533
524
Expr ( ExprKind :: Normal )
@@ -537,6 +528,7 @@ impl ExprParser {
537
528
} ;
538
529
}
539
530
531
+ self . push_str ( ) ;
540
532
match mem:: take ( & mut self . state ) {
541
533
Start => Ok ( ( ) ) ,
542
534
Expr ( kind) => {
@@ -547,19 +539,14 @@ impl ExprParser {
547
539
}
548
540
}
549
541
550
- fn into_stream ( mut self ) -> TokenStream {
551
- self . push_str ( ) ;
552
- let output = self . result . iter ( ) ;
542
+ fn into_stream ( self ) -> TokenStream {
543
+ let mut result = self . result ;
553
544
let precedence = self . precedence ;
554
-
555
- quote ! { {
556
- let mut sugg = String :: new( ) ;
557
- #( #output) *
558
- clippy_utils:: _internal:: Sugg {
559
- sugg,
560
- precedence: #precedence,
561
- }
562
- } }
545
+ result. extend ( quote ! { clippy_utils:: _internal:: Sugg {
546
+ sugg,
547
+ precedence: #precedence,
548
+ } } ) ;
549
+ TT :: Group ( Group :: new ( Delimiter :: Brace , result) ) . into ( )
563
550
}
564
551
}
565
552
@@ -568,8 +555,26 @@ fn make_error(msg: &str, span: Span) -> TokenStream {
568
555
}
569
556
570
557
pub fn expr_sugg ( input : TokenStream ) -> TokenStream {
571
- let mut parser = ExprParser :: default ( ) ;
572
- match parser. parse ( input) {
558
+ let mut iter = input. into_iter ( ) ;
559
+ let cx = match iter. next ( ) {
560
+ Some ( TT :: Ident ( cx) ) => TT :: Ident ( cx) ,
561
+ _ => panic ! ( ) ,
562
+ } ;
563
+ match iter. next ( ) {
564
+ Some ( TT :: Punct ( p) ) if p. as_char ( ) == ',' => ( ) ,
565
+ _ => panic ! ( ) ,
566
+ } ;
567
+ let app = match iter. next ( ) {
568
+ Some ( TT :: Ident ( app) ) => TT :: Ident ( app) ,
569
+ _ => panic ! ( ) ,
570
+ } ;
571
+ match iter. next ( ) {
572
+ Some ( TT :: Punct ( p) ) if p. as_char ( ) == ',' => ( ) ,
573
+ _ => panic ! ( ) ,
574
+ } ;
575
+
576
+ let mut parser = ExprParser :: new ( cx, app) ;
577
+ match parser. parse ( iter) {
573
578
Ok ( ( ) ) => parser. into_stream ( ) ,
574
579
Err ( Error :: UnexpectedToken ( span) ) => make_error ( "unexpected token" , span) ,
575
580
Err ( Error :: UnexpectedMut ( span) ) => make_error ( "unexpected `mut` command" , span) ,
0 commit comments