@@ -3,6 +3,7 @@ use crate::utils::{ErrAction, expect_action, walk_dir_no_dot_or_target};
33use  core:: ops:: Range ; 
44use  core:: slice; 
55use  rustc_data_structures:: fx:: FxHashMap ; 
6+ use  rustc_index:: { IndexVec ,  newtype_index} ; 
67use  rustc_lexer:: { self  as  lexer,  FrontmatterAllowed } ; 
78use  std:: collections:: hash_map:: { Entry ,  VacantEntry } ; 
89use  std:: panic:: Location ; 
@@ -27,13 +28,15 @@ pub enum Token<'a> {
2728DoubleColon , 
2829    Comma , 
2930    Eq , 
31+     FatArrow , 
3032    Lifetime , 
3133    Literal , 
3234    Lt , 
3335    Gt , 
3436    OpenBrace , 
3537    OpenBracket , 
3638    OpenParen , 
39+     OptLifetimeArgs , 
3740    Pound , 
3841    Semi , 
3942} 
@@ -134,6 +137,7 @@ impl<'txt> RustSearcher<'txt> {
134137
135138    /// Consumes the next token if it matches the requested value and captures the value if 
136139/// requested. Returns `true` if a token was matched. 
140+ #[ expect( clippy:: too_many_lines) ]  
137141    fn  read_token ( & mut  self ,  token :  Token < ' _ > ,  captures :  & mut  slice:: IterMut < ' _ ,  Capture > )  -> bool  { 
138142        loop  { 
139143            match  ( token,  self . next_token . kind )  { 
@@ -202,6 +206,25 @@ impl<'txt> RustSearcher<'txt> {
202206                    } 
203207                    return  false ; 
204208                } , 
209+                 ( Token :: FatArrow ,  lexer:: TokenKind :: Eq )  => { 
210+                     self . step ( ) ; 
211+                     if  matches ! ( self . next_token. kind,  lexer:: TokenKind :: Gt )  { 
212+                         self . step ( ) ; 
213+                         return  true ; 
214+                     } 
215+                     return  false ; 
216+                 } , 
217+                 ( Token :: OptLifetimeArgs ,  lexer:: TokenKind :: Lt )  => { 
218+                     self . step ( ) ; 
219+                     while  self . read_token ( Token :: Lifetime ,  captures)  { 
220+                         if  !self . read_token ( Token :: Comma ,  captures)  { 
221+                             break ; 
222+                         } 
223+                     } 
224+                     return  self . read_token ( Token :: Gt ,  captures) ; 
225+                 } , 
226+                 #[ expect( clippy:: match_same_arms) ]  
227+                 ( Token :: OptLifetimeArgs ,  _)  => return  true , 
205228                #[ rustfmt:: skip]  
206229                ( 
207230                    Token :: CaptureLitStr , 
@@ -235,16 +258,28 @@ impl<'txt> RustSearcher<'txt> {
235258    } 
236259
237260    #[ 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 ; 
261+     pub  fn  find_any_ident ( & mut  self )  -> Option < & ' txt  str >  { 
262+         loop  { 
263+             match  self . next_token . kind  { 
264+                 lexer:: TokenKind :: Ident  => { 
265+                     let  res = self . peek_text ( ) ; 
266+                     self . step ( ) ; 
267+                     return  Some ( res) ; 
268+                 } , 
269+                 lexer:: TokenKind :: Eof  => return  None , 
270+                 _ => self . step ( ) , 
245271            } 
246272        } 
247-         Some ( & self . text [ capture. to_index ( ) ] ) 
273+     } 
274+ 
275+     #[ must_use]  
276+     pub  fn  find_ident ( & mut  self ,  s :  & str )  -> bool  { 
277+         while  let  Some ( x)  = self . find_any_ident ( )  { 
278+             if  x == s { 
279+                 return  true ; 
280+             } 
281+         } 
282+         false 
248283    } 
249284
250285    #[ must_use]  
@@ -286,9 +321,27 @@ pub struct Lint {
286321    pub  name_span :  Span , 
287322} 
288323
324+ pub  struct  LintPassData  { 
325+     pub  name :  String , 
326+     /// Span of the `impl_lint_pass` or `declare_lint_pass` macro call. 
327+ pub  mac_span :  Span , 
328+ } 
329+ 
330+ newtype_index !  { 
331+     #[ orderable] 
332+     pub  struct  LintPass  { } 
333+ } 
334+ 
335+ pub  struct  LintRegistration  { 
336+     pub  name :  String , 
337+     pub  pass :  LintPass , 
338+ } 
339+ 
289340pub  struct  ParsedData  { 
290341    pub  source_map :  SourceMap , 
291342    pub  lints :  FxHashMap < String ,  Lint > , 
343+     pub  lint_passes :  IndexVec < LintPass ,  LintPassData > , 
344+     pub  lint_registrations :  Vec < LintRegistration > , 
292345    pub  deprecated_span :  Range < u32 > , 
293346    pub  renamed_span :  Range < u32 > , 
294347} 
@@ -299,6 +352,8 @@ impl ParsedData {
299352        let  mut  parser = Parser  { 
300353            source_map :  SourceMap :: with_capacity ( 8 ,  1000 ) , 
301354            lints :  FxHashMap :: with_capacity_and_hasher ( 1000 ,  Default :: default ( ) ) , 
355+             lint_passes :  IndexVec :: with_capacity ( 400 ) , 
356+             lint_registrations :  Vec :: with_capacity ( 1000 ) , 
302357            deprecated_span :  0 ..0 , 
303358            renamed_span :  0 ..0 , 
304359            errors :  Vec :: new ( ) , 
@@ -355,6 +410,8 @@ impl ParsedData {
355410        ParsedData  { 
356411            source_map :  parser. source_map , 
357412            lints :  parser. lints , 
413+             lint_passes :  parser. lint_passes , 
414+             lint_registrations :  parser. lint_registrations , 
358415            deprecated_span :  parser. deprecated_span , 
359416            renamed_span :  parser. renamed_span , 
360417        } 
@@ -399,6 +456,8 @@ impl From<ErrorKind> for Error {
399456struct  Parser  { 
400457    source_map :  SourceMap , 
401458    lints :  FxHashMap < String ,  Lint > , 
459+     lint_passes :  IndexVec < LintPass ,  LintPassData > , 
460+     lint_registrations :  Vec < LintRegistration > , 
402461    deprecated_span :  Range < u32 > , 
403462    renamed_span :  Range < u32 > , 
404463    errors :  Vec < Error > , 
@@ -449,7 +508,7 @@ impl Parser {
449508        #[ allow( clippy:: enum_glob_use) ]  
450509        use  Token :: * ; 
451510        #[ rustfmt:: skip]  
452-         static  DECL_TOKENS :  & [ Token < ' _ > ]  = & [ 
511+         static  LINT_DECL_TOKENS :  & [ Token < ' _ > ]  = & [ 
453512            // { /// docs 
454513            OpenBrace ,  AnyComment , 
455514            // #[clippy::version = "version"] 
@@ -458,42 +517,81 @@ impl Parser {
458517            Ident ( "pub" ) ,  CaptureIdent ,  Comma ,  AnyComment ,  CaptureIdent ,  Comma ,  AnyComment ,  LitStr , 
459518        ] ; 
460519        #[ rustfmt:: skip]  
461-         static  EXTRA_TOKENS :  & [ Token < ' _ > ]  = & [ 
520+         static  LINT_DECL_EXTRA_TOKENS :  & [ Token < ' _ > ]  = & [ 
462521            // , @option = value 
463522            Comma ,  AnyComment ,  At ,  AnyIdent ,  Eq ,  Literal , 
464523        ] ; 
524+         #[ rustfmt:: skip]  
525+         static  LINT_PASS_TOKENS :  & [ Token < ' _ > ]  = & [ 
526+             // ( name <'lt> => [ 
527+             OpenParen ,  AnyComment ,  CaptureIdent ,  OptLifetimeArgs ,  FatArrow ,  OpenBracket , 
528+         ] ; 
465529
466530        let  mut  searcher = RustSearcher :: new ( & self . source_map . files [ file] . contents ) ; 
467531        let  mut  captures = [ Capture :: EMPTY ;  2 ] ; 
468-         # [ expect ( clippy :: cast_possible_truncation ) ] 
469-         while  searcher . find_token ( Ident ( "declare_clippy_lint" ) )   { 
470-             let  start = searcher. pos ( )  - "declare_clippy_lint" . len ( )  as  u32 ; 
532+         while   let   Some ( ident )  = searcher . find_any_ident ( )   { 
533+              # [ expect ( clippy :: cast_possible_truncation ) ] 
534+             let  start = searcher. pos  - ident . len ( )  as  u32 ; 
471535            if  searcher. match_token ( Bang )  { 
472-                 if  !searcher. match_tokens ( DECL_TOKENS ,  & mut  captures)  { 
473-                     self . errors . push ( searcher. get_unexpected_err ( file) ) ; 
474-                     return ; 
475-                 } 
476-                 let  name_span = captures[ 0 ] . to_span ( file) ; 
477-                 let  name = searcher. get_capture ( captures[ 0 ] ) . to_ascii_lowercase ( ) ; 
478-                 if  let  Some ( e)  = get_vacant_lint ( name,  name_span,  & mut  self . lints ,  & mut  self . errors )  { 
479-                     e. insert ( Lint  { 
480-                         kind :  LintKind :: Active ( ActiveLint  { 
481-                             group :  searcher. get_capture ( captures[ 1 ] ) . into ( ) , 
482-                             decl_span :  Span  { 
536+                 match  ident { 
537+                     "declare_clippy_lint"  => { 
538+                         if  !searcher. match_tokens ( LINT_DECL_TOKENS ,  & mut  captures)  { 
539+                             self . errors . push ( searcher. get_unexpected_err ( file) ) ; 
540+                             return ; 
541+                         } 
542+                         while  searcher. match_tokens ( LINT_DECL_EXTRA_TOKENS ,  & mut  [ ] )  { 
543+                             // nothing 
544+                         } 
545+                         if  !searcher. match_token ( CloseBrace )  { 
546+                             self . errors . push ( searcher. get_unexpected_err ( file) ) ; 
547+                             return ; 
548+                         } 
549+                         let  name_span = captures[ 0 ] . to_span ( file) ; 
550+                         let  name = searcher. get_capture ( captures[ 0 ] ) . to_ascii_lowercase ( ) ; 
551+                         if  let  Some ( e)  = get_vacant_lint ( name,  name_span,  & mut  self . lints ,  & mut  self . errors )  { 
552+                             e. insert ( Lint  { 
553+                                 kind :  LintKind :: Active ( ActiveLint  { 
554+                                     group :  searcher. get_capture ( captures[ 1 ] ) . into ( ) , 
555+                                     decl_span :  Span  { 
556+                                         file, 
557+                                         start, 
558+                                         end :  searcher. pos ( ) , 
559+                                     } , 
560+                                 } ) , 
561+                                 name_span, 
562+                             } ) ; 
563+                         } 
564+                     } , 
565+                     "impl_lint_pass"  | "declare_lint_pass"  => { 
566+                         if  !searcher. match_tokens ( LINT_PASS_TOKENS ,  & mut  captures)  { 
567+                             self . errors . push ( searcher. get_unexpected_err ( file) ) ; 
568+                             return ; 
569+                         } 
570+                         let  pass = self . lint_passes . next_index ( ) ; 
571+                         let  pass_name = captures[ 0 ] ; 
572+                         while  searcher. match_tokens ( & [ AnyComment ,  CaptureIdent ] ,  & mut  captures)  { 
573+                             self . lint_registrations . push ( LintRegistration  { 
574+                                 name :  searcher. get_capture ( captures[ 0 ] ) . to_ascii_lowercase ( ) , 
575+                                 pass, 
576+                             } ) ; 
577+                             if  !searcher. match_token ( Comma )  { 
578+                                 break ; 
579+                             } 
580+                         } 
581+                         if  !searcher. match_tokens ( & [ CloseBracket ,  CloseParen ] ,  & mut  [ ] )  { 
582+                             self . errors . push ( searcher. get_unexpected_err ( file) ) ; 
583+                             return ; 
584+                         } 
585+                         self . lint_passes . push ( LintPassData  { 
586+                             name :  searcher. get_capture ( pass_name) . to_owned ( ) , 
587+                             mac_span :  Span  { 
483588                                file, 
484589                                start, 
485590                                end :  searcher. pos ( ) , 
486591                            } , 
487-                         } ) , 
488-                         name_span, 
489-                     } ) ; 
490-                 } 
491-                 while  searcher. match_tokens ( EXTRA_TOKENS ,  & mut  [ ] )  { 
492-                     // nothing 
493-                 } 
494-                 if  !searcher. match_token ( CloseBrace )  { 
495-                     self . errors . push ( searcher. get_unexpected_err ( file) ) ; 
496-                     return ; 
592+                         } ) ; 
593+                     } , 
594+                     _ => { } , 
497595                } 
498596            } 
499597        } 
@@ -537,11 +635,11 @@ impl Parser {
537635        let  mut  searcher = RustSearcher :: new ( & file_data. contents ) ; 
538636        // First instance is the macro definition. 
539637        assert ! ( 
540-             searcher. find_token ( Ident ( "declare_with_version" ) ) , 
541-             "error parsing `clippy_lints/src/deprecated_lints.rs`" 
638+             searcher. find_ident ( "declare_with_version" ) , 
639+             "error parsing `clippy_lints/src/deprecated_lints.rs`" , 
542640        ) ; 
543641
544-         if  !searcher. find_token ( Ident ( "declare_with_version" ) )  || !searcher. match_tokens ( DEPRECATED_TOKENS ,  & mut  [ ] )  { 
642+         if  !searcher. find_ident ( "declare_with_version" )  || !searcher. match_tokens ( DEPRECATED_TOKENS ,  & mut  [ ] )  { 
545643            self . errors . push ( searcher. get_unexpected_err ( file) ) ; 
546644            return ; 
547645        } 
@@ -570,7 +668,7 @@ impl Parser {
570668            return ; 
571669        } 
572670
573-         if  !searcher. find_token ( Ident ( "declare_with_version" ) )  || !searcher. match_tokens ( RENAMED_TOKENS ,  & mut  [ ] )  { 
671+         if  !searcher. find_ident ( "declare_with_version" )  || !searcher. match_tokens ( RENAMED_TOKENS ,  & mut  [ ] )  { 
574672            self . errors . push ( searcher. get_unexpected_err ( file) ) ; 
575673            return ; 
576674        } 
0 commit comments