glib_macros/
derived_properties_attribute.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use proc_macro2::{Span, TokenStream};
4use quote::quote;
5
6pub const WRONG_PLACE_MSG: &str =
7    "This macro should be used on `impl` block for `glib::ObjectImpl` trait";
8
9pub fn impl_derived_properties(input: &syn::ItemImpl) -> syn::Result<TokenStream> {
10    let syn::ItemImpl {
11        attrs,
12        generics,
13        trait_,
14        self_ty,
15        items,
16        ..
17    } = input;
18
19    let trait_path = &trait_
20        .as_ref()
21        .ok_or_else(|| syn::Error::new(Span::call_site(), WRONG_PLACE_MSG))?
22        .1;
23
24    let mut has_property = false;
25    let mut has_properties = false;
26    let mut has_set_property = false;
27
28    for item in items {
29        if let syn::ImplItem::Fn(method) = item {
30            let ident = &method.sig.ident;
31
32            if ident == "properties" {
33                has_properties = true;
34            } else if ident == "set_property" {
35                has_set_property = true;
36            } else if ident == "property" {
37                has_property = true;
38            }
39        }
40    }
41
42    let crate_ident = crate::utils::crate_ident_new();
43
44    let properties = quote!(
45        fn properties() -> &'static [#crate_ident::ParamSpec] {
46            Self::derived_properties()
47        }
48    );
49
50    let set_property = quote!(
51        fn set_property(&self, id: usize, value: &#crate_ident::Value, pspec: &#crate_ident::ParamSpec) {
52            Self::derived_set_property(self, id, value, pspec)
53        }
54    );
55
56    let property = quote!(
57        fn property(&self, id: usize, pspec: &#crate_ident::ParamSpec) -> #crate_ident::Value {
58            Self::derived_property(self, id, pspec)
59        }
60    );
61
62    let generated = [
63        (!has_properties).then_some(properties),
64        (!has_set_property).then_some(set_property),
65        (!has_property).then_some(property),
66    ];
67
68    Ok(quote!(
69        #(#attrs)*
70        impl #generics #trait_path for #self_ty {
71            #(#items)*
72            #(#generated)*
73        }
74    ))
75}