@@ -6,7 +6,6 @@ use rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, Lin
6
6
use rustc:: { declare_lint_pass, declare_tool_lint} ;
7
7
use rustc_data_structures:: fx:: FxHashMap ;
8
8
use rustc_errors:: Applicability ;
9
- use std:: char;
10
9
use syntax:: ast:: * ;
11
10
use syntax:: source_map:: Span ;
12
11
use syntax:: visit:: { walk_expr, FnKind , Visitor } ;
@@ -391,91 +390,88 @@ impl EarlyLintPass for MiscEarlyLints {
391
390
392
391
impl MiscEarlyLints {
393
392
fn check_lit ( self , cx : & EarlyContext < ' _ > , lit : & Lit ) {
394
- if_chain ! {
395
- if let LitKind :: Int ( value, ..) = lit. node;
396
- if let Some ( src) = snippet_opt( cx, lit. span) ;
397
- if let Some ( firstch) = src. chars( ) . next( ) ;
398
- if char :: to_digit( firstch, 10 ) . is_some( ) ;
399
- then {
400
- let mut prev = '\0' ;
401
- for ( idx, ch) in src. chars( ) . enumerate( ) {
402
- if ch == 'i' || ch == 'u' {
403
- if prev != '_' {
404
- span_lint_and_sugg(
405
- cx,
406
- UNSEPARATED_LITERAL_SUFFIX ,
407
- lit. span,
408
- "integer type suffix should be separated by an underscore" ,
409
- "add an underscore" ,
410
- format!( "{}_{}" , & src[ 0 ..idx] , & src[ idx..] ) ,
411
- Applicability :: MachineApplicable ,
412
- ) ;
413
- }
414
- break ;
415
- }
416
- prev = ch;
393
+ if in_external_macro ( cx. sess ( ) , lit. span ) {
394
+ return ;
395
+ }
396
+
397
+ if let LitKind :: Int ( value, lit_int_type) = lit. node {
398
+ if let Some ( src) = snippet_opt ( cx, lit. span ) {
399
+ let suffix = match lit_int_type {
400
+ LitIntType :: Signed ( ty) => ty. ty_to_string ( ) ,
401
+ LitIntType :: Unsigned ( ty) => ty. ty_to_string ( ) ,
402
+ LitIntType :: Unsuffixed => "" ,
403
+ } ;
404
+
405
+ let maybe_last_sep_idx = src. len ( ) - suffix. len ( ) - 1 ;
406
+ // Do not suggest when literal is unsuffixed.
407
+ if !suffix. is_empty ( ) && src. as_bytes ( ) [ maybe_last_sep_idx] != b'_' {
408
+ span_lint_and_sugg (
409
+ cx,
410
+ UNSEPARATED_LITERAL_SUFFIX ,
411
+ lit. span ,
412
+ "integer type suffix should be separated by an underscore" ,
413
+ "add an underscore" ,
414
+ format ! ( "{}_{}" , & src[ ..=maybe_last_sep_idx] , suffix) ,
415
+ Applicability :: MachineApplicable ,
416
+ ) ;
417
417
}
418
+
418
419
if src. starts_with ( "0x" ) {
419
420
let mut seen = ( false , false ) ;
420
- for ch in src. chars ( ) {
421
+ for ch in src. as_bytes ( ) [ 2 ..=maybe_last_sep_idx ] . iter ( ) {
421
422
match ch {
422
- 'a' ..= 'f' => seen. 0 = true ,
423
- 'A' ..= 'F' => seen. 1 = true ,
424
- 'i' | 'u' => break , // start of suffix already
425
- _ => ( )
423
+ b'a' ..=b'f' => seen. 0 = true ,
424
+ b'A' ..=b'F' => seen. 1 = true ,
425
+ _ => { } ,
426
426
}
427
427
}
428
428
if seen. 0 && seen. 1 {
429
- span_lint( cx, MIXED_CASE_HEX_LITERALS , lit. span,
430
- "inconsistent casing in hexadecimal literal" ) ;
429
+ span_lint (
430
+ cx,
431
+ MIXED_CASE_HEX_LITERALS ,
432
+ lit. span ,
433
+ "inconsistent casing in hexadecimal literal" ,
434
+ ) ;
431
435
}
432
436
} else if src. starts_with ( "0b" ) || src. starts_with ( "0o" ) {
433
437
/* nothing to do */
434
438
} else if value != 0 && src. starts_with ( '0' ) {
435
- span_lint_and_then( cx,
436
- ZERO_PREFIXED_LITERAL ,
437
- lit. span,
438
- "this is a decimal constant" ,
439
- |db| {
440
- db. span_suggestion(
441
- lit. span,
442
- "if you mean to use a decimal constant, remove the `0` to remove confusion" ,
443
- src. trim_start_matches( |c| c == '_' || c == '0' ) . to_string( ) ,
444
- Applicability :: MaybeIncorrect ,
445
- ) ;
446
- db. span_suggestion(
447
- lit. span,
448
- "if you mean to use an octal constant, use `0o`" ,
449
- format!( "0o{}" , src. trim_start_matches( |c| c == '_' || c == '0' ) ) ,
450
- Applicability :: MaybeIncorrect ,
451
- ) ;
452
- } ) ;
453
- }
454
- }
455
- }
456
- if_chain ! {
457
- if let LitKind :: Float ( ..) = lit. node;
458
- if let Some ( src) = snippet_opt( cx, lit. span) ;
459
- if let Some ( firstch) = src. chars( ) . next( ) ;
460
- if char :: to_digit( firstch, 10 ) . is_some( ) ;
461
- then {
462
- let mut prev = '\0' ;
463
- for ( idx, ch) in src. chars( ) . enumerate( ) {
464
- if ch == 'f' {
465
- if prev != '_' {
466
- span_lint_and_sugg(
467
- cx,
468
- UNSEPARATED_LITERAL_SUFFIX ,
439
+ span_lint_and_then (
440
+ cx,
441
+ ZERO_PREFIXED_LITERAL ,
442
+ lit. span ,
443
+ "this is a decimal constant" ,
444
+ |db| {
445
+ db. span_suggestion (
469
446
lit. span ,
470
- "float type suffix should be separated by an underscore" ,
471
- "add an underscore" ,
472
- format!( "{}_{}" , & src[ 0 ..idx] , & src[ idx..] ) ,
473
- Applicability :: MachineApplicable ,
447
+ "if you mean to use a decimal constant, remove the `0` to avoid confusion" ,
448
+ src. trim_start_matches ( |c| c == '_' || c == '0' ) . to_string ( ) ,
449
+ Applicability :: MaybeIncorrect ,
474
450
) ;
475
- }
476
- break ;
477
- }
478
- prev = ch;
451
+ db. span_suggestion (
452
+ lit. span ,
453
+ "if you mean to use an octal constant, use `0o`" ,
454
+ format ! ( "0o{}" , src. trim_start_matches( |c| c == '_' || c == '0' ) ) ,
455
+ Applicability :: MaybeIncorrect ,
456
+ ) ;
457
+ } ,
458
+ ) ;
459
+ }
460
+ }
461
+ } else if let LitKind :: Float ( _, float_ty) = lit. node {
462
+ if let Some ( src) = snippet_opt ( cx, lit. span ) {
463
+ let suffix = float_ty. ty_to_string ( ) ;
464
+ let maybe_last_sep_idx = src. len ( ) - suffix. len ( ) - 1 ;
465
+ if src. as_bytes ( ) [ maybe_last_sep_idx] != b'_' {
466
+ span_lint_and_sugg (
467
+ cx,
468
+ UNSEPARATED_LITERAL_SUFFIX ,
469
+ lit. span ,
470
+ "float type suffix should be separated by an underscore" ,
471
+ "add an underscore" ,
472
+ format ! ( "{}_{}" , & src[ ..=maybe_last_sep_idx] , suffix) ,
473
+ Applicability :: MachineApplicable ,
474
+ ) ;
479
475
}
480
476
}
481
477
}
0 commit comments