Merge pull request #764 from DioxusLabs/jk/autofmt-loops-and-if

feat: allow ifchains and for loops in autofmt
This commit is contained in:
Jon Kelley authored and GitHub committed 2023-01-13 11:56:55 -08:00
commit fdf72b709a
6 files changed
+82 -29

No files matched your search

+2 -2
View File
@@ -365,8 +365,8 @@ impl Writer {
Some(len) => total_count += len, Some(len) => total_count += len,
None => return None, None => return None,
}, },
BodyNode::ForLoop(_) => todo!(), BodyNode::ForLoop(_forloop) => return None,
BodyNode::IfChain(_) => todo!(), BodyNode::IfChain(_chain) => return None,
} }
} }
+3 -3
View File
@@ -1,16 +1,16 @@
//! pretty printer for rsx! //! pretty printer for rsx!
use std::fmt::{Result, Write}; use std::fmt::{Result, Write};
use proc_macro2::Span;
use crate::Writer; use crate::Writer;
impl 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. We want to normalize the expr to the appropriate indent level.
*/ */
use syn::spanned::Spanned;
let placement = exp.span();
let start = placement.start(); let start = placement.start();
let end = placement.end(); let end = placement.end();
+31 -4
View File
@@ -1,10 +1,11 @@
use dioxus_rsx::{BodyNode, ElementAttr, ElementAttrNamed}; use dioxus_rsx::{BodyNode, ElementAttr, ElementAttrNamed, ForLoop};
use proc_macro2::{LineColumn, Span}; use proc_macro2::{LineColumn, Span};
use quote::ToTokens;
use std::{ use std::{
collections::{HashMap, VecDeque}, collections::{HashMap, VecDeque},
fmt::{Result, Write}, fmt::{Result, Write},
}; };
use syn::{spanned::Spanned, Expr}; use syn::{spanned::Spanned, Expr, ExprIf};
use crate::buffer::Buffer; use crate::buffer::Buffer;
@@ -37,8 +38,9 @@ impl Writer {
BodyNode::Element(el) => self.write_element(el), BodyNode::Element(el) => self.write_element(el),
BodyNode::Component(component) => self.write_component(component), BodyNode::Component(component) => self.write_component(component),
BodyNode::Text(text) => self.out.write_text(text), BodyNode::Text(text) => self.out.write_text(text),
BodyNode::RawExpr(exp) => self.write_raw_expr(exp), BodyNode::RawExpr(exp) => self.write_raw_expr(exp.span()),
_ => Ok(()), 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)) .or_insert_with(|| prettyplease::unparse_expr(expr))
.as_str() .as_str()
} }
fn write_for_loop(&mut self, forloop: &ForLoop) -> std::fmt::Result {
write!(
self.out,
"for {} in {} {{",
forloop.pat.clone().into_token_stream(),
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 { trait SpanLength {
+2 -1
View File
@@ -34,5 +34,6 @@ twoway![
commentshard, commentshard,
emoji, emoji,
messy_indent, messy_indent,
long_exprs long_exprs,
ifchain_forloop
]; ];
@@ -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
View File
@@ -95,25 +95,7 @@ impl Parse for BodyNode {
// Transform for loops into into_iter calls // Transform for loops into into_iter calls
if stream.peek(Token![for]) { if stream.peek(Token![for]) {
let _f = stream.parse::<Token![for]>()?; return Ok(BodyNode::ForLoop(stream.parse()?));
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,
}));
} }
// Transform unterminated if statements into terminated optional if statements // Transform unterminated if statements into terminated optional if statements
@@ -221,6 +203,36 @@ pub struct ForLoop {
pub in_token: Token![in], pub in_token: Token![in],
pub expr: Box<Expr>, pub expr: Box<Expr>,
pub body: Vec<BodyNode>, 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 { fn is_if_chain_terminated(chain: &ExprIf) -> bool {