fix(rsx): formatted attribute merging (#3719)
* test(rsx): add better tests for attributes merging * fix(rsx): zero-lengthed source with non-empty segments is non-trivial * refactor(rsx): use `is_empty` instead of `len() == 0` (clippy) * fix(rsx): different asserts whether in release or not
This commit is contained in:
1 parent
c58d7303b8
commit
fd65c12bf5
2 files changed
+129
-8
No files matched your search
+124
-8
@@ -524,12 +524,11 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn merges_attributes() {
|
||||
fn merge_trivial_attributes() {
|
||||
let input = quote::quote! {
|
||||
div {
|
||||
class: "hello world",
|
||||
class: if count > 3 { "abc {def}" },
|
||||
class: if count < 50 { "small" } else { "big" }
|
||||
class: "foo",
|
||||
class: "bar",
|
||||
}
|
||||
};
|
||||
|
||||
@@ -543,12 +542,129 @@ mod tests {
|
||||
|
||||
let attr = &parsed.merged_attributes[0].value;
|
||||
|
||||
println!("{}", attr.to_token_stream().pretty_unparse());
|
||||
assert_eq!(
|
||||
attr.to_token_stream().pretty_unparse().as_str(),
|
||||
"\"foo bar\""
|
||||
);
|
||||
|
||||
let _attr = match attr {
|
||||
AttributeValue::AttrLiteral(lit) => lit,
|
||||
_ => panic!("expected literal"),
|
||||
if let AttributeValue::AttrLiteral(_) = attr {
|
||||
} else {
|
||||
panic!("expected literal")
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn merge_formatted_attributes() {
|
||||
let input = quote::quote! {
|
||||
div {
|
||||
class: "foo",
|
||||
class: "{bar}",
|
||||
}
|
||||
};
|
||||
|
||||
let parsed: Element = syn::parse2(input).unwrap();
|
||||
assert_eq!(parsed.diagnostics.len(), 0);
|
||||
assert_eq!(parsed.merged_attributes.len(), 1);
|
||||
assert_eq!(
|
||||
parsed.merged_attributes[0].name.to_string(),
|
||||
"class".to_string()
|
||||
);
|
||||
|
||||
let attr = &parsed.merged_attributes[0].value;
|
||||
|
||||
assert_eq!(
|
||||
attr.to_token_stream().pretty_unparse().as_str(),
|
||||
"::std::format!(\"foo {0:}\", bar)"
|
||||
);
|
||||
|
||||
if let AttributeValue::AttrLiteral(_) = attr {
|
||||
} else {
|
||||
panic!("expected literal")
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn merge_conditional_attributes() {
|
||||
let input = quote::quote! {
|
||||
div {
|
||||
class: "foo",
|
||||
class: if true { "bar" },
|
||||
class: if false { "baz" } else { "qux" }
|
||||
}
|
||||
};
|
||||
|
||||
let parsed: Element = syn::parse2(input).unwrap();
|
||||
assert_eq!(parsed.diagnostics.len(), 0);
|
||||
assert_eq!(parsed.merged_attributes.len(), 1);
|
||||
assert_eq!(
|
||||
parsed.merged_attributes[0].name.to_string(),
|
||||
"class".to_string()
|
||||
);
|
||||
|
||||
let attr = &parsed.merged_attributes[0].value;
|
||||
|
||||
assert_eq!(
|
||||
attr.to_token_stream().pretty_unparse().as_str(),
|
||||
"::std::format!(\n \
|
||||
\"foo {0:} {1:}\",\n \
|
||||
{ if true { \"bar\".to_string() } else { ::std::string::String::new() } },\n \
|
||||
{ if false { \"baz\".to_string() } else { \"qux\".to_string() } },\n\
|
||||
)"
|
||||
);
|
||||
|
||||
if let AttributeValue::AttrLiteral(_) = attr {
|
||||
} else {
|
||||
panic!("expected literal")
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn merge_all_attributes() {
|
||||
let input = quote::quote! {
|
||||
div {
|
||||
class: "foo",
|
||||
class: "{bar}",
|
||||
class: if true { "baz" },
|
||||
class: if false { "{qux}" } else { "quux" }
|
||||
}
|
||||
};
|
||||
|
||||
let parsed: Element = syn::parse2(input).unwrap();
|
||||
assert_eq!(parsed.diagnostics.len(), 0);
|
||||
assert_eq!(parsed.merged_attributes.len(), 1);
|
||||
assert_eq!(
|
||||
parsed.merged_attributes[0].name.to_string(),
|
||||
"class".to_string()
|
||||
);
|
||||
|
||||
let attr = &parsed.merged_attributes[0].value;
|
||||
|
||||
if cfg!(debug_assertions) {
|
||||
assert_eq!(
|
||||
attr.to_token_stream().pretty_unparse().as_str(),
|
||||
"::std::format!(\n \
|
||||
\"foo {0:} {1:} {2:}\",\n \
|
||||
bar,\n \
|
||||
{ if true { \"baz\".to_string() } else { ::std::string::String::new() } },\n \
|
||||
{ if false { ::std::format!(\"{qux}\").to_string() } else { \"quux\".to_string() } },\n\
|
||||
)"
|
||||
);
|
||||
} else {
|
||||
assert_eq!(
|
||||
attr.to_token_stream().pretty_unparse().as_str(),
|
||||
"::std::format!(\n \
|
||||
\"foo {0:} {1:} {2:}\",\n \
|
||||
bar,\n \
|
||||
{ if true { \"baz\".to_string() } else { ::std::string::String::new() } },\n \
|
||||
{ if false { (qux).to_string().to_string() } else { \"quux\".to_string() } },\n\
|
||||
)"
|
||||
);
|
||||
}
|
||||
|
||||
if let AttributeValue::AttrLiteral(_) = attr {
|
||||
} else {
|
||||
panic!("expected literal")
|
||||
}
|
||||
}
|
||||
|
||||
/// There are a number of cases where merging attributes doesn't make sense
|
||||
|
||||
@@ -90,6 +90,11 @@ impl IfmtInput {
|
||||
}
|
||||
|
||||
fn is_simple_expr(&self) -> bool {
|
||||
// If there are segments but the source is empty, it's not a simple expression.
|
||||
if !self.segments.is_empty() && self.source.span().byte_range().is_empty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
self.segments.iter().all(|seg| match seg {
|
||||
Segment::Literal(_) => true,
|
||||
Segment::Formatted(FormattedSegment { segment, .. }) => {
|
||||
|
||||
Reference in new issue
Block a user