1
0
Эх сурвалжийг харах

Feat: Auto Default Into (#2757)

* feat: auto default into

* fix: fmt

* fix: type infer

* feat: text auto into
Miles Murgaw 11 сар өмнө
parent
commit
4ffcef16af

+ 21 - 3
packages/core-macro/src/props/mod.rs

@@ -213,6 +213,9 @@ mod field_info {
                 {
                     builder_attr.from_displayable = true;
                     // ToString is both more general and provides a more useful error message than From<String>. If the user tries to use `#[into]`, use ToString instead.
+                    if builder_attr.auto_into {
+                        builder_attr.auto_to_string = true;
+                    }
                     builder_attr.auto_into = false;
                 }
 
@@ -275,6 +278,7 @@ mod field_info {
         pub docs: Vec<syn::Attribute>,
         pub skip: bool,
         pub auto_into: bool,
+        pub auto_to_string: bool,
         pub from_displayable: bool,
         pub strip_option: bool,
         pub ignore_option: bool,
@@ -512,7 +516,7 @@ mod struct_info {
     use syn::parse::Error;
     use syn::punctuated::Punctuated;
     use syn::spanned::Spanned;
-    use syn::{Expr, Ident};
+    use syn::{parse_quote, Expr, Ident};
 
     use crate::props::strip_option;
 
@@ -1368,10 +1372,24 @@ Finally, call `.build()` to create the instance of `{name}`.
                 if !field.builder_attr.extends.is_empty() {
                     quote!(let #name = self.#name;)
                 } else if let Some(ref default) = field.builder_attr.default {
+
+                    // If field has `into`, apply it to the default value.
+                    // Ignore any blank defaults as it causes type inference errors.
+                    let is_default = *default == parse_quote!(::core::default::Default::default());
+                    let mut into = quote!{};
+
+                    if !is_default {
+                        if field.builder_attr.auto_into {
+                            into = quote!{ .into() }
+                        } else if field.builder_attr.auto_to_string {
+                            into = quote!{ .to_string() }
+                        }
+                    }
+
                     if field.builder_attr.skip {
-                        quote!(let #name = #default;)
+                        quote!(let #name = #default #into;)
                     } else {
-                        quote!(let #name = #helper_trait_name::into_value(#name, || #default);)
+                        quote!(let #name = #helper_trait_name::into_value(#name, || #default #into);)
                     }
                 } else {
                     quote!(let #name = #name.0;)

+ 48 - 0
packages/core-macro/tests/rsx.rs

@@ -3,3 +3,51 @@ fn rsx() {
     let t = trybuild::TestCases::new();
     t.compile_fail("tests/rsx/trailing-comma-0.rs");
 }
+
+/// This test ensures that automatic `into` conversion occurs for default values.
+///
+/// These are compile-time tests.
+/// See https://github.com/DioxusLabs/dioxus/issues/2373
+#[cfg(test)]
+mod test_default_into {
+    use dioxus::prelude::*;
+
+    #[derive(Props, Clone, PartialEq)]
+    struct MyCoolProps {
+        // Test different into configurations
+        #[props(into, default = true)]
+        pub val_into_w_default_val: u16,
+
+        #[props(into, default)]
+        pub val_into_w_default: u16,
+
+        #[props(default = true.into())]
+        pub val_default: u16,
+
+        // Test different into configurations with strings
+        #[props(into, default = "abc")]
+        pub str_into_w_default_val: String,
+
+        #[props(into, default)]
+        pub str_into_w_default: String,
+
+        #[props(default = "abc".into())]
+        pub str_default: String,
+
+        // Test options
+        #[props(into, default = Some("abc"))]
+        pub opt_into_w_default_val: Option<String>,
+
+        #[props(into, default)]
+        pub opt_into_w_default: Option<String>,
+
+        #[props(default = Some("abc"))]
+        pub opt_default: Option<String>,
+
+        // Test no default
+        #[props(into)]
+        pub some_data: bool,
+
+        pub some_other_data: bool,
+    }
+}