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:
Jim Fasarakis-Hilliard
2021-09-13 22:59:26 +03:00
committed by GitHub
3 changed files with 61 additions and 44 deletions

View File

@@ -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| {

View File

@@ -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)

View File

@@ -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(", "))
}