#![feature(proc_macro_span)] extern crate proc_macro; use proc_macro::TokenStream; use quote::quote; #[proc_macro_derive(Model, attributes(model))] pub fn model_derive(input: TokenStream) -> TokenStream { // Construct a representation of Rust code as a syntax tree // that we can manipulate let ast = syn::parse(input).unwrap(); // Build the trait implementation impl_model(&ast) } fn impl_model(ast: &syn::DeriveInput) -> TokenStream { let name = &ast.ident; let gen = quote! { impl #name { fn hello_macro() { println!("Hello, Macro! My name is {}!", stringify!(#name)); } } }; gen.into() } #[proc_macro] pub fn gather_migrations(_input: TokenStream) -> TokenStream { let call_site = proc_macro::Span::call_site(); let call_site_file = call_site.source_file(); let call_site_path = call_site_file.path(); if !call_site_file.is_real() { panic!("call site does not have a real path"); } let migrations_dir = call_site_path.parent().unwrap(); let migrations: Vec = migrations_dir.read_dir() .unwrap() .map(Result::unwrap) .map(|x| x.path().file_stem().unwrap().to_string_lossy().into_owned()) .filter(|x| x != "mod") .map(|x| syn::parse_str(&x).unwrap()) .collect(); let gen = quote! { #( mod #migrations; )* pub const migrations: &[Migration] = &[ #(#migrations::MIGRATION),* ]; }; gen.into() }