better error handling

This commit is contained in:
Evan Almloff committed 2022-05-29 08:04:08 -05:00
1 parent 29be00e9f5
commit 2183ecf3fb
7 files changed
+174 -89

No files matched your search

+7 -4
View File
@@ -1,5 +1,5 @@
use proc_macro::TokenStream;
use quote::{quote, ToTokens};
use quote::ToTokens;
use syn::parse_macro_input;
mod inlineprops;
@@ -189,7 +189,7 @@ pub fn rsx(s: TokenStream) -> TokenStream {
use dioxus_rsx_interperter::captuered_context::CapturedContextBuilder;
let captured = CapturedContextBuilder::from_call_body(body);
quote! {
quote::quote! {
{
let __line_num = get_line_num();
let __rsx_text_index: RsxTextIndex = cx.consume_context().unwrap();
@@ -206,11 +206,14 @@ pub fn rsx(s: TokenStream) -> TokenStream {
// clone prevents deadlock on nested rsx calls
read.get(&__line_num).cloned()
} {
interpert_rsx(
match interpert_rsx(
__cx,
&__text,
#captured
)
){
Ok(vnode) => vnode,
Err(err) => __cx.text(format_args!("{:?}", err))
}
}
else {
panic!("rsx: line number {:?} not found in rsx index", __line_num);
+1 -1
View File
@@ -5,7 +5,7 @@ edition = "2021"
license = "MIT/Apache-2.0"
[dependencies]
syn = "1.0"
syn = { version = "1.0", features = ["extra-traits"] }
quote = "1.0"
dioxus-rsx = { path = "../rsx", default-features = false }
dioxus-ssr = { path = "../ssr" }
+13
View File
@@ -0,0 +1,13 @@
#[derive(Debug)]
pub enum Error {
ParseError(syn::Error),
RecompileRequiredError(RecompileReason),
}
#[derive(Debug)]
pub enum RecompileReason {
CapturedVariable(String),
CapturedExpression(String),
CapturedComponent(String),
CapturedListener(String),
}
+56 -42
View File
@@ -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()),
))
}
}
}
+8 -2
View File
@@ -1,5 +1,6 @@
use dioxus_core::{Component, Element, LazyNodes, Scope, VNode};
use dioxus_hooks::*;
use error::Error;
use interperter::build;
use std::collections::HashMap;
use std::panic::Location;
@@ -10,6 +11,7 @@ use syn::parse_str;
mod attributes;
pub mod captuered_context;
mod elements;
mod error;
mod interperter;
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
@@ -35,8 +37,12 @@ pub fn interpert_rsx<'a, 'b>(
factory: dioxus_core::NodeFactory<'a>,
text: &str,
context: captuered_context::CapturedContext<'a>,
) -> VNode<'a> {
build(parse_str(text).unwrap(), context, &factory)
) -> Result<VNode<'a>, Error> {
build(
parse_str(text).map_err(|err| Error::ParseError(err))?,
context,
&factory,
)
}
#[track_caller]