@@ -56,16 +56,20 @@ pub struct Argument<'a> {
5656/// Specification for the formatting of an argument in the format string.
5757#[ derive( Copy , Clone , PartialEq ) ]
5858pub struct FormatSpec < ' a > {
59- /// Optionally specified character to fill alignment with
59+ /// Optionally specified character to fill alignment with.
6060 pub fill : Option < char > ,
61- /// Optionally specified alignment
61+ /// Optionally specified alignment.
6262 pub align : Alignment ,
63- /// Packed version of various flags provided
63+ /// Packed version of various flags provided.
6464 pub flags : u32 ,
65- /// The integer precision to use
65+ /// The integer precision to use.
6666 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.
6870 pub width : Count ,
71+ /// The span of the width formatting flag (for diagnostics).
72+ pub width_span : Option < InnerSpan > ,
6973 /// The descriptor string representing the name of the format desired for
7074 /// this argument, this can be empty or any number of characters, although
7175 /// it is required to be one word.
@@ -282,19 +286,24 @@ impl<'a> Parser<'a> {
282286 }
283287
284288 /// 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.
287291 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 ( ) {
289301 if c == maybe {
290302 self . cur . next ( ) ;
291- true
292- } else {
293- false
303+ return Some ( pos) ;
294304 }
295- } else {
296- false
297305 }
306+ None
298307 }
299308
300309 fn to_span_index ( & self , pos : usize ) -> InnerOffset {
@@ -462,7 +471,9 @@ impl<'a> Parser<'a> {
462471 align : AlignUnknown ,
463472 flags : 0 ,
464473 precision : CountImplied ,
474+ precision_span : None ,
465475 width : CountImplied ,
476+ width_span : None ,
466477 ty : & self . input [ ..0 ] ,
467478 } ;
468479 if !self . consume ( ':' ) {
@@ -499,6 +510,7 @@ impl<'a> Parser<'a> {
499510 }
500511 // Width and precision
501512 let mut havewidth = false ;
513+
502514 if self . consume ( '0' ) {
503515 // small ambiguity with '0$' as a format string. In theory this is a
504516 // '0' flag and then an ill-formatted format string with just a '$'
@@ -512,17 +524,28 @@ impl<'a> Parser<'a> {
512524 }
513525 }
514526 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;
516535 }
517- if self . consume ( '.' ) {
518- if self . consume ( '*' ) {
536+ if let Some ( start ) = self . consume_pos ( '.' ) {
537+ if let Some ( end ) = self . consume_pos ( '*' ) {
519538 // Resolve `CountIsNextParam`.
520539 // We can do this immediately as `position` is resolved later.
521540 let i = self . curarg ;
522541 self . curarg += 1 ;
523542 spec. precision = CountIsParam ( i) ;
543+ spec. precision_span =
544+ Some ( self . to_span_index ( start) . to ( self . to_span_index ( end + 1 ) ) ) ;
524545 } else {
525- spec. precision = self . count ( ) ;
546+ let ( p, sp) = self . count ( start) ;
547+ spec. precision = p;
548+ spec. precision_span = sp;
526549 }
527550 }
528551 // Optional radix followed by the actual format specifier
@@ -551,24 +574,25 @@ impl<'a> Parser<'a> {
551574 /// Parses a Count parameter at the current position. This does not check
552575 /// for 'CountIsNextParam' because that is only used in precision, not
553576 /// width.
554- fn count ( & mut self ) -> Count {
577+ fn count ( & mut self , start : usize ) -> ( Count , Option < InnerSpan > ) {
555578 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) )
558582 } else {
559- CountIs ( i)
583+ ( CountIs ( i) , None )
560584 }
561585 } else {
562586 let tmp = self . cur . clone ( ) ;
563587 let word = self . word ( ) ;
564588 if word. is_empty ( ) {
565589 self . cur = tmp;
566- CountImplied
590+ ( CountImplied , None )
567591 } else if self . consume ( '$' ) {
568- CountIsName ( Symbol :: intern ( word) )
592+ ( CountIsName ( Symbol :: intern ( word) ) , None )
569593 } else {
570594 self . cur = tmp;
571- CountImplied
595+ ( CountImplied , None )
572596 }
573597 }
574598 }
0 commit comments