@@ -100,6 +100,30 @@ pub struct Argument<'a> {
100
100
pub format : FormatSpec < ' a > ,
101
101
}
102
102
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
+
103
127
/// Specification for the formatting of an argument in the format string.
104
128
#[ derive( Copy , Clone , Debug , PartialEq ) ]
105
129
pub struct FormatSpec < ' a > {
@@ -894,52 +918,73 @@ impl<'a> Parser<'a> {
894
918
}
895
919
896
920
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
+ }
942
969
}
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
+ ) ;
943
988
}
944
989
}
945
990
0 commit comments