mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-02 19:39:49 +09:00
py* macro checks type before generation
This commit is contained in:
@@ -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<Attribute>,
|
||||
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<ItemIdent>) -> Result<TokenStream2, Diagnos
|
||||
let mut class = Class::default();
|
||||
|
||||
for item in items.iter_mut() {
|
||||
push_diag_result!(
|
||||
diagnostics,
|
||||
class.extract_item_from_syn(&mut item.attrs, &item.ident),
|
||||
);
|
||||
push_diag_result!(diagnostics, class.extract_item_from_syn(item),);
|
||||
}
|
||||
|
||||
let mut properties: HashMap<&str, (Option<&Ident>, Option<&Ident>)> = HashMap::new();
|
||||
@@ -380,6 +375,7 @@ pub fn impl_pyimpl(attr: AttributeArgs, item: Item) -> Result<TokenStream2, Diag
|
||||
.filter_map(|item| match item {
|
||||
syn::ImplItem::Method(syn::ImplItemMethod { attrs, sig, .. }) => {
|
||||
Some(ItemIdent {
|
||||
typ: ItemType::Method,
|
||||
attrs,
|
||||
ident: &sig.ident,
|
||||
})
|
||||
@@ -413,6 +409,7 @@ pub fn impl_pyimpl(attr: AttributeArgs, item: Item) -> Result<TokenStream2, Diag
|
||||
.filter_map(|item| match item {
|
||||
syn::TraitItem::Method(syn::TraitItemMethod { attrs, sig, .. }) => {
|
||||
Some(ItemIdent {
|
||||
typ: ItemType::Method,
|
||||
attrs,
|
||||
ident: &sig.ident,
|
||||
})
|
||||
|
||||
@@ -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<Vec<NestedMeta>, Meta> {
|
||||
match meta {
|
||||
@@ -128,15 +128,12 @@ impl Module {
|
||||
})
|
||||
}
|
||||
|
||||
fn extract_item_from_syn(
|
||||
&mut self,
|
||||
attrs: &mut Vec<Attribute>,
|
||||
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<TokenStream2, Di
|
||||
.iter_mut()
|
||||
.filter_map(|item| match item {
|
||||
Item::Fn(syn::ItemFn { attrs, sig, .. }) => 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();
|
||||
|
||||
@@ -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<Attribute>,
|
||||
pub ident: &'a Ident,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user