mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
use meta item rather than parent name
This commit is contained in:
1 parent
9d025b0e4e
commit
8d46a96068
3 files changed
+90
-67
No files matched your search
+32
-24
@@ -90,35 +90,38 @@ impl Class {
|
||||
}
|
||||
|
||||
fn extract_method(
|
||||
ident: &Ident,
|
||||
nested: PunctuatedNestedMeta,
|
||||
item: &Ident,
|
||||
(meta, nested): (&Ident, PunctuatedNestedMeta),
|
||||
) -> Result<ClassItem, Diagnostic> {
|
||||
let item_meta = MethodItemMeta::from_nested("pymethod", &ident, nested.into_iter())?;
|
||||
let item_meta =
|
||||
MethodItemMeta::from_nested(item.clone(), meta.clone(), nested.into_iter())?;
|
||||
Ok(ClassItem::Method {
|
||||
item_ident: ident.clone(),
|
||||
item_ident: item.clone(),
|
||||
py_name: item_meta.method_name()?,
|
||||
})
|
||||
}
|
||||
|
||||
fn extract_classmethod(
|
||||
ident: &Ident,
|
||||
nested: PunctuatedNestedMeta,
|
||||
item: &Ident,
|
||||
(meta, nested): (&Ident, PunctuatedNestedMeta),
|
||||
) -> Result<ClassItem, Diagnostic> {
|
||||
let item_meta = MethodItemMeta::from_nested("pyclassmethod", &ident, nested.into_iter())?;
|
||||
let item_meta =
|
||||
MethodItemMeta::from_nested(item.clone(), meta.clone(), nested.into_iter())?;
|
||||
Ok(ClassItem::ClassMethod {
|
||||
item_ident: ident.clone(),
|
||||
item_ident: item.clone(),
|
||||
py_name: item_meta.method_name()?,
|
||||
})
|
||||
}
|
||||
|
||||
fn extract_property(
|
||||
ident: &Ident,
|
||||
nested: PunctuatedNestedMeta,
|
||||
item: &Ident,
|
||||
(meta, nested): (&Ident, PunctuatedNestedMeta),
|
||||
) -> Result<ClassItem, Diagnostic> {
|
||||
let item_meta = PropertyItemMeta::from_nested("pyproperty", &ident, nested.into_iter())?;
|
||||
let item_meta =
|
||||
PropertyItemMeta::from_nested(item.clone(), meta.clone(), nested.into_iter())?;
|
||||
Ok(ClassItem::Property {
|
||||
item_ident: item.clone(),
|
||||
py_name: item_meta.property_name()?,
|
||||
item_ident: ident.clone(),
|
||||
setter: item_meta.setter()?,
|
||||
})
|
||||
}
|
||||
@@ -159,9 +162,13 @@ impl Class {
|
||||
};
|
||||
|
||||
let item = match name.to_string().as_str() {
|
||||
"pymethod" => Self::extract_method(item.ident, attr.promoted_nested()?)?,
|
||||
"pyclassmethod" => Self::extract_classmethod(item.ident, attr.promoted_nested()?)?,
|
||||
"pyproperty" => Self::extract_property(item.ident, attr.promoted_nested()?)?,
|
||||
"pymethod" => Self::extract_method(item.ident, attr.ident_and_promoted_nested()?)?,
|
||||
"pyclassmethod" => {
|
||||
Self::extract_classmethod(item.ident, attr.ident_and_promoted_nested()?)?
|
||||
}
|
||||
"pyproperty" => {
|
||||
Self::extract_property(item.ident, attr.ident_and_promoted_nested()?)?
|
||||
}
|
||||
"pyslot" => Self::extract_slot(item.ident, attr.promoted_nested()?)?,
|
||||
_ => {
|
||||
continue;
|
||||
@@ -208,7 +215,7 @@ impl MethodItemMeta {
|
||||
Ok(if let Some(name) = name {
|
||||
name
|
||||
} else {
|
||||
let name = inner.ident.to_string();
|
||||
let name = inner.item_name();
|
||||
if magic {
|
||||
format!("__{}__", name)
|
||||
} else {
|
||||
@@ -241,24 +248,24 @@ impl PropertyItemMeta {
|
||||
Ok(if let Some(name) = name {
|
||||
name
|
||||
} else {
|
||||
let sig_name = inner.ident.to_string();
|
||||
let sig_name = inner.item_name();
|
||||
let name = if setter {
|
||||
if let Some(name) = sig_name.strip_prefix("set_") {
|
||||
if name.is_empty() {
|
||||
bail_span!(
|
||||
&inner.ident,
|
||||
&inner.meta_ident,
|
||||
"A #[{}(setter)] fn with a set_* name must \
|
||||
have something after \"set_\"",
|
||||
inner.parent_type
|
||||
inner.meta_name()
|
||||
)
|
||||
}
|
||||
name.to_string()
|
||||
} else {
|
||||
bail_span!(
|
||||
&inner.ident,
|
||||
&inner.meta_ident,
|
||||
"A #[{}(setter)] fn must either have a `name` \
|
||||
parameter or a fn name along the lines of \"set_*\"",
|
||||
inner.parent_type
|
||||
inner.meta_name()
|
||||
)
|
||||
}
|
||||
} else {
|
||||
@@ -572,7 +579,8 @@ pub fn impl_pyclass(attr: AttributeArgs, item: Item) -> Result<TokenStream2, Dia
|
||||
),
|
||||
};
|
||||
|
||||
let class_meta = ClassItemMeta::from_nested("pyclass", ident, attr.into_iter())?;
|
||||
let fake_ident = Ident::new("pyclass", item.span());
|
||||
let class_meta = ClassItemMeta::from_nested(ident.clone(), fake_ident, attr.into_iter())?;
|
||||
let class_name = class_meta.class_name()?;
|
||||
let module_name = class_meta.module()?;
|
||||
let class_def = generate_class_def(&ident, &class_name, module_name.as_deref(), &attrs)?;
|
||||
@@ -593,8 +601,8 @@ pub fn impl_pystruct_sequence(attr: AttributeArgs, item: Item) -> Result<TokenSt
|
||||
"#[pystruct_sequence] can only be on a struct declaration"
|
||||
)
|
||||
};
|
||||
let class_meta =
|
||||
ClassItemMeta::from_nested("pystruct_sequence", &struc.ident, attr.into_iter())?;
|
||||
let fake_ident = Ident::new("pystruct_sequence", struc.span());
|
||||
let class_meta = ClassItemMeta::from_nested(struc.ident.clone(), fake_ident, attr.into_iter())?;
|
||||
let class_name = class_meta.class_name()?;
|
||||
let module_name = class_meta.mandatory_module()?;
|
||||
|
||||
|
||||
+16
-14
@@ -21,8 +21,9 @@ pub fn impl_pymodule(
|
||||
Item::Mod(m) => m,
|
||||
other => bail_span!(other, "#[pymodule] can only be on a module declaration"),
|
||||
};
|
||||
let fake_ident = Ident::new("pymodule", module_item.span());
|
||||
let module_meta =
|
||||
SimpleItemMeta::from_nested("pymodule", &module_item.ident, attr.into_iter())?;
|
||||
SimpleItemMeta::from_nested(module_item.ident.clone(), fake_ident, attr.into_iter())?;
|
||||
let mut module_context = Module {
|
||||
name: module_meta.simple_name()?,
|
||||
items: ItemNursery::default(),
|
||||
@@ -260,8 +261,8 @@ impl ModuleItem for FunctionItem {
|
||||
};
|
||||
let item_attr = attrs.remove(self.index());
|
||||
let item_meta = SimpleItemMeta::from_nested(
|
||||
"pyfunction",
|
||||
&args.ident,
|
||||
args.ident.clone(),
|
||||
item_attr.get_ident().unwrap().clone(),
|
||||
item_attr.promoted_nested()?.into_iter(),
|
||||
)?;
|
||||
|
||||
@@ -309,14 +310,10 @@ impl ModuleItem for ClassItem {
|
||||
));
|
||||
}
|
||||
}
|
||||
let static_name = match self.attr_name() {
|
||||
"pyclass" => "pyclass",
|
||||
"pystruct_sequence" => "pystruct_sequence",
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let class_meta = ClassItemMeta::from_nested(
|
||||
static_name,
|
||||
&args.ident,
|
||||
args.ident.clone(),
|
||||
class_attr.get_ident().unwrap().clone(),
|
||||
class_attr.promoted_nested()?.into_iter(),
|
||||
)?;
|
||||
let module_name = args.module.name.clone();
|
||||
@@ -328,8 +325,12 @@ impl ModuleItem for ClassItem {
|
||||
};
|
||||
for attr_index in self.pyattrs.iter().rev() {
|
||||
let attr_attr = attrs.remove(*attr_index);
|
||||
let nested = attr_attr.promoted_nested()?;
|
||||
let item_meta = SimpleItemMeta::from_nested("pyattr", &args.ident, nested.into_iter())?;
|
||||
let (meta_ident, nested) = attr_attr.ident_and_promoted_nested()?;
|
||||
let item_meta = SimpleItemMeta::from_nested(
|
||||
args.ident.clone(),
|
||||
meta_ident.clone(),
|
||||
nested.into_iter(),
|
||||
)?;
|
||||
|
||||
let py_name = item_meta
|
||||
.optional_name()
|
||||
@@ -356,8 +357,9 @@ impl ModuleItem for AttributeItem {
|
||||
fn gen_module_item(&self, args: ModuleItemArgs<'_>) -> Result<()> {
|
||||
let ident = &args.ident;
|
||||
let get_py_name = |attrs: &mut Vec<Attribute>| -> Result<_> {
|
||||
let nested = attrs[self.inner.index].promoted_nested()?;
|
||||
let item_meta = SimpleItemMeta::from_nested("pyattr", &ident, nested.into_iter())?;
|
||||
let (meta_ident, nested) = attrs[self.inner.index].ident_and_promoted_nested()?;
|
||||
let item_meta =
|
||||
SimpleItemMeta::from_nested(ident.clone(), meta_ident.clone(), nested.into_iter())?;
|
||||
let py_name = item_meta.simple_name()?;
|
||||
Ok(py_name)
|
||||
};
|
||||
|
||||
+42
-29
@@ -68,22 +68,22 @@ pub(crate) trait ContentItem {
|
||||
}
|
||||
|
||||
pub(crate) struct ItemMetaInner {
|
||||
pub ident: Ident,
|
||||
pub parent_type: &'static str,
|
||||
pub meta: HashMap<String, (usize, Meta)>,
|
||||
pub item_ident: Ident,
|
||||
pub meta_ident: Ident,
|
||||
pub meta_map: HashMap<String, (usize, Meta)>,
|
||||
}
|
||||
|
||||
impl ItemMetaInner {
|
||||
pub fn from_nested<I>(
|
||||
parent_type: &'static str,
|
||||
ident: &Ident,
|
||||
item_ident: Ident,
|
||||
meta_ident: Ident,
|
||||
nested: I,
|
||||
allowed_names: &[&'static str],
|
||||
) -> Result<Self>
|
||||
where
|
||||
I: std::iter::Iterator<Item = NestedMeta>,
|
||||
{
|
||||
let (named_map, lits) = nested.into_unique_map_and_lits(|path| {
|
||||
let (meta_map, lits) = nested.into_unique_map_and_lits(|path| {
|
||||
if let Some(ident) = path.get_ident() {
|
||||
let name = ident.to_string();
|
||||
if allowed_names.contains(&name.as_str()) {
|
||||
@@ -93,7 +93,7 @@ impl ItemMetaInner {
|
||||
ident,
|
||||
format!(
|
||||
"#[{}({})] is not one of allowed attributes {}",
|
||||
parent_type,
|
||||
meta_ident.to_string(),
|
||||
name,
|
||||
allowed_names.join(", ")
|
||||
),
|
||||
@@ -105,20 +105,28 @@ impl ItemMetaInner {
|
||||
})?;
|
||||
if !lits.is_empty() {
|
||||
return Err(syn::Error::new_spanned(
|
||||
ident,
|
||||
format!("#[{}(..)] cannot contain literal", parent_type),
|
||||
&meta_ident,
|
||||
format!("#[{}(..)] cannot contain literal", meta_ident.to_string()),
|
||||
));
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
ident: ident.clone(),
|
||||
parent_type,
|
||||
meta: named_map,
|
||||
item_ident,
|
||||
meta_ident,
|
||||
meta_map,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn item_name(&self) -> String {
|
||||
self.item_ident.to_string()
|
||||
}
|
||||
|
||||
pub fn meta_name(&self) -> String {
|
||||
self.meta_ident.to_string()
|
||||
}
|
||||
|
||||
pub fn _optional_str(&self, key: &str) -> Result<Option<String>> {
|
||||
let value = if let Some((_, meta)) = self.meta.get(key) {
|
||||
let value = if let Some((_, meta)) = self.meta_map.get(key) {
|
||||
match meta {
|
||||
Meta::NameValue(syn::MetaNameValue {
|
||||
lit: syn::Lit::Str(lit),
|
||||
@@ -129,7 +137,8 @@ impl ItemMetaInner {
|
||||
other,
|
||||
format!(
|
||||
"#[{}({} = ...)] must exist as a string",
|
||||
self.parent_type, key
|
||||
self.meta_name(),
|
||||
key
|
||||
),
|
||||
));
|
||||
}
|
||||
@@ -141,7 +150,7 @@ impl ItemMetaInner {
|
||||
}
|
||||
|
||||
pub fn _bool(&self, key: &str) -> Result<bool> {
|
||||
let value = if let Some((_, meta)) = self.meta.get(key) {
|
||||
let value = if let Some((_, meta)) = self.meta_map.get(key) {
|
||||
match meta {
|
||||
Meta::NameValue(syn::MetaNameValue {
|
||||
lit: syn::Lit::Bool(lit),
|
||||
@@ -151,7 +160,7 @@ impl ItemMetaInner {
|
||||
other => {
|
||||
return Err(syn::Error::new_spanned(
|
||||
other,
|
||||
format!("#[{}({})] is expected", self.parent_type, key),
|
||||
format!("#[{}({})] is expected", self.meta_name(), key),
|
||||
))
|
||||
}
|
||||
}
|
||||
@@ -165,13 +174,13 @@ impl ItemMetaInner {
|
||||
pub(crate) trait ItemMeta: Sized {
|
||||
const ALLOWED_NAMES: &'static [&'static str];
|
||||
|
||||
fn from_nested<I>(parent_type: &'static str, ident: &Ident, nested: I) -> Result<Self>
|
||||
fn from_nested<I>(item_ident: Ident, meta_ident: Ident, nested: I) -> Result<Self>
|
||||
where
|
||||
I: std::iter::Iterator<Item = NestedMeta>,
|
||||
{
|
||||
Ok(Self::from_inner(ItemMetaInner::from_nested(
|
||||
parent_type,
|
||||
ident,
|
||||
item_ident,
|
||||
meta_ident,
|
||||
nested,
|
||||
Self::ALLOWED_NAMES,
|
||||
)?))
|
||||
@@ -184,7 +193,7 @@ pub(crate) trait ItemMeta: Sized {
|
||||
let inner = self.inner();
|
||||
Ok(inner
|
||||
._optional_str("name")?
|
||||
.unwrap_or_else(|| inner.ident.to_string()))
|
||||
.unwrap_or_else(|| inner.item_name()))
|
||||
}
|
||||
|
||||
fn optional_name(&self) -> Option<String> {
|
||||
@@ -221,22 +230,22 @@ impl ClassItemMeta {
|
||||
pub fn class_name(&self) -> Result<String> {
|
||||
const KEY: &str = "name";
|
||||
let inner = self.inner();
|
||||
let value = if let Some((_, meta)) = inner.meta.get(KEY) {
|
||||
let value = if let Some((_, meta)) = inner.meta_map.get(KEY) {
|
||||
match meta {
|
||||
Meta::NameValue(syn::MetaNameValue {
|
||||
lit: syn::Lit::Str(lit),
|
||||
..
|
||||
}) => Some(lit.value()),
|
||||
Meta::Path(_) => Some(inner.ident.to_string()),
|
||||
Meta::Path(_) => Some(inner.item_name()),
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}.ok_or_else(|| syn::Error::new_spanned(
|
||||
&inner.ident,
|
||||
&inner.meta_ident,
|
||||
format!(
|
||||
"#[{attr_name}(name = ...)] must exist as a string. Try #[{attr_name}(name)] to use rust type name.",
|
||||
attr_name=inner.parent_type
|
||||
attr_name=inner.meta_name()
|
||||
),
|
||||
))?;
|
||||
Ok(value)
|
||||
@@ -245,7 +254,7 @@ impl ClassItemMeta {
|
||||
pub fn module(&self) -> Result<Option<String>> {
|
||||
const KEY: &str = "module";
|
||||
let inner = self.inner();
|
||||
let value = if let Some((_, meta)) = inner.meta.get(KEY) {
|
||||
let value = if let Some((_, meta)) = inner.meta_map.get(KEY) {
|
||||
match meta {
|
||||
Meta::NameValue(syn::MetaNameValue {
|
||||
lit: syn::Lit::Str(lit),
|
||||
@@ -262,12 +271,12 @@ impl ClassItemMeta {
|
||||
other => Err(other.span()),
|
||||
}
|
||||
} else {
|
||||
Err(inner.ident.span())
|
||||
Err(inner.item_ident.span())
|
||||
}.map_err(|span| syn::Error::new(
|
||||
span,
|
||||
format!(
|
||||
"#[{attr_name}(module = ...)] must exist as a string or false. Try #[{attr_name}(module=false)] for built-in types.",
|
||||
attr_name=inner.parent_type
|
||||
attr_name=inner.meta_name()
|
||||
),
|
||||
))?;
|
||||
Ok(value)
|
||||
@@ -277,10 +286,10 @@ impl ClassItemMeta {
|
||||
let inner = self.inner();
|
||||
let value = self.module().ok().flatten().
|
||||
ok_or_else(|| syn::Error::new_spanned(
|
||||
&inner.ident,
|
||||
&inner.meta_ident,
|
||||
format!(
|
||||
"#[{attr_name}(module = ...)] must exist as a string. Built-in module is not allowed here.",
|
||||
attr_name=inner.parent_type
|
||||
attr_name=inner.meta_name()
|
||||
),
|
||||
))?;
|
||||
Ok(value)
|
||||
@@ -293,6 +302,7 @@ pub(crate) fn path_eq(path: &Path, s: &str) -> bool {
|
||||
|
||||
pub(crate) trait AttributeExt: SynAttributeExt {
|
||||
fn promoted_nested(&self) -> Result<PunctuatedNestedMeta>;
|
||||
fn ident_and_promoted_nested(&self) -> Result<(&Ident, PunctuatedNestedMeta)>;
|
||||
fn try_remove_name(&mut self, name: &str) -> Result<Option<syn::NestedMeta>>;
|
||||
fn fill_nested_meta<F>(&mut self, name: &str, new_item: F) -> Result<()>
|
||||
where
|
||||
@@ -315,6 +325,9 @@ impl AttributeExt for Attribute {
|
||||
})?;
|
||||
Ok(list.nested)
|
||||
}
|
||||
fn ident_and_promoted_nested(&self) -> Result<(&Ident, PunctuatedNestedMeta)> {
|
||||
Ok((self.get_ident().unwrap(), self.promoted_nested()?))
|
||||
}
|
||||
|
||||
fn try_remove_name(&mut self, item_name: &str) -> Result<Option<syn::NestedMeta>> {
|
||||
self.try_meta_mut(|meta| {
|
||||
|
||||
Reference in new issue
Block a user