Skip to content

Commit

Permalink
Merge pull request #1127 from yuraiz/with-derived-properties
Browse files Browse the repository at this point in the history
glib-macros: Add `use_derived_properties` macro
  • Loading branch information
ranfdev committed Jul 7, 2023
2 parents 6b43d6f + 11d20e6 commit 2660212
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 56 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
@@ -1,6 +1,8 @@
# Change Log

## [Unreleased]
Yuri Izmer:
- glib-macros: Add `derived_properties` macro

## [0.17.10]
Ben Kimock:
Expand Down
76 changes: 76 additions & 0 deletions glib-macros/src/derived_properties_attribute.rs
@@ -0,0 +1,76 @@
// Take a look at the license at the top of the repository in the LICENSE file.

use proc_macro2::TokenStream;
use proc_macro_error::abort_call_site;
use quote::quote;

pub const WRONG_PLACE_MSG: &str =
"This macro should be used on `impl` block for `glib::ObjectImpl` trait";

pub fn impl_derived_properties(input: &syn::ItemImpl) -> TokenStream {
let syn::ItemImpl {
attrs,
generics,
trait_,
self_ty,
items,
..
} = input;

let trait_path = match &trait_ {
Some(path) => &path.1,
None => abort_call_site!(WRONG_PLACE_MSG),
};

let mut has_property = false;
let mut has_properties = false;
let mut has_set_property = false;

for item in items {
if let syn::ImplItem::Fn(method) = item {
let ident = &method.sig.ident;

if ident == "properties" {
has_properties = true;
} else if ident == "set_property" {
has_set_property = true;
} else if ident == "property" {
has_property = true;
}
}
}

let crate_ident = crate::utils::crate_ident_new();

let properties = quote!(
fn properties() -> &'static [#crate_ident::ParamSpec] {
Self::derived_properties()
}
);

let set_property = quote!(
fn set_property(&self, id: usize, value: &#crate_ident::Value, pspec: &#crate_ident::ParamSpec) {
Self::derived_set_property(self, id, value, pspec)
}
);

let property = quote!(
fn property(&self, id: usize, pspec: &#crate_ident::ParamSpec) -> #crate_ident::Value {
Self::derived_property(self, id, pspec)
}
);

let generated = [
(!has_properties).then_some(properties),
(!has_set_property).then_some(set_property),
(!has_property).then_some(property),
];

quote!(
#(#attrs)*
impl #generics #trait_path for #self_ty {
#(#items)*
#(#generated)*
}
)
}
42 changes: 29 additions & 13 deletions glib-macros/src/lib.rs
Expand Up @@ -3,6 +3,7 @@
mod boxed_derive;
mod clone;
mod closure;
mod derived_properties_attribute;
mod downgrade_derive;
mod enum_derive;
mod error_domain_derive;
Expand Down Expand Up @@ -942,7 +943,6 @@ pub fn cstr_bytes(item: TokenStream) -> TokenStream {
/// }
///
/// pub mod imp {
/// use glib::{ParamSpec, Value};
/// use std::rc::Rc;
///
/// use super::*;
Expand All @@ -966,18 +966,9 @@ pub fn cstr_bytes(item: TokenStream) -> TokenStream {
/// #[property(get, set)]
/// smart_pointer: Rc<RefCell<String>>,
/// }
///
/// impl ObjectImpl for Foo {
/// fn properties() -> &'static [ParamSpec] {
/// Self::derived_properties()
/// }
/// fn set_property(&self, id: usize, value: &Value, pspec: &ParamSpec) {
/// self.derived_set_property(id, value, pspec)
/// }
/// fn property(&self, id: usize, pspec: &ParamSpec) -> Value {
/// self.derived_property(id, pspec)
/// }
/// }
///
/// #[glib::derived_properties]
/// impl ObjectImpl for Foo {}
///
/// #[glib::object_subclass]
/// impl ObjectSubclass for Foo {
Expand Down Expand Up @@ -1010,6 +1001,31 @@ pub fn derive_props(input: TokenStream) -> TokenStream {
properties::impl_derive_props(input)
}

/// This macro is shorteng for:
///
/// ```ignore
/// fn properties() -> &'static [glib::ParamSpec] {
/// Self::derived_properties()
/// }
/// fn set_property(&self, id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
/// self.derived_set_property(id, value, pspec)
/// }
/// fn property(&self, id: usize, pspec: &glib::ParamSpec) -> glib::Value {
/// self.derived_property(id, pspec)
/// }
/// ```
///
/// for ObjectImpl trait implementation
#[proc_macro_attribute]
#[proc_macro_error]
pub fn derived_properties(_attr: TokenStream, item: TokenStream) -> TokenStream {
use proc_macro_error::abort_call_site;
match syn::parse::<syn::ItemImpl>(item) {
Ok(input) => derived_properties_attribute::impl_derived_properties(&input).into(),
Err(_) => abort_call_site!(derived_properties_attribute::WRONG_PLACE_MSG),
}
}

/// # Example
/// ```
/// use glib::prelude::*;
Expand Down
49 changes: 8 additions & 41 deletions glib-macros/tests/properties.rs
Expand Up @@ -11,8 +11,6 @@ mod base {
use std::marker::PhantomData;

pub mod imp {
use glib::{ParamSpec, Value};

use super::*;

#[derive(Properties, Default)]
Expand All @@ -24,17 +22,8 @@ mod base {
not_overridden: PhantomData<u32>,
}

impl ObjectImpl for Base {
fn properties() -> &'static [ParamSpec] {
Self::derived_properties()
}
fn set_property(&self, _id: usize, _value: &Value, _pspec: &ParamSpec) {
Self::derived_set_property(self, _id, _value, _pspec)
}
fn property(&self, id: usize, _pspec: &ParamSpec) -> Value {
Self::derived_property(self, id, _pspec)
}
}
#[glib::derived_properties]
impl ObjectImpl for Base {}

#[glib::object_subclass]
impl ObjectSubclass for Base {
Expand Down Expand Up @@ -90,7 +79,6 @@ mod foo {
}

pub mod imp {
use glib::{ParamSpec, Value};
use std::rc::Rc;

use super::*;
Expand Down Expand Up @@ -166,25 +154,16 @@ mod foo {
construct_only_custom_setter: OnceCell<Option<String>>,
}

impl ObjectImpl for Foo {
fn properties() -> &'static [ParamSpec] {
Self::derived_properties()
}
fn set_property(&self, _id: usize, _value: &Value, _pspec: &ParamSpec) {
Self::derived_set_property(self, _id, _value, _pspec)
}
fn property(&self, id: usize, _pspec: &ParamSpec) -> Value {
Self::derived_property(self, id, _pspec)
}
}

#[glib::object_subclass]
impl ObjectSubclass for Foo {
const NAME: &'static str = "MyFoo";
type Type = super::Foo;
type ParentType = Base;
}

#[glib::derived_properties]
impl ObjectImpl for Foo {}

impl Foo {
fn set_author_name(&self, value: String) {
self.author.borrow_mut().name = value;
Expand Down Expand Up @@ -417,10 +396,7 @@ mod kw_names {
use glib::ObjectExt;
use std::cell::Cell;

use glib::{
subclass::{prelude::ObjectImpl, types::ObjectSubclass},
ParamSpec, Value,
};
use glib::subclass::{prelude::ObjectImpl, types::ObjectSubclass};
use glib_macros::Properties;

#[derive(Properties, Default)]
Expand Down Expand Up @@ -461,17 +437,8 @@ mod kw_names {
type Type = super::KwNames;
}

impl ObjectImpl for KwNames {
fn properties() -> &'static [ParamSpec] {
Self::derived_properties()
}
fn set_property(&self, _id: usize, _value: &Value, _pspec: &ParamSpec) {
Self::derived_set_property(self, _id, _value, _pspec)
}
fn property(&self, id: usize, _pspec: &ParamSpec) -> Value {
Self::derived_property(self, id, _pspec)
}
}
#[glib::derived_properties]
impl ObjectImpl for KwNames {}
}

glib::wrapper! {
Expand Down
4 changes: 2 additions & 2 deletions glib/src/lib.rs
Expand Up @@ -10,8 +10,8 @@ pub use ffi;
#[doc(hidden)]
pub use glib_macros::cstr_bytes;
pub use glib_macros::{
clone, closure, closure_local, flags, object_interface, object_subclass, Boxed, Downgrade,
Enum, ErrorDomain, Properties, SharedBoxed, ValueDelegate, Variant,
clone, closure, closure_local, derived_properties, flags, object_interface, object_subclass,
Boxed, Downgrade, Enum, ErrorDomain, Properties, SharedBoxed, ValueDelegate, Variant,
};
pub use gobject_ffi;
#[doc(hidden)]
Expand Down

0 comments on commit 2660212

Please sign in to comment.