From d9e0b9a918622edef7fae6bf66090a81e9cd93a7 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Fri, 2 Jun 2023 12:03:56 -0500 Subject: [PATCH] fix autoformatting raw strings --- packages/autofmt/src/buffer.rs | 4 +- packages/autofmt/src/component.rs | 8 ++-- packages/autofmt/src/element.rs | 29 +++++--------- packages/autofmt/src/lib.rs | 28 +++++++++++-- packages/autofmt/src/writer.rs | 7 ++-- packages/autofmt/tests/samples.rs | 40 ++++++++++--------- packages/autofmt/tests/samples/complex.rsx | 4 +- .../autofmt/tests/samples/raw_strings.rsx | 12 ++++++ packages/autofmt/tests/wrong.rs | 5 +++ 9 files changed, 89 insertions(+), 48 deletions(-) create mode 100644 packages/autofmt/tests/samples/raw_strings.rsx diff --git a/packages/autofmt/src/buffer.rs b/packages/autofmt/src/buffer.rs index 26c47f54b..fea5a4a3f 100644 --- a/packages/autofmt/src/buffer.rs +++ b/packages/autofmt/src/buffer.rs @@ -8,6 +8,8 @@ use std::fmt::{Result, Write}; use dioxus_rsx::IfmtInput; +use crate::write_ifmt; + /// The output buffer that tracks indent and string #[derive(Debug, Default)] pub struct Buffer { @@ -48,7 +50,7 @@ impl Buffer { } pub fn write_text(&mut self, text: &IfmtInput) -> Result { - write!(self.buf, "\"{}\"", text.source.as_ref().unwrap().value()) + write_ifmt(text, &mut self.buf) } } diff --git a/packages/autofmt/src/component.rs b/packages/autofmt/src/component.rs index 89ebe2229..d5d92b79a 100644 --- a/packages/autofmt/src/component.rs +++ b/packages/autofmt/src/component.rs @@ -1,4 +1,4 @@ -use crate::{writer::Location, Writer}; +use crate::{ifmt_to_string, writer::Location, Writer}; use dioxus_rsx::*; use quote::ToTokens; use std::fmt::{Result, Write}; @@ -170,9 +170,9 @@ impl Writer<'_> { ContentField::Formatted(s) => { write!( self.out, - "{}: \"{}\"", + "{}: {}", name, - s.source.as_ref().unwrap().value() + s.source.as_ref().unwrap().to_token_stream() )?; } ContentField::OnHandlerRaw(exp) => { @@ -215,7 +215,7 @@ impl Writer<'_> { let attr_len = fields .iter() .map(|field| match &field.content { - ContentField::Formatted(s) => s.source.as_ref().unwrap().value().len() , + ContentField::Formatted(s) => ifmt_to_string(s).len() , ContentField::OnHandlerRaw(exp) | ContentField::ManExpr(exp) => { let formatted = prettyplease::unparse_expr(exp); let len = if formatted.contains('\n') { diff --git a/packages/autofmt/src/element.rs b/packages/autofmt/src/element.rs index 5bb7d42fc..50a991897 100644 --- a/packages/autofmt/src/element.rs +++ b/packages/autofmt/src/element.rs @@ -1,6 +1,7 @@ -use crate::Writer; +use crate::{ifmt_to_string, Writer}; use dioxus_rsx::*; use proc_macro2::Span; +use quote::ToTokens; use std::{ fmt::Result, fmt::{self, Write}, @@ -175,11 +176,7 @@ impl Writer<'_> { if !sameline { self.out.indented_tabbed_line()?; } - write!( - self.out, - "key: \"{}\"", - key.source.as_ref().unwrap().value() - )?; + write!(self.out, "key: {}", ifmt_to_string(key))?; if !attributes.is_empty() { write!(self.out, ",")?; if sameline { @@ -216,11 +213,7 @@ impl Writer<'_> { fn write_attribute(&mut self, attr: &ElementAttrNamed) -> Result { match &attr.attr { ElementAttr::AttrText { name, value } => { - write!( - self.out, - "{name}: \"{value}\"", - value = value.source.as_ref().unwrap().value() - )?; + write!(self.out, "{name}: {value}", value = ifmt_to_string(value))?; } ElementAttr::AttrExpression { name, value } => { let out = prettyplease::unparse_expr(value); @@ -230,15 +223,15 @@ impl Writer<'_> { ElementAttr::CustomAttrText { name, value } => { write!( self.out, - "\"{name}\": \"{value}\"", - name = name.value(), - value = value.source.as_ref().unwrap().value() + "{name}: {value}", + name = name.to_token_stream(), + value = ifmt_to_string(value) )?; } ElementAttr::CustomAttrExpression { name, value } => { let out = prettyplease::unparse_expr(value); - write!(self.out, "\"{}\": {}", name.value(), out)?; + write!(self.out, "{}: {}", name.to_token_stream(), out)?; } ElementAttr::EventTokens { name, tokens } => { @@ -315,7 +308,7 @@ impl Writer<'_> { } match children { - [BodyNode::Text(ref text)] => Some(text.source.as_ref().unwrap().value().len()), + [BodyNode::Text(ref text)] => Some(ifmt_to_string(text).len()), [BodyNode::Component(ref comp)] => { let attr_len = self.field_len(&comp.fields, &comp.manual_props); @@ -338,7 +331,7 @@ impl Writer<'_> { if el.children.len() == 1 { if let BodyNode::Text(ref text) = el.children[0] { - let value = text.source.as_ref().unwrap().value(); + let value = ifmt_to_string(text); if value.len() + el.name.to_string().len() + attr_len < 80 { return Some(value.len() + el.name.to_string().len() + attr_len); @@ -356,7 +349,7 @@ impl Writer<'_> { match item { BodyNode::Component(_) | BodyNode::Element(_) => return None, BodyNode::Text(text) => { - total_count += text.source.as_ref().unwrap().value().len() + total_count += ifmt_to_string(text).len(); } BodyNode::RawExpr(expr) => match get_expr_length(expr) { Some(len) => total_count += len, diff --git a/packages/autofmt/src/lib.rs b/packages/autofmt/src/lib.rs index 12bf00585..0d2426a0b 100644 --- a/packages/autofmt/src/lib.rs +++ b/packages/autofmt/src/lib.rs @@ -1,7 +1,10 @@ +use std::fmt::{Display, Write}; + use crate::writer::*; use collect_macros::byte_offset; -use dioxus_rsx::{BodyNode, CallBody}; +use dioxus_rsx::{BodyNode, CallBody, IfmtInput}; use proc_macro2::LineColumn; +use quote::ToTokens; use syn::{ExprMacro, MacroDelimiter}; mod buffer; @@ -130,8 +133,6 @@ pub fn write_block_out(body: CallBody) -> Option { } fn write_body(buf: &mut Writer, body: &CallBody) { - use std::fmt::Write; - if buf.is_short_children(&body.roots).is_some() { // write all the indents with spaces and commas between for idx in 0..body.roots.len() - 1 { @@ -208,3 +209,24 @@ pub fn apply_formats(input: &str, blocks: Vec) -> String { out } + +struct DisplayIfmt<'a>(&'a IfmtInput); + +impl Display for DisplayIfmt<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let inner_tokens = self.0.source.as_ref().unwrap().to_token_stream(); + inner_tokens.fmt(f) + } +} + +pub(crate) fn ifmt_to_string(input: &IfmtInput) -> String { + let mut buf = String::new(); + let display = DisplayIfmt(input); + write!(&mut buf, "{}", display).unwrap(); + buf +} + +pub(crate) fn write_ifmt(input: &IfmtInput, writable: &mut impl Write) -> std::fmt::Result { + let display = DisplayIfmt(input); + write!(writable, "{}", display) +} diff --git a/packages/autofmt/src/writer.rs b/packages/autofmt/src/writer.rs index 6a0e38d82..59f135592 100644 --- a/packages/autofmt/src/writer.rs +++ b/packages/autofmt/src/writer.rs @@ -8,6 +8,7 @@ use std::{ use syn::{spanned::Spanned, Expr, ExprIf}; use crate::buffer::Buffer; +use crate::ifmt_to_string; #[derive(Debug)] pub struct Writer<'a> { @@ -147,16 +148,16 @@ impl<'a> Writer<'a> { total += match &attr.attr { ElementAttr::AttrText { value, name } => { - value.source.as_ref().unwrap().value().len() + name.span().line_length() + 6 + ifmt_to_string(value).len() + name.span().line_length() + 6 } ElementAttr::AttrExpression { name, value } => { value.span().line_length() + name.span().line_length() + 6 } ElementAttr::CustomAttrText { value, name } => { - value.source.as_ref().unwrap().value().len() + name.value().len() + 6 + ifmt_to_string(value).len() + name.to_token_stream().to_string().len() + 6 } ElementAttr::CustomAttrExpression { name, value } => { - name.value().len() + value.span().line_length() + 6 + name.to_token_stream().to_string().len() + value.span().line_length() + 6 } ElementAttr::EventTokens { tokens, name } => { let location = Location::new(tokens.span().start()); diff --git a/packages/autofmt/tests/samples.rs b/packages/autofmt/tests/samples.rs index 19e636926..8145b0e8e 100644 --- a/packages/autofmt/tests/samples.rs +++ b/packages/autofmt/tests/samples.rs @@ -4,8 +4,8 @@ macro_rules! twoway { // doc attrs $( #[doc = $doc:expr] )* - $name:ident - ),* + $name:ident, + )* ) => { $( $( #[doc = $doc] )* @@ -14,6 +14,9 @@ macro_rules! twoway { let src = include_str!(concat!("./samples/", stringify!($name), ".rsx")); let formatted = dioxus_autofmt::fmt_file(src); let out = dioxus_autofmt::apply_formats(src, formatted); + // normalize line endings + let out = out.replace("\r", ""); + let src = src.replace("\r", ""); pretty_assertions::assert_eq!(&src, &out); } )* @@ -21,24 +24,25 @@ macro_rules! twoway { } twoway![ - simple, - comments, attributes, - manual_props, + collapse_expr, + comments, + commentshard, complex, + emoji, + ifchain_forloop, + immediate_expr, + key, + long_exprs, + long, + manual_props, + messy_indent, + multirsx, + raw_strings, + reallylong, + simple, + t2, tiny, tinynoopt, - long, - key, - multirsx, - commentshard, - emoji, - messy_indent, - long_exprs, - ifchain_forloop, - t2, - reallylong, - immediate_expr, - collapse_expr, - trailing_expr + trailing_expr, ]; diff --git a/packages/autofmt/tests/samples/complex.rsx b/packages/autofmt/tests/samples/complex.rsx index 598d08a82..1bf29a767 100644 --- a/packages/autofmt/tests/samples/complex.rsx +++ b/packages/autofmt/tests/samples/complex.rsx @@ -13,7 +13,9 @@ rsx! { // Complex nesting with handlers li { - Link { class: "flex items-center pl-3 py-3 pr-4 {active_class} rounded", to: "{to}", + Link { + class: "flex items-center pl-3 py-3 pr-4 {active_class} rounded", + to: "{to}", span { class: "inline-block mr-3", icons::icon_0 {} } span { "{name}" } children.is_some().then(|| rsx! { diff --git a/packages/autofmt/tests/samples/raw_strings.rsx b/packages/autofmt/tests/samples/raw_strings.rsx new file mode 100644 index 000000000..8a4d0c38f --- /dev/null +++ b/packages/autofmt/tests/samples/raw_strings.rsx @@ -0,0 +1,12 @@ +rsx! { + // Raw text strings + button { r#"Click me"#, r##"Click me"##, r######"Click me"######, r#"dynamic {1}"# } + + // Raw attribute strings + div { + width: r#"10px"#, + height: r##"{10}px"##, + "raw-attr": r###"raw-attr"###, + "raw-attr2": r###"{100}"### + } +} diff --git a/packages/autofmt/tests/wrong.rs b/packages/autofmt/tests/wrong.rs index acf930b40..5a0fb8a87 100644 --- a/packages/autofmt/tests/wrong.rs +++ b/packages/autofmt/tests/wrong.rs @@ -6,6 +6,11 @@ macro_rules! twoway { let src_wrong = include_str!(concat!("./wrong/", $val, ".wrong.rsx")); let formatted = dioxus_autofmt::fmt_file(src_wrong); let out = dioxus_autofmt::apply_formats(src_wrong, formatted); + + // normalize line endings + let out = out.replace("\r", ""); + let src_right = src_right.replace("\r", ""); + pretty_assertions::assert_eq!(&src_right, &out); } };