diff --git a/packages/autofmt/src/element.rs b/packages/autofmt/src/element.rs index f96969845..b9903dc47 100644 --- a/packages/autofmt/src/element.rs +++ b/packages/autofmt/src/element.rs @@ -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, } } diff --git a/packages/autofmt/src/expr.rs b/packages/autofmt/src/expr.rs index 55a5fa9eb..4a916c71a 100644 --- a/packages/autofmt/src/expr.rs +++ b/packages/autofmt/src/expr.rs @@ -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(); diff --git a/packages/autofmt/src/writer.rs b/packages/autofmt/src/writer.rs index 4d4aed4a3..cba6d4ec4 100644 --- a/packages/autofmt/src/writer.rs +++ b/packages/autofmt/src/writer.rs @@ -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 { diff --git a/packages/autofmt/tests/samples.rs b/packages/autofmt/tests/samples.rs index 9042a7f1a..26492e141 100644 --- a/packages/autofmt/tests/samples.rs +++ b/packages/autofmt/tests/samples.rs @@ -34,5 +34,6 @@ twoway![ commentshard, emoji, messy_indent, - long_exprs + long_exprs, + ifchain_forloop ]; diff --git a/packages/autofmt/tests/samples/ifchain_forloop.rsx b/packages/autofmt/tests/samples/ifchain_forloop.rsx new file mode 100644 index 000000000..9ec7326af --- /dev/null +++ b/packages/autofmt/tests/samples/ifchain_forloop.rsx @@ -0,0 +1,13 @@ +rsx! { + // Does this work? + for i in b { + // Hey it works? + div {} + } + + // Some ifchain + if a > 10 { + // + rsx! { div {} } + } +} diff --git a/packages/rsx/src/node.rs b/packages/rsx/src/node.rs index ef76d14ff..0d5556552 100644 --- a/packages/rsx/src/node.rs +++ b/packages/rsx/src/node.rs @@ -95,25 +95,7 @@ impl Parse for BodyNode { // Transform for loops into into_iter calls if stream.peek(Token![for]) { - let _f = stream.parse::()?; - let pat = stream.parse::()?; - let _i = stream.parse::()?; - let expr = stream.parse::>()?; - - 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, pub body: Vec, + pub brace_token: token::Brace, +} + +impl Parse for ForLoop { + fn parse(input: ParseStream) -> Result { + 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 {