2021-09-08 13:19:14 +00:00
#![ cfg_attr(feature = " deny-warnings " , deny(warnings)) ]
#![ warn(rust_2018_idioms, unused_lifetimes) ]
2021-02-24 12:56:04 +00:00
use std ::ffi ::OsStr ;
2021-02-24 12:50:11 +00:00
use std ::path ::PathBuf ;
use regex ::RegexSet ;
#[ derive(Debug) ]
struct Message {
path : PathBuf ,
bad_lines : Vec < String > ,
}
impl Message {
fn new ( path : PathBuf ) -> Self {
let content : String = std ::fs ::read_to_string ( & path ) . unwrap ( ) ;
// we don't want the first letter after "error: ", "help: " ... to be capitalized
// also no puncutation (except for "?" ?) at the end of a line
let regex_set : RegexSet = RegexSet ::new ( & [
r "error: [A-Z]" ,
r "help: [A-Z]" ,
r "warning: [A-Z]" ,
r "note: [A-Z]" ,
r "try this: [A-Z]" ,
r "error: .*[.!]$" ,
r "help: .*[.!]$" ,
r "warning: .*[.!]$" ,
r "note: .*[.!]$" ,
r "try this: .*[.!]$" ,
] )
. unwrap ( ) ;
2021-02-28 13:01:03 +00:00
// sometimes the first character is capitalized and it is legal (like in "C-like enum variants") or
2021-02-24 12:50:11 +00:00
// we want to ask a question ending in "?"
let exceptions_set : RegexSet = RegexSet ::new ( & [
r ".*C-like enum variant discriminant is not portable to 32-bit targets" ,
r ".*did you mean `unix`?" ,
r ".*the arguments may be inverted..." ,
r ".*Intel x86 assembly syntax used" ,
r ".*AT&T x86 assembly syntax used" ,
2021-02-24 13:02:51 +00:00
r ".*remove .*the return type..." ,
2021-02-24 12:50:11 +00:00
r "note: Clippy version: .*" ,
2021-02-24 13:02:51 +00:00
r "the compiler unexpectedly panicked. this is a bug." ,
2021-02-24 12:50:11 +00:00
] )
. unwrap ( ) ;
let bad_lines = content
. lines ( )
. filter ( | line | regex_set . matches ( line ) . matched_any ( ) )
// ignore exceptions
. filter ( | line | ! exceptions_set . matches ( line ) . matched_any ( ) )
2021-02-24 12:56:04 +00:00
. map ( ToOwned ::to_owned )
2021-02-24 12:50:11 +00:00
. collect ::< Vec < String > > ( ) ;
Message { path , bad_lines }
}
}
#[ test ]
fn lint_message_convention ( ) {
2021-02-25 11:30:51 +00:00
// disable the test inside the rustc test suite
if option_env! ( " RUSTC_TEST_SUITE " ) . is_some ( ) {
return ;
}
2021-02-24 12:50:11 +00:00
// make sure that lint messages:
// * are not capitalized
// * don't have puncuation at the end of the last sentence
// these directories have interesting tests
let test_dirs = [ " ui " , " ui-cargo " , " ui-internal " , " ui-toml " ]
. iter ( )
. map ( PathBuf ::from )
. map ( | p | {
let base = PathBuf ::from ( " tests " ) ;
base . join ( p )
} ) ;
// gather all .stderr files
let tests = test_dirs
2021-02-24 12:56:04 +00:00
. flat_map ( | dir | {
2021-02-24 12:50:11 +00:00
std ::fs ::read_dir ( dir )
. expect ( " failed to read dir " )
. map ( | direntry | direntry . unwrap ( ) . path ( ) )
} )
2021-02-24 12:56:04 +00:00
. filter ( | file | matches! ( file . extension ( ) . map ( OsStr ::to_str ) , Some ( Some ( " stderr " ) ) ) ) ;
2021-02-24 12:50:11 +00:00
// get all files that have any "bad lines" in them
let bad_tests : Vec < Message > = tests
2021-02-24 12:56:04 +00:00
. map ( Message ::new )
2021-02-24 12:50:11 +00:00
. filter ( | message | ! message . bad_lines . is_empty ( ) )
. collect ( ) ;
2021-03-13 06:23:57 +00:00
for message in & bad_tests {
2021-02-24 12:50:11 +00:00
eprintln! (
" error: the test '{}' contained the following nonconforming lines : " ,
message . path . display ( )
) ;
message . bad_lines . iter ( ) . for_each ( | line | eprintln! ( " {} " , line ) ) ;
eprintln! ( " \n \n " ) ;
2021-03-13 06:23:57 +00:00
}
2021-02-24 12:50:11 +00:00
2021-03-01 17:53:33 +00:00
eprintln! (
" \n \n \n Lint message should not start with a capital letter and should not have punctuation at the end of the message unless multiple sentences are needed. "
) ;
2021-02-24 12:50:11 +00:00
eprintln! ( " Check out the rustc-dev-guide for more information: " ) ;
2021-02-24 13:02:51 +00:00
eprintln! ( " https://rustc-dev-guide.rust-lang.org/diagnostics.html#diagnostic-structure \n \n \n " ) ;
2021-02-24 12:50:11 +00:00
assert! ( bad_tests . is_empty ( ) ) ;
}