1use super::{escape_return_type, parse_pyo3_attrs, Attr};
2
3use proc_macro2::TokenStream as TokenStream2;
4use quote::{quote, ToTokens, TokenStreamExt};
5use syn::{Error, Field, ImplItemFn, Result, Type};
6
7#[derive(Debug)]
8pub struct MemberInfo {
9 name: String,
10 r#type: Type,
11}
12
13impl MemberInfo {
14 pub fn is_candidate_item(item: &ImplItemFn) -> Result<bool> {
15 let attrs: Vec = parse_pyo3_attrs(&item.attrs)?;
16 Ok(attrs.iter().any(|attr: &Attr| matches!(attr, Attr::Getter(_))))
17 }
18
19 pub fn is_candidate_field(field: &Field) -> Result<bool> {
20 let Field { attrs: &Vec, .. } = field;
21 Ok(parse_pyo3_attrsIter<'_, Attr>(attrs)?
22 .iter()
23 .any(|attr: &Attr| matches!(attr, Attr::Get)))
24 }
25}
26
27impl TryFrom<ImplItemFn> for MemberInfo {
28 type Error = Error;
29 fn try_from(item: ImplItemFn) -> Result<Self> {
30 assert!(Self::is_candidate_item(&item)?);
31 let ImplItemFn { attrs: &Vec, sig: &Signature, .. } = &item;
32 let attrs: Vec = parse_pyo3_attrs(attrs)?;
33 for attr: Attr in attrs {
34 if let Attr::Getter(name: Option) = attr {
35 return Ok(MemberInfo {
36 name: name.unwrap_or(default:sig.ident.to_string()),
37 r#type: escape_return_type(&sig.output).expect(msg:"Getter must return a type"),
38 });
39 }
40 }
41 unreachable!("Not a getter: {:?}", item)
42 }
43}
44
45impl TryFrom<Field> for MemberInfo {
46 type Error = Error;
47 fn try_from(field: Field) -> Result<Self> {
48 let Field {
49 ident: Option, ty: Type, attrs: Vec, ..
50 } = field;
51 let mut field_name: Option = None;
52 for attr: Attr in parse_pyo3_attrs(&attrs)? {
53 if let Attr::Name(name: String) = attr {
54 field_name = Some(name);
55 }
56 }
57 Ok(Self {
58 name: field_name.unwrap_or(default:ident.unwrap().to_string()),
59 r#type: ty,
60 })
61 }
62}
63
64impl ToTokens for MemberInfo {
65 fn to_tokens(&self, tokens: &mut TokenStream2) {
66 let Self { name: &String, r#type: ty: &Type } = self;
67 let name: &str = name.strip_prefix("get_").unwrap_or(default:name);
68 tokens.append_all(iter:quote! {
69 ::pyo3_stub_gen::type_info::MemberInfo {
70 name: #name,
71 r#type: <#ty as ::pyo3_stub_gen::PyStubType>::type_output
72 }
73 })
74 }
75}
76