gtk_properties_macro/
lib.rs

1#![feature(proc_macro_diagnostic)]
2use proc_macro::TokenStream;
3use quote::quote;
4use syn::parse_macro_input;
5
6mod generate;
7mod parse;
8
9#[proc_macro]
10pub fn properties(tokens: TokenStream) -> TokenStream {
11    let properties = parse_macro_input!(tokens as parse::Properties);
12
13    let mut param_specs: Vec<proc_macro2::TokenStream> = vec![];
14    let mut getters: Vec<proc_macro2::TokenStream> = vec![];
15    let mut setters: Vec<proc_macro2::TokenStream> = vec![];
16
17    for (index, property) in properties.0 .0.into_iter().enumerate() {
18        let id = index + 1;
19        let (param_spec, getter, setter) = generate::property(id, property);
20        param_specs.push(param_spec);
21        if let Some(getter) = getter {
22            getters.push(getter);
23        }
24        if let Some(setter) = setter {
25            setters.push(setter);
26        }
27    }
28
29    TokenStream::from(quote! {
30        fn properties() -> &'static [gtk::glib::ParamSpec] {
31            use once_cell::sync::Lazy;
32            use gtk::glib::*;
33            static PROPERTIES: Lazy<Vec<ParamSpec>> = Lazy::new(|| {
34                vec![#(#param_specs),*]
35            });
36            PROPERTIES.as_ref()
37        }
38
39        fn property(&self, object: &Self::Type, id: usize, pspec: &gtk::glib::ParamSpec) -> gtk::glib::Value {
40            use gtk::glib::prelude::*;
41            match id {
42                #(#getters),*
43                _ => unimplemented!()
44            }
45        }
46
47        fn set_property(&self, object: &Self::Type, id: usize, value: &gtk::glib::Value, pspec: &gtk::glib::ParamSpec) {
48            use gtk::glib::prelude::*;
49            match id {
50                #(#setters),*
51                _ => unimplemented!()
52            }
53        }
54    })
55}
56
57#[test]
58fn test_expansion() {
59    macrotest::expand("tests/expand/*.rs");
60}