multiple error tracking

This commit is contained in:
Jeong YunWon committed 2020-08-23 18:30:14 +09:00
1 parent 2458307dc3
commit 29dc4dabbb
3 files changed
+138 -103

No files matched your search

+65 -60
View File
@@ -16,92 +16,99 @@ use syn_ext::ext::*;
struct ImplContext {
impl_extend_items: ItemNursery,
getset_items: GetSetNursery,
errors: Vec<syn::Error>,
}
pub(crate) fn impl_pyimpl(
attr: AttributeArgs,
item: Item,
) -> std::result::Result<TokenStream, Diagnostic> {
match item {
let mut context = ImplContext::default();
let mut tokens = match item {
Item::Impl(mut imp) => {
let mut context = ImplContext::default();
for item in imp.items.iter_mut() {
item.try_split_attr_mut(|attrs, item| {
let r = item.try_split_attr_mut(|attrs, item| {
let (pyitems, cfgs) =
attrs_to_content_items(&attrs, new_impl_item::<syn::ImplItem>)?;
for pyitem in pyitems.iter().rev() {
pyitem.gen_impl_item(ImplItemArgs {
let r = pyitem.gen_impl_item(ImplItemArgs {
item,
attrs,
context: &mut context,
cfgs: cfgs.as_slice(),
})?;
});
context.errors.ok_or_push(r);
}
Ok(())
})?;
});
context.errors.ok_or_push(r);
}
context.getset_items.validate()?;
context.errors.ok_or_push(context.getset_items.validate());
let tokens = {
let (with_impl, flags) = extract_impl_attrs(attr)?;
let ty = &imp.self_ty;
let getset_impl = &context.getset_items;
let extend_impl = &context.impl_extend_items;
quote! {
#imp
impl ::rustpython_vm::pyobject::PyClassImpl for #ty {
const TP_FLAGS: ::rustpython_vm::slots::PyTpFlags = ::rustpython_vm::slots::PyTpFlags::from_bits_truncate(#flags);
let (with_impl, flags) = extract_impl_attrs(attr)?;
let ty = &imp.self_ty;
let getset_impl = &context.getset_items;
let extend_impl = &context.impl_extend_items;
quote! {
#imp
impl ::rustpython_vm::pyobject::PyClassImpl for #ty {
const TP_FLAGS: ::rustpython_vm::slots::PyTpFlags = ::rustpython_vm::slots::PyTpFlags::from_bits_truncate(#flags);
fn impl_extend_class(
ctx: &::rustpython_vm::pyobject::PyContext,
class: &::rustpython_vm::obj::objtype::PyClassRef,
) {
#getset_impl
#extend_impl
#with_impl
}
}
}
};
Ok(tokens)
}
Item::Trait(mut trai) => {
let mut context = ImplContext::default();
for item in trai.items.iter_mut() {
item.try_split_attr_mut(|attrs, item| {
let (pyitems, cfgs) =
attrs_to_content_items(&attrs, new_impl_item::<syn::TraitItem>)?;
for pyitem in pyitems.iter().rev() {
pyitem.gen_impl_item(ImplItemArgs {
item,
attrs,
context: &mut context,
cfgs: cfgs.as_slice(),
})?;
}
Ok(())
})?;
}
context.getset_items.validate()?;
let tokens = {
let getset_impl = &context.getset_items;
let extend_impl = &context.impl_extend_items;
trai.items.push(parse_quote! {
fn __extend_py_class(
fn impl_extend_class(
ctx: &::rustpython_vm::pyobject::PyContext,
class: &::rustpython_vm::obj::objtype::PyClassRef,
) {
#getset_impl
#extend_impl
#with_impl
}
}
}
}
Item::Trait(mut trai) => {
let mut context = ImplContext::default();
for item in trai.items.iter_mut() {
let r = item.try_split_attr_mut(|attrs, item| {
let (pyitems, cfgs) =
attrs_to_content_items(&attrs, new_impl_item::<syn::TraitItem>)?;
for pyitem in pyitems.iter().rev() {
let r = pyitem.gen_impl_item(ImplItemArgs {
item,
attrs,
context: &mut context,
cfgs: cfgs.as_slice(),
});
context.errors.ok_or_push(r);
}
Ok(())
});
trai.into_token_stream()
};
Ok(tokens)
context.errors.ok_or_push(r);
}
context.errors.ok_or_push(context.getset_items.validate());
let getset_impl = &context.getset_items;
let extend_impl = &context.impl_extend_items;
trai.items.push(parse_quote! {
fn __extend_py_class(
ctx: &::rustpython_vm::pyobject::PyContext,
class: &::rustpython_vm::obj::objtype::PyClassRef,
) {
#getset_impl
#extend_impl
}
});
trai.into_token_stream()
}
item => quote!(#item),
};
if let Some(error) = context.errors.into_error() {
let error = Diagnostic::from(error);
tokens = quote! {
#tokens
#error
}
item => Ok(quote!(#item)),
}
Ok(tokens)
}
fn generate_class_def(
@@ -478,9 +485,7 @@ impl GetSetNursery {
));
};
}
if !errors.is_empty() {
return Err(errors.into_error());
}
errors.into_result()?;
self.validated = true;
Ok(())
}
+56 -36
View File
@@ -1,6 +1,6 @@
use crate::error::Diagnostic;
use crate::util::{
AttributeExt, ClassItemMeta, ContentItem, ContentItemInner, ItemMeta, ItemNursery,
AttributeExt, ClassItemMeta, ContentItem, ContentItemInner, ErrorVec, ItemMeta, ItemNursery,
SimpleItemMeta, ALL_ALLOWED_NAMES,
};
use proc_macro2::TokenStream;
@@ -8,9 +8,11 @@ use quote::{quote, quote_spanned, ToTokens};
use syn::{parse_quote, spanned::Spanned, Attribute, AttributeArgs, Ident, Item, Result, UseTree};
use syn_ext::ext::*;
#[derive(Default)]
struct ModuleContext {
name: String,
module_extend_items: ItemNursery,
errors: Vec<syn::Error>,
}
pub fn impl_pymodule(
@@ -19,16 +21,16 @@ pub fn impl_pymodule(
) -> std::result::Result<TokenStream, Diagnostic> {
let mut module_item = match module_item {
Item::Mod(m) => m,
other => bail_span!(other, "#[pymodule] can only be on a module declaration"),
other => bail_span!(other, "#[pymodule] can only be on a full module"),
};
let fake_ident = Ident::new("pymodule", module_item.span());
let module_meta =
SimpleItemMeta::from_nested(module_item.ident.clone(), fake_ident, attr.into_iter())?;
// generation resources
let mut module_context = ModuleContext {
let mut context = ModuleContext {
name: module_meta.simple_name()?,
module_extend_items: ItemNursery::default(),
..Default::default()
};
let items = module_item.items_mut().ok_or_else(|| {
module_meta.new_meta_error("requires actual module, not a module declaration")
@@ -36,23 +38,25 @@ pub fn impl_pymodule(
// collect to context
for item in items.iter_mut() {
item.try_split_attr_mut(|attrs, item| {
let r = item.try_split_attr_mut(|attrs, item| {
let (pyitems, cfgs) = attrs_to_module_items(&attrs, new_module_item)?;
for pyitem in pyitems.iter().rev() {
pyitem.gen_module_item(ModuleItemArgs {
let r = pyitem.gen_module_item(ModuleItemArgs {
item,
attrs,
module: &mut module_context,
context: &mut context,
cfgs: cfgs.as_slice(),
})?;
});
context.errors.ok_or_push(r);
}
Ok(())
})?;
});
context.errors.ok_or_push(r);
}
// append additional items
let module_name = module_context.name.as_str();
let module_extend_items = module_context.module_extend_items;
let module_name = context.name.as_str();
let module_extend_items = context.module_extend_items;
items.extend(vec![
parse_quote! {
pub(crate) const MODULE_NAME: &'static str = #module_name;
@@ -77,7 +81,15 @@ pub fn impl_pymodule(
},
]);
Ok(module_item.into_token_stream())
Ok(if let Some(error) = context.errors.into_error() {
let error = Diagnostic::from(error);
quote! {
#module_item
#error
}
} else {
module_item.into_token_stream()
})
}
fn new_module_item(
@@ -219,13 +231,13 @@ impl ContentItem for AttributeItem {
struct ModuleItemArgs<'a> {
item: &'a Item,
attrs: &'a mut Vec<Attribute>,
module: &'a mut ModuleContext,
context: &'a mut ModuleContext,
cfgs: &'a [Attribute],
}
impl<'a> ModuleItemArgs<'a> {
fn module_name(&'a self) -> &'a str {
self.module.name.as_str()
self.context.name.as_str()
}
}
@@ -258,7 +270,7 @@ impl ModuleItem for FunctionItem {
}
};
args.module
args.context
.module_extend_items
.add_item(py_name, args.cfgs.to_vec(), item)?;
Ok(())
@@ -284,7 +296,7 @@ impl ModuleItem for ClassItem {
class_attr,
format!(
"#[{name}] requires #[pyattr] to be a module attribute. \
To keep it free type, try #[{name}(noattr)]",
To keep it free type, try #[{name}(noattr)]",
name = self.attr_name()
),
));
@@ -296,7 +308,7 @@ impl ModuleItem for ClassItem {
class_attr.get_ident().unwrap().clone(),
class_attr.promoted_nested()?.into_iter(),
)?;
let module_name = args.module.name.clone();
let module_name = args.context.name.clone();
class_attr.fill_nested_meta("module", || {
parse_quote! {module = #module_name}
})?;
@@ -304,26 +316,34 @@ impl ModuleItem for ClassItem {
(module_name, class_name)
};
for attr_index in self.pyattrs.iter().rev() {
let attr_attr = args.attrs.remove(*attr_index);
let (meta_ident, nested) = attr_attr.ident_and_promoted_nested()?;
let item_meta =
SimpleItemMeta::from_nested(ident.clone(), meta_ident.clone(), nested.into_iter())?;
let mut loop_unit = || {
let attr_attr = args.attrs.remove(*attr_index);
let (meta_ident, nested) = attr_attr.ident_and_promoted_nested()?;
let item_meta = SimpleItemMeta::from_nested(
ident.clone(),
meta_ident.clone(),
nested.into_iter(),
)?;
let py_name = item_meta
.optional_name()
.unwrap_or_else(|| class_name.clone());
let new_class = quote_spanned!(ident.span() =>
#ident::make_class(&vm.ctx);
);
let item = quote! {
let new_class = #new_class;
new_class.set_str_attr("__module__", vm.ctx.new_str(#module_name));
vm.__module_set_attr(&module, #py_name, new_class).unwrap();
let py_name = item_meta
.optional_name()
.unwrap_or_else(|| class_name.clone());
let new_class = quote_spanned!(ident.span() =>
#ident::make_class(&vm.ctx);
);
let item = quote! {
let new_class = #new_class;
new_class.set_str_attr("__module__", vm.ctx.new_str(#module_name));
vm.__module_set_attr(&module, #py_name, new_class).unwrap();
};
args.context
.module_extend_items
.add_item(py_name, args.cfgs.to_vec(), item)?;
Ok(())
};
args.module
.module_extend_items
.add_item(py_name.clone(), args.cfgs.to_vec(), item)?;
let r = loop_unit();
args.context.errors.ok_or_push(r);
}
Ok(())
}
@@ -386,7 +406,7 @@ impl ModuleItem for AttributeItem {
};
args.attrs.remove(self.index());
args.module
args.context
.module_extend_items
.add_item(py_name, args.cfgs.to_vec(), tokens)?;
+17 -7
View File
@@ -397,19 +397,29 @@ impl AttributeExt for Attribute {
}
}
pub(crate) trait ErrorVec {
fn into_error(self) -> syn::Error;
pub(crate) trait ErrorVec: Sized {
fn into_error(self) -> Option<syn::Error>;
fn into_result(self) -> Result<()> {
if let Some(error) = self.into_error() {
Err(error)
} else {
Ok(())
}
}
fn ok_or_push<T>(&mut self, r: Result<T>) -> Option<T>;
}
impl ErrorVec for Vec<syn::Error> {
fn into_error(self) -> syn::Error {
fn into_error(self) -> Option<syn::Error> {
let mut iter = self.into_iter();
let mut first = iter.next().expect("Cannot convert empty vec to syn::Error");
for err in iter {
first.combine(err);
if let Some(mut first) = iter.next() {
for err in iter {
first.combine(err);
}
Some(first)
} else {
None
}
first
}
fn ok_or_push<T>(&mut self, r: Result<T>) -> Option<T> {
match r {