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