2021-09-08 09:31:47 -05:00
#![ cfg_attr(feature = " deny-warnings " , deny(warnings)) ]
#![ warn(rust_2018_idioms, unused_lifetimes) ]
2021-03-12 08:30:50 -06:00
use std ::ffi ::OsStr ;
use std ::path ::PathBuf ;
2022-07-18 02:39:37 -05:00
use std ::sync ::LazyLock ;
2021-03-12 08:30:50 -06:00
use regex ::RegexSet ;
#[ derive(Debug) ]
struct Message {
path : PathBuf ,
bad_lines : Vec < String > ,
}
impl Message {
fn new ( path : PathBuf ) -> Self {
// we don't want the first letter after "error: ", "help: " ... to be capitalized
2022-03-16 07:12:30 -05:00
// also no punctuation (except for "?" ?) at the end of a line
2023-07-17 03:19:29 -05:00
// Prefer "try" over "try this".
2022-07-18 02:39:37 -05:00
static REGEX_SET : LazyLock < RegexSet > = LazyLock ::new ( | | {
2022-08-31 08:24:45 -05:00
RegexSet ::new ( [
2023-07-02 07:35:19 -05:00
" error: [A-Z] " ,
" help: [A-Z] " ,
" warning: [A-Z] " ,
" note: [A-Z] " ,
2023-07-17 03:19:29 -05:00
" try: [A-Z] " ,
2023-07-02 07:35:19 -05:00
" error: .*[.!]$ " ,
" help: .*[.!]$ " ,
" warning: .*[.!]$ " ,
" note: .*[.!]$ " ,
2023-07-17 03:19:29 -05:00
" try: .*[.!]$ " ,
" try this " ,
2022-07-18 02:39:37 -05:00
] )
. unwrap ( )
} ) ;
2021-03-12 08:30:50 -06:00
// sometimes the first character is capitalized and it is legal (like in "C-like enum variants") or
// we want to ask a question ending in "?"
2022-07-18 02:39:37 -05:00
static EXCEPTIONS_SET : LazyLock < RegexSet > = LazyLock ::new ( | | {
2022-08-31 08:24:45 -05:00
RegexSet ::new ( [
2022-07-18 02:39:37 -05:00
r "\.\.\.$" ,
2023-07-02 07:35:19 -05:00
" .*C-like enum variant discriminant is not portable to 32-bit targets " ,
" .*Intel x86 assembly syntax used " ,
" .*AT&T x86 assembly syntax used " ,
" note: Clippy version: .* " ,
" the compiler unexpectedly panicked. this is a bug. " ,
2022-07-18 02:39:37 -05:00
] )
. unwrap ( )
} ) ;
let content : String = std ::fs ::read_to_string ( & path ) . unwrap ( ) ;
2021-03-12 08:30:50 -06:00
let bad_lines = content
. lines ( )
2022-07-18 02:39:37 -05:00
. filter ( | line | REGEX_SET . matches ( line ) . matched_any ( ) )
2021-03-12 08:30:50 -06:00
// ignore exceptions
2022-07-18 02:39:37 -05:00
. filter ( | line | ! EXCEPTIONS_SET . matches ( line ) . matched_any ( ) )
2021-03-12 08:30:50 -06:00
. map ( ToOwned ::to_owned )
. collect ::< Vec < String > > ( ) ;
Message { path , bad_lines }
}
}
#[ test ]
fn lint_message_convention ( ) {
// disable the test inside the rustc test suite
if option_env! ( " RUSTC_TEST_SUITE " ) . is_some ( ) {
return ;
}
// make sure that lint messages:
// * are not capitalized
2022-05-05 09:12:52 -05:00
// * don't have punctuation at the end of the last sentence
2021-03-12 08:30:50 -06:00
// 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
. flat_map ( | dir | {
std ::fs ::read_dir ( dir )
. expect ( " failed to read dir " )
. map ( | direntry | direntry . unwrap ( ) . path ( ) )
} )
. filter ( | file | matches! ( file . extension ( ) . map ( OsStr ::to_str ) , Some ( Some ( " stderr " ) ) ) ) ;
// get all files that have any "bad lines" in them
let bad_tests : Vec < Message > = tests
. map ( Message ::new )
. filter ( | message | ! message . bad_lines . is_empty ( ) )
. collect ( ) ;
2021-04-08 10:50:13 -05:00
for message in & bad_tests {
2021-03-12 08:30:50 -06:00
eprintln! (
" error: the test '{}' contained the following nonconforming lines : " ,
message . path . display ( )
) ;
2022-10-06 02:44:38 -05:00
message . bad_lines . iter ( ) . for_each ( | line | eprintln! ( " {line} " ) ) ;
2021-03-12 08:30:50 -06:00
eprintln! ( " \n \n " ) ;
2021-04-08 10:50:13 -05:00
}
2021-03-12 08:30:50 -06: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. "
) ;
eprintln! ( " Check out the rustc-dev-guide for more information: " ) ;
eprintln! ( " https://rustc-dev-guide.rust-lang.org/diagnostics.html#diagnostic-structure \n \n \n " ) ;
assert! ( bad_tests . is_empty ( ) ) ;
}