Skip to content

Commit

Permalink
glib-macros: Properties: copy property docs to getter
Browse files Browse the repository at this point in the history
We take the docs directly preceding a `#[property]` and copy them into the
generated getter method.
  • Loading branch information
carlosmn committed Aug 26, 2024
1 parent 98201f9 commit b3b6241
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 22 deletions.
6 changes: 6 additions & 0 deletions glib-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1367,6 +1367,10 @@ pub fn cstr_bytes(item: TokenStream) -> TokenStream {
/// * `connect_$property_notify()`
/// * `notify_$property()`
///
/// # Documentation
///
/// Doc comments preceding a `#[property]` attribute will be copied to the generated getter method.
///
/// ## Extension trait
/// You can choose to move the method definitions to a trait by using `#[properties(wrapper_type = super::MyType, ext_trait = MyTypePropertiesExt)]`.
/// The trait name is optional, and defaults to `MyTypePropertiesExt`, where `MyType` is extracted from the wrapper type.
Expand Down Expand Up @@ -1430,7 +1434,9 @@ pub fn cstr_bytes(item: TokenStream) -> TokenStream {
/// pub struct Foo {
/// #[property(get, set = Self::set_fizz)]
/// fizz: RefCell<String>,
/// /// The author's name
/// #[property(name = "author-name", get, set, type = String, member = name)]
/// /// The author's childhood nickname
/// #[property(name = "author-nick", get, set, type = String, member = nick)]
/// author: RefCell<Author>,
/// #[property(get, set, explicit_notify, lax_validation)]
Expand Down
60 changes: 38 additions & 22 deletions glib-macros/src/properties.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use syn::parse::Parse;
use syn::punctuated::Punctuated;
use syn::spanned::Spanned;
use syn::Token;
use syn::{parse_quote_spanned, LitStr};
use syn::{parse_quote_spanned, Attribute, LitStr};

pub struct PropsMacroInput {
wrapper_ty: syn::Path,
Expand Down Expand Up @@ -255,6 +255,7 @@ struct PropDesc {
field_ident: syn::Ident,
ty: syn::Type,
name: syn::LitStr,
comments: Vec<Attribute>,
override_class: Option<syn::Type>,
override_interface: Option<syn::Type>,
nullable: bool,
Expand All @@ -271,6 +272,7 @@ impl PropDesc {
attrs_span: proc_macro2::Span,
field_ident: syn::Ident,
field_ty: syn::Type,
comments: Vec<Attribute>,
attrs: ReceivedAttrs,
) -> syn::Result<Self> {
let ReceivedAttrs {
Expand Down Expand Up @@ -321,6 +323,7 @@ impl PropDesc {
field_ident,
ty,
name,
comments,
override_class,
override_interface,
nullable,
Expand Down Expand Up @@ -524,26 +527,33 @@ fn expand_set_property_fn(props: &[PropDesc]) -> TokenStream2 {
}

fn parse_fields(fields: syn::Fields) -> syn::Result<Vec<PropDesc>> {
fields
.into_iter()
.flat_map(|field| {
let syn::Field {
ident, attrs, ty, ..
} = field;
attrs
.into_iter()
.filter(|a| a.path().is_ident("property"))
.map(move |prop_attrs| {
let span = prop_attrs.span();
PropDesc::new(
span,
ident.as_ref().unwrap().clone(),
ty.clone(),
prop_attrs.parse_args()?,
)
})
})
.collect::<syn::Result<_>>()
let mut properties = vec![];

for field in fields.into_iter() {
let syn::Field {
ident, attrs, ty, ..
} = field;
// Store the comments until the next `#[property]` we see and then attach them to it.
let mut comments: Vec<Attribute> = vec![];
for prop_attr in attrs.iter() {
if prop_attr.path().is_ident("doc") {
comments.push(prop_attr.clone());
} else if prop_attr.path().is_ident("property") {
let span = prop_attr.span();
let existing_comments = comments;
comments = vec![];
properties.push(PropDesc::new(
span,
ident.as_ref().unwrap().clone(),
ty.clone(),
existing_comments,
prop_attr.parse_args()?,
)?);
}
}
}

Ok(properties)
}

/// Converts a glib property name to a correct rust ident
Expand All @@ -567,7 +577,7 @@ fn expand_impl_getset_properties(props: &[PropDesc]) -> Vec<syn::ImplItemFn> {
let ident = name_to_ident(name);
let ty = &p.ty;

let getter = p.get.is_some().then(|| {
let mut getter: Option<syn::ImplItemFn> = p.get.is_some().then(|| {
let span = p.attrs_span;
parse_quote_spanned!(span=>
#[must_use]
Expand All @@ -578,6 +588,12 @@ fn expand_impl_getset_properties(props: &[PropDesc]) -> Vec<syn::ImplItemFn> {
)
});

if let Some(ref mut getter) = getter {
for lit in &p.comments {
getter.attrs.push(lit.clone());
}
}

let setter = (p.set.is_some() && !p.is_construct_only).then(|| {
let ident = format_ident!("set_{}", ident);
let target_ty = quote!(<<#ty as #crate_ident::property::Property>::Value as #crate_ident::prelude::HasParamSpec>::SetValue);
Expand Down

0 comments on commit b3b6241

Please sign in to comment.