diff --git a/glib-macros/src/properties.rs b/glib-macros/src/properties.rs index f0d89280b97d..4c7959e2d5db 100644 --- a/glib-macros/src/properties.rs +++ b/glib-macros/src/properties.rs @@ -564,7 +564,7 @@ fn expand_impl_getset_properties(props: &[PropDesc]) -> Vec { let ident = name_to_ident(name); let ty = &p.ty; - let getter = p.get.is_some().then(|| { + let getter = (p.get.is_some() && p.override_class.is_none() && p.override_interface.is_none() ).then(|| { let span = p.attrs_span; parse_quote_spanned!(span=> #[must_use] @@ -573,7 +573,7 @@ fn expand_impl_getset_properties(props: &[PropDesc]) -> Vec { }) }); - let setter = (p.set.is_some() && !p.is_construct_only).then(|| { + let setter = (p.set.is_some() && p.override_class.is_none() && p.override_interface.is_none() && !p.is_construct_only).then(|| { let ident = format_ident!("set_{}", ident); let target_ty = quote!(<<#ty as #crate_ident::Property>::Value as #crate_ident::HasParamSpec>::SetValue); let set_ty = if p.nullable { @@ -618,7 +618,7 @@ fn expand_impl_connect_prop_notify(props: &[PropDesc]) -> Vec { connection_fns.collect::>() } -fn expand_impl_notify_prop(props: &[PropDesc]) -> Vec { +fn expand_impl_notify_prop(wrapper_type: &syn::Path, props: &[PropDesc]) -> Vec { let crate_ident = crate_ident_new(); let emit_fns = props.iter().map(|p| -> syn::ImplItemFn { let name = strip_raw_prefix_from_name(&p.name); @@ -627,7 +627,7 @@ fn expand_impl_notify_prop(props: &[PropDesc]) -> Vec { let enum_ident = name_to_enum_ident(name.value()); parse_quote_spanned!(span=> pub fn #fn_ident(&self) { self.notify_by_pspec( - &<::Subclass + &<<#wrapper_type as #crate_ident::object::ObjectSubclassIs>::Subclass as #crate_ident::subclass::object::DerivedObjectProperties>::derived_properties() [DerivedPropertiesEnum::#enum_ident as usize] ); @@ -692,7 +692,7 @@ pub fn impl_derive_props(input: PropsMacroInput) -> TokenStream { let fn_set_property = expand_set_property_fn(&input.props); let getset_properties = expand_impl_getset_properties(&input.props); let connect_prop_notify = expand_impl_connect_prop_notify(&input.props); - let notify_prop = expand_impl_notify_prop(&input.props); + let notify_prop = expand_impl_notify_prop(&wrapper_type, &input.props); let properties_enum = expand_properties_enum(&input.props); let rust_interface = if let Some(ext_trait) = input.ext_trait { @@ -704,17 +704,7 @@ pub fn impl_derive_props(input: PropsMacroInput) -> TokenStream { wrapper_type.segments.last().unwrap().ident ) }; - let signatures = getset_properties - .iter() - .chain(connect_prop_notify.iter()) - .chain(notify_prop.iter()) - .map(|item| &item.sig); - let trait_def = quote! { - pub trait #trait_ident { - #(#signatures;)* - } - }; - let impls = getset_properties + let fns_without_visibility_modifier = getset_properties .into_iter() .chain(connect_prop_notify) .chain(notify_prop) @@ -723,10 +713,10 @@ pub fn impl_derive_props(input: PropsMacroInput) -> TokenStream { item }); quote! { - #trait_def - impl #trait_ident for #wrapper_type { - #(#impls)* + pub trait #trait_ident: #crate_ident::IsA<#wrapper_type> { + #(#fns_without_visibility_modifier)* } + impl> #trait_ident for T {} } } else { quote! { @@ -740,7 +730,7 @@ pub fn impl_derive_props(input: PropsMacroInput) -> TokenStream { }; let expanded = quote! { - use #crate_ident::{PropertyGet, PropertySet, ToValue}; + use #crate_ident::{PropertyGet, PropertySet, ToValue, Cast}; #properties_enum diff --git a/glib-macros/tests/properties.rs b/glib-macros/tests/properties.rs index e59548cbd21c..83f084dc5f41 100644 --- a/glib-macros/tests/properties.rs +++ b/glib-macros/tests/properties.rs @@ -14,7 +14,7 @@ mod base { use super::*; #[derive(Properties, Default)] - #[properties(wrapper_type = super::Base)] + #[properties(wrapper_type = super::Base, ext_trait)] pub struct Base { #[property(get = Self::not_overridden)] overridden: PhantomData, @@ -388,59 +388,15 @@ fn props() { ); } -mod ext_trait { - use glib::subclass::object::DerivedObjectProperties; - use glib::ObjectExt; - - use glib::subclass::{prelude::ObjectImpl, types::ObjectSubclass}; - use glib_macros::Properties; - use std::cell::RefCell; - - pub mod imp { - use super::*; - - #[derive(Properties, Default)] - #[properties(wrapper_type = super::Author, ext_trait)] - pub struct Author { - #[property(get, set)] - firstname: RefCell, - #[property(get, set)] - lastname: RefCell, - } - - #[glib::derived_properties] - impl ObjectImpl for Author {} - - #[glib::object_subclass] - impl ObjectSubclass for Author { - const NAME: &'static str = "Author"; - type Type = super::Author; - } - } - - glib::wrapper! { - pub struct Author(ObjectSubclass); - } - impl Author { - pub fn new() -> Self { - glib::Object::builder().build() - } - } - impl Default for Author { - fn default() -> Self { - Self::new() - } - } -} - #[test] fn ext_trait() { - use ext_trait::imp::AuthorPropertiesExt; - let author = ext_trait::Author::new(); - AuthorPropertiesExt::set_firstname(&author, "John"); - AuthorPropertiesExt::set_lastname(&author, "Doe"); - assert_eq!(AuthorPropertiesExt::firstname(&author), "John"); - assert_eq!(AuthorPropertiesExt::lastname(&author), "Doe"); + use base::imp::BasePropertiesExt; + let base: base::Base = glib::object::Object::builder().build(); + assert_eq!(BasePropertiesExt::overridden(&base), 42); + + let foo: foo::Foo = glib::object::Object::builder().build(); + assert_eq!(BasePropertiesExt::overridden(&foo), 43); + assert_eq!(foo.overridden(), 43); } #[test]