logo
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
use proc_macro::Span;
use syn::{spanned::Spanned, Error, Macro, Result};

use crate::additional_fields::AdditionalFields;
use crate::menu::Menus;
use crate::widgets::Widget;

pub(super) struct Macros {
    pub widgets: Widget,
    pub additional_fields: Option<AdditionalFields>,
    pub menus: Option<Menus>,
}

impl Macros {
    pub fn new(macros: &[Macro], span: Span) -> Result<Self> {
        let mut additional_fields = None;
        let mut widgets = None;
        let mut menus = None;

        for mac in macros {
            let ident = &mac
                .path
                .segments
                .first()
                .expect("No path segments in macro path")
                .ident;
            let tokens = mac.tokens.clone();

            if ident == "view" {
                if tokens.is_empty() {
                    return Err(Error::new(
                        mac.span().unwrap().into(),
                        "widget macro is empty",
                    ));
                } else if widgets.is_some() {
                    return Err(Error::new(
                        mac.span().unwrap().into(),
                        "widget macro defined multiple times",
                    ));
                }
                widgets = Some(syn::parse_macro_input::parse::<Widget>(tokens.into())?);
            } else if ident == "additional_fields" {
                if additional_fields.is_some() {
                    return Err(Error::new(
                        mac.span().unwrap().into(),
                        "additional_fields macro defined multiple times",
                    ));
                }
                additional_fields = Some(syn::parse_macro_input::parse::<AdditionalFields>(
                    tokens.into(),
                )?);
            } else if ident == "menu" {
                if tokens.is_empty() {
                    return Err(Error::new(
                        mac.span().unwrap().into(),
                        "menu macro is empty",
                    ));
                } else if menus.is_some() {
                    return Err(Error::new(
                        mac.span().unwrap().into(),
                        "menu macro defined multiple times",
                    ));
                }
                menus = Some(syn::parse_macro_input::parse::<Menus>(tokens.into())?);
            } else {
                return Err(Error::new(
                    mac.span().unwrap().into(),
                    "Expected identifier view, menu or additional_fields",
                ));
            }
        }

        Ok(Macros {
            widgets: widgets
                .ok_or_else(|| Error::new(span.into(), "No view macro in impl block"))?,
            additional_fields,
            menus,
        })
    }
}