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