fix(autofmt): add support for handling comments in various expression types (#5461)
* fix(autofmt): add support for handling comments in various expression types * fmt
This commit is contained in:
1 parent
689e39b3f6
commit
c73dc43233
6 files changed
+164
-4
No files matched your search
@@ -712,6 +712,14 @@ impl<'a> Writer<'a> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn span_has_line_comments(&self, span: Span) -> bool {
|
||||||
|
span.source_text().is_some_and(|source| {
|
||||||
|
source
|
||||||
|
.lines()
|
||||||
|
.any(|line| line.trim_start().starts_with("//"))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn attr_value_len(&mut self, value: &AttributeValue) -> usize {
|
fn attr_value_len(&mut self, value: &AttributeValue) -> usize {
|
||||||
match value {
|
match value {
|
||||||
AttributeValue::IfExpr(if_chain) => {
|
AttributeValue::IfExpr(if_chain) => {
|
||||||
@@ -734,11 +742,23 @@ impl<'a> Writer<'a> {
|
|||||||
}
|
}
|
||||||
AttributeValue::AttrExpr(expr) => expr
|
AttributeValue::AttrExpr(expr) => expr
|
||||||
.as_expr()
|
.as_expr()
|
||||||
.map(|expr| self.attr_expr_len(&expr))
|
.map(|expr| {
|
||||||
|
if self.span_has_line_comments(expr.span()) {
|
||||||
|
100000
|
||||||
|
} else {
|
||||||
|
self.attr_expr_len(&expr)
|
||||||
|
}
|
||||||
|
})
|
||||||
.unwrap_or(100000),
|
.unwrap_or(100000),
|
||||||
AttributeValue::EventTokens(closure) => closure
|
AttributeValue::EventTokens(closure) => closure
|
||||||
.as_expr()
|
.as_expr()
|
||||||
.map(|expr| self.attr_expr_len(&expr))
|
.map(|expr| {
|
||||||
|
if self.span_has_line_comments(expr.span()) {
|
||||||
|
100000
|
||||||
|
} else {
|
||||||
|
self.attr_expr_len(&expr)
|
||||||
|
}
|
||||||
|
})
|
||||||
.unwrap_or(100000),
|
.unwrap_or(100000),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -846,6 +866,9 @@ impl<'a> Writer<'a> {
|
|||||||
|
|
||||||
let pretty = self.retrieve_formatted_expr(&expr).to_string();
|
let pretty = self.retrieve_formatted_expr(&expr).to_string();
|
||||||
let source = src_span.source_text().unwrap_or_default();
|
let source = src_span.source_text().unwrap_or_default();
|
||||||
|
let source_has_line_comments = source
|
||||||
|
.lines()
|
||||||
|
.any(|line| line.trim_start().starts_with("//"));
|
||||||
let mut src_lines = source.lines().peekable();
|
let mut src_lines = source.lines().peekable();
|
||||||
|
|
||||||
// Comments already in pretty output (from nested rsx!) - skip these from source
|
// Comments already in pretty output (from nested rsx!) - skip these from source
|
||||||
@@ -940,7 +963,9 @@ impl<'a> Writer<'a> {
|
|||||||
let is_call = src_trimmed.ends_with('(')
|
let is_call = src_trimmed.ends_with('(')
|
||||||
|| src_trimmed.ends_with(',')
|
|| src_trimmed.ends_with(',')
|
||||||
|| src_trimmed.ends_with('{');
|
|| src_trimmed.ends_with('{');
|
||||||
if !is_call {
|
let is_commented_block =
|
||||||
|
source_has_line_comments && src_trimmed.ends_with('{');
|
||||||
|
if is_commented_block || !is_call {
|
||||||
multiline = Some(vec![*src]);
|
multiline = Some(vec![*src]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1008,7 +1033,17 @@ impl<'a> Writer<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Write multi-line with adjusted indentation
|
// Write multi-line with adjusted indentation
|
||||||
let base_indent = ml[0].chars().take_while(|c| c.is_whitespace()).count();
|
let base_indent = if source_has_line_comments && ml[0].trim_end().ends_with('{')
|
||||||
|
{
|
||||||
|
ml.iter()
|
||||||
|
.skip(1)
|
||||||
|
.filter(|line| !line.trim().is_empty())
|
||||||
|
.map(|line| line.chars().take_while(|c| c.is_whitespace()).count())
|
||||||
|
.min()
|
||||||
|
.unwrap_or(0)
|
||||||
|
} else {
|
||||||
|
ml[0].chars().take_while(|c| c.is_whitespace()).count()
|
||||||
|
};
|
||||||
let target: String = line.chars().take_while(|c| c.is_whitespace()).collect();
|
let target: String = line.chars().take_while(|c| c.is_whitespace()).collect();
|
||||||
|
|
||||||
for (i, src_line) in ml.iter().enumerate() {
|
for (i, src_line) in ml.iter().enumerate() {
|
||||||
|
|||||||
@@ -28,7 +28,11 @@ twoway![
|
|||||||
attributes,
|
attributes,
|
||||||
basic_expr,
|
basic_expr,
|
||||||
collapse_expr,
|
collapse_expr,
|
||||||
|
comments_attr_expr_blocks,
|
||||||
comments,
|
comments,
|
||||||
|
comments_async_closure,
|
||||||
|
comments_expr_with_strings,
|
||||||
|
comments_nested_closures,
|
||||||
commentshard,
|
commentshard,
|
||||||
complex,
|
complex,
|
||||||
docsite,
|
docsite,
|
||||||
@@ -66,3 +70,37 @@ twoway![
|
|||||||
blank_lines_preserved,
|
blank_lines_preserved,
|
||||||
forloop_tuple,
|
forloop_tuple,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
fn assert_idempotent(src: &str) {
|
||||||
|
let src = src.replace("\r", "");
|
||||||
|
|
||||||
|
let once =
|
||||||
|
dioxus_autofmt::apply_formats(&src, dioxus_autofmt::fmt_file(&src, Default::default()))
|
||||||
|
.replace("\r", "");
|
||||||
|
let twice =
|
||||||
|
dioxus_autofmt::apply_formats(&once, dioxus_autofmt::fmt_file(&once, Default::default()))
|
||||||
|
.replace("\r", "");
|
||||||
|
|
||||||
|
pretty_assertions::assert_eq!(src, once);
|
||||||
|
pretty_assertions::assert_eq!(once, twice);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn comments_async_closure_is_idempotent() {
|
||||||
|
assert_idempotent(include_str!("./samples/comments_async_closure.rsx"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn comments_nested_closures_is_idempotent() {
|
||||||
|
assert_idempotent(include_str!("./samples/comments_nested_closures.rsx"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn comments_attr_expr_blocks_is_idempotent() {
|
||||||
|
assert_idempotent(include_str!("./samples/comments_attr_expr_blocks.rsx"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn comments_expr_with_strings_is_idempotent() {
|
||||||
|
assert_idempotent(include_str!("./samples/comments_expr_with_strings.rsx"));
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
rsx! {
|
||||||
|
button {
|
||||||
|
class: "control-button",
|
||||||
|
onclick: move |_| async move {
|
||||||
|
// comment
|
||||||
|
()
|
||||||
|
},
|
||||||
|
"print content"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
rsx! {
|
||||||
|
Component {
|
||||||
|
label: {
|
||||||
|
let url = "https://example.com";
|
||||||
|
|
||||||
|
// comment before formatted tail expr
|
||||||
|
format!("{url}/docs")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
status: {
|
||||||
|
// comment before branch
|
||||||
|
if is_ready() {
|
||||||
|
"ready"
|
||||||
|
} else {
|
||||||
|
"waiting"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
div {
|
||||||
|
data_mode: {
|
||||||
|
// comment before block expr
|
||||||
|
if is_ready() {
|
||||||
|
"ready"
|
||||||
|
} else {
|
||||||
|
"waiting"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
rsx! {
|
||||||
|
button {
|
||||||
|
onclick: move |_| async move {
|
||||||
|
let url = "https://example.com";
|
||||||
|
|
||||||
|
// keep this comment with the block, not the string literal
|
||||||
|
println!("{url}");
|
||||||
|
},
|
||||||
|
"strings"
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
message: {
|
||||||
|
let prefix = "value://";
|
||||||
|
|
||||||
|
// comment before final expression that contains //
|
||||||
|
format!("{prefix}done")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
rsx! {
|
||||||
|
button {
|
||||||
|
onclick: move |_| async move {
|
||||||
|
let nested = move || {
|
||||||
|
// nested closure comment
|
||||||
|
()
|
||||||
|
};
|
||||||
|
|
||||||
|
nested();
|
||||||
|
},
|
||||||
|
"nested closure"
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
onclick: move |_| async move {
|
||||||
|
let nested = move || async move {
|
||||||
|
// nested async closure comment
|
||||||
|
()
|
||||||
|
};
|
||||||
|
|
||||||
|
nested().await;
|
||||||
|
},
|
||||||
|
"nested async closure"
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user