Fix if chain attributes with mixed expressions and strings (#3149)
* Fix if chain attributes with mixed expressions and strings
This commit is contained in:
1 parent
292f757d5d
commit
37a6e9200f
2 files changed
+61
-8
No files matched your search
@@ -10,4 +10,23 @@ fn partially_formatted_conditional_attribute() {
|
|||||||
width: if true { "{width}" } else { "100px" }
|
width: if true { "{width}" } else { "100px" }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// And make sure it works if one of those branches is an expression
|
||||||
|
// Regression test for https://github.com/DioxusLabs/dioxus/issues/3146
|
||||||
|
let opt = "button";
|
||||||
|
|
||||||
|
_ = rsx! {
|
||||||
|
input {
|
||||||
|
type: if true { opt } else { "text" },
|
||||||
|
}
|
||||||
|
input {
|
||||||
|
type: if true { opt.to_string() } else { "text with" },
|
||||||
|
}
|
||||||
|
input {
|
||||||
|
type: if true { opt.to_string() } else { "text with {width}" },
|
||||||
|
}
|
||||||
|
input {
|
||||||
|
type: if true { opt.to_string() } else if true { "" } else { "text with {width}" },
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
@@ -582,6 +582,20 @@ impl IfAttributeValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn contains_expression(&self) -> bool {
|
||||||
|
if let AttributeValue::AttrExpr(_) = &*self.then_value {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
match &self.else_value {
|
||||||
|
Some(attribute) => match attribute.as_ref() {
|
||||||
|
AttributeValue::IfExpr(if_expr) => if_expr.is_terminated(),
|
||||||
|
AttributeValue::AttrExpr(_) => true,
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
None => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_attribute_value_from_block(block: &Block) -> syn::Result<Box<AttributeValue>> {
|
fn parse_attribute_value_from_block(block: &Block) -> syn::Result<Box<AttributeValue>> {
|
||||||
let stmts = &block.stmts;
|
let stmts = &block.stmts;
|
||||||
|
|
||||||
@@ -609,7 +623,12 @@ impl IfAttributeValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_tokens_with_terminated(&self, tokens: &mut TokenStream2, terminated: bool) {
|
fn to_tokens_with_terminated(
|
||||||
|
&self,
|
||||||
|
tokens: &mut TokenStream2,
|
||||||
|
terminated: bool,
|
||||||
|
contains_expression: bool,
|
||||||
|
) {
|
||||||
let IfAttributeValue {
|
let IfAttributeValue {
|
||||||
condition,
|
condition,
|
||||||
then_value,
|
then_value,
|
||||||
@@ -619,15 +638,29 @@ impl IfAttributeValue {
|
|||||||
// Quote an attribute value and convert the value to a string if it is formatted
|
// Quote an attribute value and convert the value to a string if it is formatted
|
||||||
// We always quote formatted segments as strings inside if statements so they have a consistent type
|
// We always quote formatted segments as strings inside if statements so they have a consistent type
|
||||||
// This fixes https://github.com/DioxusLabs/dioxus/issues/2997
|
// This fixes https://github.com/DioxusLabs/dioxus/issues/2997
|
||||||
fn quote_attribute_value_string(value: &AttributeValue) -> TokenStream2 {
|
fn quote_attribute_value_string(
|
||||||
if matches!(value, AttributeValue::AttrLiteral(HotLiteral::Fmted(_))) {
|
value: &AttributeValue,
|
||||||
quote! { #value.to_string() }
|
contains_expression: bool,
|
||||||
|
) -> TokenStream2 {
|
||||||
|
if let AttributeValue::AttrLiteral(HotLiteral::Fmted(fmted)) = value {
|
||||||
|
if let Some(str) = fmted.to_static().filter(|_| contains_expression) {
|
||||||
|
// If this is actually a static string, the user may be using a static string expression in another branch
|
||||||
|
// use into to convert the string to whatever the other branch is using
|
||||||
|
quote! {
|
||||||
|
{
|
||||||
|
#[allow(clippy::useless_conversion)]
|
||||||
|
#str.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! { #value.to_string() }
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
value.to_token_stream()
|
value.to_token_stream()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let then_value = quote_attribute_value_string(then_value);
|
let then_value = quote_attribute_value_string(then_value, terminated);
|
||||||
|
|
||||||
let then_value = if terminated {
|
let then_value = if terminated {
|
||||||
quote! { #then_value }
|
quote! { #then_value }
|
||||||
@@ -640,11 +673,11 @@ impl IfAttributeValue {
|
|||||||
let else_value = match else_value.as_deref() {
|
let else_value = match else_value.as_deref() {
|
||||||
Some(AttributeValue::IfExpr(else_value)) => {
|
Some(AttributeValue::IfExpr(else_value)) => {
|
||||||
let mut tokens = TokenStream2::new();
|
let mut tokens = TokenStream2::new();
|
||||||
else_value.to_tokens_with_terminated(&mut tokens, terminated);
|
else_value.to_tokens_with_terminated(&mut tokens, terminated, contains_expression);
|
||||||
tokens
|
tokens
|
||||||
}
|
}
|
||||||
Some(other) => {
|
Some(other) => {
|
||||||
let other = quote_attribute_value_string(other);
|
let other = quote_attribute_value_string(other, contains_expression);
|
||||||
if terminated {
|
if terminated {
|
||||||
quote! { #other }
|
quote! { #other }
|
||||||
} else {
|
} else {
|
||||||
@@ -709,7 +742,8 @@ impl ToTokens for IfAttributeValue {
|
|||||||
fn to_tokens(&self, tokens: &mut TokenStream2) {
|
fn to_tokens(&self, tokens: &mut TokenStream2) {
|
||||||
// If the if expression is terminated, we can just return the then value
|
// If the if expression is terminated, we can just return the then value
|
||||||
let terminated = self.is_terminated();
|
let terminated = self.is_terminated();
|
||||||
self.to_tokens_with_terminated(tokens, terminated)
|
let contains_expression = self.contains_expression();
|
||||||
|
self.to_tokens_with_terminated(tokens, terminated, contains_expression)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user