| 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 | |