11pub mod cursor;
22
33use self :: cursor:: { Capture , Cursor } ;
4- use crate :: utils:: { ErrAction , File , expect_action} ;
4+ use crate :: utils:: { ErrAction , File , Scoped , expect_action} ;
55use core:: range:: Range ;
66use std:: fs;
77use std:: path:: { Path , PathBuf } ;
88use walkdir:: { DirEntry , WalkDir } ;
99
10+ pub struct ParseCxImpl ;
11+ pub type ParseCx < ' cx > = & ' cx mut ParseCxImpl ;
12+
13+ /// Calls the given function inside a newly created parsing context.
14+ pub fn new_parse_cx < ' env , T > ( f : impl for < ' cx > FnOnce ( & ' cx mut Scoped < ' cx , ' env , ParseCxImpl > ) -> T ) -> T {
15+ f ( & mut Scoped :: new ( ParseCxImpl ) )
16+ }
17+
1018pub struct Lint {
1119 pub name : String ,
1220 pub group : String ,
@@ -27,33 +35,101 @@ pub struct RenamedLint {
2735 pub version : String ,
2836}
2937
30- /// Finds all lint declarations (`declare_clippy_lint!`)
31- #[ must_use]
32- pub fn find_lint_decls ( ) -> Vec < Lint > {
33- let mut lints = Vec :: with_capacity ( 1000 ) ;
34- let mut contents = String :: new ( ) ;
35- for e in expect_action ( fs:: read_dir ( "." ) , ErrAction :: Read , "." ) {
36- let e = expect_action ( e, ErrAction :: Read , "." ) ;
37- if !expect_action ( e. file_type ( ) , ErrAction :: Read , "." ) . is_dir ( ) {
38- continue ;
38+ impl ParseCxImpl {
39+ /// Finds all lint declarations (`declare_clippy_lint!`)
40+ #[ must_use]
41+ pub fn find_lint_decls ( & mut self ) -> Vec < Lint > {
42+ let mut lints = Vec :: with_capacity ( 1000 ) ;
43+ let mut contents = String :: new ( ) ;
44+ for e in expect_action ( fs:: read_dir ( "." ) , ErrAction :: Read , "." ) {
45+ let e = expect_action ( e, ErrAction :: Read , "." ) ;
46+ if !expect_action ( e. file_type ( ) , ErrAction :: Read , "." ) . is_dir ( ) {
47+ continue ;
48+ }
49+ let Ok ( mut name) = e. file_name ( ) . into_string ( ) else {
50+ continue ;
51+ } ;
52+ if name. starts_with ( "clippy_lints" ) && name != "clippy_lints_internal" {
53+ name. push_str ( "/src" ) ;
54+ for ( file, module) in read_src_with_module ( name. as_ref ( ) ) {
55+ parse_clippy_lint_decls (
56+ file. path ( ) ,
57+ File :: open_read_to_cleared_string ( file. path ( ) , & mut contents) ,
58+ & module,
59+ & mut lints,
60+ ) ;
61+ }
62+ }
3963 }
40- let Ok ( mut name) = e. file_name ( ) . into_string ( ) else {
41- continue ;
42- } ;
43- if name. starts_with ( "clippy_lints" ) && name != "clippy_lints_internal" {
44- name. push_str ( "/src" ) ;
45- for ( file, module) in read_src_with_module ( name. as_ref ( ) ) {
46- parse_clippy_lint_decls (
47- file. path ( ) ,
48- File :: open_read_to_cleared_string ( file. path ( ) , & mut contents) ,
49- & module,
50- & mut lints,
51- ) ;
64+ lints. sort_by ( |lhs, rhs| lhs. name . cmp ( & rhs. name ) ) ;
65+ lints
66+ }
67+
68+ #[ must_use]
69+ pub fn read_deprecated_lints ( & mut self ) -> ( Vec < DeprecatedLint > , Vec < RenamedLint > ) {
70+ #[ allow( clippy:: enum_glob_use) ]
71+ use cursor:: Pat :: * ;
72+ #[ rustfmt:: skip]
73+ static DECL_TOKENS : & [ cursor:: Pat < ' _ > ] = & [
74+ // #[clippy::version = "version"]
75+ Pound , OpenBracket , Ident ( "clippy" ) , DoubleColon , Ident ( "version" ) , Eq , CaptureLitStr , CloseBracket ,
76+ // ("first", "second"),
77+ OpenParen , CaptureLitStr , Comma , CaptureLitStr , CloseParen , Comma ,
78+ ] ;
79+ #[ rustfmt:: skip]
80+ static DEPRECATED_TOKENS : & [ cursor:: Pat < ' _ > ] = & [
81+ // !{ DEPRECATED(DEPRECATED_VERSION) = [
82+ Bang , OpenBrace , Ident ( "DEPRECATED" ) , OpenParen , Ident ( "DEPRECATED_VERSION" ) , CloseParen , Eq , OpenBracket ,
83+ ] ;
84+ #[ rustfmt:: skip]
85+ static RENAMED_TOKENS : & [ cursor:: Pat < ' _ > ] = & [
86+ // !{ RENAMED(RENAMED_VERSION) = [
87+ Bang , OpenBrace , Ident ( "RENAMED" ) , OpenParen , Ident ( "RENAMED_VERSION" ) , CloseParen , Eq , OpenBracket ,
88+ ] ;
89+
90+ let path = "clippy_lints/src/deprecated_lints.rs" ;
91+ let mut deprecated = Vec :: with_capacity ( 30 ) ;
92+ let mut renamed = Vec :: with_capacity ( 80 ) ;
93+ let mut contents = String :: new ( ) ;
94+ File :: open_read_to_cleared_string ( path, & mut contents) ;
95+
96+ let mut cursor = Cursor :: new ( & contents) ;
97+ let mut captures = [ Capture :: EMPTY ; 3 ] ;
98+
99+ // First instance is the macro definition.
100+ assert ! (
101+ cursor. find_ident( "declare_with_version" ) . is_some( ) ,
102+ "error reading deprecated lints"
103+ ) ;
104+
105+ if cursor. find_ident ( "declare_with_version" ) . is_some ( ) && cursor. match_all ( DEPRECATED_TOKENS , & mut [ ] ) {
106+ while cursor. match_all ( DECL_TOKENS , & mut captures) {
107+ deprecated. push ( DeprecatedLint {
108+ name : parse_str_single_line ( path. as_ref ( ) , cursor. get_text ( captures[ 1 ] ) ) ,
109+ reason : parse_str_single_line ( path. as_ref ( ) , cursor. get_text ( captures[ 2 ] ) ) ,
110+ version : parse_str_single_line ( path. as_ref ( ) , cursor. get_text ( captures[ 0 ] ) ) ,
111+ } ) ;
52112 }
113+ } else {
114+ panic ! ( "error reading deprecated lints" ) ;
53115 }
116+
117+ if cursor. find_ident ( "declare_with_version" ) . is_some ( ) && cursor. match_all ( RENAMED_TOKENS , & mut [ ] ) {
118+ while cursor. match_all ( DECL_TOKENS , & mut captures) {
119+ renamed. push ( RenamedLint {
120+ old_name : parse_str_single_line ( path. as_ref ( ) , cursor. get_text ( captures[ 1 ] ) ) ,
121+ new_name : parse_str_single_line ( path. as_ref ( ) , cursor. get_text ( captures[ 2 ] ) ) ,
122+ version : parse_str_single_line ( path. as_ref ( ) , cursor. get_text ( captures[ 0 ] ) ) ,
123+ } ) ;
124+ }
125+ } else {
126+ panic ! ( "error reading renamed lints" ) ;
127+ }
128+
129+ deprecated. sort_by ( |lhs, rhs| lhs. name . cmp ( & rhs. name ) ) ;
130+ renamed. sort_by ( |lhs, rhs| lhs. old_name . cmp ( & rhs. old_name ) ) ;
131+ ( deprecated, renamed)
54132 }
55- lints. sort_by ( |lhs, rhs| lhs. name . cmp ( & rhs. name ) ) ;
56- lints
57133}
58134
59135/// Reads the source files from the given root directory
@@ -116,72 +192,6 @@ fn parse_clippy_lint_decls(path: &Path, contents: &str, module: &str, lints: &mu
116192 }
117193}
118194
119- #[ must_use]
120- pub fn read_deprecated_lints ( ) -> ( Vec < DeprecatedLint > , Vec < RenamedLint > ) {
121- #[ allow( clippy:: enum_glob_use) ]
122- use cursor:: Pat :: * ;
123- #[ rustfmt:: skip]
124- static DECL_TOKENS : & [ cursor:: Pat < ' _ > ] = & [
125- // #[clippy::version = "version"]
126- Pound , OpenBracket , Ident ( "clippy" ) , DoubleColon , Ident ( "version" ) , Eq , CaptureLitStr , CloseBracket ,
127- // ("first", "second"),
128- OpenParen , CaptureLitStr , Comma , CaptureLitStr , CloseParen , Comma ,
129- ] ;
130- #[ rustfmt:: skip]
131- static DEPRECATED_TOKENS : & [ cursor:: Pat < ' _ > ] = & [
132- // !{ DEPRECATED(DEPRECATED_VERSION) = [
133- Bang , OpenBrace , Ident ( "DEPRECATED" ) , OpenParen , Ident ( "DEPRECATED_VERSION" ) , CloseParen , Eq , OpenBracket ,
134- ] ;
135- #[ rustfmt:: skip]
136- static RENAMED_TOKENS : & [ cursor:: Pat < ' _ > ] = & [
137- // !{ RENAMED(RENAMED_VERSION) = [
138- Bang , OpenBrace , Ident ( "RENAMED" ) , OpenParen , Ident ( "RENAMED_VERSION" ) , CloseParen , Eq , OpenBracket ,
139- ] ;
140-
141- let path = "clippy_lints/src/deprecated_lints.rs" ;
142- let mut deprecated = Vec :: with_capacity ( 30 ) ;
143- let mut renamed = Vec :: with_capacity ( 80 ) ;
144- let mut contents = String :: new ( ) ;
145- File :: open_read_to_cleared_string ( path, & mut contents) ;
146-
147- let mut cursor = Cursor :: new ( & contents) ;
148- let mut captures = [ Capture :: EMPTY ; 3 ] ;
149-
150- // First instance is the macro definition.
151- assert ! (
152- cursor. find_ident( "declare_with_version" ) . is_some( ) ,
153- "error reading deprecated lints"
154- ) ;
155-
156- if cursor. find_ident ( "declare_with_version" ) . is_some ( ) && cursor. match_all ( DEPRECATED_TOKENS , & mut [ ] ) {
157- while cursor. match_all ( DECL_TOKENS , & mut captures) {
158- deprecated. push ( DeprecatedLint {
159- name : parse_str_single_line ( path. as_ref ( ) , cursor. get_text ( captures[ 1 ] ) ) ,
160- reason : parse_str_single_line ( path. as_ref ( ) , cursor. get_text ( captures[ 2 ] ) ) ,
161- version : parse_str_single_line ( path. as_ref ( ) , cursor. get_text ( captures[ 0 ] ) ) ,
162- } ) ;
163- }
164- } else {
165- panic ! ( "error reading deprecated lints" ) ;
166- }
167-
168- if cursor. find_ident ( "declare_with_version" ) . is_some ( ) && cursor. match_all ( RENAMED_TOKENS , & mut [ ] ) {
169- while cursor. match_all ( DECL_TOKENS , & mut captures) {
170- renamed. push ( RenamedLint {
171- old_name : parse_str_single_line ( path. as_ref ( ) , cursor. get_text ( captures[ 1 ] ) ) ,
172- new_name : parse_str_single_line ( path. as_ref ( ) , cursor. get_text ( captures[ 2 ] ) ) ,
173- version : parse_str_single_line ( path. as_ref ( ) , cursor. get_text ( captures[ 0 ] ) ) ,
174- } ) ;
175- }
176- } else {
177- panic ! ( "error reading renamed lints" ) ;
178- }
179-
180- deprecated. sort_by ( |lhs, rhs| lhs. name . cmp ( & rhs. name ) ) ;
181- renamed. sort_by ( |lhs, rhs| lhs. old_name . cmp ( & rhs. old_name ) ) ;
182- ( deprecated, renamed)
183- }
184-
185195/// Removes the line splices and surrounding quotes from a string literal
186196fn parse_str_lit ( s : & str ) -> String {
187197 let ( s, is_raw) = if let Some ( s) = s. strip_prefix ( "r" ) {
0 commit comments