|
@@ -7,6 +7,7 @@ use syn::{parse2, parse_str, Expr};
|
|
|
use crate::attributes::attrbute_to_static_str;
|
|
|
use crate::captuered_context::{CapturedContext, IfmtArgs};
|
|
|
use crate::elements::element_to_static_str;
|
|
|
+use crate::error::{Error, RecompileReason};
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
enum Segment {
|
|
@@ -88,25 +89,25 @@ pub fn build<'a>(
|
|
|
rsx: CallBody,
|
|
|
mut ctx: CapturedContext<'a>,
|
|
|
factory: &NodeFactory<'a>,
|
|
|
-) -> VNode<'a> {
|
|
|
+) -> Result<VNode<'a>, Error> {
|
|
|
let children_built = factory.bump().alloc(Vec::new());
|
|
|
for child in rsx.roots {
|
|
|
- children_built.push(build_node(child, &mut ctx, factory));
|
|
|
+ children_built.push(build_node(child, &mut ctx, factory)?);
|
|
|
}
|
|
|
- factory.fragment_from_iter(children_built.iter())
|
|
|
+ Ok(factory.fragment_from_iter(children_built.iter()))
|
|
|
}
|
|
|
|
|
|
fn build_node<'a>(
|
|
|
node: BodyNode,
|
|
|
ctx: &mut CapturedContext<'a>,
|
|
|
factory: &NodeFactory<'a>,
|
|
|
-) -> Option<VNode<'a>> {
|
|
|
+) -> Result<VNode<'a>, Error> {
|
|
|
let bump = factory.bump();
|
|
|
match node {
|
|
|
BodyNode::Text(text) => {
|
|
|
let ifmt: InterperedIfmt = text.value().parse().unwrap();
|
|
|
let text = bump.alloc(ifmt.resolve(&ctx.captured));
|
|
|
- Some(factory.text(format_args!("{}", text)))
|
|
|
+ Ok(factory.text(format_args!("{}", text)))
|
|
|
}
|
|
|
BodyNode::Element(el) => {
|
|
|
let attributes: &mut Vec<Attribute> = bump.alloc(Vec::new());
|
|
@@ -132,8 +133,6 @@ fn build_node<'a>(
|
|
|
is_volatile: false,
|
|
|
namespace,
|
|
|
});
|
|
|
- } else {
|
|
|
- return None;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -165,7 +164,11 @@ fn build_node<'a>(
|
|
|
});
|
|
|
}
|
|
|
} else {
|
|
|
- panic!("could not resolve expression {:?}", value);
|
|
|
+ return Err(Error::RecompileRequiredError(
|
|
|
+ RecompileReason::CapturedExpression(
|
|
|
+ value.into_token_stream().to_string(),
|
|
|
+ ),
|
|
|
+ ));
|
|
|
}
|
|
|
}
|
|
|
_ => (),
|
|
@@ -174,7 +177,7 @@ fn build_node<'a>(
|
|
|
let children = bump.alloc(Vec::new());
|
|
|
for child in el.children {
|
|
|
let node = build_node(child, ctx, factory);
|
|
|
- if let Some(node) = node {
|
|
|
+ if let Ok(node) = node {
|
|
|
children.push(node);
|
|
|
}
|
|
|
}
|
|
@@ -182,20 +185,23 @@ fn build_node<'a>(
|
|
|
for attr in el.attributes {
|
|
|
match attr.attr {
|
|
|
ElementAttr::EventTokens { .. } => {
|
|
|
- let expr: Expr = parse2(attr.to_token_stream()).unwrap();
|
|
|
- if let Some(idx) = ctx
|
|
|
- .listeners
|
|
|
- .iter()
|
|
|
- .position(|(code, _)| parse_str::<Expr>(*code).unwrap() == expr)
|
|
|
- {
|
|
|
+ let expr: Expr =
|
|
|
+ parse2(attr.to_token_stream()).map_err(|err| Error::ParseError(err))?;
|
|
|
+ if let Some(idx) = ctx.listeners.iter().position(|(code, _)| {
|
|
|
+ if let Ok(parsed) = parse_str::<Expr>(*code) {
|
|
|
+ parsed == expr
|
|
|
+ } else {
|
|
|
+ false
|
|
|
+ }
|
|
|
+ }) {
|
|
|
let (_, listener) = ctx.listeners.remove(idx);
|
|
|
listeners.push(listener)
|
|
|
} else {
|
|
|
- panic!(
|
|
|
- "could not resolve listener {:?} \n in: {:#?}",
|
|
|
- expr.to_token_stream().to_string(),
|
|
|
- ctx.listeners.iter().map(|(s, _)| s).collect::<Vec<_>>()
|
|
|
- );
|
|
|
+ return Err(Error::RecompileRequiredError(
|
|
|
+ RecompileReason::CapturedListener(
|
|
|
+ expr.to_token_stream().to_string(),
|
|
|
+ ),
|
|
|
+ ));
|
|
|
}
|
|
|
}
|
|
|
_ => (),
|
|
@@ -204,7 +210,7 @@ fn build_node<'a>(
|
|
|
let tag = bump.alloc(el.name.to_string());
|
|
|
if let Some((tag, ns)) = element_to_static_str(tag) {
|
|
|
match el.key {
|
|
|
- None => Some(factory.raw_element(
|
|
|
+ None => Ok(factory.raw_element(
|
|
|
tag,
|
|
|
ns,
|
|
|
listeners,
|
|
@@ -216,7 +222,7 @@ fn build_node<'a>(
|
|
|
let ifmt: InterperedIfmt = lit.value().parse().unwrap();
|
|
|
let key = bump.alloc(ifmt.resolve(&ctx.captured));
|
|
|
|
|
|
- Some(factory.raw_element(
|
|
|
+ Ok(factory.raw_element(
|
|
|
tag,
|
|
|
ns,
|
|
|
listeners,
|
|
@@ -227,36 +233,44 @@ fn build_node<'a>(
|
|
|
}
|
|
|
}
|
|
|
} else {
|
|
|
- None
|
|
|
+ Err(Error::ParseError(syn::Error::new(
|
|
|
+ el.name.span(),
|
|
|
+ "unknown element",
|
|
|
+ )))
|
|
|
}
|
|
|
}
|
|
|
BodyNode::Component(comp) => {
|
|
|
- let expr: Expr = parse2(comp.to_token_stream()).unwrap();
|
|
|
- if let Some(idx) = ctx
|
|
|
- .components
|
|
|
- .iter()
|
|
|
- .position(|(code, _)| parse_str::<Expr>(*code).unwrap() == expr)
|
|
|
- {
|
|
|
+ let expr: Expr =
|
|
|
+ parse2(comp.to_token_stream()).map_err(|err| Error::ParseError(err))?;
|
|
|
+ if let Some(idx) = ctx.components.iter().position(|(code, _)| {
|
|
|
+ if let Ok(parsed) = parse_str::<Expr>(*code) {
|
|
|
+ parsed == expr
|
|
|
+ } else {
|
|
|
+ false
|
|
|
+ }
|
|
|
+ }) {
|
|
|
let (_, vnode) = ctx.components.remove(idx);
|
|
|
- Some(vnode)
|
|
|
+ Ok(vnode)
|
|
|
} else {
|
|
|
- panic!("could not resolve component {:?}", comp.name);
|
|
|
+ Err(Error::RecompileRequiredError(
|
|
|
+ RecompileReason::CapturedComponent(comp.name.to_token_stream().to_string()),
|
|
|
+ ))
|
|
|
}
|
|
|
}
|
|
|
BodyNode::RawExpr(iterator) => {
|
|
|
- if let Some(idx) = ctx
|
|
|
- .iterators
|
|
|
- .iter()
|
|
|
- .position(|(code, _)| parse_str::<Expr>(*code).unwrap() == iterator)
|
|
|
- {
|
|
|
+ if let Some(idx) = ctx.iterators.iter().position(|(code, _)| {
|
|
|
+ if let Ok(parsed) = parse_str::<Expr>(*code) {
|
|
|
+ parsed == iterator
|
|
|
+ } else {
|
|
|
+ false
|
|
|
+ }
|
|
|
+ }) {
|
|
|
let (_, vnode) = ctx.iterators.remove(idx);
|
|
|
- Some(vnode)
|
|
|
+ Ok(vnode)
|
|
|
} else {
|
|
|
- panic!(
|
|
|
- "could not resolve iterator {} \n fron {:?}",
|
|
|
- iterator.to_token_stream(),
|
|
|
- ctx.iterators.iter().map(|(s, _)| s).collect::<Vec<_>>()
|
|
|
- );
|
|
|
+ Err(Error::RecompileRequiredError(
|
|
|
+ RecompileReason::CapturedExpression(iterator.to_token_stream().to_string()),
|
|
|
+ ))
|
|
|
}
|
|
|
}
|
|
|
}
|