1 use syn::{Attribute, Lifetime, Token};
2 
3 use super::PatType;
4 
5 ast_enum_of_structs! {
6     /// An argument in a function signature: the `n: usize` in `fn f(n: usize)`.
7     pub enum FnArg {
8         /// The `self` argument of an associated method, whether taken by value
9         /// or by reference.
10         Receiver(Receiver),
11 
12         /// A function argument accepted by pattern and type.
13         Typed(PatType),
14     }
15 }
16 
17 ast_struct! {
18     /// The `self` argument of an associated method, whether taken by value
19     /// or by reference.
20     pub struct Receiver {
21         pub attrs: Vec<Attribute>,
22         pub reference: Option<(Token![&], Option<Lifetime>)>,
23         pub mutability: Option<Token![mut]>,
24         pub self_token: Token![self],
25     }
26 }
27 
28 mod parsing {
29     use syn::{
30         parse::{discouraged::Speculative, Parse, ParseStream, Result},
31         Attribute, Token,
32     };
33 
34     use super::{FnArg, PatType, Receiver};
35 
36     impl Parse for FnArg {
parse(input: ParseStream<'_>) -> Result<Self>37         fn parse(input: ParseStream<'_>) -> Result<Self> {
38             let attrs = input.call(Attribute::parse_outer)?;
39 
40             let ahead = input.fork();
41             if let Ok(mut receiver) = ahead.parse::<Receiver>() {
42                 if !ahead.peek(Token![:]) {
43                     input.advance_to(&ahead);
44                     receiver.attrs = attrs;
45                     return Ok(FnArg::Receiver(receiver));
46                 }
47             }
48 
49             let mut typed = input.call(fn_arg_typed)?;
50             typed.attrs = attrs;
51             Ok(FnArg::Typed(typed))
52         }
53     }
54 
55     impl Parse for Receiver {
parse(input: ParseStream<'_>) -> Result<Self>56         fn parse(input: ParseStream<'_>) -> Result<Self> {
57             Ok(Self {
58                 attrs: Vec::new(),
59                 reference: {
60                     if input.peek(Token![&]) {
61                         Some((input.parse()?, input.parse()?))
62                     } else {
63                         None
64                     }
65                 },
66                 mutability: input.parse()?,
67                 self_token: input.parse()?,
68             })
69         }
70     }
71 
fn_arg_typed(input: ParseStream<'_>) -> Result<PatType>72     fn fn_arg_typed(input: ParseStream<'_>) -> Result<PatType> {
73         Ok(PatType {
74             attrs: Vec::new(),
75             pat: input.parse()?,
76             colon_token: input.parse()?,
77             ty: Box::new(input.parse()?),
78         })
79     }
80 }
81 
82 mod printing {
83     use proc_macro2::TokenStream;
84     use quote::{ToTokens, TokenStreamExt};
85 
86     use super::Receiver;
87 
88     impl ToTokens for Receiver {
to_tokens(&self, tokens: &mut TokenStream)89         fn to_tokens(&self, tokens: &mut TokenStream) {
90             tokens.append_all(&self.attrs);
91             if let Some((ampersand, lifetime)) = &self.reference {
92                 ampersand.to_tokens(tokens);
93                 lifetime.to_tokens(tokens);
94             }
95             self.mutability.to_tokens(tokens);
96             self.self_token.to_tokens(tokens);
97         }
98     }
99 }
100