use proc_macro2::Span;
use std::collections::HashMap;
use syn::spanned::Spanned;
use syn::{Attribute, DeriveInput, Variant};
pub fn extract_eure_attr_spans(attrs: &[Attribute]) -> HashMap<String, Span> {
let mut spans = HashMap::new();
for attr in attrs {
if !attr.path().is_ident("eure") {
continue;
}
let _ = attr.parse_nested_meta(|meta| {
if let Some(ident) = meta.path.get_ident() {
let key = ident.to_string();
spans.insert(key.clone(), meta.path.span());
if meta.input.peek(syn::Token![=]) {
let _: syn::Token![=] = meta.input.parse()?;
let expr: syn::Expr = meta.input.parse()?;
if key == "via" {
spans.insert("via_value".to_string(), expr.span());
}
}
}
Ok(())
});
}
spans
}
pub fn extract_container_attr_spans(input: &DeriveInput) -> HashMap<String, Span> {
extract_eure_attr_spans(&input.attrs)
}
pub fn extract_variant_attr_spans(variant: &Variant) -> HashMap<String, Span> {
extract_eure_attr_spans(&variant.attrs)
}
#[cfg(test)]
mod tests {
use super::*;
use syn::parse_quote;
#[test]
fn extracts_simple_attributes() {
let field: syn::Field = parse_quote! {
#[eure(flatten, ext)]
field: String
};
let spans = extract_eure_attr_spans(&field.attrs);
assert!(spans.contains_key("flatten"));
assert!(spans.contains_key("ext"));
}
#[test]
fn extracts_name_value_attributes() {
let field: syn::Field = parse_quote! {
#[eure(via = "SomeType", rename = "other_name")]
field: String
};
let spans = extract_eure_attr_spans(&field.attrs);
assert!(spans.contains_key("via"));
assert!(spans.contains_key("rename"));
}
#[test]
fn handles_multiple_eure_attributes() {
let field: syn::Field = parse_quote! {
#[eure(flatten)]
#[eure(ext)]
field: String
};
let spans = extract_eure_attr_spans(&field.attrs);
assert!(spans.contains_key("flatten"));
assert!(spans.contains_key("ext"));
}
#[test]
fn ignores_non_eure_attributes() {
let field: syn::Field = parse_quote! {
#[serde(rename = "foo")]
#[eure(flatten)]
field: String
};
let spans = extract_eure_attr_spans(&field.attrs);
assert!(spans.contains_key("flatten"));
assert!(!spans.contains_key("rename")); }
}