@@ -56,16 +56,20 @@ pub struct Argument<'a> {
56
56
/// Specification for the formatting of an argument in the format string.
57
57
#[ derive( Copy , Clone , PartialEq ) ]
58
58
pub struct FormatSpec < ' a > {
59
- /// Optionally specified character to fill alignment with
59
+ /// Optionally specified character to fill alignment with.
60
60
pub fill : Option < char > ,
61
- /// Optionally specified alignment
61
+ /// Optionally specified alignment.
62
62
pub align : Alignment ,
63
- /// Packed version of various flags provided
63
+ /// Packed version of various flags provided.
64
64
pub flags : u32 ,
65
- /// The integer precision to use
65
+ /// The integer precision to use.
66
66
pub precision : Count ,
67
- /// The string width requested for the resulting format
67
+ /// The span of the precision formatting flag (for diagnostics).
68
+ pub precision_span : Option < InnerSpan > ,
69
+ /// The string width requested for the resulting format.
68
70
pub width : Count ,
71
+ /// The span of the width formatting flag (for diagnostics).
72
+ pub width_span : Option < InnerSpan > ,
69
73
/// The descriptor string representing the name of the format desired for
70
74
/// this argument, this can be empty or any number of characters, although
71
75
/// it is required to be one word.
@@ -282,19 +286,24 @@ impl<'a> Parser<'a> {
282
286
}
283
287
284
288
/// Optionally consumes the specified character. If the character is not at
285
- /// the current position, then the current iterator isn't moved and false is
286
- /// returned, otherwise the character is consumed and true is returned.
289
+ /// the current position, then the current iterator isn't moved and ` false` is
290
+ /// returned, otherwise the character is consumed and ` true` is returned.
287
291
fn consume ( & mut self , c : char ) -> bool {
288
- if let Some ( & ( _, maybe) ) = self . cur . peek ( ) {
292
+ self . consume_pos ( c) . is_some ( )
293
+ }
294
+
295
+ /// Optionally consumes the specified character. If the character is not at
296
+ /// the current position, then the current iterator isn't moved and `None` is
297
+ /// returned, otherwise the character is consumed and the current position is
298
+ /// returned.
299
+ fn consume_pos ( & mut self , c : char ) -> Option < usize > {
300
+ if let Some ( & ( pos, maybe) ) = self . cur . peek ( ) {
289
301
if c == maybe {
290
302
self . cur . next ( ) ;
291
- true
292
- } else {
293
- false
303
+ return Some ( pos) ;
294
304
}
295
- } else {
296
- false
297
305
}
306
+ None
298
307
}
299
308
300
309
fn to_span_index ( & self , pos : usize ) -> InnerOffset {
@@ -462,7 +471,9 @@ impl<'a> Parser<'a> {
462
471
align : AlignUnknown ,
463
472
flags : 0 ,
464
473
precision : CountImplied ,
474
+ precision_span : None ,
465
475
width : CountImplied ,
476
+ width_span : None ,
466
477
ty : & self . input [ ..0 ] ,
467
478
} ;
468
479
if !self . consume ( ':' ) {
@@ -499,6 +510,7 @@ impl<'a> Parser<'a> {
499
510
}
500
511
// Width and precision
501
512
let mut havewidth = false ;
513
+
502
514
if self . consume ( '0' ) {
503
515
// small ambiguity with '0$' as a format string. In theory this is a
504
516
// '0' flag and then an ill-formatted format string with just a '$'
@@ -512,17 +524,28 @@ impl<'a> Parser<'a> {
512
524
}
513
525
}
514
526
if !havewidth {
515
- spec. width = self . count ( ) ;
527
+ let width_span_start = if let Some ( ( pos, _) ) = self . cur . peek ( ) {
528
+ * pos
529
+ } else {
530
+ 0
531
+ } ;
532
+ let ( w, sp) = self . count ( width_span_start) ;
533
+ spec. width = w;
534
+ spec. width_span = sp;
516
535
}
517
- if self . consume ( '.' ) {
518
- if self . consume ( '*' ) {
536
+ if let Some ( start ) = self . consume_pos ( '.' ) {
537
+ if let Some ( end ) = self . consume_pos ( '*' ) {
519
538
// Resolve `CountIsNextParam`.
520
539
// We can do this immediately as `position` is resolved later.
521
540
let i = self . curarg ;
522
541
self . curarg += 1 ;
523
542
spec. precision = CountIsParam ( i) ;
543
+ spec. precision_span =
544
+ Some ( self . to_span_index ( start) . to ( self . to_span_index ( end + 1 ) ) ) ;
524
545
} else {
525
- spec. precision = self . count ( ) ;
546
+ let ( p, sp) = self . count ( start) ;
547
+ spec. precision = p;
548
+ spec. precision_span = sp;
526
549
}
527
550
}
528
551
// Optional radix followed by the actual format specifier
@@ -551,24 +574,25 @@ impl<'a> Parser<'a> {
551
574
/// Parses a Count parameter at the current position. This does not check
552
575
/// for 'CountIsNextParam' because that is only used in precision, not
553
576
/// width.
554
- fn count ( & mut self ) -> Count {
577
+ fn count ( & mut self , start : usize ) -> ( Count , Option < InnerSpan > ) {
555
578
if let Some ( i) = self . integer ( ) {
556
- if self . consume ( '$' ) {
557
- CountIsParam ( i)
579
+ if let Some ( end) = self . consume_pos ( '$' ) {
580
+ let span = self . to_span_index ( start) . to ( self . to_span_index ( end + 1 ) ) ;
581
+ ( CountIsParam ( i) , Some ( span) )
558
582
} else {
559
- CountIs ( i)
583
+ ( CountIs ( i) , None )
560
584
}
561
585
} else {
562
586
let tmp = self . cur . clone ( ) ;
563
587
let word = self . word ( ) ;
564
588
if word. is_empty ( ) {
565
589
self . cur = tmp;
566
- CountImplied
590
+ ( CountImplied , None )
567
591
} else if self . consume ( '$' ) {
568
- CountIsName ( Symbol :: intern ( word) )
592
+ ( CountIsName ( Symbol :: intern ( word) ) , None )
569
593
} else {
570
594
self . cur = tmp;
571
- CountImplied
595
+ ( CountImplied , None )
572
596
}
573
597
}
574
598
}
0 commit comments