@@ -683,7 +683,20 @@ pub fn expand_format_args<'cx>(ecx: &'cx mut ExtCtxt,
683
683
sp = sp. apply_mark ( ecx. current_expansion . mark ) ;
684
684
match parse_args ( ecx, sp, tts) {
685
685
Some ( ( efmt, args, names) ) => {
686
- MacEager :: expr ( expand_preparsed_format_args ( ecx, sp, efmt, args, names) )
686
+ MacEager :: expr ( expand_preparsed_format_args ( ecx, sp, efmt, args, names, false ) )
687
+ }
688
+ None => DummyResult :: expr ( sp) ,
689
+ }
690
+ }
691
+
692
+ pub fn expand_format_args_nl < ' cx > ( ecx : & ' cx mut ExtCtxt ,
693
+ mut sp : Span ,
694
+ tts : & [ tokenstream:: TokenTree ] )
695
+ -> Box < dyn base:: MacResult + ' cx > {
696
+ sp = sp. apply_mark ( ecx. current_expansion . mark ) ;
697
+ match parse_args ( ecx, sp, tts) {
698
+ Some ( ( efmt, args, names) ) => {
699
+ MacEager :: expr ( expand_preparsed_format_args ( ecx, sp, efmt, args, names, true ) )
687
700
}
688
701
None => DummyResult :: expr ( sp) ,
689
702
}
@@ -695,18 +708,37 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
695
708
sp : Span ,
696
709
efmt : P < ast:: Expr > ,
697
710
args : Vec < P < ast:: Expr > > ,
698
- names : HashMap < String , usize > )
711
+ names : HashMap < String , usize > ,
712
+ append_newline : bool )
699
713
-> P < ast:: Expr > {
700
714
// NOTE: this verbose way of initializing `Vec<Vec<ArgumentType>>` is because
701
715
// `ArgumentType` does not derive `Clone`.
702
716
let arg_types: Vec < _ > = ( 0 ..args. len ( ) ) . map ( |_| Vec :: new ( ) ) . collect ( ) ;
703
717
let arg_unique_types: Vec < _ > = ( 0 ..args. len ( ) ) . map ( |_| Vec :: new ( ) ) . collect ( ) ;
704
718
let mut macsp = ecx. call_site ( ) ;
705
719
macsp = macsp. apply_mark ( ecx. current_expansion . mark ) ;
706
- let msg = "format argument must be a string literal." ;
720
+ let msg = "format argument must be a string literal" ;
721
+ let fmt_sp = efmt. span ;
707
722
let fmt = match expr_to_spanned_string ( ecx, efmt, msg) {
708
- Some ( fmt) => fmt,
709
- None => return DummyResult :: raw_expr ( sp) ,
723
+ Ok ( mut fmt) if append_newline => {
724
+ fmt. node . 0 = Symbol :: intern ( & format ! ( "{}\n " , fmt. node. 0 ) ) ;
725
+ fmt
726
+ }
727
+ Ok ( fmt) => fmt,
728
+ Err ( mut err) => {
729
+ let sugg_fmt = match args. len ( ) {
730
+ 0 => "{}" . to_string ( ) ,
731
+ _ => format ! ( "{}{{}}" , "{}, " . repeat( args. len( ) ) ) ,
732
+
733
+ } ;
734
+ err. span_suggestion (
735
+ fmt_sp. shrink_to_lo ( ) ,
736
+ "you might be missing a string literal to format with" ,
737
+ format ! ( "\" {}\" , " , sugg_fmt) ,
738
+ ) ;
739
+ err. emit ( ) ;
740
+ return DummyResult :: raw_expr ( sp) ;
741
+ } ,
710
742
} ;
711
743
712
744
let mut cx = Context {
@@ -731,7 +763,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
731
763
} ;
732
764
733
765
let fmt_str = & * fmt. node . 0 . as_str ( ) ;
734
- let mut parser = parse:: Parser :: new ( fmt_str) ;
766
+ let mut parser = parse:: Parser :: new ( fmt_str, fmt . node . 1 ) ;
735
767
let mut pieces = vec ! [ ] ;
736
768
737
769
while let Some ( mut piece) = parser. next ( ) {
@@ -818,7 +850,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
818
850
errs. iter ( ) . map ( |& ( sp, _) | sp) . collect :: < Vec < Span > > ( ) ,
819
851
"multiple unused formatting arguments"
820
852
) ;
821
- diag. span_label ( cx. fmtsp , "multiple unused arguments in this statement " ) ;
853
+ diag. span_label ( cx. fmtsp , "multiple missing formatting arguments " ) ;
822
854
diag
823
855
}
824
856
} ;
@@ -861,8 +893,10 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
861
893
}
862
894
863
895
if show_doc_note {
864
- diag. note( concat!( stringify!( $kind) , " formatting not supported; see \
865
- the documentation for `std::fmt`") ) ;
896
+ diag. note( concat!(
897
+ stringify!( $kind) ,
898
+ " formatting not supported; see the documentation for `std::fmt`" ,
899
+ ) ) ;
866
900
}
867
901
} } ;
868
902
}
0 commit comments