awesome: arbitrary expressions excepted without braces
This commit is contained in:
1 parent
14961023f9
commit
4c85bcfdc8
40 files changed
+825
-767
No files matched your search
@@ -4,7 +4,7 @@ use proc_macro2::TokenStream as TokenStream2;
|
||||
use quote::{quote, ToTokens, TokenStreamExt};
|
||||
use syn::{
|
||||
parse::{Parse, ParseBuffer, ParseStream},
|
||||
token, Expr, ExprClosure, Ident, LitStr, Result, Token,
|
||||
Expr, Ident, LitStr, Result, Token,
|
||||
};
|
||||
|
||||
// =======================================
|
||||
@@ -33,45 +33,69 @@ impl Parse for Element {
|
||||
let mut key = None;
|
||||
let mut _el_ref = None;
|
||||
|
||||
// todo: more descriptive error handling
|
||||
while !content.is_empty() {
|
||||
// parse fields with commas
|
||||
// break when we don't get this pattern anymore
|
||||
// start parsing bodynodes
|
||||
// "def": 456,
|
||||
// abc: 123,
|
||||
loop {
|
||||
// Parse the raw literal fields
|
||||
if content.peek(LitStr) && content.peek2(Token![:]) && !content.peek3(Token![:]) {
|
||||
let name = content.parse::<LitStr>()?;
|
||||
let ident = name.clone();
|
||||
|
||||
content.parse::<Token![:]>()?;
|
||||
|
||||
if content.peek(LitStr) {
|
||||
let value = content.parse::<LitStr>()?;
|
||||
attributes.push(ElementAttrNamed {
|
||||
el_name: el_name.clone(),
|
||||
attr: ElementAttr::CustomAttrText { name, value },
|
||||
});
|
||||
} else {
|
||||
let value = content.parse::<Expr>()?;
|
||||
attributes.push(ElementAttrNamed {
|
||||
el_name: el_name.clone(),
|
||||
attr: ElementAttr::CustomAttrExpression { name, value },
|
||||
});
|
||||
}
|
||||
|
||||
if content.is_empty() {
|
||||
break;
|
||||
}
|
||||
|
||||
// todo: add a message saying you need to include commas between fields
|
||||
if content.parse::<Token![,]>().is_err() {
|
||||
proc_macro_error::emit_error!(
|
||||
ident,
|
||||
"This attribute is misisng a trailing comma"
|
||||
)
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if content.peek(Ident) && content.peek2(Token![:]) && !content.peek3(Token![:]) {
|
||||
let name = content.parse::<Ident>()?;
|
||||
let ident = name.clone();
|
||||
|
||||
let name_str = name.to_string();
|
||||
content.parse::<Token![:]>()?;
|
||||
|
||||
if name_str.starts_with("on") {
|
||||
if content.peek(token::Brace) {
|
||||
let mycontent;
|
||||
syn::braced!(mycontent in content);
|
||||
|
||||
listeners.push(ElementAttrNamed {
|
||||
el_name: el_name.clone(),
|
||||
attr: ElementAttr::EventTokens {
|
||||
name,
|
||||
tokens: mycontent.parse()?,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
listeners.push(ElementAttrNamed {
|
||||
el_name: el_name.clone(),
|
||||
attr: ElementAttr::EventClosure {
|
||||
name,
|
||||
closure: content.parse()?,
|
||||
},
|
||||
});
|
||||
};
|
||||
listeners.push(ElementAttrNamed {
|
||||
el_name: el_name.clone(),
|
||||
attr: ElementAttr::EventTokens {
|
||||
name,
|
||||
tokens: content.parse()?,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
match name_str.as_str() {
|
||||
"key" => {
|
||||
key = Some(content.parse()?);
|
||||
}
|
||||
"classes" => {
|
||||
todo!("custom class list not supported")
|
||||
}
|
||||
"namespace" => {
|
||||
todo!("custom namespace not supported")
|
||||
}
|
||||
"classes" => todo!("custom class list not supported yet"),
|
||||
// "namespace" => todo!("custom namespace not supported yet"),
|
||||
"node_ref" => {
|
||||
_el_ref = Some(content.parse::<Expr>()?);
|
||||
}
|
||||
@@ -96,27 +120,56 @@ impl Parse for Element {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if content.peek(LitStr) && content.peek2(Token![:]) {
|
||||
let name = content.parse::<LitStr>()?;
|
||||
content.parse::<Token![:]>()?;
|
||||
|
||||
if content.peek(LitStr) {
|
||||
let value = content.parse::<LitStr>()?;
|
||||
attributes.push(ElementAttrNamed {
|
||||
el_name: el_name.clone(),
|
||||
attr: ElementAttr::CustomAttrText { name, value },
|
||||
});
|
||||
} else {
|
||||
let value = content.parse::<Expr>()?;
|
||||
attributes.push(ElementAttrNamed {
|
||||
el_name: el_name.clone(),
|
||||
attr: ElementAttr::CustomAttrExpression { name, value },
|
||||
});
|
||||
if content.is_empty() {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
children.push(content.parse::<BodyNode>()?);
|
||||
|
||||
// todo: add a message saying you need to include commas between fields
|
||||
if content.parse::<Token![,]>().is_err() {
|
||||
proc_macro_error::emit_error!(
|
||||
ident,
|
||||
"This attribute is misisng a trailing comma"
|
||||
)
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
while !content.is_empty() {
|
||||
if (content.peek(LitStr) && content.peek2(Token![:])) && !content.peek3(Token![:]) {
|
||||
let ident = content.parse::<LitStr>().unwrap();
|
||||
let name = ident.value();
|
||||
proc_macro_error::emit_error!(
|
||||
ident, "This attribute `{}` is in the wrong place.", name;
|
||||
help =
|
||||
"All attribute fields must be placed above children elements.
|
||||
|
||||
div {
|
||||
attr: \"...\", <---- attribute is above children
|
||||
div { } <---- children are below attributes
|
||||
}";
|
||||
)
|
||||
}
|
||||
|
||||
if (content.peek(Ident) && content.peek2(Token![:])) && !content.peek3(Token![:]) {
|
||||
let ident = content.parse::<Ident>().unwrap();
|
||||
let name = ident.to_string();
|
||||
proc_macro_error::emit_error!(
|
||||
ident, "This attribute `{}` is in the wrong place.", name;
|
||||
help =
|
||||
"All attribute fields must be placed above children elements.
|
||||
|
||||
div {
|
||||
attr: \"...\", <---- attribute is above children
|
||||
div { } <---- children are below attributes
|
||||
}";
|
||||
)
|
||||
}
|
||||
|
||||
children.push(content.parse::<BodyNode>()?);
|
||||
// consume comma if it exists
|
||||
// we don't actually care if there *are* commas after elements/text
|
||||
if content.peek(Token![,]) {
|
||||
@@ -138,7 +191,7 @@ impl Parse for Element {
|
||||
impl ToTokens for Element {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream2) {
|
||||
let name = &self.name;
|
||||
let childs = &self.children;
|
||||
let children = &self.children;
|
||||
|
||||
let listeners = &self.listeners;
|
||||
let attr = &self.attributes;
|
||||
@@ -153,7 +206,7 @@ impl ToTokens for Element {
|
||||
dioxus_elements::#name,
|
||||
[ #(#listeners),* ],
|
||||
[ #(#attr),* ],
|
||||
[ #(#childs),* ],
|
||||
[ #(#children),* ],
|
||||
#key,
|
||||
)
|
||||
});
|
||||
@@ -173,8 +226,8 @@ enum ElementAttr {
|
||||
// "attribute": true,
|
||||
CustomAttrExpression { name: LitStr, value: Expr },
|
||||
|
||||
// onclick: move |_| {}
|
||||
EventClosure { name: Ident, closure: ExprClosure },
|
||||
// // onclick: move |_| {}
|
||||
// EventClosure { name: Ident, closure: ExprClosure },
|
||||
|
||||
// onclick: {}
|
||||
EventTokens { name: Ident, tokens: Expr },
|
||||
@@ -189,7 +242,7 @@ impl ToTokens for ElementAttrNamed {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream2) {
|
||||
let ElementAttrNamed { el_name, attr } = self;
|
||||
|
||||
let toks = match attr {
|
||||
tokens.append_all(match attr {
|
||||
ElementAttr::AttrText { name, value } => {
|
||||
quote! {
|
||||
dioxus_elements::#el_name.#name(__cx, format_args_f!(#value))
|
||||
@@ -200,26 +253,26 @@ impl ToTokens for ElementAttrNamed {
|
||||
dioxus_elements::#el_name.#name(__cx, #value)
|
||||
}
|
||||
}
|
||||
|
||||
ElementAttr::CustomAttrText { name, value } => {
|
||||
quote! { __cx.attr( #name, format_args_f!(#value), None, false ) }
|
||||
}
|
||||
ElementAttr::CustomAttrExpression { name, value } => {
|
||||
quote! { __cx.attr( #name, format_args_f!(#value), None, false ) }
|
||||
}
|
||||
|
||||
ElementAttr::EventClosure { name, closure } => {
|
||||
quote! {
|
||||
dioxus_elements::on::#name(__cx, #closure)
|
||||
__cx.attr( #name, format_args_f!(#value), None, false )
|
||||
}
|
||||
}
|
||||
ElementAttr::CustomAttrExpression { name, value } => {
|
||||
quote! {
|
||||
__cx.attr( #name, format_args_f!(#value), None, false )
|
||||
}
|
||||
}
|
||||
// ElementAttr::EventClosure { name, closure } => {
|
||||
// quote! {
|
||||
// dioxus_elements::on::#name(__cx, #closure)
|
||||
// }
|
||||
// }
|
||||
ElementAttr::EventTokens { name, tokens } => {
|
||||
quote! {
|
||||
dioxus_elements::on::#name(__cx, #tokens)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
tokens.append_all(toks);
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user