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