1 | // Take a look at the license at the top of the repository in the LICENSE file. |
2 | |
3 | use proc_macro2::TokenStream; |
4 | use proc_macro_error::abort_call_site; |
5 | use quote::quote; |
6 | |
7 | pub const WRONG_PLACE_MSG: &str = |
8 | "This macro should be used on `impl` block for `glib::ObjectSubclass` trait" ; |
9 | |
10 | pub fn impl_object_subclass(input: &syn::ItemImpl) -> TokenStream { |
11 | let mut has_new = false; |
12 | let mut has_parent_type = false; |
13 | let mut has_interfaces = false; |
14 | let mut has_instance = false; |
15 | let mut has_class = false; |
16 | for item in &input.items { |
17 | match item { |
18 | syn::ImplItem::Fn(method) => { |
19 | let name = &method.sig.ident; |
20 | if name == "new" || name == "with_class" { |
21 | has_new = true; |
22 | } |
23 | } |
24 | syn::ImplItem::Type(type_) => { |
25 | let name = &type_.ident; |
26 | if name == "ParentType" { |
27 | has_parent_type = true; |
28 | } else if name == "Interfaces" { |
29 | has_interfaces = true; |
30 | } else if name == "Instance" { |
31 | has_instance = true; |
32 | } else if name == "Class" { |
33 | has_class = true; |
34 | } |
35 | } |
36 | _ => {} |
37 | } |
38 | } |
39 | |
40 | let syn::ItemImpl { |
41 | attrs, |
42 | generics, |
43 | trait_, |
44 | self_ty, |
45 | items, |
46 | .. |
47 | } = &input; |
48 | |
49 | let crate_ident = crate::utils::crate_ident_new(); |
50 | |
51 | let parent_type_opt = (!has_parent_type).then(|| { |
52 | quote!( |
53 | type ParentType = #crate_ident::Object; |
54 | ) |
55 | }); |
56 | |
57 | let interfaces_opt = (!has_interfaces).then(|| { |
58 | quote!( |
59 | type Interfaces = (); |
60 | ) |
61 | }); |
62 | |
63 | let new_opt = (!has_new).then(|| { |
64 | quote! { |
65 | #[inline] |
66 | fn new() -> Self { |
67 | ::std::default::Default::default() |
68 | } |
69 | } |
70 | }); |
71 | |
72 | let class_opt = (!has_class) |
73 | .then(|| quote!(type Class = #crate_ident::subclass::basic::ClassStruct<Self>;)); |
74 | |
75 | let instance_opt = (!has_instance) |
76 | .then(|| quote!(type Instance = #crate_ident::subclass::basic::InstanceStruct<Self>;)); |
77 | |
78 | let trait_path = match &trait_ { |
79 | Some(path) => &path.1, |
80 | None => abort_call_site!(WRONG_PLACE_MSG), |
81 | }; |
82 | |
83 | quote! { |
84 | #(#attrs)* |
85 | impl #generics #trait_path for #self_ty { |
86 | #parent_type_opt |
87 | #interfaces_opt |
88 | #class_opt |
89 | #instance_opt |
90 | #new_opt |
91 | #(#items)* |
92 | } |
93 | |
94 | unsafe impl #crate_ident::subclass::types::ObjectSubclassType for #self_ty { |
95 | #[inline] |
96 | fn type_data() -> ::std::ptr::NonNull<#crate_ident::subclass::TypeData> { |
97 | static mut DATA: #crate_ident::subclass::TypeData = |
98 | #crate_ident::subclass::types::INIT_TYPE_DATA; |
99 | unsafe { ::std::ptr::NonNull::from(&mut DATA) } |
100 | } |
101 | |
102 | #[inline] |
103 | fn type_() -> #crate_ident::Type { |
104 | static ONCE: ::std::sync::Once = ::std::sync::Once::new(); |
105 | |
106 | ONCE.call_once(|| { |
107 | #crate_ident::subclass::register_type::<Self>(); |
108 | }); |
109 | |
110 | unsafe { |
111 | let data = Self::type_data(); |
112 | let type_ = data.as_ref().type_(); |
113 | |
114 | type_ |
115 | } |
116 | } |
117 | } |
118 | |
119 | #[doc(hidden)] |
120 | impl #crate_ident::subclass::types::FromObject for #self_ty { |
121 | type FromObjectType = <Self as #crate_ident::subclass::types::ObjectSubclass>::Type; |
122 | #[inline] |
123 | fn from_object(obj: &Self::FromObjectType) -> &Self { |
124 | <Self as #crate_ident::subclass::types::ObjectSubclassExt>::from_obj(obj) |
125 | } |
126 | } |
127 | |
128 | #[doc(hidden)] |
129 | impl #crate_ident::clone::Downgrade for #self_ty { |
130 | type Weak = #crate_ident::subclass::ObjectImplWeakRef<#self_ty>; |
131 | |
132 | #[inline] |
133 | fn downgrade(&self) -> Self::Weak { |
134 | let ref_counted = #crate_ident::subclass::prelude::ObjectSubclassExt::ref_counted(self); |
135 | #crate_ident::clone::Downgrade::downgrade(&ref_counted) |
136 | } |
137 | } |
138 | |
139 | impl #self_ty { |
140 | #[inline] |
141 | pub fn downgrade(&self) -> <Self as #crate_ident::clone::Downgrade>::Weak { |
142 | #crate_ident::clone::Downgrade::downgrade(self) |
143 | } |
144 | } |
145 | |
146 | #[doc(hidden)] |
147 | impl ::std::borrow::ToOwned for #self_ty { |
148 | type Owned = #crate_ident::subclass::ObjectImplRef<#self_ty>; |
149 | |
150 | #[inline] |
151 | fn to_owned(&self) -> Self::Owned { |
152 | #crate_ident::subclass::prelude::ObjectSubclassExt::ref_counted(self) |
153 | } |
154 | } |
155 | |
156 | #[doc(hidden)] |
157 | impl ::std::borrow::Borrow<#self_ty> for #crate_ident::subclass::ObjectImplRef<#self_ty> { |
158 | #[inline] |
159 | fn borrow(&self) -> &#self_ty { |
160 | self |
161 | } |
162 | } |
163 | } |
164 | } |
165 | |