mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-10 14:44:12 +00:00
feat: allow ifchains and for loops
This commit is contained in:
parent
2dd2d7fe66
commit
6cd87796f2
6 changed files with 82 additions and 29 deletions
|
@ -365,8 +365,8 @@ impl Writer {
|
|||
Some(len) => total_count += len,
|
||||
None => return None,
|
||||
},
|
||||
BodyNode::ForLoop(_) => todo!(),
|
||||
BodyNode::IfChain(_) => todo!(),
|
||||
BodyNode::ForLoop(_forloop) => return None,
|
||||
BodyNode::IfChain(_chain) => return None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
//! pretty printer for rsx!
|
||||
use std::fmt::{Result, Write};
|
||||
|
||||
use proc_macro2::Span;
|
||||
|
||||
use crate::Writer;
|
||||
|
||||
impl Writer {
|
||||
pub fn write_raw_expr(&mut self, exp: &syn::Expr) -> Result {
|
||||
pub fn write_raw_expr(&mut self, placement: Span) -> Result {
|
||||
/*
|
||||
We want to normalize the expr to the appropriate indent level.
|
||||
*/
|
||||
|
||||
use syn::spanned::Spanned;
|
||||
let placement = exp.span();
|
||||
let start = placement.start();
|
||||
let end = placement.end();
|
||||
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
use dioxus_rsx::{BodyNode, ElementAttr, ElementAttrNamed};
|
||||
use dioxus_rsx::{BodyNode, ElementAttr, ElementAttrNamed, ForLoop};
|
||||
use proc_macro2::{LineColumn, Span};
|
||||
use quote::ToTokens;
|
||||
use std::{
|
||||
collections::{HashMap, VecDeque},
|
||||
fmt::{Result, Write},
|
||||
};
|
||||
use syn::{spanned::Spanned, Expr};
|
||||
use syn::{spanned::Spanned, Expr, ExprIf};
|
||||
|
||||
use crate::buffer::Buffer;
|
||||
|
||||
|
@ -37,8 +38,9 @@ impl Writer {
|
|||
BodyNode::Element(el) => self.write_element(el),
|
||||
BodyNode::Component(component) => self.write_component(component),
|
||||
BodyNode::Text(text) => self.out.write_text(text),
|
||||
BodyNode::RawExpr(exp) => self.write_raw_expr(exp),
|
||||
_ => Ok(()),
|
||||
BodyNode::RawExpr(exp) => self.write_raw_expr(exp.span()),
|
||||
BodyNode::ForLoop(forloop) => self.write_for_loop(forloop),
|
||||
BodyNode::IfChain(ifchain) => self.write_if_chain(ifchain),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -176,6 +178,31 @@ impl Writer {
|
|||
.or_insert_with(|| prettyplease::unparse_expr(expr))
|
||||
.as_str()
|
||||
}
|
||||
|
||||
fn write_for_loop(&mut self, forloop: &ForLoop) -> std::fmt::Result {
|
||||
write!(
|
||||
self.out,
|
||||
"for {} in {} {{",
|
||||
forloop.pat.clone().into_token_stream().to_string(),
|
||||
prettyplease::unparse_expr(&forloop.expr)
|
||||
)?;
|
||||
|
||||
if forloop.body.is_empty() {
|
||||
write!(self.out, "}}")?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
self.write_body_indented(&forloop.body)?;
|
||||
|
||||
self.out.tabbed_line()?;
|
||||
write!(self.out, "}}")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_if_chain(&mut self, ifchain: &ExprIf) -> std::fmt::Result {
|
||||
self.write_raw_expr(ifchain.span())
|
||||
}
|
||||
}
|
||||
|
||||
trait SpanLength {
|
||||
|
|
|
@ -34,5 +34,6 @@ twoway![
|
|||
commentshard,
|
||||
emoji,
|
||||
messy_indent,
|
||||
long_exprs
|
||||
long_exprs,
|
||||
ifchain_forloop
|
||||
];
|
||||
|
|
13
packages/autofmt/tests/samples/ifchain_forloop.rsx
Normal file
13
packages/autofmt/tests/samples/ifchain_forloop.rsx
Normal file
|
@ -0,0 +1,13 @@
|
|||
rsx! {
|
||||
// Does this work?
|
||||
for i in b {
|
||||
// Hey it works?
|
||||
div {}
|
||||
}
|
||||
|
||||
// Some ifchain
|
||||
if a > 10 {
|
||||
//
|
||||
rsx! { div {} }
|
||||
}
|
||||
}
|
|
@ -95,25 +95,7 @@ impl Parse for BodyNode {
|
|||
|
||||
// Transform for loops into into_iter calls
|
||||
if stream.peek(Token![for]) {
|
||||
let _f = stream.parse::<Token![for]>()?;
|
||||
let pat = stream.parse::<Pat>()?;
|
||||
let _i = stream.parse::<Token![in]>()?;
|
||||
let expr = stream.parse::<Box<Expr>>()?;
|
||||
|
||||
let body;
|
||||
braced!(body in stream);
|
||||
let mut children = vec![];
|
||||
while !body.is_empty() {
|
||||
children.push(body.parse()?);
|
||||
}
|
||||
|
||||
return Ok(BodyNode::ForLoop(ForLoop {
|
||||
for_token: _f,
|
||||
pat,
|
||||
in_token: _i,
|
||||
expr,
|
||||
body: children,
|
||||
}));
|
||||
return Ok(BodyNode::ForLoop(stream.parse()?));
|
||||
}
|
||||
|
||||
// Transform unterminated if statements into terminated optional if statements
|
||||
|
@ -221,6 +203,36 @@ pub struct ForLoop {
|
|||
pub in_token: Token![in],
|
||||
pub expr: Box<Expr>,
|
||||
pub body: Vec<BodyNode>,
|
||||
pub brace_token: token::Brace,
|
||||
}
|
||||
|
||||
impl Parse for ForLoop {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let for_token: Token![for] = input.parse()?;
|
||||
|
||||
let pat = input.parse()?;
|
||||
|
||||
let in_token: Token![in] = input.parse()?;
|
||||
let expr: Expr = input.call(Expr::parse_without_eager_brace)?;
|
||||
|
||||
let content;
|
||||
let brace_token = braced!(content in input);
|
||||
|
||||
let mut children = vec![];
|
||||
|
||||
while !content.is_empty() {
|
||||
children.push(content.parse()?);
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
for_token,
|
||||
pat,
|
||||
in_token,
|
||||
body: children,
|
||||
expr: Box::new(expr),
|
||||
brace_token,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn is_if_chain_terminated(chain: &ExprIf) -> bool {
|
||||
|
|
Loading…
Reference in a new issue