diff --git a/derive/src/pyclass.rs b/derive/src/pyclass.rs index c5089ef15..7817dfca1 100644 --- a/derive/src/pyclass.rs +++ b/derive/src/pyclass.rs @@ -1,7 +1,7 @@ use super::Diagnostic; use crate::util::{ def_to_name, module_class_name, optional_attribute_arg, path_eq, strip_prefix, ItemIdent, - ItemMeta, + ItemMeta, ItemType, }; use proc_macro2::{Span, TokenStream as TokenStream2}; use quote::{quote, quote_spanned, ToTokens}; @@ -160,13 +160,10 @@ impl Class { }) } - fn extract_item_from_syn( - &mut self, - attrs: &mut Vec, - ident: &Ident, - ) -> Result<(), Diagnostic> { + fn extract_item_from_syn(&mut self, item: &mut ItemIdent) -> Result<(), Diagnostic> { let mut attr_idxs = Vec::new(); - for (i, meta) in attrs + for (i, meta) in item + .attrs .iter() .filter_map(|attr| attr.parse_meta().ok()) .enumerate() @@ -176,11 +173,12 @@ impl Class { Some(name) => name, None => continue, }; + assert!(item.typ == ItemType::Method); let item = match name.to_string().as_str() { - "pymethod" => Self::extract_method(ident, meta)?, - "pyclassmethod" => Self::extract_classmethod(ident, meta)?, - "pyproperty" => Self::extract_property(ident, meta)?, - "pyslot" => Self::extract_slot(ident, meta)?, + "pymethod" => Self::extract_method(item.ident, meta)?, + "pyclassmethod" => Self::extract_classmethod(item.ident, meta)?, + "pyproperty" => Self::extract_property(item.ident, meta)?, + "pyslot" => Self::extract_slot(item.ident, meta)?, _ => { continue; } @@ -190,7 +188,7 @@ impl Class { } let mut i = 0; let mut attr_idxs = &*attr_idxs; - attrs.retain(|_| { + item.attrs.retain(|_| { let drop = attr_idxs.first().copied() == Some(i); if drop { attr_idxs = &attr_idxs[1..]; @@ -199,7 +197,7 @@ impl Class { !drop }); for (i, idx) in attr_idxs.iter().enumerate() { - attrs.remove(idx - i); + item.attrs.remove(idx - i); } Ok(()) } @@ -211,10 +209,7 @@ fn extract_impl_items(mut items: Vec) -> Result, Option<&Ident>)> = HashMap::new(); @@ -380,6 +375,7 @@ pub fn impl_pyimpl(attr: AttributeArgs, item: Item) -> Result { Some(ItemIdent { + typ: ItemType::Method, attrs, ident: &sig.ident, }) @@ -413,6 +409,7 @@ pub fn impl_pyimpl(attr: AttributeArgs, item: Item) -> Result { Some(ItemIdent { + typ: ItemType::Method, attrs, ident: &sig.ident, }) diff --git a/derive/src/pymodule.rs b/derive/src/pymodule.rs index 38096105c..134d9b4f1 100644 --- a/derive/src/pymodule.rs +++ b/derive/src/pymodule.rs @@ -1,9 +1,9 @@ use super::Diagnostic; -use crate::util::{def_to_name, ItemIdent, ItemMeta}; +use crate::util::{def_to_name, ItemIdent, ItemMeta, ItemType}; use proc_macro2::{Span, TokenStream as TokenStream2}; use quote::{quote, quote_spanned, ToTokens}; use std::collections::HashMap; -use syn::{parse_quote, spanned::Spanned, Attribute, AttributeArgs, Ident, Item, Meta, NestedMeta}; +use syn::{parse_quote, spanned::Spanned, AttributeArgs, Ident, Item, Meta, NestedMeta}; fn meta_to_vec(meta: Meta) -> Result, Meta> { match meta { @@ -128,15 +128,12 @@ impl Module { }) } - fn extract_item_from_syn( - &mut self, - attrs: &mut Vec, - ident: &Ident, - ) -> Result<(), Diagnostic> { + fn extract_item_from_syn(&mut self, item: &mut ItemIdent) -> Result<(), Diagnostic> { let mut attr_idxs = Vec::new(); let mut items = Vec::new(); let mut cfgs = Vec::new(); - for (i, meta) in attrs + for (i, meta) in item + .attrs .iter() .filter_map(|attr| attr.parse_meta().ok()) .enumerate() @@ -148,18 +145,22 @@ impl Module { }; match name.to_string().as_str() { "pyfunction" => { + assert!(item.typ == ItemType::Fn); attr_idxs.push(i); - items.push((Self::extract_function(ident, meta)?, meta_span)); + items.push((Self::extract_function(item.ident, meta)?, meta_span)); } "pyattr" => { + assert!(item.typ == ItemType::Fn); attr_idxs.push(i); - items.push((Self::extract_attr(ident, meta)?, meta_span)); + items.push((Self::extract_attr(item.ident, meta)?, meta_span)); } "pyclass" => { - items.push((Self::extract_class(ident, meta)?, meta_span)); + assert!(item.typ == ItemType::Struct); + items.push((Self::extract_class(item.ident, meta)?, meta_span)); } "pystruct_sequence" => { - items.push((Self::extract_struct_sequence(ident, meta)?, meta_span)); + assert!(item.typ == ItemType::Struct); + items.push((Self::extract_struct_sequence(item.ident, meta)?, meta_span)); } "cfg" => { cfgs.push(meta); @@ -175,7 +176,7 @@ impl Module { } let mut i = 0; let mut attr_idxs = &*attr_idxs; - attrs.retain(|_| { + item.attrs.retain(|_| { let drop = attr_idxs.first().copied() == Some(i); if drop { attr_idxs = &attr_idxs[1..]; @@ -184,7 +185,7 @@ impl Module { !drop }); for (i, idx) in attr_idxs.iter().enumerate() { - attrs.remove(idx - i); + item.attrs.remove(idx - i); } Ok(()) } @@ -199,10 +200,7 @@ fn extract_module_items( let mut module = Module::default(); for item in items.iter_mut() { - push_diag_result!( - diagnostics, - module.extract_item_from_syn(&mut item.attrs, item.ident), - ); + push_diag_result!(diagnostics, module.extract_item_from_syn(item),); } let functions = module @@ -273,11 +271,20 @@ pub fn impl_pymodule(attr: AttributeArgs, item: Item) -> Result Some(ItemIdent { + typ: ItemType::Fn, attrs, ident: &sig.ident, }), - Item::Struct(syn::ItemStruct { attrs, ident, .. }) => Some(ItemIdent { attrs, ident }), - Item::Enum(syn::ItemEnum { attrs, ident, .. }) => Some(ItemIdent { attrs, ident }), + Item::Struct(syn::ItemStruct { attrs, ident, .. }) => Some(ItemIdent { + typ: ItemType::Struct, + attrs, + ident, + }), + Item::Enum(syn::ItemEnum { attrs, ident, .. }) => Some(ItemIdent { + typ: ItemType::Enum, + attrs, + ident, + }), _ => None, }) .collect(); diff --git a/derive/src/util.rs b/derive/src/util.rs index d57d25404..6bc8a8e36 100644 --- a/derive/src/util.rs +++ b/derive/src/util.rs @@ -75,7 +75,16 @@ pub fn strip_prefix<'a>(s: &'a str, prefix: &str) -> Option<&'a str> { } } +#[derive(PartialEq)] +pub enum ItemType { + Fn, + Method, + Struct, + Enum, +} + pub struct ItemIdent<'a> { + pub typ: ItemType, pub attrs: &'a mut Vec, pub ident: &'a Ident, }