Improved rsx parsing
This commit is contained in:
+1
-8
@@ -33,15 +33,8 @@ fn emit_deps_vec(deps: &[Dep]) -> TokenStream {
|
|||||||
let deps = deps.iter().map(|d| {
|
let deps = deps.iter().map(|d| {
|
||||||
let ident = &d.ident;
|
let ident = &d.ident;
|
||||||
|
|
||||||
if let Some(pat) = &d.pat {
|
|
||||||
quote! {{
|
|
||||||
let #pat = #ident.clone();
|
|
||||||
Box::new(#pat) as Box<dyn HookDependency>
|
|
||||||
}}
|
|
||||||
} else {
|
|
||||||
quote! {
|
quote! {
|
||||||
Box::new(#ident.clone()) as Box<dyn HookDependency>
|
std::sync::Arc::new(#ident) as std::sync::Arc<dyn HookDependency>
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+31
-32
@@ -1,4 +1,5 @@
|
|||||||
use syn::braced;
|
use syn::braced;
|
||||||
|
use syn::parse::discouraged::Speculative;
|
||||||
use syn::{
|
use syn::{
|
||||||
Expr, Ident, LitStr, Pat, Path, Result, Token,
|
Expr, Ident, LitStr, Pat, Path, Result, Token,
|
||||||
parse::{Parse, ParseStream},
|
parse::{Parse, ParseStream},
|
||||||
@@ -82,7 +83,7 @@ fn parse_deps(input: ParseStream) -> Result<Vec<Dep>> {
|
|||||||
|
|
||||||
impl Parse for RsxNode {
|
impl Parse for RsxNode {
|
||||||
fn parse(input: ParseStream) -> Result<Self> {
|
fn parse(input: ParseStream) -> Result<Self> {
|
||||||
// --- @{ expr } ---
|
// @{ $expr }
|
||||||
if input.peek(Token![@]) {
|
if input.peek(Token![@]) {
|
||||||
input.parse::<Token![@]>()?;
|
input.parse::<Token![@]>()?;
|
||||||
|
|
||||||
@@ -93,7 +94,7 @@ impl Parse for RsxNode {
|
|||||||
return Ok(RsxNode::Expr(expr));
|
return Ok(RsxNode::Expr(expr));
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- existing code ---
|
// !$ident
|
||||||
if input.peek(Token![!]) {
|
if input.peek(Token![!]) {
|
||||||
input.parse::<Token![!]>()?;
|
input.parse::<Token![!]>()?;
|
||||||
let mount: Ident = input.parse()?;
|
let mount: Ident = input.parse()?;
|
||||||
@@ -102,6 +103,7 @@ impl Parse for RsxNode {
|
|||||||
|
|
||||||
let deps = parse_deps(input)?;
|
let deps = parse_deps(input)?;
|
||||||
|
|
||||||
|
// %$dep if $expr { $rsx }
|
||||||
if input.peek(Token![if]) {
|
if input.peek(Token![if]) {
|
||||||
input.parse::<Token![if]>()?;
|
input.parse::<Token![if]>()?;
|
||||||
let cond: Expr = input.parse()?;
|
let cond: Expr = input.parse()?;
|
||||||
@@ -115,6 +117,7 @@ impl Parse for RsxNode {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// %$dep for $pat in $expr { $rsx }
|
||||||
if input.peek(Token![for]) {
|
if input.peek(Token![for]) {
|
||||||
input.parse::<Token![for]>()?;
|
input.parse::<Token![for]>()?;
|
||||||
let pat: Pat = Pat::parse_multi(input)?;
|
let pat: Pat = Pat::parse_multi(input)?;
|
||||||
@@ -131,6 +134,7 @@ impl Parse for RsxNode {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// "%$dep for $pat in $expr { $rsx }"
|
||||||
if input.peek(LitStr) {
|
if input.peek(LitStr) {
|
||||||
return Ok(RsxNode::Text(input.parse()?));
|
return Ok(RsxNode::Text(input.parse()?));
|
||||||
}
|
}
|
||||||
@@ -163,49 +167,44 @@ fn parse_component_invocation(input: ParseStream) -> Result<RsxNode> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses comma-separated "ident: expr" (props) and RsxNode (children) inside braces.
|
|
||||||
fn parse_props_and_children(input: ParseStream) -> Result<(Vec<RsxProp>, Vec<RsxNode>)> {
|
fn parse_props_and_children(input: ParseStream) -> Result<(Vec<RsxProp>, Vec<RsxNode>)> {
|
||||||
|
Ok((parse_props(input)?, RsxRoot::parse(input)?.nodes))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_props(input: ParseStream) -> Result<Vec<RsxProp>> {
|
||||||
let mut props = Vec::new();
|
let mut props = Vec::new();
|
||||||
let mut children = Vec::new();
|
|
||||||
|
|
||||||
while !input.is_empty() {
|
while !input.is_empty() {
|
||||||
if input.peek(LitStr) {
|
let fork = input.fork();
|
||||||
children.push(input.parse()?);
|
|
||||||
} else {
|
|
||||||
let path: Path = input.parse()?;
|
|
||||||
|
|
||||||
if input.peek(Token![:]) {
|
let path: Path = match fork.parse() {
|
||||||
|
Ok(p) => p,
|
||||||
|
Err(_) => break,
|
||||||
|
};
|
||||||
|
|
||||||
|
if fork.peek(Token![:]) {
|
||||||
let name = path
|
let name = path
|
||||||
.get_ident()
|
.get_ident()
|
||||||
.cloned()
|
.cloned()
|
||||||
.ok_or_else(|| input.error("prop name must be a single identifier"))?;
|
.ok_or_else(|| fork.error("prop name must be a single identifier"))?;
|
||||||
input.parse::<Token![:]>()?;
|
|
||||||
let value: Expr = input.parse()?;
|
|
||||||
props.push(RsxProp { name, value });
|
|
||||||
} else if input.peek(Brace) {
|
|
||||||
let nested_content;
|
|
||||||
braced!(nested_content in input);
|
|
||||||
let (nested_props, nested_children) = parse_props_and_children(&nested_content)?;
|
|
||||||
children.push(RsxNode::Component {
|
|
||||||
path,
|
|
||||||
props: nested_props,
|
|
||||||
children: nested_children,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
children.push(RsxNode::Component {
|
|
||||||
path,
|
|
||||||
props: Vec::new(),
|
|
||||||
children: Vec::new(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !input.is_empty() {
|
fork.parse::<Token![:]>()?;
|
||||||
|
let value: Expr = fork.parse()?;
|
||||||
|
|
||||||
|
input.advance_to(&fork);
|
||||||
|
|
||||||
|
props.push(RsxProp { name, value });
|
||||||
|
|
||||||
|
if input.peek(Token![,]) {
|
||||||
input.parse::<Token![,]>()?;
|
input.parse::<Token![,]>()?;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// ❌ do not commit → nothing consumed
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((props, children))
|
Ok(props)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_children(input: ParseStream) -> Result<Vec<RsxNode>> {
|
fn parse_children(input: ParseStream) -> Result<Vec<RsxNode>> {
|
||||||
|
|||||||
Reference in New Issue
Block a user