18
18
// ignore-tidy-dbg
19
19
20
20
use crate :: walk:: { filter_dirs, walk} ;
21
- use regex:: RegexSet ;
21
+ use regex:: RegexSetBuilder ;
22
22
use rustc_hash:: FxHashMap ;
23
- use std:: { ffi:: OsStr , path:: Path } ;
23
+ use std:: { ffi:: OsStr , path:: Path , sync :: LazyLock } ;
24
24
25
25
#[ cfg( test) ]
26
26
mod tests;
@@ -110,16 +110,26 @@ const ROOT_PROBLEMATIC_CONSTS: &[u32] = &[
110
110
173390526 , 721077 ,
111
111
] ;
112
112
113
+ const LETTER_DIGIT : & [ ( char , char ) ] = & [ ( 'A' , '4' ) , ( 'B' , '8' ) , ( 'E' , '3' ) ] ;
114
+
113
115
// Returns all permutations of problematic consts, over 2000 elements.
114
116
fn generate_problematic_strings (
115
117
consts : & [ u32 ] ,
116
118
letter_digit : & FxHashMap < char , char > ,
117
119
) -> Vec < String > {
118
120
generate_problems ( consts, letter_digit)
119
- . flat_map ( |v| vec ! [ v. to_string( ) , format!( "{:x}" , v ) , format! ( "{: X}", v) ] )
121
+ . flat_map ( |v| vec ! [ v. to_string( ) , format!( "{:X}" , v) ] )
120
122
. collect ( )
121
123
}
122
124
125
+ static PROBLEMATIC_CONSTS_STRINGS : LazyLock < Vec < String > > = LazyLock :: new ( || {
126
+ generate_problematic_strings ( ROOT_PROBLEMATIC_CONSTS , & LETTER_DIGIT . iter ( ) . cloned ( ) . collect ( ) )
127
+ } ) ;
128
+
129
+ fn contains_problematic_const ( trimmed : & str ) -> bool {
130
+ PROBLEMATIC_CONSTS_STRINGS . iter ( ) . any ( |s| trimmed. to_uppercase ( ) . contains ( s) )
131
+ }
132
+
123
133
const INTERNAL_COMPILER_DOCS_LINE : & str = "#### This error code is internal to the compiler and will not be emitted with normal Rust code." ;
124
134
125
135
/// Parser states for `line_is_url`.
@@ -316,14 +326,14 @@ pub fn check(path: &Path, bad: &mut bool) {
316
326
// We only check CSS files in rustdoc.
317
327
path. extension ( ) . map_or ( false , |e| e == "css" ) && !is_in ( path, "src" , "librustdoc" )
318
328
}
319
- let problematic_consts_strings = generate_problematic_strings (
320
- ROOT_PROBLEMATIC_CONSTS ,
321
- & [ ( 'A' , '4' ) , ( 'B' , '8' ) , ( 'E' , '3' ) ] . iter ( ) . cloned ( ) . collect ( ) ,
322
- ) ;
329
+
323
330
// This creates a RegexSet as regex contains performance optimizations to be able to deal with these over
324
331
// 2000 needles efficiently. This runs over the entire source code, so performance matters.
325
- let problematic_regex = RegexSet :: new ( problematic_consts_strings. as_slice ( ) ) . unwrap ( ) ;
326
-
332
+ let problematic_regex = RegexSetBuilder :: new ( PROBLEMATIC_CONSTS_STRINGS . as_slice ( ) )
333
+ . case_insensitive ( true )
334
+ . build ( )
335
+ . unwrap ( ) ;
336
+ let style_file = Path :: new ( file ! ( ) ) ;
327
337
walk ( path, skip, & mut |entry, contents| {
328
338
let file = entry. path ( ) ;
329
339
let filename = file. file_name ( ) . unwrap ( ) . to_string_lossy ( ) ;
@@ -389,10 +399,15 @@ pub fn check(path: &Path, bad: &mut bool) {
389
399
let mut lines = 0 ;
390
400
let mut last_safety_comment = false ;
391
401
let mut comment_block: Option < ( usize , usize ) > = None ;
392
- let is_test = file. components ( ) . any ( |c| c. as_os_str ( ) == "tests" ) ;
402
+ let is_test = file. components ( ) . any ( |c| c. as_os_str ( ) == "tests" )
403
+ || file. file_stem ( ) . unwrap ( ) == "tests" ;
404
+ let is_style = file. ends_with ( style_file) || style_file. ends_with ( file) ;
405
+ let is_style_test =
406
+ is_test && file. parent ( ) . unwrap ( ) . ends_with ( style_file. with_extension ( "" ) ) ;
393
407
// scanning the whole file for multiple needles at once is more efficient than
394
408
// executing lines times needles separate searches.
395
- let any_problematic_line = problematic_regex. is_match ( contents) ;
409
+ let any_problematic_line =
410
+ !is_style && !is_style_test && problematic_regex. is_match ( contents) ;
396
411
for ( i, line) in contents. split ( '\n' ) . enumerate ( ) {
397
412
if line. is_empty ( ) {
398
413
if i == 0 {
@@ -451,7 +466,7 @@ pub fn check(path: &Path, bad: &mut bool) {
451
466
if line. contains ( '\r' ) {
452
467
suppressible_tidy_err ! ( err, skip_cr, "CR character" ) ;
453
468
}
454
- if filename != "style.rs" {
469
+ if !is_style {
455
470
// Allow using TODO in diagnostic suggestions by marking the
456
471
// relevant line with `// ignore-tidy-todo`.
457
472
if trimmed. contains ( "TODO" ) && !trimmed. contains ( "ignore-tidy-todo" ) {
@@ -462,12 +477,8 @@ pub fn check(path: &Path, bad: &mut bool) {
462
477
if trimmed. contains ( "//" ) && trimmed. contains ( " XXX" ) {
463
478
err ( "Instead of XXX use FIXME" )
464
479
}
465
- if any_problematic_line {
466
- for s in problematic_consts_strings. iter ( ) {
467
- if trimmed. contains ( s) {
468
- err ( "Don't use magic numbers that spell things (consider 0x12345678)" ) ;
469
- }
470
- }
480
+ if any_problematic_line && contains_problematic_const ( trimmed) {
481
+ err ( "Don't use magic numbers that spell things (consider 0x12345678)" ) ;
471
482
}
472
483
}
473
484
// for now we just check libcore
0 commit comments