1+ pub mod cursor;
2+
3+ use self :: cursor:: Cursor ;
14use crate :: utils:: { ErrAction , File , expect_action} ;
25use core:: ops:: Range ;
3- use core:: slice;
4- use rustc_lexer:: { self as lexer, FrontmatterAllowed } ;
56use std:: fs;
67use std:: path:: { Path , PathBuf } ;
78use walkdir:: { DirEntry , WalkDir } ;
89
9- #[ derive( Clone , Copy ) ]
10- pub enum Token < ' a > {
11- /// Matches any number of comments / doc comments.
12- AnyComment ,
13- Ident ( & ' a str ) ,
14- CaptureIdent ,
15- LitStr ,
16- CaptureLitStr ,
17- Bang ,
18- CloseBrace ,
19- CloseBracket ,
20- CloseParen ,
21- /// This will consume the first colon even if the second doesn't exist.
22- DoubleColon ,
23- Comma ,
24- Eq ,
25- Lifetime ,
26- Lt ,
27- Gt ,
28- OpenBrace ,
29- OpenBracket ,
30- OpenParen ,
31- Pound ,
32- Semi ,
33- }
34-
35- pub struct RustSearcher < ' txt > {
36- text : & ' txt str ,
37- cursor : lexer:: Cursor < ' txt > ,
38- pos : u32 ,
39- next_token : lexer:: Token ,
40- }
41- impl < ' txt > RustSearcher < ' txt > {
42- #[ must_use]
43- #[ expect( clippy:: inconsistent_struct_constructor) ]
44- pub fn new ( text : & ' txt str ) -> Self {
45- let mut cursor = lexer:: Cursor :: new ( text, FrontmatterAllowed :: Yes ) ;
46- Self {
47- text,
48- pos : 0 ,
49- next_token : cursor. advance_token ( ) ,
50- cursor,
51- }
52- }
53-
54- #[ must_use]
55- pub fn peek_text ( & self ) -> & ' txt str {
56- & self . text [ self . pos as usize ..( self . pos + self . next_token . len ) as usize ]
57- }
58-
59- #[ must_use]
60- pub fn peek_len ( & self ) -> u32 {
61- self . next_token . len
62- }
63-
64- #[ must_use]
65- pub fn peek ( & self ) -> lexer:: TokenKind {
66- self . next_token . kind
67- }
68-
69- #[ must_use]
70- pub fn pos ( & self ) -> u32 {
71- self . pos
72- }
73-
74- #[ must_use]
75- pub fn at_end ( & self ) -> bool {
76- self . next_token . kind == lexer:: TokenKind :: Eof
77- }
78-
79- pub fn step ( & mut self ) {
80- // `next_token.len` is zero for the eof marker.
81- self . pos += self . next_token . len ;
82- self . next_token = self . cursor . advance_token ( ) ;
83- }
84-
85- /// Consumes the next token if it matches the requested value and captures the value if
86- /// requested. Returns true if a token was matched.
87- fn read_token ( & mut self , token : Token < ' _ > , captures : & mut slice:: IterMut < ' _ , & mut & ' txt str > ) -> bool {
88- loop {
89- match ( token, self . next_token . kind ) {
90- ( _, lexer:: TokenKind :: Whitespace )
91- | (
92- Token :: AnyComment ,
93- lexer:: TokenKind :: BlockComment { terminated : true , .. } | lexer:: TokenKind :: LineComment { .. } ,
94- ) => self . step ( ) ,
95- ( Token :: AnyComment , _) => return true ,
96- ( Token :: Bang , lexer:: TokenKind :: Bang )
97- | ( Token :: CloseBrace , lexer:: TokenKind :: CloseBrace )
98- | ( Token :: CloseBracket , lexer:: TokenKind :: CloseBracket )
99- | ( Token :: CloseParen , lexer:: TokenKind :: CloseParen )
100- | ( Token :: Comma , lexer:: TokenKind :: Comma )
101- | ( Token :: Eq , lexer:: TokenKind :: Eq )
102- | ( Token :: Lifetime , lexer:: TokenKind :: Lifetime { .. } )
103- | ( Token :: Lt , lexer:: TokenKind :: Lt )
104- | ( Token :: Gt , lexer:: TokenKind :: Gt )
105- | ( Token :: OpenBrace , lexer:: TokenKind :: OpenBrace )
106- | ( Token :: OpenBracket , lexer:: TokenKind :: OpenBracket )
107- | ( Token :: OpenParen , lexer:: TokenKind :: OpenParen )
108- | ( Token :: Pound , lexer:: TokenKind :: Pound )
109- | ( Token :: Semi , lexer:: TokenKind :: Semi )
110- | (
111- Token :: LitStr ,
112- lexer:: TokenKind :: Literal {
113- kind : lexer:: LiteralKind :: Str { terminated : true } | lexer:: LiteralKind :: RawStr { .. } ,
114- ..
115- } ,
116- ) => {
117- self . step ( ) ;
118- return true ;
119- } ,
120- ( Token :: Ident ( x) , lexer:: TokenKind :: Ident ) if x == self . peek_text ( ) => {
121- self . step ( ) ;
122- return true ;
123- } ,
124- ( Token :: DoubleColon , lexer:: TokenKind :: Colon ) => {
125- self . step ( ) ;
126- if !self . at_end ( ) && matches ! ( self . next_token. kind, lexer:: TokenKind :: Colon ) {
127- self . step ( ) ;
128- return true ;
129- }
130- return false ;
131- } ,
132- #[ rustfmt:: skip]
133- (
134- Token :: CaptureLitStr ,
135- lexer:: TokenKind :: Literal {
136- kind :
137- lexer:: LiteralKind :: Str { terminated : true }
138- | lexer:: LiteralKind :: RawStr { n_hashes : Some ( _) } ,
139- ..
140- } ,
141- )
142- | ( Token :: CaptureIdent , lexer:: TokenKind :: Ident ) => {
143- * * captures. next ( ) . unwrap ( ) = self . peek_text ( ) ;
144- self . step ( ) ;
145- return true ;
146- } ,
147- _ => return false ,
148- }
149- }
150- }
151-
152- #[ must_use]
153- pub fn find_token ( & mut self , token : Token < ' _ > ) -> bool {
154- let mut capture = [ ] . iter_mut ( ) ;
155- while !self . read_token ( token, & mut capture) {
156- self . step ( ) ;
157- if self . at_end ( ) {
158- return false ;
159- }
160- }
161- true
162- }
163-
164- #[ must_use]
165- pub fn find_capture_token ( & mut self , token : Token < ' _ > ) -> Option < & ' txt str > {
166- let mut res = "" ;
167- let mut capture = & mut res;
168- let mut capture = slice:: from_mut ( & mut capture) . iter_mut ( ) ;
169- while !self . read_token ( token, & mut capture) {
170- self . step ( ) ;
171- if self . at_end ( ) {
172- return None ;
173- }
174- }
175- Some ( res)
176- }
177-
178- #[ must_use]
179- pub fn match_tokens ( & mut self , tokens : & [ Token < ' _ > ] , captures : & mut [ & mut & ' txt str ] ) -> bool {
180- let mut captures = captures. iter_mut ( ) ;
181- tokens. iter ( ) . all ( |& t| self . read_token ( t, & mut captures) )
182- }
183- }
184-
18510pub struct Lint {
18611 pub name : String ,
18712 pub group : String ,
@@ -265,9 +90,9 @@ fn read_src_with_module(src_root: &Path) -> impl use<'_> + Iterator<Item = (DirE
26590/// Parse a source file looking for `declare_clippy_lint` macro invocations.
26691fn parse_clippy_lint_decls ( path : & Path , contents : & str , module : & str , lints : & mut Vec < Lint > ) {
26792 #[ allow( clippy:: enum_glob_use) ]
268- use Token :: * ;
93+ use cursor :: Pat :: * ;
26994 #[ rustfmt:: skip]
270- static DECL_TOKENS : & [ Token < ' _ > ] = & [
95+ static DECL_TOKENS : & [ cursor :: Pat < ' _ > ] = & [
27196 // !{ /// docs
27297 Bang , OpenBrace , AnyComment ,
27398 // #[clippy::version = "version"]
@@ -276,17 +101,17 @@ fn parse_clippy_lint_decls(path: &Path, contents: &str, module: &str, lints: &mu
276101 Ident ( "pub" ) , CaptureIdent , Comma , AnyComment , CaptureIdent , Comma ,
277102 ] ;
278103
279- let mut searcher = RustSearcher :: new ( contents) ;
280- while searcher . find_token ( Ident ( "declare_clippy_lint" ) ) {
281- let start = searcher . pos ( ) as usize - "declare_clippy_lint" . len ( ) ;
104+ let mut cursor = Cursor :: new ( contents) ;
105+ while cursor . find_pat ( Ident ( "declare_clippy_lint" ) ) {
106+ let start = cursor . pos ( ) as usize - "declare_clippy_lint" . len ( ) ;
282107 let ( mut name, mut group) = ( "" , "" ) ;
283- if searcher . match_tokens ( DECL_TOKENS , & mut [ & mut name, & mut group] ) && searcher . find_token ( CloseBrace ) {
108+ if cursor . match_all ( DECL_TOKENS , & mut [ & mut name, & mut group] ) && cursor . find_pat ( CloseBrace ) {
284109 lints. push ( Lint {
285110 name : name. to_lowercase ( ) ,
286111 group : group. into ( ) ,
287112 module : module. into ( ) ,
288113 path : path. into ( ) ,
289- declaration_range : start..searcher . pos ( ) as usize ,
114+ declaration_range : start..cursor . pos ( ) as usize ,
290115 } ) ;
291116 }
292117 }
@@ -295,21 +120,21 @@ fn parse_clippy_lint_decls(path: &Path, contents: &str, module: &str, lints: &mu
295120#[ must_use]
296121pub fn read_deprecated_lints ( ) -> ( Vec < DeprecatedLint > , Vec < RenamedLint > ) {
297122 #[ allow( clippy:: enum_glob_use) ]
298- use Token :: * ;
123+ use cursor :: Pat :: * ;
299124 #[ rustfmt:: skip]
300- static DECL_TOKENS : & [ Token < ' _ > ] = & [
125+ static DECL_TOKENS : & [ cursor :: Pat < ' _ > ] = & [
301126 // #[clippy::version = "version"]
302127 Pound , OpenBracket , Ident ( "clippy" ) , DoubleColon , Ident ( "version" ) , Eq , CaptureLitStr , CloseBracket ,
303128 // ("first", "second"),
304129 OpenParen , CaptureLitStr , Comma , CaptureLitStr , CloseParen , Comma ,
305130 ] ;
306131 #[ rustfmt:: skip]
307- static DEPRECATED_TOKENS : & [ Token < ' _ > ] = & [
132+ static DEPRECATED_TOKENS : & [ cursor :: Pat < ' _ > ] = & [
308133 // !{ DEPRECATED(DEPRECATED_VERSION) = [
309134 Bang , OpenBrace , Ident ( "DEPRECATED" ) , OpenParen , Ident ( "DEPRECATED_VERSION" ) , CloseParen , Eq , OpenBracket ,
310135 ] ;
311136 #[ rustfmt:: skip]
312- static RENAMED_TOKENS : & [ Token < ' _ > ] = & [
137+ static RENAMED_TOKENS : & [ cursor :: Pat < ' _ > ] = & [
313138 // !{ RENAMED(RENAMED_VERSION) = [
314139 Bang , OpenBrace , Ident ( "RENAMED" ) , OpenParen , Ident ( "RENAMED_VERSION" ) , CloseParen , Eq , OpenBracket ,
315140 ] ;
@@ -320,19 +145,19 @@ pub fn read_deprecated_lints() -> (Vec<DeprecatedLint>, Vec<RenamedLint>) {
320145 let mut contents = String :: new ( ) ;
321146 File :: open_read_to_cleared_string ( path, & mut contents) ;
322147
323- let mut searcher = RustSearcher :: new ( & contents) ;
148+ let mut cursor = Cursor :: new ( & contents) ;
324149
325150 // First instance is the macro definition.
326151 assert ! (
327- searcher . find_token ( Ident ( "declare_with_version" ) ) ,
152+ cursor . find_pat ( Ident ( "declare_with_version" ) ) ,
328153 "error reading deprecated lints"
329154 ) ;
330155
331- if searcher . find_token ( Ident ( "declare_with_version" ) ) && searcher . match_tokens ( DEPRECATED_TOKENS , & mut [ ] ) {
156+ if cursor . find_pat ( Ident ( "declare_with_version" ) ) && cursor . match_all ( DEPRECATED_TOKENS , & mut [ ] ) {
332157 let mut version = "" ;
333158 let mut name = "" ;
334159 let mut reason = "" ;
335- while searcher . match_tokens ( DECL_TOKENS , & mut [ & mut version, & mut name, & mut reason] ) {
160+ while cursor . match_all ( DECL_TOKENS , & mut [ & mut version, & mut name, & mut reason] ) {
336161 deprecated. push ( DeprecatedLint {
337162 name : parse_str_single_line ( path. as_ref ( ) , name) ,
338163 reason : parse_str_single_line ( path. as_ref ( ) , reason) ,
@@ -343,11 +168,11 @@ pub fn read_deprecated_lints() -> (Vec<DeprecatedLint>, Vec<RenamedLint>) {
343168 panic ! ( "error reading deprecated lints" ) ;
344169 }
345170
346- if searcher . find_token ( Ident ( "declare_with_version" ) ) && searcher . match_tokens ( RENAMED_TOKENS , & mut [ ] ) {
171+ if cursor . find_pat ( Ident ( "declare_with_version" ) ) && cursor . match_all ( RENAMED_TOKENS , & mut [ ] ) {
347172 let mut version = "" ;
348173 let mut old_name = "" ;
349174 let mut new_name = "" ;
350- while searcher . match_tokens ( DECL_TOKENS , & mut [ & mut version, & mut old_name, & mut new_name] ) {
175+ while cursor . match_all ( DECL_TOKENS , & mut [ & mut version, & mut old_name, & mut new_name] ) {
351176 renamed. push ( RenamedLint {
352177 old_name : parse_str_single_line ( path. as_ref ( ) , old_name) ,
353178 new_name : parse_str_single_line ( path. as_ref ( ) , new_name) ,
0 commit comments