ligen_parser/parser/universal/attributes/attribute/
mod.rs

1//! Attribute enumeration.
2
3use intermediary_attribute::IntermediaryAttribute;
4use ligen_ir::macro_attributes::{Named, Group};
5use syn::__private::ToTokens;
6use crate::prelude::*;
7use crate::universal::parser::PathParser;
8use ligen_ir::{Attribute, Literal};
9use crate::parser::{Parser, ParserConfig};
10use crate::parser::universal::identifier::IdentifierParser;
11use crate::parser::universal::attributes::AttributesParser;
12use crate::parser::universal::literal::LiteralParser;
13
14pub(crate) mod intermediary_attribute;
15
16#[derive(Default)]
17pub struct AttributeParser<T: LiteralParser> {
18    literal_parser: T
19}
20
21impl<T: LiteralParser> Parser<syn::ItemMacro> for AttributeParser<T> {
22    type Output = Attribute;
23    fn parse(&self, call: syn::ItemMacro, config: &ParserConfig) -> Result<Self::Output> {
24        let identifier = call
25            .mac
26            .path
27            .segments
28            .last()
29            .ok_or(Error::Message("Failed to get identifier from syn::ItemMacro".to_string()))?
30            .ident
31            .clone();
32        let identifier = IdentifierParser::new().parse(identifier, config)?;
33        let attributes = AttributesParser::<T>::default().parse(call.mac.tokens.to_string().as_str(), config)?;
34        let group = Group::new(identifier, attributes).into();
35        Ok(group)
36    }
37}
38
39impl<T: LiteralParser> Parser<syn::MetaList> for AttributeParser<T> {
40    type Output = Attribute;
41    fn parse(&self, meta_list: syn::MetaList, config: &ParserConfig) -> Result<Self::Output> {
42        let path = PathParser::default().parse(meta_list.path.clone(), config)?;
43        let inner = meta_list.tokens.into_iter().map(|token| token.to_string()).collect::<Vec<_>>().join("");
44        let attributes = AttributesParser::<T>::default().parse(inner.as_str(), config)?;
45        let group = Group::new(path, attributes);
46        Ok(group.into())
47    }
48}
49
50impl<T: LiteralParser> Parser<syn::Lit> for AttributeParser<T> {
51    type Output = Attribute;
52    fn parse(&self, lit: syn::Lit, config: &ParserConfig) -> Result<Self::Output> {
53        self.literal_parser.parse(lit.to_token_stream().to_string(), config).map(Attribute::Literal)
54    }
55}
56
57impl<T: LiteralParser> Parser<syn::ExprCall> for AttributeParser<T> {
58    type Output = Attribute;
59    fn parse(&self, expr_call: syn::ExprCall, config: &ParserConfig) -> Result<Self::Output> {
60        let identifier = expr_call
61            .func
62            .to_token_stream()
63            .to_string();
64        let identifier = IdentifierParser::new().parse(identifier, config)?;
65        let attributes = AttributesParser::<T>::default().parse(expr_call.args, config)?;
66        let group = Group::new(identifier, attributes);
67        Ok(group.into())
68    }
69}
70
71impl<T: LiteralParser> Parser<syn::ExprAssign> for AttributeParser<T> {
72    type Output = Attribute;
73    fn parse(&self, expr_assign: syn::ExprAssign, config: &ParserConfig) -> Result<Self::Output> {
74        let identifier = expr_assign
75            .left
76            .to_token_stream()
77            .to_string();
78        let identifier = IdentifierParser::new().parse(identifier, config)?;
79        let literal = self.literal_parser.parse(expr_assign.right.to_token_stream().to_string(), config)?;
80        let group = Named::new(identifier, literal);
81        Ok(group.into())
82    }
83}
84
85impl<T: LiteralParser> Parser<syn::Expr> for AttributeParser<T> {
86    type Output = Attribute;
87    fn parse(&self, expr: syn::Expr, config: &ParserConfig) -> Result<Self::Output> {
88        match expr {
89            syn::Expr::Path(expr) => self.parse(expr, config),
90            syn::Expr::Lit(expr) => self.literal_parser.parse(expr.to_token_stream().to_string(), config).map(Attribute::Literal),
91            syn::Expr::Call(expr) => self.parse(expr, config),
92            syn::Expr::Assign(expr) => self.parse(expr, config),
93            _ => Ok(Attribute::Literal(Literal::Unknown(expr.to_token_stream().into_iter().map(|token| token.to_string()).collect::<Vec<_>>().join("")))),
94        }
95    }
96}
97
98impl<T: LiteralParser> Parser<syn::ExprPath> for AttributeParser<T> {
99    type Output = Attribute;
100    fn parse(&self, input: syn::ExprPath, config: &ParserConfig) -> Result<Self::Output> {
101        self.parse(input.path, config)
102    }
103}
104
105impl<T: LiteralParser> Parser<syn::Path> for AttributeParser<T> {
106    type Output = Attribute;
107    fn parse(&self, path: syn::Path, config: &ParserConfig) -> Result<Self::Output> {
108        let path = PathParser::default().parse(path, config)?;
109        let attribute = Group::from(path).into();
110        Ok(attribute)
111    }
112}
113
114
115impl<T: LiteralParser> Parser<syn::MetaNameValue> for AttributeParser<T> {
116    type Output = Attribute;
117    fn parse(&self, meta_name_value: syn::MetaNameValue, config: &ParserConfig) -> Result<Self::Output> {
118        let path = PathParser::default().parse(meta_name_value.path, config)?;
119        let literal = self.literal_parser.parse(meta_name_value.value.to_token_stream().to_string(), config)?;
120        let attribute = Named::new(path, literal).into();
121        Ok(attribute)
122    }
123}
124
125impl<T: LiteralParser> Parser<syn::Meta> for AttributeParser<T> {
126    type Output = Attribute;
127    fn parse(&self, meta: syn::Meta, config: &ParserConfig) -> Result<Self::Output> {
128        match meta {
129            syn::Meta::Path(path) => self.parse(path, config),
130            syn::Meta::List(list) => self.parse(list, config),
131            syn::Meta::NameValue(name_value) => self.parse(name_value, config),
132        }
133    }
134}
135
136impl<T: LiteralParser> Parser<syn::Attribute> for AttributeParser<T> {
137    type Output = Attribute;
138    fn parse(&self, attribute: syn::Attribute, config: &ParserConfig) -> Result<Self::Output> {
139        self.parse(attribute.meta, config)
140    }
141}
142
143impl<T: LiteralParser> Parser<String> for AttributeParser<T> {
144    type Output = Attribute;
145    fn parse(&self, input: String, config: &ParserConfig) -> Result<Self::Output> {
146        self.parse(input.as_str(), config)
147    }
148}
149
150impl<T: LiteralParser> Parser<IntermediaryAttribute> for AttributeParser<T> {
151    type Output = Attribute;
152    fn parse(&self, input: IntermediaryAttribute, config: &ParserConfig) -> Result<Self::Output> {
153        match input {
154            IntermediaryAttribute::Meta(meta) => self.parse(meta, config),
155            IntermediaryAttribute::Lit(lit) => self.parse(lit, config),
156            IntermediaryAttribute::Expr(expr) => self.parse(expr, config),
157            IntermediaryAttribute::Unknown(unknown) => Ok(Attribute::Literal(Literal::Unknown(unknown))),
158        }
159    }
160}
161
162impl<T: LiteralParser> Parser<&str> for AttributeParser<T> {
163    type Output = Attribute;
164    fn parse(&self, input: &str, config: &ParserConfig) -> Result<Self::Output> {
165        let attribute = syn::parse_str::<IntermediaryAttribute>(input)
166            .map_err(|e| Error::Message(format!("Failed to parse attribute: {:?} - {}", e, input)))?;
167        self.parse(attribute, config)
168    }
169}