Props, reconciler fixes, demo fixes

This commit is contained in:
Ryan McGrath 2019-06-05 21:15:46 -07:00
parent 47163c64f9
commit 290b57d336
No known key found for this signature in database
GPG key ID: 811674B62B666830
17 changed files with 284 additions and 190 deletions

View file

@ -22,9 +22,10 @@ mod parser;
mod span;
use proc_macro::TokenStream;
use proc_macro2::{TokenStream as TokenStream2, Literal};
use proc_macro2::{Ident, TokenStream as TokenStream2, Literal, Span};
use proc_macro_hack::proc_macro_hack;
use quote::quote;
use syn::{DeriveInput, parse_macro_input};
use alchemy_styles::cssparser::{Parser, ParserInput, RuleListParser};
use alchemy_styles::styles_parser::{Rule, RuleParser};
@ -77,3 +78,30 @@ pub fn styles(input: TokenStream) -> TokenStream {
styles
})).into()
}
/// Implements a derive macro for automating props setting and conversion.
#[proc_macro_derive(Props)]
pub fn writable_props_derive(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let name = &input.ident;
let name_props = Ident::new(&format!("{}Props", name), Span::call_site());
let generics = input.generics;
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
TokenStream::from(quote! {
impl #impl_generics #name #ty_generics #where_clause {
fn default_props() -> #name_props {
#name_props::default()
}
}
impl #impl_generics alchemy::ComponentProps for #name #ty_generics #where_clause {
fn set_props(&mut self, new_props: &mut Any) {
match new_props.downcast_ref::<#name_props>() {
Some(props) => { },
None => { panic!("Woah there, somehow the wrong props were being passed!"); }
}
}
}
})
}

View file

@ -125,8 +125,7 @@ impl Element {
let name = key.to_string();
let token = TokenTree::Ident(ident::new_raw(&name, key.span()));
(name, token, value)
});
});
let mut attributes = TokenStream::new();
let mut styles = TokenStream::new();
@ -159,29 +158,29 @@ impl Element {
eprintln_msg += "\nERROR: rebuild with nightly to print source location";
}
//body.extend(quote!(
/*element.attrs.#key = Some(#lit.parse().unwrap_or_else(|err| {
attributes.extend(quote!(
props.#key = #lit.parse().unwrap_or_else(|err| {
eprintln!(#eprintln_msg, err);
panic!("failed to parse string literal");
}));*/
//));
panic!("Failed to parse string literal");
});
));
},
value => {
let key = key.to_string();
let prop = key.to_string();
let value = process_value(value);
if key == "r#styles" {
if prop == "r#styles" {
styles = quote!(std::convert::Into::into(#value));
continue;
}
if key == "r#key" {
if prop == "r#key" {
continue;
}
attributes.extend(quote!(
attributes.insert(#key, std::convert::Into::into(#value));
props.#key = std::convert::Into::into(#value);
));
}
}
@ -219,19 +218,19 @@ impl Element {
let component_name = Literal::string(&typename.to_string());
Ok(quote!(
alchemy::RSX::node(#component_name, |key| {
Box::new(#typename::constructor(key))
}, alchemy::Props::new("".into(), #styles, {
let mut attributes = std::collections::HashMap::new();
Ok(quote! {
alchemy::RSX::node(#component_name, #styles, |key| {
Box::new(<#typename as alchemy::Component>::new(key))
}, {
let props = #typename::default_props();
#attributes
attributes
Box::new(props)
}, {
let mut children = vec![];
#children
children
}))
))
})
})
}
}