parsable_macro/
root_attributes.rs

1use proc_macro2::TokenStream;
2use syn::{*, parse::{Parse, ParseStream}};
3use crate::{markers::MarkerOutput};
4
5// TODO: add prefix and suffix
6pub struct RootAttributes {
7    pub located: bool,
8    pub impl_display: bool,
9    pub cascade: bool,
10    pub name: Option<String>,
11    pub token: Option<String>,
12    pub declared_markers: Vec<LitStr>,
13    pub set_markers: Vec<LitStr>,
14    pub unset_markers: Vec<LitStr>,
15    pub ignore_if_marker: Vec<LitStr>,
16    pub ignore_if_not_marker: Vec<LitStr>,
17}
18
19impl Default for RootAttributes {
20    fn default() -> Self {
21        Self {
22            located: true,
23            impl_display: false,
24            cascade: false,
25            name: None,
26            token: None,
27            declared_markers: vec![],
28            set_markers: vec![],
29            unset_markers: vec![],
30            ignore_if_marker: vec![],
31            ignore_if_not_marker: vec![],
32        }
33    }
34}
35
36impl Parse for RootAttributes {
37    fn parse(content: ParseStream) -> syn::Result<Self> {
38        let mut attributes = RootAttributes::default();
39
40        while !content.is_empty() {
41            let name = content.parse::<Ident>()?.to_string();
42            content.parse::<Token![=]>()?;
43
44            match name.as_str() {
45                "located" => attributes.located = content.parse::<LitBool>()?.value(),
46                "impl_display" => attributes.impl_display = content.parse::<LitBool>()?.value(),
47                "cascade" => attributes.cascade = content.parse::<LitBool>()?.value(),
48                "name" => attributes.name = Some(content.parse::<LitStr>()?.value()),
49                "declare_marker" => attributes.declared_markers.push(content.parse::<LitStr>()?),
50                "set_marker" => attributes.set_markers.push(content.parse::<LitStr>()?),
51                "unset_marker" => attributes.unset_markers.push(content.parse::<LitStr>()?),
52                "ignore_if_marker" => attributes.ignore_if_marker.push(content.parse::<LitStr>()?),
53                "ignore_if_not_marker" => attributes.ignore_if_not_marker.push(content.parse::<LitStr>()?),
54                _ => {}
55            }
56
57            if !content.is_empty() {
58                content.parse::<Token![,]>()?;
59            }
60        }
61
62        Ok(attributes)
63    }
64}
65
66impl RootAttributes {
67    pub fn get_push_pop_markers(&self) -> (TokenStream, TokenStream, TokenStream) {
68        MarkerOutput::from_attributes(&self.declared_markers, &self.set_markers, &self.unset_markers, None).to_tuple()
69    }
70}