Merge branch 'master' into jk/autofmt-fixues
This commit is contained in:
commit
09b38574db
336 files changed
+19973
-16881
No files matched your search
+209
-17
@@ -13,14 +13,14 @@
|
||||
|
||||
#[macro_use]
|
||||
mod errors;
|
||||
|
||||
mod component;
|
||||
mod element;
|
||||
mod ifmt;
|
||||
mod node;
|
||||
mod whitespace;
|
||||
mod raw_expr;
|
||||
mod template;
|
||||
mod text;
|
||||
mod whitespace;
|
||||
|
||||
// Re-export the namespaces into each other
|
||||
pub use component::*;
|
||||
@@ -36,9 +36,13 @@ use syn::{
|
||||
Result, Token,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
/// Fundametnally, every CallBody is a template
|
||||
#[derive(Default, Debug)]
|
||||
pub struct CallBody {
|
||||
pub roots: Vec<BodyNode>,
|
||||
|
||||
// set this after
|
||||
pub inline_cx: bool,
|
||||
}
|
||||
|
||||
impl Parse for CallBody {
|
||||
@@ -55,27 +59,215 @@ impl Parse for CallBody {
|
||||
roots.push(node);
|
||||
}
|
||||
|
||||
Ok(Self { roots })
|
||||
Ok(Self {
|
||||
roots,
|
||||
inline_cx: false,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Serialize the same way, regardless of flavor
|
||||
impl ToTokens for CallBody {
|
||||
fn to_tokens(&self, out_tokens: &mut TokenStream2) {
|
||||
let inner = if self.roots.len() == 1 {
|
||||
let inner = &self.roots[0];
|
||||
quote! { #inner }
|
||||
} else {
|
||||
let childs = &self.roots;
|
||||
quote! { __cx.fragment_root([ #(#childs),* ]) }
|
||||
};
|
||||
let body = TemplateRenderer { roots: &self.roots };
|
||||
|
||||
// Otherwise we just build the LazyNode wrapper
|
||||
out_tokens.append_all(quote! {
|
||||
LazyNodes::new(move |__cx: NodeFactory| -> VNode {
|
||||
use dioxus_elements::{GlobalAttributes, SvgAttributes};
|
||||
#inner
|
||||
if self.inline_cx {
|
||||
out_tokens.append_all(quote! {
|
||||
Ok({
|
||||
let __cx = cx;
|
||||
#body
|
||||
})
|
||||
})
|
||||
})
|
||||
} else {
|
||||
out_tokens.append_all(quote! {
|
||||
::dioxus::core::LazyNodes::new( move | __cx: &::dioxus::core::ScopeState| -> ::dioxus::core::VNode {
|
||||
#body
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TemplateRenderer<'a> {
|
||||
pub roots: &'a [BodyNode],
|
||||
}
|
||||
|
||||
impl<'a> ToTokens for TemplateRenderer<'a> {
|
||||
fn to_tokens(&self, out_tokens: &mut TokenStream2) {
|
||||
let mut context = DynamicContext {
|
||||
dynamic_nodes: vec![],
|
||||
dynamic_attributes: vec![],
|
||||
current_path: vec![],
|
||||
attr_paths: vec![],
|
||||
node_paths: vec![],
|
||||
};
|
||||
|
||||
let key = match self.roots.get(0) {
|
||||
Some(BodyNode::Element(el)) if self.roots.len() == 1 => el.key.clone(),
|
||||
Some(BodyNode::Component(comp)) if self.roots.len() == 1 => comp.key().cloned(),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let key_tokens = match key {
|
||||
Some(tok) => quote! { Some( __cx.raw_text(#tok) ) },
|
||||
None => quote! { None },
|
||||
};
|
||||
|
||||
let spndbg = format!("{:?}", self.roots[0].span());
|
||||
let root_col = spndbg[9..].split("..").next().unwrap();
|
||||
|
||||
let root_printer = self.roots.iter().enumerate().map(|(idx, root)| {
|
||||
context.current_path.push(idx as u8);
|
||||
let out = context.render_static_node(root);
|
||||
context.current_path.pop();
|
||||
out
|
||||
});
|
||||
|
||||
// Render and release the mutable borrow on context
|
||||
let num_roots = self.roots.len();
|
||||
let roots = quote! { #( #root_printer ),* };
|
||||
let node_printer = &context.dynamic_nodes;
|
||||
let dyn_attr_printer = &context.dynamic_attributes;
|
||||
let node_paths = context.node_paths.iter().map(|it| quote!(&[#(#it),*]));
|
||||
let attr_paths = context.attr_paths.iter().map(|it| quote!(&[#(#it),*]));
|
||||
|
||||
out_tokens.append_all(quote! {
|
||||
static TEMPLATE: ::dioxus::core::Template = ::dioxus::core::Template {
|
||||
name: concat!(
|
||||
file!(),
|
||||
":",
|
||||
line!(),
|
||||
":",
|
||||
column!(),
|
||||
":",
|
||||
#root_col
|
||||
),
|
||||
roots: &[ #roots ],
|
||||
node_paths: &[ #(#node_paths),* ],
|
||||
attr_paths: &[ #(#attr_paths),* ],
|
||||
};
|
||||
::dioxus::core::VNode {
|
||||
parent: None,
|
||||
key: #key_tokens,
|
||||
template: TEMPLATE,
|
||||
root_ids: std::cell::Cell::from_mut( __cx.bump().alloc([None; #num_roots]) as &mut _).as_slice_of_cells(),
|
||||
// root_ids: std::cell::Cell::from_mut( __cx.bump().alloc([None; #num_roots]) as &mut [::dioxus::core::ElementId]).as_slice_of_cells(),
|
||||
dynamic_nodes: __cx.bump().alloc([ #( #node_printer ),* ]),
|
||||
dynamic_attrs: __cx.bump().alloc([ #( #dyn_attr_printer ),* ]),
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
// As we print out the dynamic nodes, we want to keep track of them in a linear fashion
|
||||
// We'll use the size of the vecs to determine the index of the dynamic node in the final
|
||||
pub struct DynamicContext<'a> {
|
||||
dynamic_nodes: Vec<&'a BodyNode>,
|
||||
dynamic_attributes: Vec<&'a ElementAttrNamed>,
|
||||
current_path: Vec<u8>,
|
||||
|
||||
node_paths: Vec<Vec<u8>>,
|
||||
attr_paths: Vec<Vec<u8>>,
|
||||
}
|
||||
|
||||
impl<'a> DynamicContext<'a> {
|
||||
fn render_static_node(&mut self, root: &'a BodyNode) -> TokenStream2 {
|
||||
match root {
|
||||
BodyNode::Element(el) => {
|
||||
let el_name = &el.name;
|
||||
|
||||
// dynamic attributes
|
||||
// [0]
|
||||
// [0, 1]
|
||||
// [0, 1]
|
||||
// [0, 1]
|
||||
// [0, 1, 2]
|
||||
// [0, 2]
|
||||
// [0, 2, 1]
|
||||
|
||||
let static_attrs = el.attributes.iter().map(|attr| match &attr.attr {
|
||||
ElementAttr::AttrText { name, value } if value.is_static() => {
|
||||
let value = value.to_static().unwrap();
|
||||
quote! {
|
||||
::dioxus::core::TemplateAttribute::Static {
|
||||
name: dioxus_elements::#el_name::#name.0,
|
||||
namespace: dioxus_elements::#el_name::#name.1,
|
||||
value: #value,
|
||||
|
||||
// todo: we don't diff these so we never apply the volatile flag
|
||||
// volatile: dioxus_elements::#el_name::#name.2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ElementAttr::CustomAttrText { name, value } if value.is_static() => {
|
||||
let value = value.to_static().unwrap();
|
||||
quote! {
|
||||
::dioxus::core::TemplateAttribute::Static {
|
||||
name: #name,
|
||||
namespace: None,
|
||||
value: #value,
|
||||
|
||||
// todo: we don't diff these so we never apply the volatile flag
|
||||
// volatile: dioxus_elements::#el_name::#name.2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ElementAttr::AttrExpression { .. }
|
||||
| ElementAttr::AttrText { .. }
|
||||
| ElementAttr::CustomAttrText { .. }
|
||||
| ElementAttr::CustomAttrExpression { .. }
|
||||
| ElementAttr::EventTokens { .. } => {
|
||||
let ct = self.dynamic_attributes.len();
|
||||
self.dynamic_attributes.push(attr);
|
||||
self.attr_paths.push(self.current_path.clone());
|
||||
quote! { ::dioxus::core::TemplateAttribute::Dynamic { id: #ct } }
|
||||
}
|
||||
});
|
||||
|
||||
let attrs = quote! { #(#static_attrs),*};
|
||||
|
||||
let children = el.children.iter().enumerate().map(|(idx, root)| {
|
||||
self.current_path.push(idx as u8);
|
||||
let out = self.render_static_node(root);
|
||||
self.current_path.pop();
|
||||
out
|
||||
});
|
||||
|
||||
let _opt = el.children.len() == 1;
|
||||
let children = quote! { #(#children),* };
|
||||
|
||||
quote! {
|
||||
::dioxus::core::TemplateNode::Element {
|
||||
tag: dioxus_elements::#el_name::TAG_NAME,
|
||||
namespace: dioxus_elements::#el_name::NAME_SPACE,
|
||||
attrs: &[ #attrs ],
|
||||
children: &[ #children ],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BodyNode::Text(text) if text.is_static() => {
|
||||
let text = text.to_static().unwrap();
|
||||
quote! { ::dioxus::core::TemplateNode::Text{ text: #text } }
|
||||
}
|
||||
|
||||
BodyNode::RawExpr(_)
|
||||
| BodyNode::Text(_)
|
||||
| BodyNode::ForLoop(_)
|
||||
| BodyNode::IfChain(_)
|
||||
| BodyNode::Component(_) => {
|
||||
let ct = self.dynamic_nodes.len();
|
||||
self.dynamic_nodes.push(root);
|
||||
self.node_paths.push(self.current_path.clone());
|
||||
|
||||
match root {
|
||||
BodyNode::Text(_) => {
|
||||
quote! { ::dioxus::core::TemplateNode::DynamicText { id: #ct } }
|
||||
}
|
||||
_ => quote! { ::dioxus::core::TemplateNode::Dynamic { id: #ct } },
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user