浏览代码

fix tests

Jonathan Kelley 1 年之前
父节点
当前提交
f1e8faffb5

+ 3 - 0
packages/autofmt/src/element.rs

@@ -237,6 +237,9 @@ impl Writer<'_> {
             ElementAttrValue::AttrLiteral(value) => {
                 write!(self.out, "{value}", value = ifmt_to_string(value))?;
             }
+            ElementAttrValue::Shorthand(value) => {
+                write!(self.out, "{value}",)?;
+            }
             ElementAttrValue::AttrExpr(value) => {
                 let out = prettyplease::unparse_expr(value);
                 let mut lines = out.split('\n').peekable();

+ 1 - 0
packages/autofmt/src/writer.rs

@@ -142,6 +142,7 @@ impl<'a> Writer<'a> {
             }
             ElementAttrValue::AttrLiteral(lit) => ifmt_to_string(lit).len(),
             ElementAttrValue::AttrExpr(expr) => expr.span().line_length(),
+            ElementAttrValue::Shorthand(expr) => expr.span().line_length(),
             ElementAttrValue::EventTokens(tokens) => {
                 let location = Location::new(tokens.span().start());
 

+ 1 - 1
packages/core/tests/miri_stress.rs

@@ -15,7 +15,7 @@ fn test_memory_leak() {
         cx.spawn(async {});
 
         if val == 2 || val == 4 {
-            return None;
+            return render!({ () });
         }
 
         let name = cx.use_hook(|| String::from("numbers: "));

+ 15 - 2
packages/rsx/src/attribute.rs

@@ -20,6 +20,13 @@ impl AttributeType {
         }
     }
 
+    pub fn matches_attr_name(&self, other: &Self) -> bool {
+        match (self, other) {
+            (Self::Named(a), Self::Named(b)) => a.attr.name == b.attr.name,
+            _ => false,
+        }
+    }
+
     pub(crate) fn try_combine(&self, other: &Self) -> Option<Self> {
         match (self, other) {
             (Self::Named(a), Self::Named(b)) => a.try_combine(b).map(Self::Named),
@@ -105,6 +112,7 @@ impl ToTokens for ElementAttrNamed {
             match &attr.value {
                 ElementAttrValue::AttrLiteral(_)
                 | ElementAttrValue::AttrExpr(_)
+                | ElementAttrValue::Shorthand(_)
                 | ElementAttrValue::AttrOptionalExpr { .. } => {
                     let name = &self.attr.name;
                     let ns = ns(name);
@@ -144,6 +152,8 @@ pub struct ElementAttr {
 
 #[derive(PartialEq, Eq, Clone, Debug, Hash)]
 pub enum ElementAttrValue {
+    /// attribute,
+    Shorthand(Ident),
     /// attribute: "value"
     AttrLiteral(IfmtInput),
     /// attribute: if bool { "value" }
@@ -159,7 +169,7 @@ pub enum ElementAttrValue {
 
 impl Parse for ElementAttrValue {
     fn parse(input: ParseStream) -> syn::Result<Self> {
-        Ok(if input.peek(Token![if]) {
+        let element_attr_value = if input.peek(Token![if]) {
             let if_expr = input.parse::<ExprIf>()?;
             if is_if_chain_terminated(&if_expr) {
                 ElementAttrValue::AttrExpr(Expr::If(if_expr))
@@ -180,13 +190,16 @@ impl Parse for ElementAttrValue {
         } else {
             let value = input.parse::<Expr>()?;
             ElementAttrValue::AttrExpr(value)
-        })
+        };
+
+        Ok(element_attr_value)
     }
 }
 
 impl ToTokens for ElementAttrValue {
     fn to_tokens(&self, tokens: &mut TokenStream2) {
         match self {
+            ElementAttrValue::Shorthand(i) => tokens.append_all(quote! { #i }),
             ElementAttrValue::AttrLiteral(lit) => tokens.append_all(quote! { #lit }),
             ElementAttrValue::AttrOptionalExpr { condition, value } => {
                 tokens.append_all(quote! { if #condition { Some(#value) } else { None } })

+ 51 - 35
packages/rsx/src/element.rs

@@ -8,6 +8,7 @@ use syn::{
     parse::{Parse, ParseBuffer, ParseStream},
     punctuated::Punctuated,
     spanned::Spanned,
+    token::Brace,
     Expr, Ident, LitStr, Result, Token,
 };
 
@@ -59,6 +60,7 @@ impl Parse for Element {
             }
 
             // Parse the raw literal fields
+            // "def": 456,
             if content.peek(LitStr) && content.peek2(Token![:]) && !content.peek3(Token![:]) {
                 let name = content.parse::<LitStr>()?;
                 let ident = name.clone();
@@ -84,6 +86,8 @@ impl Parse for Element {
                 continue;
             }
 
+            // Parse
+            // abc: 123,
             if content.peek(Ident) && content.peek2(Token![:]) && !content.peek3(Token![:]) {
                 let name = content.parse::<Ident>()?;
 
@@ -102,22 +106,17 @@ impl Parse for Element {
                             value: ElementAttrValue::EventTokens(content.parse()?),
                         },
                     }));
+                } else if name_str == "key" {
+                    key = Some(content.parse()?);
                 } else {
-                    match name_str.as_str() {
-                        "key" => {
-                            key = Some(content.parse()?);
-                        }
-                        _ => {
-                            let value = content.parse::<ElementAttrValue>()?;
-                            attributes.push(attribute::AttributeType::Named(ElementAttrNamed {
-                                el_name: el_name.clone(),
-                                attr: ElementAttr {
-                                    name: ElementAttrName::BuiltIn(name),
-                                    value,
-                                },
-                            }));
-                        }
-                    }
+                    let value = content.parse::<ElementAttrValue>()?;
+                    attributes.push(attribute::AttributeType::Named(ElementAttrNamed {
+                        el_name: el_name.clone(),
+                        attr: ElementAttr {
+                            name: ElementAttrName::BuiltIn(name),
+                            value,
+                        },
+                    }));
                 }
 
                 if content.is_empty() {
@@ -130,6 +129,33 @@ impl Parse for Element {
                 continue;
             }
 
+            // Parse shorthand fields
+            if content.peek(Ident)
+                && !content.peek2(Brace)
+                && !content.peek2(Token![:])
+                && !content.peek2(Token![-])
+            {
+                let name = content.parse::<Ident>()?;
+                let name_ = name.clone();
+                let value = ElementAttrValue::Shorthand(name.clone());
+                attributes.push(attribute::AttributeType::Named(ElementAttrNamed {
+                    el_name: el_name.clone(),
+                    attr: ElementAttr {
+                        name: ElementAttrName::BuiltIn(name),
+                        value,
+                    },
+                }));
+
+                if content.is_empty() {
+                    break;
+                }
+
+                if content.parse::<Token![,]>().is_err() {
+                    missing_trailing_comma!(name_.span());
+                }
+                continue;
+            }
+
             break;
         }
 
@@ -137,31 +163,21 @@ impl Parse for Element {
         // For example, if there are two `class` attributes, combine them into one
         let mut merged_attributes: Vec<AttributeType> = Vec::new();
         for attr in &attributes {
-            if let Some(old_attr_index) = merged_attributes.iter().position(|a| {
-                matches!((a, attr), (
-                                AttributeType::Named(ElementAttrNamed {
-                                    attr: ElementAttr {
-                                        name: ElementAttrName::BuiltIn(old_name),
-                                        ..
-                                    },
-                                    ..
-                                }),
-                                AttributeType::Named(ElementAttrNamed {
-                                    attr: ElementAttr {
-                                        name: ElementAttrName::BuiltIn(new_name),
-                                        ..
-                                    },
-                                    ..
-                                }),
-                            ) if old_name == new_name)
-            }) {
+            let attr_index = merged_attributes
+                .iter()
+                .position(|a| a.matches_attr_name(attr));
+
+            if let Some(old_attr_index) = attr_index {
                 let old_attr = &mut merged_attributes[old_attr_index];
+
                 if let Some(combined) = old_attr.try_combine(attr) {
                     *old_attr = combined;
                 }
-            } else {
-                merged_attributes.push(attr.clone());
+
+                continue;
             }
+
+            merged_attributes.push(attr.clone());
         }
 
         while !content.is_empty() {

+ 6 - 6
packages/rsx/src/lib.rs

@@ -668,9 +668,9 @@ fn diff_template() {
             p {
                 "hello world"
             }
-            (0..10).map(|i| rsx!{"{i}"}),
-            (0..10).map(|i| rsx!{"{i}"}),
-            (0..11).map(|i| rsx!{"{i}"}),
+            {(0..10).map(|i| rsx!{"{i}"})},
+            {(0..10).map(|i| rsx!{"{i}"})},
+            {(0..11).map(|i| rsx!{"{i}"})},
             Comp{}
         }
     };
@@ -714,9 +714,9 @@ fn diff_template() {
             "height2": "100px",
             width: 100,
             Comp{}
-            (0..11).map(|i| rsx!{"{i}"}),
-            (0..10).map(|i| rsx!{"{i}"}),
-            (0..10).map(|i| rsx!{"{i}"}),
+            {(0..11).map(|i| rsx!{"{i}"})},
+            {(0..10).map(|i| rsx!{"{i}"})},
+            {(0..10).map(|i| rsx!{"{i}"})},
             p {
                 "hello world"
             }