Skip to content

Commit 8c9d1a4

Browse files
authored
Merge pull request #959 from pbor/prop-override
macros: support overrides in the properties macro
2 parents aa525e2 + b918bee commit 8c9d1a4

File tree

2 files changed

+115
-5
lines changed

2 files changed

+115
-5
lines changed

glib-macros/src/properties.rs

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ enum PropAttr {
8585
Get(Option<syn::Expr>),
8686
Set(Option<syn::Expr>),
8787

88+
// ident [= expr]
89+
OverrideClass(syn::Type),
90+
OverrideInterface(syn::Type),
91+
8892
// ident = expr
8993
Type(syn::Type),
9094

@@ -112,6 +116,8 @@ impl Parse for PropAttr {
112116
"name" => PropAttr::Name(input.parse()?),
113117
"get" => PropAttr::Get(Some(input.parse()?)),
114118
"set" => PropAttr::Set(Some(input.parse()?)),
119+
"override_class" => PropAttr::OverrideClass(input.parse()?),
120+
"override_interface" => PropAttr::OverrideInterface(input.parse()?),
115121
"type" => PropAttr::Type(input.parse()?),
116122
"member" => PropAttr::Member(input.parse()?),
117123
// Special case "default = ..." and map it to .default_value(...)
@@ -138,8 +144,7 @@ impl Parse for PropAttr {
138144
}
139145
}
140146
} else {
141-
// attributes with only the identifier
142-
// name
147+
// attributes with only the identifier name
143148
match &*name_str {
144149
"get" => PropAttr::Get(None),
145150
"set" => PropAttr::Set(None),
@@ -163,12 +168,15 @@ impl Parse for PropAttr {
163168
struct ReceivedAttrs {
164169
get: Option<MaybeCustomFn>,
165170
set: Option<MaybeCustomFn>,
171+
override_class: Option<syn::Type>,
172+
override_interface: Option<syn::Type>,
166173
ty: Option<syn::Type>,
167174
member: Option<syn::Ident>,
168175
name: Option<syn::LitStr>,
169176
builder: Option<(Punctuated<syn::Expr, Token![,]>, TokenStream2)>,
170177
builder_fields: HashMap<syn::Ident, Option<syn::Expr>>,
171178
}
179+
172180
impl ReceivedAttrs {
173181
fn new(
174182
attrs_span: &proc_macro2::Span,
@@ -185,13 +193,24 @@ impl ReceivedAttrs {
185193
"No `get` or `set` specified: at least one is required.".to_string(),
186194
));
187195
}
196+
197+
if this.override_class.is_some() && this.override_interface.is_some() {
198+
return Err(syn::Error::new(
199+
*attrs_span,
200+
"Both `override_class` and `override_interface` specified.".to_string(),
201+
));
202+
}
203+
188204
Ok(this)
189205
}
206+
190207
fn set_from_attr(&mut self, attr: PropAttr) {
191208
match attr {
192209
PropAttr::Get(some_fn) => self.get = Some(some_fn.into()),
193210
PropAttr::Set(some_fn) => self.set = Some(some_fn.into()),
194211
PropAttr::Name(lit) => self.name = Some(lit),
212+
PropAttr::OverrideClass(ty) => self.override_class = Some(ty),
213+
PropAttr::OverrideInterface(ty) => self.override_interface = Some(ty),
195214
PropAttr::Type(ty) => self.ty = Some(ty),
196215
PropAttr::Member(member) => self.member = Some(member),
197216
PropAttr::Builder(required_params, optionals) => {
@@ -211,12 +230,15 @@ struct PropDesc {
211230
field_ident: syn::Ident,
212231
ty: syn::Type,
213232
name: syn::LitStr,
233+
override_class: Option<syn::Type>,
234+
override_interface: Option<syn::Type>,
214235
get: Option<MaybeCustomFn>,
215236
set: Option<MaybeCustomFn>,
216237
member: Option<syn::Ident>,
217238
builder: Option<(Punctuated<syn::Expr, Token![,]>, TokenStream2)>,
218239
builder_fields: HashMap<syn::Ident, Option<syn::Expr>>,
219240
}
241+
220242
impl PropDesc {
221243
fn new(
222244
attrs_span: proc_macro2::Span,
@@ -227,6 +249,8 @@ impl PropDesc {
227249
let ReceivedAttrs {
228250
get,
229251
set,
252+
override_class,
253+
override_interface,
230254
ty,
231255
member,
232256
name,
@@ -247,11 +271,13 @@ impl PropDesc {
247271
Ok(Self {
248272
attrs_span,
249273
field_ident,
274+
ty,
275+
name,
276+
override_class,
277+
override_interface,
250278
get,
251279
set,
252-
ty,
253280
member,
254-
name,
255281
builder,
256282
builder_fields,
257283
})
@@ -273,6 +299,19 @@ fn expand_properties_fn(props: &[PropDesc]) -> TokenStream2 {
273299
(None, None) => unreachable!("No `get` or `set` specified"),
274300
};
275301

302+
match (&prop.override_class, &prop.override_interface) {
303+
(Some(c), None) => {
304+
return quote!(#crate_ident::ParamSpecOverride::for_class::<#c>(#name))
305+
}
306+
(None, Some(i)) => {
307+
return quote!(#crate_ident::ParamSpecOverride::for_interface::<#i>(#name))
308+
}
309+
(Some(_), Some(_)) => {
310+
unreachable!("Both `override_class` and `override_interface` specified")
311+
}
312+
(None, None) => (),
313+
};
314+
276315
let builder_call = builder
277316
.as_ref()
278317
.cloned()
@@ -309,6 +348,7 @@ fn expand_properties_fn(props: &[PropDesc]) -> TokenStream2 {
309348
}
310349
)
311350
}
351+
312352
fn expand_property_fn(props: &[PropDesc]) -> TokenStream2 {
313353
let crate_ident = crate_ident_new();
314354
let match_branch_get = props.iter().flat_map(|p| {
@@ -360,6 +400,7 @@ fn expand_property_fn(props: &[PropDesc]) -> TokenStream2 {
360400
}
361401
)
362402
}
403+
363404
fn expand_set_property_fn(props: &[PropDesc]) -> TokenStream2 {
364405
let crate_ident = crate_ident_new();
365406
let match_branch_set = props.iter().flat_map(|p| {

glib-macros/tests/properties.rs

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,59 @@
33
use glib::prelude::*;
44
use glib::ParamFlags;
55

6+
#[cfg(test)]
7+
mod base {
8+
use glib::prelude::*;
9+
use glib::subclass::prelude::*;
10+
use glib_macros::Properties;
11+
use std::marker::PhantomData;
12+
13+
pub mod imp {
14+
use glib::{ParamSpec, Value};
15+
16+
use super::*;
17+
18+
#[derive(Properties, Default)]
19+
#[properties(wrapper_type = super::Base)]
20+
pub struct Base {
21+
#[property(get = Self::not_overridden)]
22+
overridden: PhantomData<u32>,
23+
#[property(get = Self::not_overridden)]
24+
not_overridden: PhantomData<u32>,
25+
}
26+
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+
39+
#[glib::object_subclass]
40+
impl ObjectSubclass for Base {
41+
const NAME: &'static str = "MyBase";
42+
type Type = super::Base;
43+
}
44+
45+
impl Base {
46+
fn not_overridden(&self) -> u32 {
47+
42
48+
}
49+
}
50+
}
51+
52+
glib::wrapper! {
53+
pub struct Base(ObjectSubclass<imp::Base>);
54+
}
55+
56+
unsafe impl<T: ObjectImpl> IsSubclassable<T> for Base {}
57+
}
58+
659
#[cfg(test)]
760
mod foo {
861
use glib::prelude::*;
@@ -14,6 +67,8 @@ mod foo {
1467
use std::marker::PhantomData;
1568
use std::sync::Mutex;
1669

70+
use super::base::Base;
71+
1772
#[derive(Clone, Default, Debug, PartialEq, Eq, glib::Boxed)]
1873
#[boxed_type(name = "SimpleBoxedString")]
1974
pub struct SimpleBoxedString(pub String);
@@ -88,6 +143,8 @@ mod foo {
88143
once_cell: OnceCell<u8>,
89144
#[property(get, set)]
90145
cell: Cell<u8>,
146+
#[property(get = Self::overridden, override_class = Base)]
147+
overridden: PhantomData<u32>,
91148
}
92149

93150
impl ObjectImpl for Foo {
@@ -106,6 +163,7 @@ mod foo {
106163
impl ObjectSubclass for Foo {
107164
const NAME: &'static str = "MyFoo";
108165
type Type = super::Foo;
166+
type ParentType = Base;
109167
}
110168

111169
impl Foo {
@@ -118,11 +176,14 @@ mod foo {
118176
fn set_fizz(&self, value: String) {
119177
*self.fizz.borrow_mut() = format!("custom set: {}", value);
120178
}
179+
fn overridden(&self) -> u32 {
180+
43
181+
}
121182
}
122183
}
123184

124185
glib::wrapper! {
125-
pub struct Foo(ObjectSubclass<imp::Foo>);
186+
pub struct Foo(ObjectSubclass<imp::Foo>) @extends Base;
126187
}
127188
}
128189

@@ -275,4 +336,12 @@ fn props() {
275336
"setter nick".to_string()
276337
);
277338
}
339+
340+
// overrides
341+
{
342+
let overridden: u32 = myfoo.property("overridden");
343+
assert_eq!(overridden, 43);
344+
let not_overridden: u32 = myfoo.property("not-overridden");
345+
assert_eq!(not_overridden, 42);
346+
}
278347
}

0 commit comments

Comments
 (0)