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