| 1 | // Take a look at the license at the top of the repository in the LICENSE file. |
| 2 | |
| 3 | use proc_macro2::{Span, TokenStream}; |
| 4 | use quote::quote; |
| 5 | |
| 6 | pub const WRONG_PLACE_MSG: &str = |
| 7 | "This macro should be used on `impl` block for `glib::ObjectImpl` trait" ; |
| 8 | |
| 9 | pub 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 | } |
| 76 | |