enum-tree-derive 0.1.0

Derive macros for the enum-tree crate
Documentation
use proc_macro2::TokenStream;
use quote::ToTokens as _;
use syn::{DeriveInput, Ident, Path};

struct Edge
{
    parent:      TokenStream,
    into_parent: Path,
}

pub fn derive_into_ancestors(input: &DeriveInput) -> TokenStream
{
    let type_name = &input.ident;

    let mut edges: Vec<Edge> = Vec::new();

    for attr in &input.attrs {
        if !attr.path().is_ident("ancestors") {
            continue;
        }
        let result = attr.parse_nested_meta(|meta| {
            let parent = meta.path.segments[0].to_token_stream();
            edges.push(Edge {
                parent,
                into_parent: meta.path,
            });
            Ok(())
        });
        if let Err(e) = result {
            return e.to_compile_error();
        }
    }

    let mut expanded = TokenStream::new();

    for edge in edges {
        expanded.extend(generate_impl_for_edge(type_name, edge));
    }
    expanded
}

fn generate_impl_for_edge(type_name: &Ident, edge: Edge) -> TokenStream
{
    let ancestor = edge.parent;
    let conversion = edge.into_parent;

    quote::quote! {
        impl ::core::convert::From<#type_name> for #ancestor {
            fn from(child: #type_name) -> #ancestor {
                #conversion(::core::convert::Into::into(child))
            }
        }
    }
}