sylvia_derive/parser/
entry_point.rs

1use proc_macro2::TokenStream as TokenStream2;
2use proc_macro_error::{emit_error, emit_warning};
3use syn::parse::{Error, Nothing, Parse, ParseStream, Parser};
4use syn::punctuated::Punctuated;
5use syn::spanned::Spanned;
6use syn::{parenthesized, parse2, GenericArgument, Path, Result, Token};
7
8use crate::parser::Custom;
9
10use super::extract_generics_from_path;
11
12/// Parsed arguments for `entry_points` macro
13#[derive(Default)]
14pub struct EntryPointArgs {
15    /// Types used in place of contracts generics.
16    pub generics: Punctuated<GenericArgument, Token![,]>,
17}
18
19impl EntryPointArgs {
20    pub fn new(attr: &TokenStream2) -> Result<Self> {
21        let args: Self = parse2(attr.clone()).map_err(|err| {
22            emit_error!(attr, err);
23            err
24        })?;
25
26        Ok(args)
27    }
28}
29
30impl Parse for EntryPointArgs {
31    fn parse(input: ParseStream) -> Result<Self> {
32        let mut entry_points_args = Self::default();
33        if input.is_empty() {
34            return Ok(entry_points_args);
35        }
36
37        let generics: Path = input.parse()?;
38        match generics.segments.last() {
39            Some(segment) if segment.ident == "generics" => {
40                entry_points_args.generics = extract_generics_from_path(&generics)
41            }
42            _ => return Err(Error::new(generics.span(), "Expected `generics`.")),
43        };
44
45        let comma: Option<Token![,]> = input.parse().ok();
46        if comma.is_some() {
47            emit_warning!(
48                comma.span(), "Deprecated `, custom(msg=.., query=..)` found.";
49                note = "You can safely remove this parameter as `entry_points` macro does not require it anymore."
50            );
51
52            // Parse custom attribute to not break semver
53            let custom: Option<Path> = input.parse().ok();
54            match custom {
55                Some(custom)
56                    if custom.get_ident().map(|custom| custom.to_string())
57                        == Some("custom".to_owned()) =>
58                {
59                    let content;
60                    parenthesized!(content in input);
61                    let _ = Custom::parse.parse2(content.parse()?);
62                }
63                _ => (),
64            };
65        }
66
67        let _: Nothing = input.parse()?;
68
69        Ok(entry_points_args)
70    }
71}