Преглед на файлове

feat: flatten props attrs

Jonathan Kelley преди 3 години
родител
ревизия
d237271
променени са 4 файла, в които са добавени 79 реда и са изтрити 118 реда
  1. 37 0
      examples/optional_props.rs
  2. 38 114
      packages/core-macro/src/props/mod.rs
  3. 3 3
      packages/router/src/components/link.rs
  4. 1 1
      packages/router/src/components/router.rs

+ 37 - 0
examples/optional_props.rs

@@ -0,0 +1,37 @@
+//! Example: README.md showcase
+//!
+//! The example from the README.md.
+
+use dioxus::prelude::*;
+
+fn main() {
+    dioxus::desktop::launch(app);
+}
+
+fn app(cx: Scope) -> Element {
+    cx.render(rsx! {
+        Button {
+            a: "asd".to_string(),
+            c: Some("asd".to_string()),
+            d: "asd".to_string(),
+        }
+    })
+}
+
+#[derive(Props, PartialEq)]
+struct ButtonProps {
+    a: String,
+
+    #[props(default)]
+    b: Option<String>,
+
+    #[props(default)]
+    c: Option<String>,
+
+    #[props(default)]
+    d: Option<String>,
+}
+
+fn Button(cx: Scope<ButtonProps>) -> Element {
+    todo!()
+}

+ 38 - 114
packages/core-macro/src/props/mod.rs

@@ -267,11 +267,6 @@ mod field_info {
     #[derive(Debug, Default, Clone)]
     pub struct FieldBuilderAttr {
         pub default: Option<syn::Expr>,
-        pub setter: SetterSettings,
-    }
-
-    #[derive(Debug, Clone, Default)]
-    pub struct SetterSettings {
         pub doc: Option<syn::Expr>,
         pub skip: bool,
         pub auto_into: bool,
@@ -305,12 +300,12 @@ mod field_info {
                     }
                 }
                 // Stash its span for later (we don’t yet know if it’ll be an error)
-                if self.setter.skip && skip_tokens.is_none() {
+                if self.skip && skip_tokens.is_none() {
                     skip_tokens = Some(attr.tokens.clone());
                 }
             }
 
-            if self.setter.skip && self.default.is_none() {
+            if self.skip && self.default.is_none() {
                 return Err(Error::new_spanned(
                     skip_tokens.unwrap(),
                     "#[props(skip)] must be accompanied by default or default_code",
@@ -331,6 +326,10 @@ mod field_info {
                             self.default = Some(*assign.right);
                             Ok(())
                         }
+                        "doc" => {
+                            self.doc = Some(*assign.right);
+                            Ok(())
+                        }
                         "default_code" => {
                             if let syn::Expr::Lit(syn::ExprLit {
                                 lit: syn::Lit::Str(code),
@@ -355,7 +354,7 @@ mod field_info {
                     }
                 }
 
-                // uh not sure
+                // #[props(default)]
                 syn::Expr::Path(path) => {
                     let name = path_to_single_string(&path.path)
                         .ok_or_else(|| Error::new_spanned(&path, "Expected identifier"))?;
@@ -365,39 +364,33 @@ mod field_info {
                                 Some(syn::parse(quote!(Default::default()).into()).unwrap());
                             Ok(())
                         }
-                        _ => Err(Error::new_spanned(
-                            &path,
-                            format!("Unknown parameter {:?}", name),
-                        )),
-                    }
-                }
-
-                //
-                syn::Expr::Call(call) => {
-                    let subsetting_name = if let syn::Expr::Path(path) = &*call.func {
-                        path_to_single_string(&path.path)
-                    } else {
-                        None
-                    }
-                    .ok_or_else(|| {
-                        let call_func = &call.func;
-                        let call_func = quote!(#call_func);
-                        Error::new_spanned(
-                            &call.func,
-                            format!("Illegal builder setting group {}", call_func),
-                        )
-                    })?;
-                    match subsetting_name.as_ref() {
-                        "setter" => {
-                            for arg in call.args {
-                                self.setter.apply_meta(arg)?;
+                        _ => {
+                            macro_rules! handle_fields {
+                                ( $( $flag:expr, $field:ident, $already:expr; )* ) => {
+                                    match name.as_str() {
+                                        $(
+                                            $flag => {
+                                                if self.$field {
+                                                    Err(Error::new(path.span(), concat!("Illegal setting - field is already ", $already)))
+                                                } else {
+                                                    self.$field = true;
+                                                    Ok(())
+                                                }
+                                            }
+                                        )*
+                                        _ => Err(Error::new_spanned(
+                                                &path,
+                                                format!("Unknown setter parameter {:?}", name),
+                                        ))
+                                    }
+                                }
                             }
-                            Ok(())
+                            handle_fields!(
+                                "skip", skip, "skipped";
+                                "into", auto_into, "calling into() on the argument";
+                                "strip_option", strip_option, "putting the argument in Some(...)";
+                            )
                         }
-                        _ => Err(Error::new_spanned(
-                            &call.func,
-                            format!("Illegal builder setting group name {}", subsetting_name),
-                        )),
                     }
                 }
 
@@ -414,75 +407,6 @@ mod field_info {
                                 self.default = None;
                                 Ok(())
                             }
-                            _ => Err(Error::new_spanned(path, "Unknown setting".to_owned())),
-                        }
-                    } else {
-                        Err(Error::new_spanned(
-                            expr,
-                            "Expected simple identifier".to_owned(),
-                        ))
-                    }
-                }
-                _ => Err(Error::new_spanned(expr, "Expected (<...>=<...>)")),
-            }
-        }
-    }
-
-    impl SetterSettings {
-        fn apply_meta(&mut self, expr: syn::Expr) -> Result<(), Error> {
-            match expr {
-                syn::Expr::Assign(assign) => {
-                    let name = expr_to_single_string(&assign.left)
-                        .ok_or_else(|| Error::new_spanned(&assign.left, "Expected identifier"))?;
-                    match name.as_str() {
-                        "doc" => {
-                            self.doc = Some(*assign.right);
-                            Ok(())
-                        }
-                        _ => Err(Error::new_spanned(
-                            &assign,
-                            format!("Unknown parameter {:?}", name),
-                        )),
-                    }
-                }
-                syn::Expr::Path(path) => {
-                    let name = path_to_single_string(&path.path)
-                        .ok_or_else(|| Error::new_spanned(&path, "Expected identifier"))?;
-                    macro_rules! handle_fields {
-                    ( $( $flag:expr, $field:ident, $already:expr; )* ) => {
-                        match name.as_str() {
-                            $(
-                                $flag => {
-                                    if self.$field {
-                                        Err(Error::new(path.span(), concat!("Illegal setting - field is already ", $already)))
-                                    } else {
-                                        self.$field = true;
-                                        Ok(())
-                                    }
-                                }
-                            )*
-                            _ => Err(Error::new_spanned(
-                                    &path,
-                                    format!("Unknown setter parameter {:?}", name),
-                            ))
-                        }
-                    }
-                }
-                    handle_fields!(
-                        "skip", skip, "skipped";
-                        "into", auto_into, "calling into() on the argument";
-                        "strip_option", strip_option, "putting the argument in Some(...)";
-                    )
-                }
-                syn::Expr::Unary(syn::ExprUnary {
-                    op: syn::UnOp::Not(_),
-                    expr,
-                    ..
-                }) => {
-                    if let syn::Expr::Path(path) = *expr {
-                        let name = path_to_single_string(&path.path)
-                            .ok_or_else(|| Error::new_spanned(&path, "Expected identifier"))?;
-                        match name.as_str() {
                             "doc" => {
                                 self.doc = None;
                                 Ok(())
@@ -540,7 +464,7 @@ mod struct_info {
 
     impl<'a> StructInfo<'a> {
         pub fn included_fields(&self) -> impl Iterator<Item = &FieldInfo<'a>> {
-            self.fields.iter().filter(|f| !f.builder_attr.setter.skip)
+            self.fields.iter().filter(|f| !f.builder_attr.skip)
         }
 
         pub fn new(
@@ -826,14 +750,14 @@ Finally, call `.build()` to create the instance of `{name}`.
                 syn::GenericArgument::Type(ty_generics_tuple.into()),
             );
             let (impl_generics, _, where_clause) = generics.split_for_impl();
-            let doc = match field.builder_attr.setter.doc {
+            let doc = match field.builder_attr.doc {
                 Some(ref doc) => quote!(#[doc = #doc]),
                 None => quote!(),
             };
 
             // NOTE: both auto_into and strip_option affect `arg_type` and `arg_expr`, but the order of
             // nesting is different so we have to do this little dance.
-            let arg_type = if field.builder_attr.setter.strip_option {
+            let arg_type = if field.builder_attr.strip_option {
                 let internal_type = field.type_from_inside_option().ok_or_else(|| {
                     Error::new_spanned(
                         &field_type,
@@ -844,7 +768,7 @@ Finally, call `.build()` to create the instance of `{name}`.
             } else {
                 field_type
             };
-            let (arg_type, arg_expr) = if field.builder_attr.setter.auto_into {
+            let (arg_type, arg_expr) = if field.builder_attr.auto_into {
                 (
                     quote!(impl core::convert::Into<#arg_type>),
                     quote!(#field_name.into()),
@@ -852,7 +776,7 @@ Finally, call `.build()` to create the instance of `{name}`.
             } else {
                 (quote!(#arg_type), quote!(#field_name))
             };
-            let arg_expr = if field.builder_attr.setter.strip_option {
+            let arg_expr = if field.builder_attr.strip_option {
                 quote!(Some(#arg_expr))
             } else {
                 arg_expr
@@ -1076,7 +1000,7 @@ Finally, call `.build()` to create the instance of `{name}`.
             let assignments = self.fields.iter().map(|field| {
                 let name = &field.name;
                 if let Some(ref default) = field.builder_attr.default {
-                    if field.builder_attr.setter.skip {
+                    if field.builder_attr.skip {
                         quote!(let #name = #default;)
                     } else {
                         quote!(let #name = #helper_trait_name::into_value(#name, || #default);)

+ 3 - 3
packages/router/src/components/link.rs

@@ -22,13 +22,13 @@ pub struct LinkProps<'a> {
     /// Link { to: Route::Home, href: Route::as_url }
     ///
     /// ```
-    #[props(default, setter(strip_option))]
+    #[props(default, strip_option)]
     href: Option<&'a str>,
 
-    #[props(default, setter(strip_option))]
+    #[props(default, strip_option)]
     class: Option<&'a str>,
 
-    #[props(default, setter(strip_option))]
+    #[props(default, strip_option)]
     id: Option<&'a str>,
 
     children: Element<'a>,

+ 1 - 1
packages/router/src/components/router.rs

@@ -11,7 +11,7 @@ use crate::RouterService;
 pub struct RouterProps<'a> {
     children: Element<'a>,
 
-    #[props(default, setter(strip_option))]
+    #[props(default, strip_option)]
     onchange: Option<&'a Fn(&'a str)>,
 }