@@ -100,6 +100,30 @@ pub struct Argument<'a> {
100100 pub format : FormatSpec < ' a > ,
101101}
102102
103+ impl < ' a > Argument < ' a > {
104+ pub fn is_identifier ( & self ) -> bool {
105+ matches ! ( self . position, Position :: ArgumentNamed ( _) )
106+ && matches ! (
107+ self . format,
108+ FormatSpec {
109+ fill: None ,
110+ fill_span: None ,
111+ align: AlignUnknown ,
112+ sign: None ,
113+ alternate: false ,
114+ zero_pad: false ,
115+ debug_hex: None ,
116+ precision: CountImplied ,
117+ precision_span: None ,
118+ width: CountImplied ,
119+ width_span: None ,
120+ ty: "" ,
121+ ty_span: None ,
122+ } ,
123+ )
124+ }
125+ }
126+
103127/// Specification for the formatting of an argument in the format string.
104128#[ derive( Copy , Clone , Debug , PartialEq ) ]
105129pub struct FormatSpec < ' a > {
@@ -894,52 +918,73 @@ impl<'a> Parser<'a> {
894918 }
895919
896920 fn suggest_positional_arg_instead_of_captured_arg ( & mut self , arg : Argument < ' a > ) {
897- if let Some ( end) = self . consume_pos ( '.' ) {
898- let byte_pos = self . to_span_index ( end) ;
899- let start = InnerOffset ( byte_pos. 0 + 1 ) ;
900- let field = self . argument ( start) ;
901- // We can only parse simple `foo.bar` field access or `foo.0` tuple index access, any
902- // deeper nesting, or another type of expression, like method calls, are not supported
903- if !self . consume ( '}' ) {
904- return ;
905- }
906- if let ArgumentNamed ( _) = arg. position {
907- match field. position {
908- ArgumentNamed ( _) => {
909- self . errors . insert (
910- 0 ,
911- ParseError {
912- description : "field access isn't supported" . to_string ( ) ,
913- note : None ,
914- label : "not supported" . to_string ( ) ,
915- span : InnerSpan :: new (
916- arg. position_span . start ,
917- field. position_span . end ,
918- ) ,
919- secondary_label : None ,
920- suggestion : Suggestion :: UsePositional ,
921- } ,
922- ) ;
923- }
924- ArgumentIs ( _) => {
925- self . errors . insert (
926- 0 ,
927- ParseError {
928- description : "tuple index access isn't supported" . to_string ( ) ,
929- note : None ,
930- label : "not supported" . to_string ( ) ,
931- span : InnerSpan :: new (
932- arg. position_span . start ,
933- field. position_span . end ,
934- ) ,
935- secondary_label : None ,
936- suggestion : Suggestion :: UsePositional ,
937- } ,
938- ) ;
939- }
940- _ => { }
941- } ;
921+ // If the argument is an identifier, it may be a field access.
922+ if arg. is_identifier ( ) {
923+ if let Some ( end) = self . consume_pos ( '.' ) {
924+ let byte_pos = self . to_span_index ( end) ;
925+ let start = InnerOffset ( byte_pos. 0 + 1 ) ;
926+ let field = self . argument ( start) ;
927+ // We can only parse simple `foo.bar` field access or `foo.0` tuple index access, any
928+ // deeper nesting, or another type of expression, like method calls, are not supported
929+ if !self . consume ( '}' ) {
930+ return ;
931+ }
932+ if let ArgumentNamed ( _) = arg. position {
933+ match field. position {
934+ ArgumentNamed ( _) => {
935+ self . errors . insert (
936+ 0 ,
937+ ParseError {
938+ description : "field access isn't supported" . to_string ( ) ,
939+ note : None ,
940+ label : "not supported" . to_string ( ) ,
941+ span : InnerSpan :: new (
942+ arg. position_span . start ,
943+ field. position_span . end ,
944+ ) ,
945+ secondary_label : None ,
946+ suggestion : Suggestion :: UsePositional ,
947+ } ,
948+ ) ;
949+ }
950+ ArgumentIs ( _) => {
951+ self . errors . insert (
952+ 0 ,
953+ ParseError {
954+ description : "tuple index access isn't supported" . to_string ( ) ,
955+ note : None ,
956+ label : "not supported" . to_string ( ) ,
957+ span : InnerSpan :: new (
958+ arg. position_span . start ,
959+ field. position_span . end ,
960+ ) ,
961+ secondary_label : None ,
962+ suggestion : Suggestion :: UsePositional ,
963+ } ,
964+ ) ;
965+ }
966+ _ => { }
967+ } ;
968+ }
942969 }
970+ } else if matches ! ( arg. position, ArgumentNamed ( _) | ArgumentIs ( _) ) {
971+ let arg_name = match arg. position {
972+ ArgumentNamed ( arg_name) => & format ! ( "`{arg_name}`" ) ,
973+ ArgumentIs ( arg_index) => & format ! ( "at index `{arg_index}`" ) ,
974+ _ => unreachable ! ( ) ,
975+ } ;
976+
977+ self . errors . insert (
978+ 0 ,
979+ ParseError {
980+ description : format ! ( "invalid format string for argument {}" , arg_name) ,
981+ note : None ,
982+ label : format ! ( "invalid format specifier for this argument" ) ,
983+ span : InnerSpan :: new ( arg. position_span . start , arg. position_span . end ) ,
984+ secondary_label : None ,
985+ suggestion : Suggestion :: None ,
986+ } ,
987+ ) ;
943988 }
944989 }
945990
0 commit comments