Skip to content

Commit 287aebf

Browse files
committed
glib-macros: add ObjectImpl derive
1 parent 402a127 commit 287aebf

File tree

4 files changed

+128
-35
lines changed

4 files changed

+128
-35
lines changed

glib-macros/src/lib.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ mod downgrade_derive;
88
mod enum_derive;
99
mod error_domain_derive;
1010
mod flags_attribute;
11+
mod object_impl_derive;
1112
mod object_interface_attribute;
1213
mod object_subclass_attribute;
1314
mod properties;
@@ -965,7 +966,6 @@ pub fn derive_props(input: TokenStream) -> TokenStream {
965966
}
966967

967968
#[proc_macro_attribute]
968-
#[proc_macro_error::proc_macro_error]
969969
pub fn clone_block(_attr: TokenStream, item: TokenStream) -> TokenStream {
970970
let mut item = syn::parse_macro_input!(item as syn::Item);
971971
let errors = deluxe::Errors::new();
@@ -975,11 +975,17 @@ pub fn clone_block(_attr: TokenStream, item: TokenStream) -> TokenStream {
975975
}
976976

977977
#[proc_macro_attribute]
978-
#[proc_macro_error]
979978
pub fn wrapper(attr: TokenStream, item: TokenStream) -> TokenStream {
980979
let input = parse_macro_input!(item as syn::ItemStruct);
981980
match wrapper_attribute::impl_wrapper(attr.into(), input) {
982981
Ok(gen) => gen.into(),
983982
Err(e) => e.into_compile_error().into(),
984983
}
985984
}
985+
986+
#[proc_macro_derive(ObjectImpl, attributes(object_impl))]
987+
pub fn object_impl_derive(input: TokenStream) -> TokenStream {
988+
let input = parse_macro_input!(input as DeriveInput);
989+
let gen = object_impl_derive::impl_object_impl(input);
990+
gen.into()
991+
}

glib-macros/src/object_impl_derive.rs

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
use proc_macro2::TokenStream;
2+
use quote::quote;
3+
4+
#[derive(Default, deluxe::ExtractAttributes)]
5+
#[deluxe(attributes(object_impl))]
6+
struct ObjectImpl {
7+
derived_properties: deluxe::Flag,
8+
#[deluxe(map(|e| FlagOrExpr::into_expr(e, "signals")))]
9+
signals: Option<syn::Expr>,
10+
#[deluxe(map(|e| FlagOrExpr::into_expr(e, "constructed")))]
11+
constructed: Option<syn::Expr>,
12+
#[deluxe(map(|e| FlagOrExpr::into_expr(e, "dispose")))]
13+
dispose: Option<syn::Expr>,
14+
}
15+
16+
enum FlagOrExpr {
17+
Flag,
18+
Expr(syn::Expr),
19+
}
20+
21+
impl deluxe::ParseMetaItem for FlagOrExpr {
22+
#[inline]
23+
fn parse_meta_item(
24+
input: syn::parse::ParseStream,
25+
_mode: deluxe::ParseMode,
26+
) -> deluxe::Result<Self> {
27+
Ok(Self::Expr(input.parse()?))
28+
}
29+
#[inline]
30+
fn parse_meta_item_flag(_span: proc_macro2::Span) -> deluxe::Result<Self> {
31+
Ok(Self::Flag)
32+
}
33+
}
34+
35+
impl FlagOrExpr {
36+
#[inline]
37+
fn into_expr(e: Option<Self>, default_name: &str) -> Option<syn::Expr> {
38+
e.map(|e| match e {
39+
Self::Flag => {
40+
let func = syn::Ident::new(default_name, proc_macro2::Span::call_site());
41+
syn::parse_quote! { Self::#func }
42+
}
43+
Self::Expr(expr) => expr,
44+
})
45+
}
46+
}
47+
48+
pub fn impl_object_impl(mut input: syn::DeriveInput) -> TokenStream {
49+
let errors = deluxe::Errors::new();
50+
let ObjectImpl {
51+
derived_properties,
52+
signals,
53+
constructed,
54+
dispose,
55+
} = deluxe::extract_attributes_optional(&mut input, &errors);
56+
57+
let glib = crate::utils::crate_ident_new();
58+
let ident = &input.ident;
59+
let (impl_generics, type_generics, where_clause) = input.generics.split_for_impl();
60+
61+
let properties = derived_properties.is_set().then(|| {
62+
quote! {
63+
fn properties() -> &'static [#glib::ParamSpec] {
64+
Self::derived_properties()
65+
}
66+
fn property(&self, id: ::std::primitive::usize, pspec: &#glib::ParamSpec) -> #glib::Value {
67+
Self::derived_property(self, id, pspec)
68+
}
69+
fn set_property(&self, id: ::std::primitive::usize, value: &#glib::Value, pspec: &#glib::ParamSpec) {
70+
Self::derived_set_property(self, id, value, pspec)
71+
}
72+
}
73+
});
74+
let signals = signals.map(|signals| {
75+
quote! {
76+
fn signals() -> &'static [#glib::subclass::Signal] {
77+
(#signals)()
78+
}
79+
}
80+
});
81+
let constructed = constructed.map(|constructed| {
82+
quote! {
83+
fn constructed(&self) {
84+
(#constructed)(self)
85+
}
86+
}
87+
});
88+
let dispose = dispose.map(|dispose| {
89+
quote! {
90+
fn dispose(&self) {
91+
(#dispose)(self)
92+
}
93+
}
94+
});
95+
quote! {
96+
#errors
97+
impl #impl_generics #glib::subclass::object::ObjectImpl for #ident #type_generics #where_clause {
98+
#properties
99+
#signals
100+
#constructed
101+
#dispose
102+
}
103+
}
104+
}

glib-macros/tests/properties.rs

Lines changed: 14 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,14 @@ use glib::ParamFlags;
77
mod base {
88
use glib::prelude::*;
99
use glib::subclass::prelude::*;
10-
use glib_macros::Properties;
10+
use glib_macros::{ObjectImpl, Properties};
1111
use std::marker::PhantomData;
1212

1313
pub mod imp {
14-
use glib::{ParamSpec, Value};
15-
1614
use super::*;
1715

18-
#[derive(Properties, Default)]
16+
#[derive(Default, ObjectImpl, Properties)]
17+
#[object_impl(derived_properties)]
1918
#[properties(wrapper_type = super::Base)]
2019
pub struct Base {
2120
#[property(get = Self::not_overridden)]
@@ -24,18 +23,6 @@ mod base {
2423
not_overridden: PhantomData<u32>,
2524
}
2625

27-
impl ObjectImpl for Base {
28-
fn properties() -> &'static [ParamSpec] {
29-
Self::derived_properties()
30-
}
31-
fn set_property(&self, _id: usize, _value: &Value, _pspec: &ParamSpec) {
32-
Self::derived_set_property(self, _id, _value, _pspec)
33-
}
34-
fn property(&self, id: usize, _pspec: &ParamSpec) -> Value {
35-
Self::derived_property(self, id, _pspec)
36-
}
37-
}
38-
3926
#[glib::object_subclass]
4027
impl ObjectSubclass for Base {
4128
const NAME: &'static str = "MyBase";
@@ -60,7 +47,7 @@ mod base {
6047
mod foo {
6148
use glib::prelude::*;
6249
use glib::subclass::prelude::*;
63-
use glib_macros::Properties;
50+
use glib_macros::{ObjectImpl, Properties};
6451
use once_cell::sync::OnceCell;
6552
use std::cell::Cell;
6653
use std::cell::RefCell;
@@ -87,12 +74,14 @@ mod foo {
8774
}
8875

8976
pub mod imp {
90-
use glib::{ParamSpec, Value};
9177
use std::rc::Rc;
9278

79+
use glib::subclass::Signal;
80+
9381
use super::*;
9482

95-
#[derive(Properties, Default)]
83+
#[derive(Default, ObjectImpl, Properties)]
84+
#[object_impl(derived_properties, signals, constructed = Self::my_constructed, dispose)]
9685
#[properties(wrapper_type = super::Foo)]
9786
pub struct Foo {
9887
#[property(get, set)]
@@ -155,18 +144,6 @@ mod foo {
155144
send_weak_ref_prop: glib::SendWeakRef<glib::Object>,
156145
}
157146

158-
impl ObjectImpl for Foo {
159-
fn properties() -> &'static [ParamSpec] {
160-
Self::derived_properties()
161-
}
162-
fn set_property(&self, _id: usize, _value: &Value, _pspec: &ParamSpec) {
163-
Self::derived_set_property(self, _id, _value, _pspec)
164-
}
165-
fn property(&self, id: usize, _pspec: &ParamSpec) -> Value {
166-
Self::derived_property(self, id, _pspec)
167-
}
168-
}
169-
170147
#[glib::object_subclass]
171148
impl ObjectSubclass for Foo {
172149
const NAME: &'static str = "MyFoo";
@@ -182,11 +159,16 @@ mod foo {
182159
String::from("Hello world!")
183160
}
184161
fn set_fizz(&self, value: String) {
185-
*self.fizz.borrow_mut() = format!("custom set: {}", value);
162+
*self.fizz.borrow_mut() = format!("custom set: {value}");
186163
}
187164
fn overridden(&self) -> u32 {
188165
43
189166
}
167+
fn signals() -> &'static [Signal] {
168+
&[]
169+
}
170+
fn my_constructed(&self) {}
171+
fn dispose(&self) {}
190172
}
191173
}
192174

glib/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ pub use ffi;
1111
pub use glib_macros::cstr_bytes;
1212
pub use glib_macros::{
1313
clone, clone_block, closure, closure_local, flags, object_interface, object_subclass,
14-
wrapper as wrapper_attr, Boxed, Downgrade, Enum, ErrorDomain, Properties, SharedBoxed, Variant,
14+
wrapper as wrapper_attr, Boxed, Downgrade, Enum, ErrorDomain, ObjectImpl, Properties,
15+
SharedBoxed, Variant,
1516
};
1617
pub use gobject_ffi;
1718
#[doc(hidden)]

0 commit comments

Comments
 (0)