1 | use super::{escape_return_type, parse_pyo3_attrs, Attr}; |
2 | |
3 | use proc_macro2::TokenStream as TokenStream2; |
4 | use quote::{quote, ToTokens, TokenStreamExt}; |
5 | use syn::{Error, Field, ImplItemFn, Result, Type}; |
6 | |
7 | #[derive (Debug)] |
8 | pub struct MemberInfo { |
9 | name: String, |
10 | r#type: Type, |
11 | } |
12 | |
13 | impl 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 | |
27 | impl 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 | |
45 | impl 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 | |
64 | impl 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 | |