eure-macros 0.1.9

Derive macros for Eure schema generation
Documentation
use proc_macro2::Span;
use std::collections::HashMap;

#[derive(Debug, Clone)]
pub(crate) struct FieldSpanInfo {
    pub(crate) field_span: Span,
    pub(crate) ty_span: Span,
    pub(crate) attr_spans: HashMap<String, Span>,
}

#[derive(Debug, Clone)]
pub(crate) struct VariantSpanInfo {
    pub(crate) variant_span: Span,
    pub(crate) fields: HashMap<String, FieldSpanInfo>,
}

#[derive(Debug, Clone)]
pub(crate) struct DeriveSpanTable {
    pub(crate) derive_span: Span,
    pub(crate) container_attr_spans: HashMap<String, Span>,
    pub(crate) fields: HashMap<String, FieldSpanInfo>,
    pub(crate) variants: HashMap<String, VariantSpanInfo>,
}

impl DeriveSpanTable {
    pub(crate) fn new(derive_span: Span, container_attr_spans: HashMap<String, Span>) -> Self {
        Self {
            derive_span,
            container_attr_spans,
            fields: HashMap::new(),
            variants: HashMap::new(),
        }
    }

    pub(crate) fn container_attr_span(&self, attr: &str) -> Option<Span> {
        self.container_attr_spans.get(attr).copied()
    }

    pub(crate) fn field_span(&self, name: &str) -> Option<Span> {
        self.fields.get(name).map(|entry| entry.field_span)
    }

    pub(crate) fn field_ty_span(&self, name: &str) -> Option<Span> {
        self.fields.get(name).map(|entry| entry.ty_span)
    }

    pub(crate) fn field_attr_span(&self, name: &str, attr: &str) -> Option<Span> {
        self.fields
            .get(name)
            .and_then(|entry| entry.attr_spans.get(attr).copied())
    }

    pub(crate) fn variant_span(&self, variant: &str) -> Option<Span> {
        self.variants.get(variant).map(|entry| entry.variant_span)
    }

    pub(crate) fn variant_field_span(&self, variant: &str, field: &str) -> Option<Span> {
        self.variants
            .get(variant)
            .and_then(|entry| entry.fields.get(field).map(|field| field.field_span))
    }

    pub(crate) fn variant_field_ty_span(&self, variant: &str, field: &str) -> Option<Span> {
        self.variants
            .get(variant)
            .and_then(|entry| entry.fields.get(field).map(|field| field.ty_span))
    }

    pub(crate) fn variant_field_attr_span(
        &self,
        variant: &str,
        field: &str,
        attr: &str,
    ) -> Option<Span> {
        self.variants
            .get(variant)
            .and_then(|entry| entry.fields.get(field))
            .and_then(|entry| entry.attr_spans.get(attr).copied())
    }

    pub(crate) fn upsert_field(
        &mut self,
        field_name: String,
        field_span: Span,
        ty_span: Span,
        attr_spans: HashMap<String, Span>,
    ) {
        self.fields.insert(
            field_name,
            FieldSpanInfo {
                field_span,
                ty_span,
                attr_spans,
            },
        );
    }

    pub(crate) fn upsert_variant(
        &mut self,
        variant_name: String,
        variant_span: Span,
        _attr_spans: HashMap<String, Span>,
    ) {
        self.variants
            .entry(variant_name)
            .or_insert(VariantSpanInfo {
                variant_span,
                fields: HashMap::new(),
            });
    }

    pub(crate) fn upsert_variant_field(
        &mut self,
        variant_name: &str,
        field_name: String,
        field_span: Span,
        ty_span: Span,
        attr_spans: HashMap<String, Span>,
    ) {
        let variant = self
            .variants
            .entry(variant_name.to_string())
            .or_insert_with(|| VariantSpanInfo {
                variant_span: self.derive_span,
                fields: HashMap::new(),
            });
        variant.fields.insert(
            field_name,
            FieldSpanInfo {
                field_span,
                ty_span,
                attr_spans,
            },
        );
    }
}