@@ -37,21 +37,29 @@ const IGNORE_UI_TEST_CHECK: &[&str] = &[
37
37
"E0729" , "E0789" ,
38
38
] ;
39
39
40
- pub fn check ( root_path : & Path , search_paths : & [ & Path ] , bad : & mut bool ) {
40
+ macro_rules! verbose_print {
41
+ ( $verbose: expr, $( $fmt: tt) * ) => {
42
+ if $verbose {
43
+ println!( "{}" , format_args!( $( $fmt) * ) ) ;
44
+ }
45
+ } ;
46
+ }
47
+
48
+ pub fn check ( root_path : & Path , search_paths : & [ & Path ] , verbose : bool , bad : & mut bool ) {
41
49
let mut errors = Vec :: new ( ) ;
42
50
43
51
// Stage 1: create list
44
- let error_codes = extract_error_codes ( root_path, & mut errors) ;
52
+ let error_codes = extract_error_codes ( root_path, & mut errors, verbose ) ;
45
53
println ! ( "Found {} error codes" , error_codes. len( ) ) ;
46
54
47
55
// Stage 2: check list has docs
48
- let no_longer_emitted = check_error_codes_docs ( root_path, & error_codes, & mut errors) ;
56
+ let no_longer_emitted = check_error_codes_docs ( root_path, & error_codes, & mut errors, verbose ) ;
49
57
50
58
// Stage 3: check list has UI tests
51
- check_error_codes_tests ( root_path, & error_codes, & mut errors) ;
59
+ check_error_codes_tests ( root_path, & error_codes, & mut errors, verbose ) ;
52
60
53
61
// Stage 4: check list is emitted by compiler
54
- check_error_codes_used ( search_paths, & error_codes, & mut errors, & no_longer_emitted) ;
62
+ check_error_codes_used ( search_paths, & error_codes, & mut errors, & no_longer_emitted, verbose ) ;
55
63
56
64
// Print any errors.
57
65
for error in errors {
@@ -60,16 +68,14 @@ pub fn check(root_path: &Path, search_paths: &[&Path], bad: &mut bool) {
60
68
}
61
69
62
70
/// Stage 1: Parses a list of error codes from `error_codes.rs`.
63
- fn extract_error_codes ( root_path : & Path , errors : & mut Vec < String > ) -> Vec < String > {
71
+ fn extract_error_codes ( root_path : & Path , errors : & mut Vec < String > , verbose : bool ) -> Vec < String > {
64
72
let path = root_path. join ( Path :: new ( ERROR_CODES_PATH ) ) ;
65
73
let file =
66
74
fs:: read_to_string ( & path) . unwrap_or_else ( |e| panic ! ( "failed to read `{path:?}`: {e}" ) ) ;
67
75
68
76
let mut error_codes = Vec :: new ( ) ;
69
77
let mut reached_undocumented_codes = false ;
70
78
71
- let mut undocumented_count = 0 ;
72
-
73
79
for line in file. lines ( ) {
74
80
let line = line. trim ( ) ;
75
81
@@ -115,7 +121,7 @@ fn extract_error_codes(root_path: &Path, errors: &mut Vec<String>) -> Vec<String
115
121
}
116
122
. to_string ( ) ;
117
123
118
- undocumented_count += 1 ;
124
+ verbose_print ! ( verbose , "warning: Error code `{}` is undocumented." , err_code ) ;
119
125
120
126
if error_codes. contains ( & err_code) {
121
127
errors. push ( format ! ( "Found duplicate error code: `{}`" , err_code) ) ;
@@ -128,11 +134,6 @@ fn extract_error_codes(root_path: &Path, errors: &mut Vec<String>) -> Vec<String
128
134
}
129
135
}
130
136
131
- println ! (
132
- "WARNING: {} error codes are undocumented. This *will* become a hard error." ,
133
- undocumented_count
134
- ) ;
135
-
136
137
error_codes
137
138
}
138
139
@@ -141,13 +142,10 @@ fn check_error_codes_docs(
141
142
root_path : & Path ,
142
143
error_codes : & [ String ] ,
143
144
errors : & mut Vec < String > ,
145
+ verbose : bool ,
144
146
) -> Vec < String > {
145
147
let docs_path = root_path. join ( Path :: new ( ERROR_DOCS_PATH ) ) ;
146
148
147
- let mut emit_ignore_warning = 0 ;
148
- let mut emit_no_longer_warning = 0 ;
149
- let mut emit_no_code_warning = 0 ;
150
-
151
149
let mut no_longer_emitted_codes = Vec :: new ( ) ;
152
150
153
151
walk ( & docs_path, & mut |_| false , & mut |entry, contents| {
@@ -179,14 +177,25 @@ fn check_error_codes_docs(
179
177
// `has_test.1` checks whether the error code has a proper (definitely tested) doctest.
180
178
let has_test = check_explanation_has_doctest ( & contents, & err_code) ;
181
179
if has_test. 2 {
182
- emit_ignore_warning += 1 ;
180
+ verbose_print ! (
181
+ verbose,
182
+ "warning: Error code `{err_code}` uses the ignore header. This should not be used, add the error code to the \
183
+ `IGNORE_DOCTEST_CHECK` constant instead."
184
+ ) ;
183
185
}
184
186
if has_test. 3 {
185
187
no_longer_emitted_codes. push ( err_code. to_owned ( ) ) ;
186
- emit_no_longer_warning += 1 ;
188
+ verbose_print ! (
189
+ verbose,
190
+ "warning: Error code `{err_code}` is no longer emitted and should be removed entirely."
191
+ ) ;
187
192
}
188
193
if !has_test. 0 {
189
- emit_no_code_warning += 1 ;
194
+ verbose_print ! (
195
+ verbose,
196
+ "warning: Error code `{err_code}` doesn't have a code example, all error codes are expected to have one \
197
+ (even if untested)."
198
+ ) ;
190
199
}
191
200
192
201
let test_ignored = IGNORE_DOCTEST_CHECK . contains ( & err_code) ;
@@ -206,25 +215,6 @@ fn check_error_codes_docs(
206
215
}
207
216
} ) ;
208
217
209
- if emit_ignore_warning > 0 {
210
- println ! (
211
- "WARNING: {emit_ignore_warning} error codes use the ignore header. This should not be used, add the error codes to the \
212
- `IGNORE_DOCTEST_CHECK` constant instead. This *will* become a hard error."
213
- ) ;
214
- }
215
- if emit_no_code_warning > 0 {
216
- println ! (
217
- "WARNING: {emit_ignore_warning} error codes don't have a code example, all error codes are expected \
218
- to have one (even if untested). This *will* become a hard error."
219
- ) ;
220
- }
221
- if emit_no_longer_warning > 0 {
222
- println ! (
223
- "WARNING: {emit_no_longer_warning} error codes are no longer emitted and should be removed entirely. \
224
- This *will* become a hard error."
225
- ) ;
226
- }
227
-
228
218
no_longer_emitted_codes
229
219
}
230
220
@@ -266,18 +256,22 @@ fn check_explanation_has_doctest(explanation: &str, err_code: &str) -> (bool, bo
266
256
}
267
257
268
258
// Stage 3: Checks that each error code has a UI test in the correct directory
269
- fn check_error_codes_tests ( root_path : & Path , error_codes : & [ String ] , errors : & mut Vec < String > ) {
259
+ fn check_error_codes_tests (
260
+ root_path : & Path ,
261
+ error_codes : & [ String ] ,
262
+ errors : & mut Vec < String > ,
263
+ verbose : bool ,
264
+ ) {
270
265
let tests_path = root_path. join ( Path :: new ( ERROR_TESTS_PATH ) ) ;
271
266
272
- // Some warning counters, this whole thing is clunky but'll be removed eventually.
273
- let mut no_ui_test = 0 ;
274
- let mut no_error_code_in_test = 0 ;
275
-
276
267
for code in error_codes {
277
268
let test_path = tests_path. join ( format ! ( "{}.stderr" , code) ) ;
278
269
279
270
if !test_path. exists ( ) && !IGNORE_UI_TEST_CHECK . contains ( & code. as_str ( ) ) {
280
- no_ui_test += 1 ;
271
+ verbose_print ! (
272
+ verbose,
273
+ "warning: Error code `{code}` needs to have at least one UI test in the `src/test/ui/error-codes/` directory`!"
274
+ ) ;
281
275
continue ;
282
276
}
283
277
if IGNORE_UI_TEST_CHECK . contains ( & code. as_str ( ) ) {
@@ -292,8 +286,9 @@ fn check_error_codes_tests(root_path: &Path, error_codes: &[String], errors: &mu
292
286
let file = match fs:: read_to_string ( & test_path) {
293
287
Ok ( file) => file,
294
288
Err ( err) => {
295
- println ! (
296
- "WARNING: Failed to read UI test file (`{}`) for `{code}` but the file exists. The test is assumed to work:\n {err}" ,
289
+ verbose_print ! (
290
+ verbose,
291
+ "warning: Failed to read UI test file (`{}`) for `{code}` but the file exists. The test is assumed to work:\n {err}" ,
297
292
test_path. display( )
298
293
) ;
299
294
continue ;
@@ -314,22 +309,12 @@ fn check_error_codes_tests(root_path: &Path, error_codes: &[String], errors: &mu
314
309
}
315
310
316
311
if !found_code {
317
- no_error_code_in_test += 1 ;
312
+ verbose_print ! (
313
+ verbose,
314
+ "warning: Error code {code}`` has a UI test file, but doesn't contain its own error code!"
315
+ ) ;
318
316
}
319
317
}
320
-
321
- if no_error_code_in_test > 0 {
322
- println ! (
323
- "WARNING: {no_error_code_in_test} error codes have a UI test file, but don't contain their own error code!"
324
- ) ;
325
- }
326
-
327
- if no_ui_test > 0 {
328
- println ! (
329
- "WARNING: {no_ui_test} error codes need to have at least one UI test in the `src/test/ui/error-codes/` directory`! \
330
- This *will* become a hard error."
331
- ) ;
332
- }
333
318
}
334
319
335
320
/// Stage 4: Search `compiler/` and ensure that every error code is actually used by the compiler and that no undocumented error codes exist.
@@ -338,6 +323,7 @@ fn check_error_codes_used(
338
323
error_codes : & [ String ] ,
339
324
errors : & mut Vec < String > ,
340
325
no_longer_emitted : & [ String ] ,
326
+ verbose : bool ,
341
327
) {
342
328
// We want error codes which match the following cases:
343
329
//
@@ -380,21 +366,16 @@ fn check_error_codes_used(
380
366
}
381
367
} ) ;
382
368
383
- let mut used_when_shouldnt = 0 ;
384
-
385
369
for code in error_codes {
386
370
if !found_codes. contains ( code) && !no_longer_emitted. contains ( code) {
387
371
errors. push ( format ! ( "Error code `{code}` exists, but is not emitted by the compiler!" ) )
388
372
}
389
373
390
374
if found_codes. contains ( code) && no_longer_emitted. contains ( code) {
391
- used_when_shouldnt += 1 ;
375
+ verbose_print ! (
376
+ verbose,
377
+ "warning: Error code `{code}` is used when it's marked as \" no longer emitted\" "
378
+ ) ;
392
379
}
393
380
}
394
-
395
- if used_when_shouldnt > 0 {
396
- println ! (
397
- "WARNING: {used_when_shouldnt} error codes are used when they are marked as \" no longer emitted\" "
398
- ) ;
399
- }
400
381
}
0 commit comments