@@ -15,21 +15,57 @@ const WHITELIST: &[&str] = &[
1515 "E0727" , "E0729" ,
1616] ;
1717
18+ // Some error codes don't have any tests apparently...
19+ const IGNORE_EXPLANATION_CHECK : & [ & str ] =
20+ & [ "E0570" , "E0601" , "E0602" , "E0639" , "E0729" , "E0749" , "E0750" , "E0751" ] ;
21+
1822fn check_error_code_explanation (
1923 f : & str ,
2024 error_codes : & mut HashMap < String , bool > ,
2125 err_code : String ,
22- ) {
26+ ) -> bool {
27+ let mut invalid_compile_fail_format = false ;
28+ let mut found_error_code = false ;
29+
2330 for line in f. lines ( ) {
2431 let s = line. trim ( ) ;
25- if s. starts_with ( "```" ) && s. contains ( "compile_fail" ) && s. contains ( 'E' ) {
26- error_codes. insert ( err_code, true ) ;
27- return ;
32+ if s. starts_with ( "```" ) {
33+ if s. contains ( "compile_fail" ) && s. contains ( 'E' ) {
34+ if !found_error_code {
35+ error_codes. insert ( err_code. clone ( ) , true ) ;
36+ found_error_code = true ;
37+ }
38+ } else if s. contains ( "compile-fail" ) {
39+ invalid_compile_fail_format = true ;
40+ }
2841 } else if s. starts_with ( "#### Note: this error code is no longer emitted by the compiler" ) {
29- error_codes. get_mut ( & err_code) . map ( |x| * x = true ) ;
30- return ;
42+ if !found_error_code {
43+ error_codes. get_mut ( & err_code) . map ( |x| * x = true ) ;
44+ found_error_code = true ;
45+ }
3146 }
3247 }
48+ invalid_compile_fail_format
49+ }
50+
51+ fn check_if_error_code_is_test_in_explanation ( f : & str , err_code : & String ) -> bool {
52+ let mut can_be_ignored = false ;
53+
54+ for line in f. lines ( ) {
55+ let s = line. trim ( ) ;
56+ if s. starts_with ( "#### Note: this error code is no longer emitted by the compiler" ) {
57+ return true ;
58+ }
59+ if s. starts_with ( "```" ) {
60+ if s. contains ( "compile_fail" ) && s. contains ( err_code) {
61+ return true ;
62+ } else if s. contains ( "(" ) {
63+ // It's very likely that we can't actually make it fail compilation...
64+ can_be_ignored = true ;
65+ }
66+ }
67+ }
68+ can_be_ignored
3369}
3470
3571macro_rules! some_or_continue {
@@ -41,7 +77,12 @@ macro_rules! some_or_continue {
4177 } ;
4278}
4379
44- fn extract_error_codes ( f : & str , error_codes : & mut HashMap < String , bool > , path : & Path ) {
80+ fn extract_error_codes (
81+ f : & str ,
82+ error_codes : & mut HashMap < String , bool > ,
83+ path : & Path ,
84+ errors : & mut Vec < String > ,
85+ ) {
4586 let mut reached_no_explanation = false ;
4687
4788 for line in f. lines ( ) {
@@ -55,10 +96,26 @@ fn extract_error_codes(f: &str, error_codes: &mut HashMap<String, bool>, path: &
5596 // Now we extract the tests from the markdown file!
5697 let md = some_or_continue ! ( s. splitn( 2 , "include_str!(\" " ) . nth( 1 ) ) ;
5798 let md_file_name = some_or_continue ! ( md. splitn( 2 , "\" )" ) . next( ) ) ;
58- let path = some_or_continue ! ( path. parent( ) ) . join ( md_file_name) ;
99+ let path = some_or_continue ! ( path. parent( ) )
100+ . join ( md_file_name)
101+ . canonicalize ( )
102+ . expect ( "failed to canonicalize error explanation file path" ) ;
59103 match read_to_string ( & path) {
60104 Ok ( content) => {
61- check_error_code_explanation ( & content, error_codes, err_code) ;
105+ if !IGNORE_EXPLANATION_CHECK . contains ( & err_code. as_str ( ) )
106+ && !check_if_error_code_is_test_in_explanation ( & content, & err_code)
107+ {
108+ errors. push ( format ! (
109+ "`{}` doesn't use its own error code in compile_fail example" ,
110+ path. display( ) ,
111+ ) ) ;
112+ }
113+ if check_error_code_explanation ( & content, error_codes, err_code) {
114+ errors. push ( format ! (
115+ "`{}` uses invalid tag `compile-fail` instead of `compile_fail`" ,
116+ path. display( ) ,
117+ ) ) ;
118+ }
62119 }
63120 Err ( e) => {
64121 eprintln ! ( "Couldn't read `{}`: {}" , path. display( ) , e) ;
@@ -94,22 +151,24 @@ fn extract_error_codes_from_tests(f: &str, error_codes: &mut HashMap<String, boo
94151}
95152
96153pub fn check ( path : & Path , bad : & mut bool ) {
154+ let mut errors = Vec :: new ( ) ;
97155 println ! ( "Checking which error codes lack tests..." ) ;
98156 let mut error_codes: HashMap < String , bool > = HashMap :: new ( ) ;
99157 super :: walk ( path, & mut |path| super :: filter_dirs ( path) , & mut |entry, contents| {
100158 let file_name = entry. file_name ( ) ;
101159 if file_name == "error_codes.rs" {
102- extract_error_codes ( contents, & mut error_codes, entry. path ( ) ) ;
160+ extract_error_codes ( contents, & mut error_codes, entry. path ( ) , & mut errors ) ;
103161 } else if entry. path ( ) . extension ( ) == Some ( OsStr :: new ( "stderr" ) ) {
104162 extract_error_codes_from_tests ( contents, & mut error_codes) ;
105163 }
106164 } ) ;
107- println ! ( "Found {} error codes" , error_codes. len( ) ) ;
165+ if errors. is_empty ( ) {
166+ println ! ( "Found {} error codes" , error_codes. len( ) ) ;
108167
109- let mut errors = Vec :: new ( ) ;
110- for ( err_code , nb ) in & error_codes {
111- if ! * nb && ! WHITELIST . contains ( & err_code . as_str ( ) ) {
112- errors . push ( format ! ( "Error code {} needs to have at least one UI test!" , err_code ) ) ;
168+ for ( err_code , nb ) in & error_codes {
169+ if ! * nb && ! WHITELIST . contains ( & err_code . as_str ( ) ) {
170+ errors . push ( format ! ( "Error code {} needs to have at least one UI test!" , err_code ) ) ;
171+ }
113172 }
114173 }
115174 errors. sort ( ) ;
0 commit comments