1use proc_macro2::TokenStream;
6use syn::{
7 punctuated::Punctuated, token, Abi, Attribute, Generics, Ident, Lifetime, ReturnType, Token,
8 Type, Visibility,
9};
10
11use super::{Pat, PatType};
12
13ast_struct! {
14 pub struct ItemFn {
17 pub attrs: Vec<Attribute>,
18 pub vis: Visibility,
19 pub sig: Signature,
20 pub block: Box<Block>,
21 }
22}
23
24ast_struct! {
25 pub struct Block {
27 pub brace_token: token::Brace,
28 pub stmts: TokenStream,
30 }
31}
32
33ast_struct! {
34 pub struct Signature {
37 pub constness: Option<Token![const]>,
38 pub asyncness: Option<Token![async]>,
39 pub unsafety: Option<Token![unsafe]>,
40 pub abi: Option<Abi>,
41 pub fn_token: Token![fn],
42 pub ident: Ident,
43 pub generics: Generics,
44 pub paren_token: token::Paren,
45 pub inputs: Punctuated<FnArg, Token![,]>,
46 pub variadic: Option<Variadic>,
47 pub output: ReturnType,
48 }
49}
50
51ast_enum_of_structs! {
52 pub enum FnArg {
54 Receiver(Receiver),
57
58 Typed(PatType),
60 }
61}
62
63ast_struct! {
64 pub struct Receiver {
67 pub attrs: Vec<Attribute>,
68 pub reference: Option<(Token![&], Option<Lifetime>)>,
69 pub mutability: Option<Token![mut]>,
70 pub self_token: Token![self],
71 pub colon_token: Option<Token![:]>,
72 pub ty: Box<Type>,
73 }
74}
75
76ast_struct! {
77 pub struct Variadic {
79 pub attrs: Vec<Attribute>,
80 pub pat: Option<(Box<Pat>, Token![:])>,
81 pub dots: Token![...],
82 pub comma: Option<Token![,]>,
83 }
84}
85
86mod parsing {
87 use syn::{
88 braced, parenthesized,
89 parse::{discouraged::Speculative, Parse, ParseStream, Result},
90 punctuated::Punctuated,
91 Abi, Attribute, Error, Generics, Ident, Lifetime, Path, ReturnType, Token, Type, TypePath,
92 TypeReference, Visibility,
93 };
94
95 use super::{Block, FnArg, ItemFn, Receiver, Signature, Variadic};
96 use crate::pat::{Pat, PatType, PatWild};
97
98 impl Parse for Block {
99 fn parse(input: ParseStream<'_>) -> Result<Self> {
100 let content;
101 Ok(Self { brace_token: braced!(content in input), stmts: content.parse()? })
102 }
103 }
104
105 impl Parse for Signature {
106 fn parse(input: ParseStream<'_>) -> Result<Self> {
107 let constness: Option<Token![const]> = input.parse()?;
108 let asyncness: Option<Token![async]> = input.parse()?;
109 let unsafety: Option<Token![unsafe]> = input.parse()?;
110 let abi: Option<Abi> = input.parse()?;
111 let fn_token: Token![fn] = input.parse()?;
112 let ident: Ident = input.parse()?;
113 let mut generics: Generics = input.parse()?;
114
115 let content;
116 let paren_token = parenthesized!(content in input);
117 let (inputs, variadic) = parse_fn_args(&content)?;
118
119 let output: ReturnType = input.parse()?;
120 generics.where_clause = input.parse()?;
121
122 Ok(Self {
123 constness,
124 asyncness,
125 unsafety,
126 abi,
127 fn_token,
128 ident,
129 generics,
130 paren_token,
131 inputs,
132 variadic,
133 output,
134 })
135 }
136 }
137
138 impl Parse for ItemFn {
139 fn parse(input: ParseStream<'_>) -> Result<Self> {
140 let attrs = input.call(Attribute::parse_outer)?;
141 let vis: Visibility = input.parse()?;
142 let sig: Signature = input.parse()?;
143 let block = input.parse()?;
144 Ok(Self { attrs, vis, sig, block: Box::new(block) })
145 }
146 }
147
148 impl Parse for FnArg {
149 fn parse(input: ParseStream<'_>) -> Result<Self> {
150 let allow_variadic = false;
151 let attrs = input.call(Attribute::parse_outer)?;
152 match parse_fn_arg_or_variadic(input, attrs, allow_variadic)? {
153 FnArgOrVariadic::FnArg(arg) => Ok(arg),
154 FnArgOrVariadic::Variadic(_) => unreachable!(),
155 }
156 }
157 }
158
159 enum FnArgOrVariadic {
160 FnArg(FnArg),
161 Variadic(Variadic),
162 }
163
164 fn parse_fn_arg_or_variadic(
165 input: ParseStream<'_>,
166 attrs: Vec<Attribute>,
167 allow_variadic: bool,
168 ) -> Result<FnArgOrVariadic> {
169 let ahead = input.fork();
170 if let Ok(mut receiver) = ahead.parse::<Receiver>() {
171 input.advance_to(&ahead);
172 receiver.attrs = attrs;
173 return Ok(FnArgOrVariadic::FnArg(FnArg::Receiver(receiver)));
174 }
175
176 if input.peek(Ident) && input.peek2(Token![<]) {
180 let span = input.fork().parse::<Ident>()?.span();
181 return Ok(FnArgOrVariadic::FnArg(FnArg::Typed(PatType {
182 attrs,
183 pat: Box::new(Pat::Wild(PatWild {
184 attrs: Vec::new(),
185 underscore_token: Token,
186 })),
187 colon_token: Token,
188 ty: input.parse()?,
189 })));
190 }
191
192 let pat = Box::new(Pat::parse_single(input)?);
193 let colon_token: Token![:] = input.parse()?;
194
195 if allow_variadic {
196 if let Some(dots) = input.parse::<Option<Token![...]>>()? {
197 return Ok(FnArgOrVariadic::Variadic(Variadic {
198 attrs,
199 pat: Some((pat, colon_token)),
200 dots,
201 comma: None,
202 }));
203 }
204 }
205
206 Ok(FnArgOrVariadic::FnArg(FnArg::Typed(PatType {
207 attrs,
208 pat,
209 colon_token,
210 ty: input.parse()?,
211 })))
212 }
213
214 impl Parse for Receiver {
215 fn parse(input: ParseStream<'_>) -> Result<Self> {
216 let reference = if input.peek(Token![&]) {
217 let ampersand: Token![&] = input.parse()?;
218 let lifetime: Option<Lifetime> = input.parse()?;
219 Some((ampersand, lifetime))
220 } else {
221 None
222 };
223 let mutability: Option<Token![mut]> = input.parse()?;
224 let self_token: Token![self] = input.parse()?;
225 let colon_token: Option<Token![:]> =
226 if reference.is_some() { None } else { input.parse()? };
227 let ty: Type = if colon_token.is_some() {
228 input.parse()?
229 } else {
230 let mut ty = Type::Path(TypePath {
231 qself: None,
232 path: Path::from(Ident::new("Self", self_token.span)),
233 });
234 if let Some((ampersand, lifetime)) = reference.as_ref() {
235 ty = Type::Reference(TypeReference {
236 and_token: Token,
237 lifetime: lifetime.clone(),
238 mutability: mutability.as_ref().map(|m| Token),
239 elem: Box::new(ty),
240 });
241 }
242 ty
243 };
244 Ok(Self {
245 attrs: Vec::new(),
246 reference,
247 mutability,
248 self_token,
249 colon_token,
250 ty: Box::new(ty),
251 })
252 }
253 }
254
255 fn parse_fn_args(
256 input: ParseStream<'_>,
257 ) -> Result<(Punctuated<FnArg, Token![,]>, Option<Variadic>)> {
258 let mut args = Punctuated::new();
259 let mut variadic = None;
260 let mut has_receiver = false;
261
262 while !input.is_empty() {
263 let attrs = input.call(Attribute::parse_outer)?;
264
265 if let Some(dots) = input.parse::<Option<Token![...]>>()? {
266 variadic = Some(Variadic {
267 attrs,
268 pat: None,
269 dots,
270 comma: if input.is_empty() { None } else { Some(input.parse()?) },
271 });
272 break;
273 }
274
275 let allow_variadic = true;
276 let arg = match parse_fn_arg_or_variadic(input, attrs, allow_variadic)? {
277 FnArgOrVariadic::FnArg(arg) => arg,
278 FnArgOrVariadic::Variadic(arg) => {
279 variadic = Some(Variadic {
280 comma: if input.is_empty() { None } else { Some(input.parse()?) },
281 ..arg
282 });
283 break;
284 }
285 };
286
287 match &arg {
288 FnArg::Receiver(receiver) if has_receiver => {
289 return Err(Error::new(
290 receiver.self_token.span,
291 "unexpected second method receiver",
292 ));
293 }
294 FnArg::Receiver(receiver) if !args.is_empty() => {
295 return Err(Error::new(receiver.self_token.span, "unexpected method receiver"));
296 }
297 FnArg::Receiver(_) => has_receiver = true,
298 FnArg::Typed(_) => {}
299 }
300 args.push_value(arg);
301
302 if input.is_empty() {
303 break;
304 }
305
306 let comma: Token![,] = input.parse()?;
307 args.push_punct(comma);
308 }
309
310 Ok((args, variadic))
311 }
312}
313
314mod printing {
315 use proc_macro2::TokenStream;
316 use quote::{ToTokens, TokenStreamExt};
317 use syn::{Token, Type};
318
319 use super::{Block, ItemFn, Receiver, Signature, Variadic};
320
321 impl ToTokens for ItemFn {
322 fn to_tokens(&self, tokens: &mut TokenStream) {
323 tokens.append_all(&self.attrs);
324 self.vis.to_tokens(tokens);
325 self.sig.to_tokens(tokens);
326 self.block.to_tokens(tokens);
327 }
328 }
329
330 impl ToTokens for Block {
331 fn to_tokens(&self, tokens: &mut TokenStream) {
332 self.brace_token.surround(tokens, |tokens| {
333 tokens.append_all(self.stmts.clone());
334 });
335 }
336 }
337
338 impl ToTokens for Signature {
339 fn to_tokens(&self, tokens: &mut TokenStream) {
340 self.constness.to_tokens(tokens);
341 self.asyncness.to_tokens(tokens);
342 self.unsafety.to_tokens(tokens);
343 self.abi.to_tokens(tokens);
344 self.fn_token.to_tokens(tokens);
345 self.ident.to_tokens(tokens);
346 self.generics.to_tokens(tokens);
347 self.paren_token.surround(tokens, |tokens| {
348 self.inputs.to_tokens(tokens);
349 if let Some(variadic) = &self.variadic {
350 if !self.inputs.empty_or_trailing() {
351 <Token![,]>::default().to_tokens(tokens);
352 }
353 variadic.to_tokens(tokens);
354 }
355 });
356 self.output.to_tokens(tokens);
357 self.generics.where_clause.to_tokens(tokens);
358 }
359 }
360
361 impl ToTokens for Receiver {
362 fn to_tokens(&self, tokens: &mut TokenStream) {
363 tokens.append_all(&self.attrs);
364 if let Some((ampersand, lifetime)) = &self.reference {
365 ampersand.to_tokens(tokens);
366 lifetime.to_tokens(tokens);
367 }
368 self.mutability.to_tokens(tokens);
369 self.self_token.to_tokens(tokens);
370 if let Some(colon_token) = &self.colon_token {
371 colon_token.to_tokens(tokens);
372 self.ty.to_tokens(tokens);
373 } else {
374 let consistent = match (&self.reference, &self.mutability, &*self.ty) {
375 (Some(_), mutability, Type::Reference(ty)) => {
376 mutability.is_some() == ty.mutability.is_some()
377 && match &*ty.elem {
378 Type::Path(ty) => ty.qself.is_none() && ty.path.is_ident("Self"),
379 _ => false,
380 }
381 }
382 (None, _, Type::Path(ty)) => ty.qself.is_none() && ty.path.is_ident("Self"),
383 _ => false,
384 };
385 if !consistent {
386 <Token![:]>::default().to_tokens(tokens);
387 self.ty.to_tokens(tokens);
388 }
389 }
390 }
391 }
392
393 impl ToTokens for Variadic {
394 fn to_tokens(&self, tokens: &mut TokenStream) {
395 tokens.append_all(&self.attrs);
396 if let Some((pat, colon)) = &self.pat {
397 pat.to_tokens(tokens);
398 colon.to_tokens(tokens);
399 }
400 self.dots.to_tokens(tokens);
401 self.comma.to_tokens(tokens);
402 }
403 }
404}