@@ -3,6 +3,7 @@ use crate::utils::{ErrAction, expect_action, walk_dir_no_dot_or_target};
3
3
use core:: ops:: Range ;
4
4
use core:: slice;
5
5
use rustc_data_structures:: fx:: FxHashMap ;
6
+ use rustc_index:: { IndexVec , newtype_index} ;
6
7
use rustc_lexer:: { self as lexer, FrontmatterAllowed } ;
7
8
use std:: collections:: hash_map:: { Entry , VacantEntry } ;
8
9
use std:: panic:: Location ;
@@ -27,13 +28,15 @@ pub enum Token<'a> {
27
28
DoubleColon ,
28
29
Comma ,
29
30
Eq ,
31
+ FatArrow ,
30
32
Lifetime ,
31
33
Literal ,
32
34
Lt ,
33
35
Gt ,
34
36
OpenBrace ,
35
37
OpenBracket ,
36
38
OpenParen ,
39
+ OptLifetimeArgs ,
37
40
Pound ,
38
41
Semi ,
39
42
}
@@ -202,6 +205,24 @@ impl<'txt> RustSearcher<'txt> {
202
205
}
203
206
return false ;
204
207
} ,
208
+ ( Token :: FatArrow , lexer:: TokenKind :: Eq ) => {
209
+ self . step ( ) ;
210
+ if matches ! ( self . next_token. kind, lexer:: TokenKind :: Gt ) {
211
+ self . step ( ) ;
212
+ return true ;
213
+ }
214
+ return false ;
215
+ } ,
216
+ ( Token :: OptLifetimeArgs , lexer:: TokenKind :: Lt ) => {
217
+ self . step ( ) ;
218
+ while self . read_token ( Token :: Lifetime , captures) {
219
+ if !self . read_token ( Token :: Comma , captures) {
220
+ break ;
221
+ }
222
+ }
223
+ return self . read_token ( Token :: Gt , captures) ;
224
+ } ,
225
+ ( Token :: OptLifetimeArgs , _) => return true ,
205
226
#[ rustfmt:: skip]
206
227
(
207
228
Token :: CaptureLitStr ,
@@ -235,16 +256,28 @@ impl<'txt> RustSearcher<'txt> {
235
256
}
236
257
237
258
#[ must_use]
238
- pub fn find_capture_token ( & mut self , token : Token < ' _ > ) -> Option < & ' txt str > {
239
- let mut capture = Capture :: EMPTY ;
240
- let mut captures = slice:: from_mut ( & mut capture) . iter_mut ( ) ;
241
- while !self . read_token ( token, & mut captures) {
242
- self . step ( ) ;
243
- if self . at_end ( ) {
244
- return None ;
259
+ pub fn find_any_ident ( & mut self ) -> Option < & ' txt str > {
260
+ loop {
261
+ match self . next_token . kind {
262
+ lexer:: TokenKind :: Ident => {
263
+ let res = self . peek_text ( ) ;
264
+ self . step ( ) ;
265
+ return Some ( res) ;
266
+ } ,
267
+ lexer:: TokenKind :: Eof => return None ,
268
+ _ => self . step ( ) ,
269
+ }
270
+ }
271
+ }
272
+
273
+ #[ must_use]
274
+ pub fn find_ident ( & mut self , s : & str ) -> bool {
275
+ while let Some ( x) = self . find_any_ident ( ) {
276
+ if x == s {
277
+ return true ;
245
278
}
246
279
}
247
- Some ( & self . text [ capture . to_index ( ) ] )
280
+ false
248
281
}
249
282
250
283
#[ must_use]
@@ -286,9 +319,27 @@ pub struct Lint {
286
319
pub name_span : Span ,
287
320
}
288
321
322
+ pub struct LintPassData {
323
+ pub name : String ,
324
+ /// Span of the `impl_lint_pass` or `declare_lint_pass` macro call.
325
+ pub mac_span : Span ,
326
+ }
327
+
328
+ newtype_index ! {
329
+ #[ orderable]
330
+ pub struct LintPass { }
331
+ }
332
+
333
+ pub struct LintRegistration {
334
+ pub name : String ,
335
+ pub pass : LintPass ,
336
+ }
337
+
289
338
pub struct ParsedData {
290
339
pub source_map : SourceMap ,
291
340
pub lints : FxHashMap < String , Lint > ,
341
+ pub lint_passes : IndexVec < LintPass , LintPassData > ,
342
+ pub lint_registrations : Vec < LintRegistration > ,
292
343
pub deprecated_span : Range < u32 > ,
293
344
pub renamed_span : Range < u32 > ,
294
345
}
@@ -298,6 +349,8 @@ impl ParsedData {
298
349
let mut parser = Parser {
299
350
source_map : SourceMap :: with_capacity ( 8 , 1000 ) ,
300
351
lints : FxHashMap :: with_capacity_and_hasher ( 1000 , Default :: default ( ) ) ,
352
+ lint_passes : IndexVec :: with_capacity ( 400 ) ,
353
+ lint_registrations : Vec :: with_capacity ( 1000 ) ,
301
354
deprecated_span : 0 ..0 ,
302
355
renamed_span : 0 ..0 ,
303
356
errors : Vec :: new ( ) ,
@@ -354,6 +407,8 @@ impl ParsedData {
354
407
ParsedData {
355
408
source_map : parser. source_map ,
356
409
lints : parser. lints ,
410
+ lint_passes : parser. lint_passes ,
411
+ lint_registrations : parser. lint_registrations ,
357
412
deprecated_span : parser. deprecated_span ,
358
413
renamed_span : parser. renamed_span ,
359
414
}
@@ -398,6 +453,8 @@ impl From<ErrorKind> for Error {
398
453
struct Parser {
399
454
source_map : SourceMap ,
400
455
lints : FxHashMap < String , Lint > ,
456
+ lint_passes : IndexVec < LintPass , LintPassData > ,
457
+ lint_registrations : Vec < LintRegistration > ,
401
458
deprecated_span : Range < u32 > ,
402
459
renamed_span : Range < u32 > ,
403
460
errors : Vec < Error > ,
@@ -448,7 +505,7 @@ impl Parser {
448
505
#[ allow( clippy:: enum_glob_use) ]
449
506
use Token :: * ;
450
507
#[ rustfmt:: skip]
451
- static DECL_TOKENS : & [ Token < ' _ > ] = & [
508
+ static LINT_DECL_TOKENS : & [ Token < ' _ > ] = & [
452
509
// { /// docs
453
510
OpenBrace , AnyComment ,
454
511
// #[clippy::version = "version"]
@@ -457,41 +514,80 @@ impl Parser {
457
514
Ident ( "pub" ) , CaptureIdent , Comma , AnyComment , CaptureIdent , Comma , AnyComment , LitStr ,
458
515
] ;
459
516
#[ rustfmt:: skip]
460
- static EXTRA_TOKENS : & [ Token < ' _ > ] = & [
517
+ static LINT_DECL_EXTRA_TOKENS : & [ Token < ' _ > ] = & [
461
518
// , @option = value
462
519
Comma , AnyComment , At , AnyIdent , Eq , Literal ,
463
520
] ;
521
+ #[ rustfmt:: skip]
522
+ static LINT_PASS_TOKENS : & [ Token < ' _ > ] = & [
523
+ // ( name <'lt> => [
524
+ OpenParen , AnyComment , CaptureIdent , OptLifetimeArgs , FatArrow , OpenBracket ,
525
+ ] ;
464
526
465
527
let mut searcher = RustSearcher :: new ( & self . source_map . files [ file] . contents ) ;
466
528
let mut captures = [ Capture :: EMPTY ; 2 ] ;
467
- while searcher. find_token ( Ident ( "declare_clippy_lint" ) ) {
468
- let start = searcher. pos ( ) - "declare_clippy_lint" . len ( ) as u32 ;
529
+ while let Some ( ident ) = searcher. find_any_ident ( ) {
530
+ let start = searcher. pos - ident . len ( ) as u32 ;
469
531
if searcher. match_token ( Bang ) {
470
- if !searcher. match_tokens ( DECL_TOKENS , & mut captures) {
471
- self . errors . push ( searcher. get_unexpected_err ( file) ) ;
472
- return ;
473
- }
474
- let name_span = captures[ 0 ] . to_span ( file) ;
475
- let name = searcher. get_capture ( captures[ 0 ] ) . to_ascii_lowercase ( ) ;
476
- if let Some ( e) = get_vacant_lint ( name, name_span, & mut self . lints , & mut self . errors ) {
477
- e. insert ( Lint {
478
- name_span,
479
- kind : LintKind :: Active ( ActiveLint {
480
- decl_span : Span {
532
+ match ident {
533
+ "declare_clippy_lint" => {
534
+ if !searcher. match_tokens ( LINT_DECL_TOKENS , & mut captures) {
535
+ self . errors . push ( searcher. get_unexpected_err ( file) ) ;
536
+ return ;
537
+ }
538
+ let name_span = captures[ 0 ] . to_span ( file) ;
539
+ let name = searcher. get_capture ( captures[ 0 ] ) . to_ascii_lowercase ( ) ;
540
+ if let Some ( e) = get_vacant_lint ( name, name_span, & mut self . lints , & mut self . errors ) {
541
+ e. insert ( Lint {
542
+ name_span,
543
+ kind : LintKind :: Active ( ActiveLint {
544
+ decl_span : Span {
545
+ file,
546
+ start,
547
+ end : searcher. pos ( ) ,
548
+ } ,
549
+ group : searcher. get_capture ( captures[ 1 ] ) . into ( ) ,
550
+ } ) ,
551
+ } ) ;
552
+ }
553
+ while searcher. match_tokens ( LINT_DECL_EXTRA_TOKENS , & mut [ ] ) {
554
+ // nothing
555
+ }
556
+ if !searcher. match_token ( CloseBrace ) {
557
+ self . errors . push ( searcher. get_unexpected_err ( file) ) ;
558
+ return ;
559
+ }
560
+ } ,
561
+ "impl_lint_pass" | "declare_lint_pass" => {
562
+ if !searcher. match_tokens ( LINT_PASS_TOKENS , & mut captures) {
563
+ self . errors . push ( searcher. get_unexpected_err ( file) ) ;
564
+ return ;
565
+ }
566
+ let pass = self . lint_passes . next_index ( ) ;
567
+ let pass_name = captures[ 0 ] ;
568
+ while searcher. match_tokens ( & [ AnyComment , CaptureIdent ] , & mut captures) {
569
+ self . lint_registrations . push ( LintRegistration {
570
+ name : searcher. get_capture ( captures[ 0 ] ) . to_ascii_lowercase ( ) ,
571
+ pass,
572
+ } ) ;
573
+ if !searcher. match_token ( Comma ) {
574
+ break ;
575
+ }
576
+ }
577
+ if !searcher. match_tokens ( & [ CloseBracket , CloseParen ] , & mut [ ] ) {
578
+ self . errors . push ( searcher. get_unexpected_err ( file) ) ;
579
+ return ;
580
+ }
581
+ self . lint_passes . push ( LintPassData {
582
+ name : searcher. get_capture ( pass_name) . to_owned ( ) ,
583
+ mac_span : Span {
481
584
file,
482
585
start,
483
586
end : searcher. pos ( ) ,
484
587
} ,
485
- group : searcher. get_capture ( captures[ 1 ] ) . into ( ) ,
486
- } ) ,
487
- } ) ;
488
- }
489
- while searcher. match_tokens ( EXTRA_TOKENS , & mut [ ] ) {
490
- // nothing
491
- }
492
- if !searcher. match_token ( CloseBrace ) {
493
- self . errors . push ( searcher. get_unexpected_err ( file) ) ;
494
- return ;
588
+ } ) ;
589
+ } ,
590
+ _ => { } ,
495
591
}
496
592
}
497
593
}
@@ -535,11 +631,11 @@ impl Parser {
535
631
let mut searcher = RustSearcher :: new ( & file_data. contents ) ;
536
632
// First instance is the macro definition.
537
633
assert ! (
538
- searcher. find_token ( Ident ( "declare_with_version" ) ) ,
539
- "error parsing `clippy_lints/src/deprecated_lints.rs`"
634
+ searcher. find_ident ( "declare_with_version" ) ,
635
+ "error parsing `clippy_lints/src/deprecated_lints.rs`" ,
540
636
) ;
541
637
542
- if !searcher. find_token ( Ident ( "declare_with_version" ) ) || !searcher. match_tokens ( DEPRECATED_TOKENS , & mut [ ] ) {
638
+ if !searcher. find_ident ( "declare_with_version" ) || !searcher. match_tokens ( DEPRECATED_TOKENS , & mut [ ] ) {
543
639
self . errors . push ( searcher. get_unexpected_err ( file) ) ;
544
640
return ;
545
641
}
@@ -568,7 +664,7 @@ impl Parser {
568
664
return ;
569
665
}
570
666
571
- if !searcher. find_token ( Ident ( "declare_with_version" ) ) || !searcher. match_tokens ( RENAMED_TOKENS , & mut [ ] ) {
667
+ if !searcher. find_ident ( "declare_with_version" ) || !searcher. match_tokens ( RENAMED_TOKENS , & mut [ ] ) {
572
668
self . errors . push ( searcher. get_unexpected_err ( file) ) ;
573
669
return ;
574
670
}
0 commit comments