1
1
use crate :: ast:: Field ;
2
2
use crate :: attr:: { Display , Trait } ;
3
3
use crate :: scan_expr;
4
- use proc_macro2:: TokenTree ;
4
+ use proc_macro2:: { TokenStream , TokenTree } ;
5
5
use quote:: { format_ident, quote, quote_spanned} ;
6
6
use std:: collections:: { BTreeSet as Set , HashMap as Map } ;
7
7
use syn:: ext:: IdentExt ;
8
+ use syn:: parse:: discouraged:: Speculative ;
8
9
use syn:: parse:: { ParseStream , Parser } ;
9
10
use syn:: { Expr , Ident , Index , LitStr , Member , Result , Token } ;
10
11
@@ -118,7 +119,25 @@ impl Display<'_> {
118
119
}
119
120
}
120
121
122
+ #[ allow( clippy:: unnecessary_wraps) ]
121
123
fn explicit_named_args ( input : ParseStream ) -> Result < Set < Ident > > {
124
+ let ahead = input. fork ( ) ;
125
+ if let Ok ( set) = try_explicit_named_args ( & ahead) {
126
+ input. advance_to ( & ahead) ;
127
+ return Ok ( set) ;
128
+ }
129
+
130
+ let ahead = input. fork ( ) ;
131
+ if let Ok ( set) = fallback_explicit_named_args ( & ahead) {
132
+ input. advance_to ( & ahead) ;
133
+ return Ok ( set) ;
134
+ }
135
+
136
+ input. parse :: < TokenStream > ( ) . unwrap ( ) ;
137
+ Ok ( Set :: new ( ) )
138
+ }
139
+
140
+ fn try_explicit_named_args ( input : ParseStream ) -> Result < Set < Ident > > {
122
141
let scan_expr = if is_syn_full ( ) {
123
142
|input : ParseStream | input. parse :: < Expr > ( ) . map ( drop)
124
143
} else {
@@ -143,6 +162,21 @@ fn explicit_named_args(input: ParseStream) -> Result<Set<Ident>> {
143
162
Ok ( named_args)
144
163
}
145
164
165
+ fn fallback_explicit_named_args ( input : ParseStream ) -> Result < Set < Ident > > {
166
+ let mut named_args = Set :: new ( ) ;
167
+
168
+ while !input. is_empty ( ) {
169
+ if input. peek ( Token ! [ , ] ) && input. peek2 ( Ident :: peek_any) && input. peek3 ( Token ! [ =] ) {
170
+ input. parse :: < Token ! [ , ] > ( ) ?;
171
+ let ident = input. call ( Ident :: parse_any) ?;
172
+ input. parse :: < Token ! [ =] > ( ) ?;
173
+ named_args. insert ( ident) ;
174
+ }
175
+ }
176
+
177
+ Ok ( named_args)
178
+ }
179
+
146
180
fn is_syn_full ( ) -> bool {
147
181
// Expr::Block contains syn::Block which contains Vec<syn::Stmt>. In the
148
182
// current version of Syn, syn::Stmt is exhaustive and could only plausibly
0 commit comments