@@ -25,43 +25,206 @@ fn dogfood_clippy() {
25
25
}
26
26
}
27
27
28
- #[ test]
29
- #[ ignore]
30
- #[ cfg( feature = "internal" ) ]
31
- fn run_metadata_collection_lint ( ) {
32
- use std:: fs:: File ;
33
- use std:: time:: SystemTime ;
34
-
35
- // Setup for validation
36
- let metadata_output_path = PathBuf :: from ( env ! ( "CARGO_MANIFEST_DIR" ) ) . join ( "util/gh-pages/lints.json" ) ;
37
- let start_time = SystemTime :: now ( ) ;
38
-
39
- // Run collection as is
40
- std:: env:: set_var ( "ENABLE_METADATA_COLLECTION" , "1" ) ;
41
- run_clippy_for_package ( "clippy_lints" , & [ "-A" , "unfulfilled_lint_expectations" ] ) ;
42
-
43
- // Check if cargo caching got in the way
44
- if let Ok ( file) = File :: open ( metadata_output_path) {
45
- if let Ok ( metadata) = file. metadata ( ) {
46
- if let Ok ( last_modification) = metadata. modified ( ) {
47
- if last_modification > start_time {
48
- // The output file has been modified. Most likely by a hungry
49
- // metadata collection monster. So We'll return.
50
- return ;
28
+ #[ cfg( all( test, feature = "internal" ) ) ]
29
+ mod internal {
30
+ use super :: run_clippy_for_package;
31
+ use if_chain:: if_chain;
32
+ use serde:: Deserialize ;
33
+ use std:: collections:: HashMap ;
34
+ use std:: ffi:: OsStr ;
35
+ use std:: fs:: { read_to_string, File } ;
36
+ use std:: io:: BufReader ;
37
+ use std:: path:: PathBuf ;
38
+ use walkdir:: WalkDir ;
39
+
40
+ static UI_TEST_PATH : std:: lazy:: SyncLazy < PathBuf > =
41
+ std:: lazy:: SyncLazy :: new ( || PathBuf :: from ( env ! ( "CARGO_MANIFEST_DIR" ) ) . join ( "tests/ui" ) ) ;
42
+
43
+ static METADATA_OUTPUT_PATH : std:: lazy:: SyncLazy < PathBuf > =
44
+ std:: lazy:: SyncLazy :: new ( || PathBuf :: from ( env ! ( "CARGO_MANIFEST_DIR" ) ) . join ( "util/gh-pages/lints.json" ) ) ;
45
+
46
+ #[ derive( Debug , Deserialize ) ]
47
+ pub struct LintMetadata {
48
+ id : String ,
49
+ applicability : Option < ApplicabilityInfo > ,
50
+ }
51
+
52
+ #[ derive( Debug , Deserialize ) ]
53
+ struct ApplicabilityInfo {
54
+ applicability : Option < String > ,
55
+ }
56
+
57
+ const MACHINE_APPLICABLE : & str = "MachineApplicable" ;
58
+
59
+ const KNOWN_EXCEPTIONS : [ & str ; 33 ] = [
60
+ "assign_ops2.stderr" ,
61
+ "cast_size_32bit.stderr" ,
62
+ "char_lit_as_u8.stderr" ,
63
+ "cmp_owned/without_suggestion.stderr" ,
64
+ "dbg_macro.stderr" ,
65
+ "deref_addrof_double_trigger.stderr" ,
66
+ "doc/unbalanced_ticks.stderr" ,
67
+ "eprint_with_newline.stderr" ,
68
+ "explicit_counter_loop.stderr" ,
69
+ "iter_skip_next_unfixable.stderr" ,
70
+ "let_and_return.stderr" ,
71
+ "literals.stderr" ,
72
+ "map_flatten.stderr" ,
73
+ "map_unwrap_or.stderr" ,
74
+ "match_bool.stderr" ,
75
+ "mem_replace_macro.stderr" ,
76
+ "needless_arbitrary_self_type_unfixable.stderr" ,
77
+ "needless_borrow_pat.stderr" ,
78
+ "needless_for_each_unfixable.stderr" ,
79
+ "nonminimal_bool.stderr" ,
80
+ "print_literal.stderr" ,
81
+ "print_with_newline.stderr" ,
82
+ "redundant_static_lifetimes_multiple.stderr" ,
83
+ "result_map_unit_fn_unfixable.stderr" ,
84
+ "search_is_some.stderr" ,
85
+ "string_add.stderr" ,
86
+ "toplevel_ref_arg_non_rustfix.stderr" ,
87
+ "unit_arg.stderr" ,
88
+ "unnecessary_clone.stderr" ,
89
+ "unnecessary_lazy_eval_unfixable.stderr" ,
90
+ "write_literal_2.stderr" ,
91
+ "write_literal.stderr" ,
92
+ "write_with_newline.stderr" ,
93
+ ] ;
94
+
95
+ #[ test]
96
+ fn known_exceptions_accuracy ( ) {
97
+ for filename in KNOWN_EXCEPTIONS {
98
+ let stderr_path = UI_TEST_PATH . join ( filename) ;
99
+ assert ! (
100
+ stderr_path. exists( ) ,
101
+ "`{}` does not exists" ,
102
+ stderr_path. strip_prefix( env!( "CARGO_MANIFEST_DIR" ) ) . unwrap( ) . display( )
103
+ ) ;
104
+ let fixed_path = stderr_path. with_extension ( "fixed" ) ;
105
+ assert ! (
106
+ !fixed_path. exists( ) ,
107
+ "`{}` exists" ,
108
+ fixed_path. strip_prefix( env!( "CARGO_MANIFEST_DIR" ) ) . unwrap( ) . display( )
109
+ ) ;
110
+ }
111
+ }
112
+
113
+ #[ test]
114
+ fn fixed_path_existence ( ) {
115
+ collect_metadata ( false ) ;
116
+
117
+ let lints = read_metadata ( ) ;
118
+
119
+ let mut lint_map = HashMap :: new ( ) ;
120
+ for lint in lints {
121
+ lint_map. insert ( lint. id , lint. applicability . and_then ( |app| app. applicability ) ) ;
122
+ }
123
+
124
+ for entry in WalkDir :: new ( & * UI_TEST_PATH ) {
125
+ let entry = entry. unwrap ( ) ;
126
+
127
+ if KNOWN_EXCEPTIONS . contains ( & & * entry. path ( ) . strip_prefix ( & * UI_TEST_PATH ) . unwrap ( ) . to_string_lossy ( ) ) {
128
+ continue ;
129
+ }
130
+
131
+ if entry. path ( ) . extension ( ) != Some ( OsStr :: new ( "stderr" ) ) {
132
+ continue ;
133
+ } ;
134
+
135
+ let stderr_path = entry. path ( ) ;
136
+
137
+ let stderr_contents = read_to_string ( stderr_path) . unwrap ( ) ;
138
+
139
+ let lint_ids = stderr_contents. lines ( ) . filter_map ( |line| {
140
+ const PREFIX : & str = "`-D clippy::" ;
141
+ const SUFFIX : & str = "`" ;
142
+ if_chain ! {
143
+ if let Some ( start) = line. find( PREFIX ) . map( |n| n + PREFIX . len( ) ) ;
144
+ if let Some ( end) = line[ start..] . find( SUFFIX ) ;
145
+ then {
146
+ Some ( line[ start..] [ ..end] . replace( '-' , "_" ) )
147
+ } else {
148
+ None
149
+ }
51
150
}
151
+ } ) ;
152
+
153
+ let mach_app_lint_ids = lint_ids
154
+ . filter ( |id| {
155
+ lint_map
156
+ . get ( id)
157
+ . unwrap ( )
158
+ . as_ref ( )
159
+ . map_or ( false , |s| s == MACHINE_APPLICABLE )
160
+ } )
161
+ . collect :: < Vec < _ > > ( ) ;
162
+
163
+ if !mach_app_lint_ids. is_empty ( ) {
164
+ let fixed_path = stderr_path. with_extension ( "fixed" ) ;
165
+ assert ! (
166
+ fixed_path. exists( ) ,
167
+ "`{}` does not exist though `{}` mentions the following `{}` lints: {:#?}" ,
168
+ fixed_path. strip_prefix( env!( "CARGO_MANIFEST_DIR" ) ) . unwrap( ) . display( ) ,
169
+ stderr_path. strip_prefix( env!( "CARGO_MANIFEST_DIR" ) ) . unwrap( ) . display( ) ,
170
+ MACHINE_APPLICABLE ,
171
+ mach_app_lint_ids
172
+ ) ;
52
173
}
53
174
}
54
175
}
55
176
56
- // Force cargo to invalidate the caches
57
- filetime:: set_file_mtime (
58
- PathBuf :: from ( env ! ( "CARGO_MANIFEST_DIR" ) ) . join ( "clippy_lints/src/lib.rs" ) ,
59
- filetime:: FileTime :: now ( ) ,
60
- )
61
- . unwrap ( ) ;
177
+ #[ test]
178
+ #[ ignore]
179
+ fn run_metadata_collection_lint ( ) {
180
+ collect_metadata ( true ) ;
181
+ }
182
+
183
+ fn collect_metadata ( disable_standard_lints : bool ) {
184
+ use std:: time:: SystemTime ;
185
+
186
+ // Setup for validation
187
+ let start_time = SystemTime :: now ( ) ;
62
188
63
- // Running the collection again
64
- run_clippy_for_package ( "clippy_lints" , & [ "-A" , "unfulfilled_lint_expectations" ] ) ;
189
+ // Run collection as is
190
+ std:: env:: set_var ( "ENABLE_METADATA_COLLECTION" , "1" ) ;
191
+ let args: & [ & str ] = if disable_standard_lints {
192
+ std:: env:: set_var ( "DISABLE_STANDARD_LINTS" , "1" ) ;
193
+ & [ "-A" , "unfulfilled_lint_expectations" ]
194
+ } else {
195
+ & [ ]
196
+ } ;
197
+ run_clippy_for_package ( "clippy_lints" , args) ;
198
+
199
+ // Check if cargo caching got in the way
200
+ if let Ok ( file) = File :: open ( & * METADATA_OUTPUT_PATH ) {
201
+ if let Ok ( metadata) = file. metadata ( ) {
202
+ if let Ok ( last_modification) = metadata. modified ( ) {
203
+ if last_modification > start_time {
204
+ // The output file has been modified. Most likely by a hungry
205
+ // metadata collection monster. So We'll return.
206
+ return ;
207
+ }
208
+ }
209
+ }
210
+ }
211
+
212
+ // Force cargo to invalidate the caches
213
+ filetime:: set_file_mtime (
214
+ PathBuf :: from ( env ! ( "CARGO_MANIFEST_DIR" ) ) . join ( "clippy_lints/src/lib.rs" ) ,
215
+ filetime:: FileTime :: now ( ) ,
216
+ )
217
+ . unwrap ( ) ;
218
+
219
+ // Running the collection again
220
+ run_clippy_for_package ( "clippy_lints" , args) ;
221
+ }
222
+
223
+ fn read_metadata ( ) -> Vec < LintMetadata > {
224
+ let file = File :: open ( & * METADATA_OUTPUT_PATH ) . unwrap ( ) ;
225
+ let reader = BufReader :: new ( file) ;
226
+ serde_json:: from_reader ( reader) . unwrap ( )
227
+ }
65
228
}
66
229
67
230
fn run_clippy_for_package ( project : & str , args : & [ & str ] ) {
0 commit comments