ソースを参照

fix non extending attributes

Evan Almloff 1 年間 前
コミット
b60671e0fe

+ 1 - 6
examples/spread.rs

@@ -1,9 +1,4 @@
-use crate::dioxus_elements::ExtendedDivMarker;
-use dioxus::{
-    core::{exports::bumpalo::Bump, Attribute, HasAttributesBox},
-    html::{ExtendedGlobalAttributesMarker, GlobalAttributesExtension},
-    prelude::*,
-};
+use dioxus::prelude::*;
 
 fn main() {
     let mut dom = VirtualDom::new(app);

+ 40 - 15
packages/core-macro/src/props/mod.rs

@@ -502,7 +502,7 @@ mod struct_info {
     use syn::punctuated::Punctuated;
     use syn::spanned::Spanned;
     use syn::visit::Visit;
-    use syn::{Expr, Ident};
+    use syn::{parse_quote, Expr, Ident};
 
     use super::field_info::{FieldBuilderAttr, FieldInfo};
     use super::util::{
@@ -611,10 +611,17 @@ mod struct_info {
             // Therefore, we will generate code that shortcircuits the "comparison" in memoization
             let are_there_generics = !self.generics.params.is_empty();
 
+            let extend_lifetime = self.extend_lifetime()?;
+
             let generics = self.generics.clone();
             let (_, ty_generics, where_clause) = generics.split_for_impl();
-            let impl_generics = self.generics.clone();
-            let (impl_generics, b_initial_generics, _) = impl_generics.split_for_impl();
+            let impl_generics = self.modify_generics(|g| {
+                if extend_lifetime.is_none() {
+                    g.params.insert(0, parse_quote!('__bump));
+                }
+            });
+            let (impl_generics, _, _) = impl_generics.split_for_impl();
+            let (_, b_initial_generics, _) = self.generics.split_for_impl();
             let all_fields_param = syn::GenericParam::Type(
                 syn::Ident::new("TypedBuilderFields", proc_macro2::Span::call_site()).into(),
             );
@@ -712,9 +719,21 @@ Finally, call `.build()` to create the instance of `{name}`.
                 let name = f.name;
                 quote!(#name: Vec::new())
             });
-            let extend_lifetime = self
-                .extend_lifetime()?
-                .unwrap_or(syn::Lifetime::new("'_", proc_macro2::Span::call_site()));
+            let has_extend_fields = self.extend_fields().next().is_some();
+            let take_bump = if has_extend_fields {
+                quote!(bump: _cx.bump(),)
+            } else {
+                quote!()
+            };
+            let bump_field = if has_extend_fields {
+                quote!(bump: & #extend_lifetime ::dioxus::core::exports::bumpalo::Bump,)
+            } else {
+                quote!()
+            };
+            let extend_lifetime = extend_lifetime.unwrap_or(syn::Lifetime::new(
+                "'__bump",
+                proc_macro2::Span::call_site(),
+            ));
 
             Ok(quote! {
                 impl #impl_generics #name #ty_generics #where_clause {
@@ -723,7 +742,7 @@ Finally, call `.build()` to create the instance of `{name}`.
                     #vis fn builder(_cx: & #extend_lifetime ::dioxus::prelude::ScopeState) -> #builder_name #generics_with_empty {
                         #builder_name {
                             #(#extend_fields_value,)*
-                            bump: _cx.bump(),
+                            #take_bump
                             fields: #empties_tuple,
                             _phantom: ::core::default::Default::default(),
                         }
@@ -735,7 +754,7 @@ Finally, call `.build()` to create the instance of `{name}`.
                 #[allow(dead_code, non_camel_case_types, non_snake_case)]
                 #vis struct #builder_name #b_generics {
                     #(#extend_fields,)*
-                    bump: & #extend_lifetime ::dioxus::core::exports::bumpalo::Bump,
+                    #bump_field
                     fields: #all_fields_param,
                     _phantom: (#( #phantom_generics ),*),
                 }
@@ -862,21 +881,22 @@ Finally, call `.build()` to create the instance of `{name}`.
                 quote!(#name: self.#name)
             });
 
+            let extend_lifetime = self.extend_lifetime()?.ok_or(Error::new_spanned(
+                field_name,
+                "Unable to find lifetime for extended field. Please specify it manually",
+            ))?;
+
             let extends_impl = field.builder_attr.extends.iter().map(|path| {
                 let name_str = path_to_single_string(path).unwrap();
                 let camel_name = name_str.to_case(Case::UpperCamel);
                 let marker_name = Ident::new(
-                    format!("Extended{}Marker", &camel_name).as_str(),
+                    format!("{}Extension", &camel_name).as_str(),
                     path.span(),
                 );
                 quote! {
-                    impl #impl_generics #marker_name for #builder_name < #( #ty_generics ),* > #where_clause {}
+                    impl #impl_generics dioxus_elements::extensions::#marker_name < #extend_lifetime > for #builder_name < #( #ty_generics ),* > #where_clause {}
                 }
             });
-            let extend_lifetime = self.extend_lifetime()?.ok_or(Error::new_spanned(
-                field_name,
-                "Unable to find lifetime for extended field. Please specify it manually",
-            ))?;
 
             Ok(quote! {
                 impl #impl_generics ::dioxus::prelude::HasAttributesBox<#extend_lifetime> for #builder_name < #( #ty_generics ),* > #where_clause {
@@ -1035,6 +1055,11 @@ Finally, call `.build()` to create the instance of `{name}`.
                 let name = f.name;
                 quote!(#name: self.#name)
             });
+            let forward_bump = if self.extend_fields().next().is_some() {
+                quote!(bump: self.bump,)
+            } else {
+                quote!()
+            };
 
             Ok(quote! {
                 #[allow(dead_code, non_camel_case_types, missing_docs)]
@@ -1045,7 +1070,7 @@ Finally, call `.build()` to create the instance of `{name}`.
                         let ( #(#descructuring,)* ) = self.fields;
                         #builder_name {
                             #(#forward_extended_fields,)*
-                            bump: self.bump,
+                            #forward_bump
                             fields: ( #(#reconstructing,)* ),
                             _phantom: self._phantom,
                         }

+ 4 - 4
packages/core/src/lib.rs

@@ -89,10 +89,10 @@ pub mod prelude {
         consume_context, consume_context_from_scope, current_scope_id, fc_to_builder, has_context,
         provide_context, provide_context_to_scope, provide_root_context, push_future,
         remove_future, schedule_update_any, spawn, spawn_forever, suspend, throw, AnyValue,
-        AttributeType, Component, Element, Event, EventHandler, Fragment, HasAttributesBox,
-        IntoAttributeValue, LazyNodes, MountedAttribute, Properties, Runtime, RuntimeGuard, Scope,
-        ScopeId, ScopeState, Scoped, TaskId, Template, TemplateAttribute, TemplateNode, Throw,
-        VNode, VirtualDom,
+        Attribute, AttributeType, Component, Element, Event, EventHandler, Fragment,
+        HasAttributesBox, IntoAttributeValue, LazyNodes, MountedAttribute, Properties, Runtime,
+        RuntimeGuard, Scope, ScopeId, ScopeState, Scoped, TaskId, Template, TemplateAttribute,
+        TemplateNode, Throw, VNode, VirtualDom,
     };
 }
 

+ 6 - 16
packages/html-internal-macro/src/lib.rs

@@ -39,13 +39,13 @@ impl Parse for ImplExtensionAttributes {
 impl ToTokens for ImplExtensionAttributes {
     fn to_tokens(&self, tokens: &mut TokenStream2) {
         let name = &self.name;
-        let camel_name = name.to_string().to_case(Case::UpperCamel);
+        let name_string = name.to_string();
+        let camel_name = name_string
+            .strip_prefix("r#")
+            .unwrap_or(&name_string)
+            .to_case(Case::UpperCamel);
         let impl_name = Ident::new(format!("{}Impl", &camel_name).as_str(), name.span());
         let extension_name = Ident::new(format!("{}Extension", &camel_name).as_str(), name.span());
-        let marker_name = Ident::new(
-            format!("Extended{}Marker", &camel_name).as_str(),
-            name.span(),
-        );
 
         if !self.is_element {
             tokens.append_all(quote! {
@@ -54,11 +54,6 @@ impl ToTokens for ImplExtensionAttributes {
             });
         }
 
-        let defs = self.attrs.iter().map(|ident| {
-            quote! {
-                fn #ident(self, value: impl IntoAttributeValue<'a>) -> Self;
-            }
-        });
         let impls = self.attrs.iter().map(|ident| {
             let d = if self.is_element {
                 quote! { #name::#ident }
@@ -73,12 +68,7 @@ impl ToTokens for ImplExtensionAttributes {
             }
         });
         tokens.append_all(quote! {
-            pub trait #marker_name {}
-
-            pub trait #extension_name<'a> {
-                #(#defs)*
-            }
-            impl<'a, T> #extension_name<'a> for T where T: HasAttributesBox<'a> + #marker_name {
+            pub trait #extension_name<'a>: HasAttributesBox<'a> + Sized {
                 #(#impls)*
             }
         });

+ 7 - 2
packages/html/src/elements.rs

@@ -111,8 +111,6 @@ macro_rules! impl_element {
         }
 
         impl GlobalAttributes for $name {}
-
-        impl_extension_attributes![ELEMENT $name { $($fil,)* }];
     };
 
     (
@@ -289,6 +287,13 @@ macro_rules! builder_constructors {
                 }
             );
         )*
+
+        pub(crate) mod extensions {
+            use super::*;
+            $(
+                impl_extension_attributes![ELEMENT $name { $($fil,)* }];
+            )*
+        }
     };
 }
 

+ 7 - 0
packages/html/src/lib.rs

@@ -39,7 +39,14 @@ pub use render_template::*;
 
 mod eval;
 
+pub mod extensions {
+    pub use crate::elements::extensions::*;
+    pub use crate::global_attributes::{GlobalAttributesExtension, SvgAttributesExtension};
+}
+
 pub mod prelude {
+    pub use crate::elements::extensions::*;
     pub use crate::eval::*;
     pub use crate::events::*;
+    pub use crate::global_attributes::{GlobalAttributesExtension, SvgAttributesExtension};
 }