aboutsummaryrefslogtreecommitdiff
path: root/tosin-macros/src/lib.rs
diff options
context:
space:
mode:
authorMelody Horn / boringcactus <melody@boringcactus.com>2021-06-18 10:12:16 -0600
committerMelody Horn / boringcactus <melody@boringcactus.com>2021-06-18 10:12:16 -0600
commit709eb44ccb8d08ad7f26cdac2932eadc7ccd48e7 (patch)
treecc4aa6854147c0dc74bbd3bea9b8b9cfc083b62f /tosin-macros/src/lib.rs
parent3b880c0ae7963d783fb87a3389f98070e448495a (diff)
downloadtosin-709eb44ccb8d08ad7f26cdac2932eadc7ccd48e7.tar.gz
tosin-709eb44ccb8d08ad7f26cdac2932eadc7ccd48e7.zip
make model metadata available in AppConfig
Diffstat (limited to 'tosin-macros/src/lib.rs')
-rw-r--r--tosin-macros/src/lib.rs41
1 files changed, 38 insertions, 3 deletions
diff --git a/tosin-macros/src/lib.rs b/tosin-macros/src/lib.rs
index 7efbac6..408378f 100644
--- a/tosin-macros/src/lib.rs
+++ b/tosin-macros/src/lib.rs
@@ -2,6 +2,8 @@
extern crate proc_macro;
+use std::fs;
+
use proc_macro::TokenStream;
use quote::quote;
@@ -19,9 +21,9 @@ 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));
- }
+ pub const META: tosin::db::models::ModelMeta = tosin::db::models::ModelMeta {
+ name: stringify!(#name),
+ };
}
};
gen.into()
@@ -55,3 +57,36 @@ pub fn gather_migrations(_input: TokenStream) -> TokenStream {
gen.into()
}
+
+#[proc_macro]
+pub fn gather_models(_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 call_site_ast = syn::parse_file(&fs::read_to_string(call_site_path).unwrap()).unwrap();
+ let models = call_site_ast.items.iter()
+ .filter_map(|item| if let syn::Item::Struct(item) = item { Some(item) } else { None })
+ .filter(|item| item.attrs.iter().any(|attr| {
+ let attr = if let Ok(syn::Meta::List(attr)) = attr.parse_meta() { attr } else { return false; };
+ if attr.path.get_ident().map_or(false, |hopefully_derive| hopefully_derive == "derive") {
+ let mut derived = attr.nested.iter()
+ .filter_map(|derived| if let syn::NestedMeta::Meta(derived) = derived { Some(derived) } else { None });
+ derived.any(|derived| derived.path().get_ident().map_or(false, |hopefully_model| hopefully_model == "Model"))
+ } else {
+ false
+ }
+ }))
+ .map(|item| &item.ident);
+
+ let gen = quote! {
+ pub const ALL: &[tosin::db::models::ModelMeta] = &[
+ #(#models::META),*
+ ];
+ };
+
+ gen.into()
+}