From b60671e0feaa8cd61efe6965194bb3b11a822b7c Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Wed, 27 Sep 2023 10:02:49 -0500 Subject: [PATCH] fix non extending attributes --- examples/spread.rs | 7 +-- packages/core-macro/src/props/mod.rs | 65 +++++++++++++++++-------- packages/core/src/lib.rs | 8 +-- packages/html-internal-macro/src/lib.rs | 22 +++------ packages/html/src/elements.rs | 9 +++- packages/html/src/lib.rs | 7 +++ 6 files changed, 70 insertions(+), 48 deletions(-) diff --git a/examples/spread.rs b/examples/spread.rs index f3be4d2b7..70d677201 100644 --- a/examples/spread.rs +++ b/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); diff --git a/packages/core-macro/src/props/mod.rs b/packages/core-macro/src/props/mod.rs index 6285643c5..6b5ad30f3 100644 --- a/packages/core-macro/src/props/mod.rs +++ b/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,22 +881,23 @@ Finally, call `.build()` to create the instance of `{name}`. quote!(#name: self.#name) }); - 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(), - path.span(), - ); - quote! { - impl #impl_generics #marker_name 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", ))?; + 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!("{}Extension", &camel_name).as_str(), + path.span(), + ); + quote! { + impl #impl_generics dioxus_elements::extensions::#marker_name < #extend_lifetime > for #builder_name < #( #ty_generics ),* > #where_clause {} + } + }); + Ok(quote! { impl #impl_generics ::dioxus::prelude::HasAttributesBox<#extend_lifetime> for #builder_name < #( #ty_generics ),* > #where_clause { fn push_attribute( @@ -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, } diff --git a/packages/core/src/lib.rs b/packages/core/src/lib.rs index 5723e9418..5fb5d7ba3 100644 --- a/packages/core/src/lib.rs +++ b/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, }; } diff --git a/packages/html-internal-macro/src/lib.rs b/packages/html-internal-macro/src/lib.rs index 99c3db0d1..3de23f6d6 100644 --- a/packages/html-internal-macro/src/lib.rs +++ b/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)* } }); diff --git a/packages/html/src/elements.rs b/packages/html/src/elements.rs index ab9b6ea32..a004f65a2 100644 --- a/packages/html/src/elements.rs +++ b/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,)* }]; + )* + } }; } diff --git a/packages/html/src/lib.rs b/packages/html/src/lib.rs index 2fc1baeac..b3fccb4c9 100644 --- a/packages/html/src/lib.rs +++ b/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}; }