mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-02 19:39:49 +09:00
Merge pull request #3051 from DimitrisJim/sig_for_bltins
Try to generate a text signature template for both methods and functions
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
use super::Diagnostic;
|
||||
use crate::util::{
|
||||
path_eq, pyclass_ident_and_attrs, ClassItemMeta, ContentItem, ContentItemInner, ErrorVec,
|
||||
ItemMeta, ItemMetaInner, ItemNursery, SimpleItemMeta, ALL_ALLOWED_NAMES,
|
||||
get_func_sig, path_eq, pyclass_ident_and_attrs, ClassItemMeta, ContentItem, ContentItemInner,
|
||||
ErrorVec, ItemMeta, ItemMetaInner, ItemNursery, SimpleItemMeta, ALL_ALLOWED_NAMES,
|
||||
};
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{quote, quote_spanned, ToTokens};
|
||||
@@ -367,43 +367,13 @@ where
|
||||
|
||||
let item_attr = args.attrs.remove(self.index());
|
||||
let item_meta = MethodItemMeta::from_attr(ident.clone(), &item_attr)?;
|
||||
let py_name = item_meta.method_name()?;
|
||||
|
||||
let sig_doc = args.item.function_or_method_impl().ok().map(|item| {
|
||||
let sig = item.sig();
|
||||
let args: Vec<_> = sig
|
||||
.inputs
|
||||
.iter()
|
||||
.filter_map(|arg| {
|
||||
use syn::FnArg::*;
|
||||
let arg = match arg {
|
||||
Receiver(_) => return Some("$self".to_owned()),
|
||||
Typed(typed) => typed,
|
||||
};
|
||||
let ty = arg.ty.as_ref();
|
||||
let ty = quote!(#ty).to_string();
|
||||
if ty == "FuncArgs" {
|
||||
return Some("*args, **kwargs".to_owned());
|
||||
}
|
||||
if ty == "& VirtualMachine" {
|
||||
return None;
|
||||
}
|
||||
let ident = match arg.pat.as_ref() {
|
||||
syn::Pat::Ident(p) => p.ident.to_string(),
|
||||
// FIXME: other => unreachable!("function arg pattern must be ident but found `{}`", quote!(fn #ident(.. #other ..))),
|
||||
other => quote!(#other).to_string(),
|
||||
};
|
||||
if ident == "zelf" {
|
||||
return Some("$self".to_owned());
|
||||
}
|
||||
if ident == "vm" {
|
||||
unreachable!("type &VirtualMachine(`{}`) must be filtered already", ty);
|
||||
}
|
||||
Some(ident)
|
||||
})
|
||||
.collect();
|
||||
format!("{}({})", py_name, args.join(", "))
|
||||
});
|
||||
let py_name = item_meta.method_name()?;
|
||||
let sig_doc = args
|
||||
.item
|
||||
.function_or_method_impl()
|
||||
.ok()
|
||||
.map(|f| get_func_sig(f.sig(), &py_name));
|
||||
|
||||
let tokens = {
|
||||
let doc = args.attrs.doc().map_or_else(TokenStream::new, |mut doc| {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
use crate::error::Diagnostic;
|
||||
use crate::util::{
|
||||
iter_use_idents, pyclass_ident_and_attrs, AttributeExt, ClassItemMeta, ContentItem,
|
||||
ContentItemInner, ErrorVec, ItemMeta, ItemNursery, SimpleItemMeta, ALL_ALLOWED_NAMES,
|
||||
get_func_sig, iter_use_idents, pyclass_ident_and_attrs, AttributeExt, ClassItemMeta,
|
||||
ContentItem, ContentItemInner, ErrorVec, ItemMeta, ItemNursery, SimpleItemMeta,
|
||||
ALL_ALLOWED_NAMES,
|
||||
};
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{quote, quote_spanned, ToTokens};
|
||||
@@ -257,11 +258,19 @@ impl ModuleItem for FunctionItem {
|
||||
let item_meta = SimpleItemMeta::from_attr(ident.clone(), &item_attr)?;
|
||||
|
||||
let py_name = item_meta.simple_name()?;
|
||||
let sig_doc = args
|
||||
.item
|
||||
.function_or_method_impl()
|
||||
.ok()
|
||||
.map(|f| get_func_sig(f.sig(), &py_name));
|
||||
|
||||
let item = {
|
||||
let doc = args.attrs.doc().map_or_else(
|
||||
TokenStream::new,
|
||||
|doc| quote!(.with_doc(#doc.to_owned(), &vm.ctx)),
|
||||
);
|
||||
let doc = args.attrs.doc().map_or_else(TokenStream::new, |mut doc| {
|
||||
if let Some(sig_doc) = sig_doc {
|
||||
doc = format!("{}\n--\n\n{}", sig_doc, doc);
|
||||
}
|
||||
quote!(.with_doc(#doc.to_owned(), &vm.ctx))
|
||||
});
|
||||
let module = args.module_name();
|
||||
let new_func = quote_spanned!(ident.span()=>
|
||||
vm.ctx.make_funcdef(#py_name, #ident)
|
||||
|
||||
@@ -2,6 +2,7 @@ use indexmap::map::IndexMap;
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
use quote::{quote, ToTokens};
|
||||
use std::collections::HashMap;
|
||||
use syn::Signature;
|
||||
use syn::{spanned::Spanned, Attribute, Ident, Meta, MetaList, NestedMeta, Path, Result, UseTree};
|
||||
use syn_ext::ext::{AttributeExt as SynAttributeExt, *};
|
||||
use syn_ext::types::PunctuatedNestedMeta;
|
||||
@@ -503,3 +504,40 @@ where
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Best effort attempt to create a template from which a
|
||||
// __text_signature__ can be created.
|
||||
pub(crate) fn get_func_sig(sig: &Signature, name: &str) -> String {
|
||||
let args: Vec<_> = sig
|
||||
.inputs
|
||||
.iter()
|
||||
.filter_map(|arg| {
|
||||
use syn::FnArg::*;
|
||||
let arg = match arg {
|
||||
Receiver(_) => return Some("$self".to_owned()),
|
||||
Typed(typed) => typed,
|
||||
};
|
||||
let ty = arg.ty.as_ref();
|
||||
let ty = quote!(#ty).to_string();
|
||||
if ty == "FuncArgs" {
|
||||
return Some("*args, **kwargs".to_owned());
|
||||
}
|
||||
if ty == "& VirtualMachine" {
|
||||
return None;
|
||||
}
|
||||
let ident = match arg.pat.as_ref() {
|
||||
syn::Pat::Ident(p) => p.ident.to_string(),
|
||||
// FIXME: other => unreachable!("function arg pattern must be ident but found `{}`", quote!(fn #ident(.. #other ..))),
|
||||
other => quote!(#other).to_string(),
|
||||
};
|
||||
if ident == "zelf" {
|
||||
return Some("$self".to_owned());
|
||||
}
|
||||
if ident == "vm" {
|
||||
unreachable!("type &VirtualMachine(`{}`) must be filtered already", ty);
|
||||
}
|
||||
Some(ident)
|
||||
})
|
||||
.collect();
|
||||
format!("{}({})", name, args.join(", "))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user