@@ -4,8 +4,9 @@ use crate::utils::{
4
4
use itertools:: Itertools ;
5
5
use std:: collections:: HashSet ;
6
6
use std:: fmt:: Write ;
7
+ use std:: fs;
7
8
use std:: ops:: Range ;
8
- use std:: path:: { Path , PathBuf } ;
9
+ use std:: path:: { self , Path , PathBuf } ;
9
10
use walkdir:: { DirEntry , WalkDir } ;
10
11
11
12
const GENERATED_FILE_COMMENT : & str = "// This file was generated by `cargo dev update_lints`.\n \
@@ -36,123 +37,168 @@ pub fn generate_lint_files(
36
37
deprecated : & [ DeprecatedLint ] ,
37
38
renamed : & [ RenamedLint ] ,
38
39
) {
39
- FileUpdater :: default ( ) . update_files_checked (
40
+ let mut updater = FileUpdater :: default ( ) ;
41
+ updater. update_file_checked (
40
42
"cargo dev update_lints" ,
41
43
update_mode,
42
- & mut [
43
- (
44
- "README.md" ,
45
- & mut update_text_region_fn ( "[There are over " , " lints included in this crate!]" , |dst| {
46
- write ! ( dst, "{}" , round_to_fifty( lints. len( ) ) ) . unwrap ( ) ;
47
- } ) ,
48
- ) ,
49
- (
50
- "book/src/README.md" ,
51
- & mut update_text_region_fn ( "[There are over " , " lints included in this crate!]" , |dst| {
52
- write ! ( dst, "{}" , round_to_fifty( lints. len( ) ) ) . unwrap ( ) ;
53
- } ) ,
54
- ) ,
55
- (
56
- "CHANGELOG.md" ,
57
- & mut update_text_region_fn (
58
- "<!-- begin autogenerated links to lint list -->\n " ,
59
- "<!-- end autogenerated links to lint list -->" ,
60
- |dst| {
61
- for lint in lints
62
- . iter ( )
63
- . map ( |l| & * l. name )
64
- . chain ( deprecated. iter ( ) . filter_map ( |l| l. name . strip_prefix ( "clippy::" ) ) )
65
- . chain ( renamed. iter ( ) . filter_map ( |l| l. old_name . strip_prefix ( "clippy::" ) ) )
66
- . sorted ( )
67
- {
68
- writeln ! ( dst, "[`{lint}`]: {DOCS_LINK}#{lint}" ) . unwrap ( ) ;
69
- }
70
- } ,
71
- ) ,
72
- ) ,
73
- (
74
- "clippy_lints/src/lib.rs" ,
75
- & mut update_text_region_fn (
76
- "// begin lints modules, do not remove this comment, it’s used in `update_lints`\n " ,
77
- "// end lints modules, do not remove this comment, it’s used in `update_lints`" ,
78
- |dst| {
79
- for lint_mod in lints. iter ( ) . map ( |l| & l. module ) . sorted ( ) . dedup ( ) {
80
- writeln ! ( dst, "mod {lint_mod};" ) . unwrap ( ) ;
81
- }
82
- } ,
83
- ) ,
84
- ) ,
85
- ( "clippy_lints/src/declared_lints.rs" , & mut |_, src, dst| {
86
- dst. push_str ( GENERATED_FILE_COMMENT ) ;
87
- dst. push_str ( "pub static LINTS: &[&crate::LintInfo] = &[\n " ) ;
88
- for ( module_name, lint_name) in lints. iter ( ) . map ( |l| ( & l. module , l. name . to_uppercase ( ) ) ) . sorted ( ) {
89
- writeln ! ( dst, " crate::{module_name}::{lint_name}_INFO," ) . unwrap ( ) ;
90
- }
91
- dst. push_str ( "];\n " ) ;
92
- UpdateStatus :: from_changed ( src != dst)
93
- } ) ,
94
- ( "clippy_lints/src/deprecated_lints.rs" , & mut |_, src, dst| {
95
- let mut searcher = RustSearcher :: new ( src) ;
96
- assert ! (
97
- searcher. find_token( Token :: Ident ( "declare_with_version" ) )
98
- && searcher. find_token( Token :: Ident ( "declare_with_version" ) ) ,
99
- "error reading deprecated lints"
100
- ) ;
101
- dst. push_str ( & src[ ..searcher. pos ( ) as usize ] ) ;
102
- dst. push_str ( "! { DEPRECATED(DEPRECATED_VERSION) = [\n " ) ;
103
- for lint in deprecated {
104
- write ! (
105
- dst,
106
- " #[clippy::version = \" {}\" ]\n (\" {}\" , \" {}\" ),\n " ,
107
- lint. version, lint. name, lint. reason,
108
- )
109
- . unwrap ( ) ;
44
+ "README.md" ,
45
+ & mut update_text_region_fn ( "[There are over " , " lints included in this crate!]" , |dst| {
46
+ write ! ( dst, "{}" , round_to_fifty( lints. len( ) ) ) . unwrap ( ) ;
47
+ } ) ,
48
+ ) ;
49
+ updater. update_file_checked (
50
+ "cargo dev update_lints" ,
51
+ update_mode,
52
+ "book/src/README.md" ,
53
+ & mut update_text_region_fn ( "[There are over " , " lints included in this crate!]" , |dst| {
54
+ write ! ( dst, "{}" , round_to_fifty( lints. len( ) ) ) . unwrap ( ) ;
55
+ } ) ,
56
+ ) ;
57
+ updater. update_file_checked (
58
+ "cargo dev update_lints" ,
59
+ update_mode,
60
+ "CHANGELOG.md" ,
61
+ & mut update_text_region_fn (
62
+ "<!-- begin autogenerated links to lint list -->\n " ,
63
+ "<!-- end autogenerated links to lint list -->" ,
64
+ |dst| {
65
+ for lint in lints
66
+ . iter ( )
67
+ . map ( |l| & * l. name )
68
+ . chain ( deprecated. iter ( ) . filter_map ( |l| l. name . strip_prefix ( "clippy::" ) ) )
69
+ . chain ( renamed. iter ( ) . filter_map ( |l| l. old_name . strip_prefix ( "clippy::" ) ) )
70
+ . sorted ( )
71
+ {
72
+ writeln ! ( dst, "[`{lint}`]: {DOCS_LINK}#{lint}" ) . unwrap ( ) ;
110
73
}
111
- dst. push_str (
112
- "]}\n \n \
74
+ } ,
75
+ ) ,
76
+ ) ;
77
+ updater. update_file_checked (
78
+ "cargo dev update_lints" ,
79
+ update_mode,
80
+ "clippy_lints/src/deprecated_lints.rs" ,
81
+ & mut |_, src, dst| {
82
+ let mut searcher = RustSearcher :: new ( src) ;
83
+ assert ! (
84
+ searcher. find_token( Token :: Ident ( "declare_with_version" ) )
85
+ && searcher. find_token( Token :: Ident ( "declare_with_version" ) ) ,
86
+ "error reading deprecated lints"
87
+ ) ;
88
+ dst. push_str ( & src[ ..searcher. pos ( ) as usize ] ) ;
89
+ dst. push_str ( "! { DEPRECATED(DEPRECATED_VERSION) = [\n " ) ;
90
+ for lint in deprecated {
91
+ write ! (
92
+ dst,
93
+ " #[clippy::version = \" {}\" ]\n (\" {}\" , \" {}\" ),\n " ,
94
+ lint. version, lint. name, lint. reason,
95
+ )
96
+ . unwrap ( ) ;
97
+ }
98
+ dst. push_str (
99
+ "]}\n \n \
113
100
#[rustfmt::skip]\n \
114
101
declare_with_version! { RENAMED(RENAMED_VERSION) = [\n \
115
102
",
116
- ) ;
117
- for lint in renamed {
118
- write ! (
119
- dst,
120
- " #[clippy::version = \" {}\" ]\n (\" {}\" , \" {}\" ),\n " ,
121
- lint. version, lint. old_name, lint. new_name,
122
- )
123
- . unwrap ( ) ;
103
+ ) ;
104
+ for lint in renamed {
105
+ write ! (
106
+ dst,
107
+ " #[clippy::version = \" {}\" ]\n (\" {}\" , \" {}\" ),\n " ,
108
+ lint. version, lint. old_name, lint. new_name,
109
+ )
110
+ . unwrap ( ) ;
111
+ }
112
+ dst. push_str ( "]}\n " ) ;
113
+ UpdateStatus :: from_changed ( src != dst)
114
+ } ,
115
+ ) ;
116
+ updater. update_file_checked (
117
+ "cargo dev update_lints" ,
118
+ update_mode,
119
+ "tests/ui/deprecated.rs" ,
120
+ & mut |_, src, dst| {
121
+ dst. push_str ( GENERATED_FILE_COMMENT ) ;
122
+ for lint in deprecated {
123
+ writeln ! ( dst, "#![warn({})] //~ ERROR: lint `{}`" , lint. name, lint. name) . unwrap ( ) ;
124
+ }
125
+ dst. push_str ( "\n fn main() {}\n " ) ;
126
+ UpdateStatus :: from_changed ( src != dst)
127
+ } ,
128
+ ) ;
129
+ updater. update_file_checked (
130
+ "cargo dev update_lints" ,
131
+ update_mode,
132
+ "tests/ui/rename.rs" ,
133
+ & mut move |_, src, dst| {
134
+ let mut seen_lints = HashSet :: new ( ) ;
135
+ dst. push_str ( GENERATED_FILE_COMMENT ) ;
136
+ dst. push_str ( "#![allow(clippy::duplicated_attributes)]\n " ) ;
137
+ for lint in renamed {
138
+ if seen_lints. insert ( & lint. new_name ) {
139
+ writeln ! ( dst, "#![allow({})]" , lint. new_name) . unwrap ( ) ;
124
140
}
125
- dst. push_str ( "]}\n " ) ;
126
- UpdateStatus :: from_changed ( src != dst)
127
- } ) ,
128
- ( "tests/ui/deprecated.rs" , & mut |_, src, dst| {
129
- dst. push_str ( GENERATED_FILE_COMMENT ) ;
130
- for lint in deprecated {
131
- writeln ! ( dst, "#![warn({})] //~ ERROR: lint `{}`" , lint. name, lint. name) . unwrap ( ) ;
141
+ }
142
+ seen_lints. clear ( ) ;
143
+ for lint in renamed {
144
+ if seen_lints. insert ( & lint. old_name ) {
145
+ writeln ! ( dst, "#![warn({})] //~ ERROR: lint `{}`" , lint. old_name, lint. old_name) . unwrap ( ) ;
132
146
}
133
- dst. push_str ( "\n fn main() {}\n " ) ;
134
- UpdateStatus :: from_changed ( src != dst)
135
- } ) ,
136
- ( "tests/ui/rename.rs" , & mut move |_, src, dst| {
137
- let mut seen_lints = HashSet :: new ( ) ;
138
- dst. push_str ( GENERATED_FILE_COMMENT ) ;
139
- dst. push_str ( "#![allow(clippy::duplicated_attributes)]\n " ) ;
140
- for lint in renamed {
141
- if seen_lints. insert ( & lint. new_name ) {
142
- writeln ! ( dst, "#![allow({})]" , lint. new_name) . unwrap ( ) ;
147
+ }
148
+ dst. push_str ( "\n fn main() {}\n " ) ;
149
+ UpdateStatus :: from_changed ( src != dst)
150
+ } ,
151
+ ) ;
152
+ for ( crate_name, lints) in lints. iter ( ) . into_group_map_by ( |& l| {
153
+ let Some ( path:: Component :: Normal ( name) ) = l. path . components ( ) . next ( ) else {
154
+ // All paths should start with `{crate_name}/src` when parsed from `find_lint_decls`
155
+ panic ! ( "internal error: can't read crate name from path `{}`" , l. path. display( ) ) ;
156
+ } ;
157
+ name
158
+ } ) {
159
+ updater. update_file_checked (
160
+ "cargo dev update_lints" ,
161
+ update_mode,
162
+ Path :: new ( crate_name) . join ( "src/lib.rs" ) ,
163
+ & mut update_text_region_fn (
164
+ "// begin lints modules, do not remove this comment, it’s used in `update_lints`\n " ,
165
+ "// end lints modules, do not remove this comment, it’s used in `update_lints`" ,
166
+ |dst| {
167
+ for lint_mod in lints
168
+ . iter ( )
169
+ . filter ( |l| !l. module . is_empty ( ) )
170
+ . map ( |l| l. module . split_once ( "::" ) . map_or ( & * l. module , |x| x. 0 ) )
171
+ . sorted ( )
172
+ . dedup ( )
173
+ {
174
+ writeln ! ( dst, "mod {lint_mod};" ) . unwrap ( ) ;
143
175
}
144
- }
145
- seen_lints. clear ( ) ;
146
- for lint in renamed {
147
- if seen_lints. insert ( & lint. old_name ) {
148
- writeln ! ( dst, "#![warn({})] //~ ERROR: lint `{}`" , lint. old_name, lint. old_name) . unwrap ( ) ;
176
+ } ,
177
+ ) ,
178
+ ) ;
179
+ updater. update_file_checked (
180
+ "cargo dev update_lints" ,
181
+ update_mode,
182
+ Path :: new ( crate_name) . join ( "src/declared_lints.rs" ) ,
183
+ & mut |_, src, dst| {
184
+ dst. push_str ( GENERATED_FILE_COMMENT ) ;
185
+ dst. push_str ( "pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[\n " ) ;
186
+ for ( module_path, lint_name) in lints
187
+ . iter ( )
188
+ . map ( |l| ( & l. module , l. name . to_uppercase ( ) ) )
189
+ . sorted ( )
190
+ {
191
+ if module_path. is_empty ( ) {
192
+ writeln ! ( dst, " crate::{lint_name}_INFO," ) . unwrap ( ) ;
193
+ } else {
194
+ writeln ! ( dst, " crate::{module_path}::{lint_name}_INFO," ) . unwrap ( ) ;
149
195
}
150
196
}
151
- dst. push_str ( "\n fn main() {} \n " ) ;
197
+ dst. push_str ( "]; \n " ) ;
152
198
UpdateStatus :: from_changed ( src != dst)
153
- } ) ,
154
- ] ,
155
- ) ;
199
+ } ,
200
+ ) ;
201
+ }
156
202
}
157
203
158
204
fn round_to_fifty ( count : usize ) -> usize {
@@ -186,13 +232,25 @@ pub struct RenamedLint {
186
232
pub fn find_lint_decls ( ) -> Vec < Lint > {
187
233
let mut lints = Vec :: with_capacity ( 1000 ) ;
188
234
let mut contents = String :: new ( ) ;
189
- for ( file, module) in read_src_with_module ( "clippy_lints/src" . as_ref ( ) ) {
190
- parse_clippy_lint_decls (
191
- file. path ( ) ,
192
- File :: open_read_to_cleared_string ( file. path ( ) , & mut contents) ,
193
- & module,
194
- & mut lints,
195
- ) ;
235
+ for e in expect_action ( fs:: read_dir ( "." ) , ErrAction :: Read , "." ) {
236
+ let e = expect_action ( e, ErrAction :: Read , "." ) ;
237
+ if !expect_action ( e. file_type ( ) , ErrAction :: Read , "." ) . is_dir ( ) {
238
+ continue ;
239
+ }
240
+ let Ok ( mut name) = e. file_name ( ) . into_string ( ) else {
241
+ continue ;
242
+ } ;
243
+ if name. starts_with ( "clippy_lints" ) && name != "clippy_lints_internal" {
244
+ name. push_str ( "/src" ) ;
245
+ for ( file, module) in read_src_with_module ( name. as_ref ( ) ) {
246
+ parse_clippy_lint_decls (
247
+ file. path ( ) ,
248
+ File :: open_read_to_cleared_string ( file. path ( ) , & mut contents) ,
249
+ & module,
250
+ & mut lints,
251
+ ) ;
252
+ }
253
+ }
196
254
}
197
255
lints. sort_by ( |lhs, rhs| lhs. name . cmp ( & rhs. name ) ) ;
198
256
lints
@@ -204,7 +262,7 @@ fn read_src_with_module(src_root: &Path) -> impl use<'_> + Iterator<Item = (DirE
204
262
let e = expect_action ( e, ErrAction :: Read , src_root) ;
205
263
let path = e. path ( ) . as_os_str ( ) . as_encoded_bytes ( ) ;
206
264
if let Some ( path) = path. strip_suffix ( b".rs" )
207
- && let Some ( path) = path. get ( "clippy_lints/src/" . len ( ) ..)
265
+ && let Some ( path) = path. get ( src_root . as_os_str ( ) . len ( ) + 1 ..)
208
266
{
209
267
if path == b"lib" {
210
268
Some ( ( e, String :: new ( ) ) )
0 commit comments