Просмотр исходного кода

feat: allow ifchains and for loops

Jonathan Kelley 2 лет назад
Родитель
Сommit
6cd87796f2

+ 2 - 2
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,
                     }
                 }
 

+ 3 - 3
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();
 

+ 31 - 4
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 {

+ 2 - 1
packages/autofmt/tests/samples.rs

@@ -34,5 +34,6 @@ twoway![
     commentshard,
     emoji,
     messy_indent,
-    long_exprs
+    long_exprs,
+    ifchain_forloop
 ];

+ 13 - 0
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 {} }
+    }
+}

+ 31 - 19
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::<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 {