glib_macros/
object_impl_attributes.rs
1pub mod interface;
4pub mod subclass;
5
6use proc_macro2::Span;
7
8use crate::utils::{parse_optional_nested_meta_items, NestedMetaItem};
9
10enum AttrKind {
12 Interface,
13 Subclass,
14}
15
16pub struct Input {
20 attrs: Vec<syn::Attribute>,
21 generics: syn::Generics,
22 trait_path: syn::Path,
23 self_ty: syn::Ident,
24 unsafety: Option<syn::token::Unsafe>,
25 items: Vec<syn::ImplItem>,
26 meta_dynamic: Option<MetaDynamic>,
27}
28
29impl Input {
30 pub fn parse_interface(input: syn::parse::ParseStream) -> syn::Result<Self> {
32 Self::parse(AttrKind::Interface, input)
33 }
34
35 pub fn parse_subclass(input: syn::parse::ParseStream) -> syn::Result<Self> {
37 Self::parse(AttrKind::Subclass, input)
38 }
39
40 fn parse(kind: AttrKind, input: syn::parse::ParseStream) -> syn::Result<Self> {
42 let wrong_place_msg = match kind {
43 AttrKind::Interface => {
44 "This macro should be used on `impl` block for `glib::ObjectInterface` trait"
45 }
46 AttrKind::Subclass => {
47 "This macro should be used on `impl` block for `glib::ObjectSubclass` trait"
48 }
49 };
50
51 let syn::ItemImpl {
52 mut attrs,
53 generics,
54 trait_,
55 self_ty,
56 unsafety,
57 items,
58 ..
59 } = input
60 .parse()
61 .map_err(|_| syn::Error::new(Span::call_site(), wrong_place_msg))?;
62
63 let self_ty = match *self_ty {
65 syn::Type::Path(syn::TypePath { path, .. }) => path.require_ident().cloned(),
66 _ => Err(syn::Error::new(
67 syn::spanned::Spanned::span(&self_ty),
68 "expected this path to be an identifier",
69 )),
70 }?;
71
72 let meta_dynamic = MetaDynamic::parse_and_remove(kind, &mut attrs)?;
73
74 let trait_path = trait_
75 .as_ref()
76 .ok_or_else(|| syn::Error::new(Span::call_site(), wrong_place_msg))?
77 .1
78 .clone();
79
80 Ok(Self {
81 attrs,
82 generics,
83 trait_path,
84 self_ty,
85 unsafety,
86 items,
87 meta_dynamic,
88 })
89 }
90}
91
92struct MetaDynamic {
98 plugin_type: Option<syn::Path>,
99 lazy_registration: bool,
100}
101
102impl MetaDynamic {
103 fn parse_and_remove(
105 kind: AttrKind,
106 attrs: &mut Vec<syn::Attribute>,
107 ) -> syn::Result<Option<Self>> {
108 let attr_name = match kind {
109 AttrKind::Interface => "object_interface_dynamic",
110 AttrKind::Subclass => "object_subclass_dynamic",
111 };
112
113 let mut plugin_type = NestedMetaItem::<syn::Path>::new("plugin_type").value_required();
114 let mut lazy_registration =
115 NestedMetaItem::<syn::LitBool>::new("lazy_registration").value_required();
116
117 let found = parse_optional_nested_meta_items(
118 &*attrs,
119 attr_name,
120 &mut [&mut plugin_type, &mut lazy_registration],
121 )?
122 .is_some();
123
124 if found {
125 attrs.retain(|attr| !attr.path().is_ident(attr_name));
127
128 Ok(Some(Self {
129 plugin_type: plugin_type.value,
130 lazy_registration: lazy_registration.value.map(|b| b.value).unwrap_or_default(),
131 }))
132 } else {
133 Ok(None)
134 }
135 }
136}