1
1
// Characters and their corresponding confusables were collected from
2
2
// http://www.unicode.org/Public/security/10.0.0/confusables.txt
3
3
4
- use syntax_pos:: { Span , Pos , NO_EXPANSION } ;
5
- use errors:: { Applicability , DiagnosticBuilder } ;
6
4
use super :: StringReader ;
5
+ use errors:: { Applicability , DiagnosticBuilder } ;
6
+ use syntax_pos:: { Pos , Span , NO_EXPANSION } ;
7
7
8
+ #[ rustfmt:: skip] // for line breaks
8
9
const UNICODE_ARRAY : & [ ( char , & str , char ) ] = & [
9
10
( '
' , "Line Separator" , ' ' ) ,
10
11
( '
' , "Paragraph Separator" , ' ' ) ,
@@ -293,8 +294,8 @@ const UNICODE_ARRAY: &[(char, &str, char)] = &[
293
294
( '〉' , "Right-Pointing Angle Bracket" , '>' ) ,
294
295
( '〉' , "Right Angle Bracket" , '>' ) ,
295
296
( '》' , "Right Double Angle Bracket" , '>' ) ,
296
- ( '>' , "Fullwidth Greater-Than Sign" , '>' ) , ] ;
297
-
297
+ ( '>' , "Fullwidth Greater-Than Sign" , '>' ) ,
298
+ ] ;
298
299
299
300
const ASCII_ARRAY : & [ ( char , & str ) ] = & [
300
301
( ' ' , "Space" ) ,
@@ -321,46 +322,72 @@ const ASCII_ARRAY: &[(char, &str)] = &[
321
322
( '+' , "Plus Sign" ) ,
322
323
( '<' , "Less-Than Sign" ) ,
323
324
( '=' , "Equals Sign" ) ,
324
- ( '>' , "Greater-Than Sign" ) , ] ;
325
-
326
- crate fn check_for_substitution < ' a > ( reader : & StringReader < ' a > ,
327
- ch : char ,
328
- err : & mut DiagnosticBuilder < ' a > ) -> bool {
329
- UNICODE_ARRAY
330
- . iter ( )
331
- . find ( |& & ( c, _, _) | c == ch)
332
- . map ( |& ( _, u_name, ascii_char) | {
333
- let span = Span :: new ( reader. pos , reader. next_pos , NO_EXPANSION ) ;
334
- match ASCII_ARRAY . iter ( ) . find ( |& & ( c, _) | c == ascii_char) {
335
- Some ( & ( ascii_char, ascii_name) ) => {
336
- // special help suggestion for "directed" double quotes
337
- if let Some ( s) = reader. peek_delimited ( '“' , '”' ) {
338
- let msg = format ! ( "Unicode characters '“' (Left Double Quotation Mark) and \
339
- '”' (Right Double Quotation Mark) look like '{}' ({}), but are not",
340
- ascii_char, ascii_name) ;
341
- err. span_suggestion (
342
- Span :: new ( reader. pos , reader. next_pos + Pos :: from_usize ( s. len ( ) ) +
343
- Pos :: from_usize ( '”' . len_utf8 ( ) ) , NO_EXPANSION ) ,
344
- & msg,
345
- format ! ( "\" {}\" " , s) ,
346
- Applicability :: MaybeIncorrect ) ;
347
- } else {
348
- let msg =
349
- format ! ( "Unicode character '{}' ({}) looks like '{}' ({}), but it is not" ,
350
- ch, u_name, ascii_char, ascii_name) ;
351
- err. span_suggestion (
352
- span,
353
- & msg,
354
- ascii_char. to_string ( ) ,
355
- Applicability :: MaybeIncorrect ) ;
356
- }
357
- true
358
- } ,
359
- None => {
360
- let msg = format ! ( "substitution character not found for '{}'" , ch) ;
361
- reader. sess . span_diagnostic . span_bug_no_panic ( span, & msg) ;
362
- false
363
- }
325
+ ( '>' , "Greater-Than Sign" ) ,
326
+ ] ;
327
+
328
+ crate fn check_for_substitution < ' a > (
329
+ reader : & StringReader < ' a > ,
330
+ ch : char ,
331
+ err : & mut DiagnosticBuilder < ' a > ,
332
+ ) -> bool {
333
+ let ( u_name, ascii_char) = match UNICODE_ARRAY . iter ( ) . find ( |& & ( c, _, _) | c == ch) {
334
+ Some ( & ( _u_char, u_name, ascii_char) ) => ( u_name, ascii_char) ,
335
+ None => return false ,
336
+ } ;
337
+
338
+ let span = Span :: new ( reader. pos , reader. next_pos , NO_EXPANSION ) ;
339
+
340
+ let ascii_name = match ASCII_ARRAY . iter ( ) . find ( |& & ( c, _) | c == ascii_char) {
341
+ Some ( ( _ascii_char, ascii_name) ) => ascii_name,
342
+ None => {
343
+ let msg = format ! ( "substitution character not found for '{}'" , ch) ;
344
+ reader. sess . span_diagnostic . span_bug_no_panic ( span, & msg) ;
345
+ return false
346
+ } ,
347
+ } ;
348
+
349
+ // special help suggestion for "directed" double quotes
350
+ if let Some ( s) = reader. peek_delimited ( '“' , '”' ) {
351
+ let msg = format ! (
352
+ "Unicode characters '“' (Left Double Quotation Mark) and \
353
+ '”' (Right Double Quotation Mark) look like '{}' ({}), but are not",
354
+ ascii_char, ascii_name
355
+ ) ;
356
+ err. span_suggestion (
357
+ Span :: new (
358
+ reader. pos ,
359
+ reader. next_pos + Pos :: from_usize ( s. len ( ) ) + Pos :: from_usize ( '”' . len_utf8 ( ) ) ,
360
+ NO_EXPANSION ,
361
+ ) ,
362
+ & msg,
363
+ format ! ( "\" {}\" " , s) ,
364
+ Applicability :: MaybeIncorrect ,
365
+ ) ;
366
+ } else {
367
+ let msg = format ! (
368
+ "Unicode character '{}' ({}) looks like '{}' ({}), but it is not" ,
369
+ ch, u_name, ascii_char, ascii_name
370
+ ) ;
371
+ err. span_suggestion (
372
+ span,
373
+ & msg,
374
+ ascii_char. to_string ( ) ,
375
+ Applicability :: MaybeIncorrect ,
376
+ ) ;
377
+ }
378
+ true
379
+ }
380
+
381
+ impl StringReader < ' _ > {
382
+ /// Immutably extract string if found at current position with given delimiters
383
+ fn peek_delimited ( & self , from_ch : char , to_ch : char ) -> Option < & str > {
384
+ let tail = & self . src [ self . src_index ( self . pos ) ..] ;
385
+ let mut chars = tail. chars ( ) ;
386
+ let first_char = chars. next ( ) ?;
387
+ if first_char != from_ch {
388
+ return None ;
364
389
}
365
- } ) . unwrap_or ( false )
390
+ let last_char_idx = chars. as_str ( ) . find ( to_ch) ?;
391
+ Some ( & chars. as_str ( ) [ ..last_char_idx] )
392
+ }
366
393
}
0 commit comments