From d9b2a25d8ac33ce92fe22622ca8a6002d16bc2a1 Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Sun, 9 Aug 2020 23:14:59 +0900 Subject: [PATCH] Fix duplicated attribute checker for pyclass --- derive/src/pyclass.rs | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/derive/src/pyclass.rs b/derive/src/pyclass.rs index fd5b6eced..c5089ef15 100644 --- a/derive/src/pyclass.rs +++ b/derive/src/pyclass.rs @@ -5,7 +5,7 @@ use crate::util::{ }; use proc_macro2::{Span, TokenStream as TokenStream2}; use quote::{quote, quote_spanned, ToTokens}; -use std::collections::{HashMap, HashSet}; +use std::collections::HashMap; use syn::{ parse_quote, spanned::Spanned, Attribute, AttributeArgs, Ident, Index, Item, Lit, Meta, NestedMeta, @@ -21,7 +21,8 @@ fn meta_to_vec(meta: Meta) -> Result, Meta> { #[derive(Default)] struct Class { - items: HashSet, + // Unlike pymodule, meta variant is not supported + items: HashMap, } #[derive(PartialEq, Eq, Hash)] @@ -45,15 +46,35 @@ enum ClassItem { }, } +impl ClassItem { + fn name(&self) -> String { + use ClassItem::*; + match self { + Method { py_name, .. } => py_name.clone(), + ClassMethod { py_name, .. } => py_name.clone(), + Property { + py_name, setter, .. + } => { + if *setter { + format!("{}.setter", py_name) + } else { + py_name.clone() + } + } + Slot { slot_ident, .. } => format!("#slot({})", slot_ident), + } + } +} + impl Class { fn add_item(&mut self, item: ClassItem, span: Span) -> Result<(), Diagnostic> { - if self.items.insert(item) { - Ok(()) - } else { + if let Some(existing) = self.items.insert(item.name(), item) { Err(Diagnostic::span_error( span, - "Duplicate #[py*] attribute on pyimpl".to_owned(), + format!("Duplicate #[py*] attribute on pyimpl: {}", existing.name()), )) + } else { + Ok(()) } } @@ -197,7 +218,7 @@ fn extract_impl_items(mut items: Vec) -> Result, Option<&Ident>)> = HashMap::new(); - for item in class.items.iter() { + for item in class.items.values() { if let ClassItem::Property { ref item_ident, ref py_name, @@ -246,7 +267,7 @@ fn extract_impl_items(mut items: Vec) -> Result>(); - let methods = class.items.into_iter().filter_map(|item| match item { + let methods = class.items.values().filter_map(|item| match item { ClassItem::Method { item_ident, py_name,