Allow documenting of extern "Lua" functions
This commit is contained in:
parent
1aa9b4aa02
commit
122ef04b16
@ -6,6 +6,23 @@ use std::{
|
|||||||
hash::{Hash, Hasher},
|
hash::{Hash, Hasher},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
pub mod stub_types {
|
||||||
|
pub struct any;
|
||||||
|
pub struct nil;
|
||||||
|
pub struct boolean;
|
||||||
|
pub struct lightuserdata;
|
||||||
|
pub struct number;
|
||||||
|
pub struct integer;
|
||||||
|
pub struct string;
|
||||||
|
pub struct table;
|
||||||
|
pub struct function;
|
||||||
|
pub struct userdata;
|
||||||
|
pub struct thread;
|
||||||
|
pub struct cdata;
|
||||||
|
pub struct variadic;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn type_id<T: 'static>() -> u64 {
|
pub fn type_id<T: 'static>() -> u64 {
|
||||||
let mut hash = FxHasher::default();
|
let mut hash = FxHasher::default();
|
||||||
TypeId::of::<T>().hash(&mut hash);
|
TypeId::of::<T>().hash(&mut hash);
|
||||||
|
@ -202,10 +202,7 @@ fn get_ffi_functions(imp: &mut ItemImpl) -> Result<Vec<FfiFunction>> {
|
|||||||
{
|
{
|
||||||
func.sig.abi = None;
|
func.sig.abi = None;
|
||||||
|
|
||||||
// normalise inputs to PatType
|
let params = func
|
||||||
funcs.push(FfiFunction {
|
|
||||||
name: func.sig.ident.clone(),
|
|
||||||
params: func
|
|
||||||
.sig
|
.sig
|
||||||
.inputs
|
.inputs
|
||||||
.iter()
|
.iter()
|
||||||
@ -216,12 +213,21 @@ fn get_ffi_functions(imp: &mut ItemImpl) -> Result<Vec<FfiFunction>> {
|
|||||||
}
|
}
|
||||||
FnArg::Typed(ty) => ty.clone(),
|
FnArg::Typed(ty) => ty.clone(),
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect();
|
||||||
ret: match func.sig.output {
|
|
||||||
ReturnType::Default => parse_quote_spanned!(func.sig.span() => ()),
|
let ret = match func.sig.output {
|
||||||
|
ReturnType::Default => parse_quote!(()),
|
||||||
ReturnType::Type(_, ref ty) => (**ty).clone(),
|
ReturnType::Type(_, ref ty) => (**ty).clone(),
|
||||||
},
|
};
|
||||||
attrs: parse_ffi_function_attrs(&mut func.attrs)?,
|
|
||||||
|
let attrs = parse_ffi_function_attrs(&mut func.attrs)?;
|
||||||
|
attrs.metamethod.map(|mm| document_metamethod(func, mm));
|
||||||
|
|
||||||
|
funcs.push(FfiFunction {
|
||||||
|
name: func.sig.ident.clone(),
|
||||||
|
params,
|
||||||
|
ret,
|
||||||
|
attrs,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -339,13 +345,13 @@ fn add_ffi_function(registry: &mut FfiRegistry, func: &FfiFunction) -> Result<()
|
|||||||
|
|
||||||
match get_ffi_param_type(func_param) {
|
match get_ffi_param_type(func_param) {
|
||||||
FfiParameterType::Default => {
|
FfiParameterType::Default => {
|
||||||
shim_params.push(quote_spanned!(param.span() =>
|
shim_params.push(quote_spanned!(func_param.span() =>
|
||||||
#shim_param: <#func_param as #ffi::FromFfi>::From
|
#shim_param: <#func_param as #ffi::FromFfi>::From
|
||||||
));
|
));
|
||||||
func_args.push(quote_spanned!(param.span() =>
|
func_args.push(quote_spanned!(param.pat.span() =>
|
||||||
<#func_param as #ffi::FromFfi>::convert(#shim_param)
|
<#func_param as #ffi::FromFfi>::convert(#shim_param)
|
||||||
));
|
));
|
||||||
build.push(quote_spanned!(param.span() =>
|
build.push(quote_spanned!(param.pat.span() =>
|
||||||
b.param::<#func_param>(#name);
|
b.param::<#func_param>(#name);
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -432,15 +438,13 @@ struct LuaFunctionAttrs {
|
|||||||
|
|
||||||
fn get_lua_functions(imp: &mut ItemImpl) -> Result<Vec<LuaFunction>> {
|
fn get_lua_functions(imp: &mut ItemImpl) -> Result<Vec<LuaFunction>> {
|
||||||
let mut funcs = vec![];
|
let mut funcs = vec![];
|
||||||
let mut i = 0;
|
|
||||||
|
|
||||||
while i < imp.items.len() {
|
for item in imp.items.iter_mut() {
|
||||||
if let ImplItem::Fn(ref mut func) = imp.items[i]
|
if let ImplItem::Fn(func) = item
|
||||||
&& let Some(ref abi) = func.sig.abi
|
&& let Some(ref abi) = func.sig.abi
|
||||||
&& let Some(ref abi) = abi.name
|
&& let Some(ref abi) = abi.name
|
||||||
&& abi.value() == "Lua"
|
&& abi.value() == "Lua"
|
||||||
{
|
{
|
||||||
// normalise inputs to Pat
|
|
||||||
let mut params: Vec<_> = func
|
let mut params: Vec<_> = func
|
||||||
.sig
|
.sig
|
||||||
.inputs
|
.inputs
|
||||||
@ -448,7 +452,6 @@ fn get_lua_functions(imp: &mut ItemImpl) -> Result<Vec<LuaFunction>> {
|
|||||||
.map(|arg| {
|
.map(|arg| {
|
||||||
Ok(match arg {
|
Ok(match arg {
|
||||||
FnArg::Receiver(recv) => {
|
FnArg::Receiver(recv) => {
|
||||||
syn_assert!(ty_name(&recv.ty)? == "Self", recv, "must be `self`");
|
|
||||||
syn_assert!(recv.mutability.is_none(), recv, "cannot be mut");
|
syn_assert!(recv.mutability.is_none(), recv, "cannot be mut");
|
||||||
Pat::Type(parse_quote_spanned!(recv.span() => self: cdata))
|
Pat::Type(parse_quote_spanned!(recv.span() => self: cdata))
|
||||||
}
|
}
|
||||||
@ -461,29 +464,71 @@ fn get_lua_functions(imp: &mut ItemImpl) -> Result<Vec<LuaFunction>> {
|
|||||||
params.push(parse_quote_spanned!(variadic.span() => variadic!()));
|
params.push(parse_quote_spanned!(variadic.span() => variadic!()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// shouldn't specify an output type
|
let attrs = parse_lua_function_attrs(&mut func.attrs)?;
|
||||||
syn_assert!(
|
attrs.metamethod.map(|mm| document_metamethod(func, mm));
|
||||||
matches!(func.sig.output, ReturnType::Default),
|
|
||||||
func.sig.output,
|
|
||||||
"cannot have return type"
|
|
||||||
);
|
|
||||||
|
|
||||||
funcs.push(LuaFunction {
|
funcs.push(LuaFunction {
|
||||||
name: func.sig.ident.clone(),
|
name: func.sig.ident.clone(),
|
||||||
params,
|
params,
|
||||||
body: func.block.clone(),
|
body: func.block.clone(),
|
||||||
attrs: parse_lua_function_attrs(&mut func.attrs)?,
|
attrs,
|
||||||
});
|
});
|
||||||
|
|
||||||
imp.items.remove(i);
|
stub_lua_function(func)?;
|
||||||
} else {
|
|
||||||
i += 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(funcs)
|
Ok(funcs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn stub_lua_function(func: &mut ImplItemFn) -> Result<()> {
|
||||||
|
// converts an extern "Lua" function into a regular function with no body to allow for
|
||||||
|
// documentation generation
|
||||||
|
let ffi = ffi_crate();
|
||||||
|
|
||||||
|
func.sig.abi = None;
|
||||||
|
func.attrs.push(parse_quote!(#[allow(unused)]));
|
||||||
|
func.block = parse_quote!({
|
||||||
|
::std::unreachable!("cannot call lua function from rust");
|
||||||
|
});
|
||||||
|
|
||||||
|
let inputs = &mut func.sig.inputs;
|
||||||
|
for input in inputs.iter_mut() {
|
||||||
|
if let FnArg::Typed(pat) = input {
|
||||||
|
let span = pat.ty.span();
|
||||||
|
let ty = if let Type::Infer(_) = *pat.ty {
|
||||||
|
quote_spanned!(span => any)
|
||||||
|
} else {
|
||||||
|
match ty_name(&pat.ty)?.to_string().as_str() {
|
||||||
|
"any" => quote_spanned!(span => any),
|
||||||
|
"nil" => quote_spanned!(span => nil),
|
||||||
|
"boolean" => quote_spanned!(span => boolean),
|
||||||
|
"lightuserdata" => quote_spanned!(span => lightuserdata),
|
||||||
|
"number" => quote_spanned!(span => number),
|
||||||
|
"integer" => quote_spanned!(span => integer),
|
||||||
|
"string" => quote_spanned!(span => string),
|
||||||
|
"table" => quote_spanned!(span => table),
|
||||||
|
"function" => quote_spanned!(span => function),
|
||||||
|
"userdata" => quote_spanned!(span => userdata),
|
||||||
|
"thread" => quote_spanned!(span => thread),
|
||||||
|
"cdata" => quote_spanned!(span => cdata),
|
||||||
|
_ => syn_error!(pat, "unknown lua type"),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pat.ty = Box::new(parse_quote!(#ffi::__internal::stub_types::#ty));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(ref variadic) = func.sig.variadic {
|
||||||
|
let ty = quote_spanned!(variadic.span() => variadic);
|
||||||
|
inputs.push(parse_quote!(rest: #ffi::__internal::stub_types::#ty));
|
||||||
|
func.sig.variadic = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_lua_function_attrs(attrs: &mut Vec<Attribute>) -> Result<LuaFunctionAttrs> {
|
fn parse_lua_function_attrs(attrs: &mut Vec<Attribute>) -> Result<LuaFunctionAttrs> {
|
||||||
let mut parsed = LuaFunctionAttrs::default();
|
let mut parsed = LuaFunctionAttrs::default();
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
@ -532,6 +577,36 @@ fn add_lua_function(registry: &mut LuaRegistry, func: &LuaFunction) -> Result<()
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn document_metamethod(func: &mut ImplItemFn, method: Metamethod) {
|
||||||
|
let s = match method {
|
||||||
|
Metamethod::Eq => "This is a metamethod which is called by the `==` operator.".into(),
|
||||||
|
Metamethod::Len => "This is a metamethod which is called by the `#` operator.".into(),
|
||||||
|
Metamethod::Lt => "This is a metamethod which is called by the `<` operator.".into(),
|
||||||
|
Metamethod::Le => "This is a metamethod which is called by the `<=` operator.".into(),
|
||||||
|
Metamethod::Concat => "This is a metamethod which is called by the `..` operator.".into(),
|
||||||
|
Metamethod::Add => "This is a metamethod which is called by the `+` operator.".into(),
|
||||||
|
Metamethod::Sub => "This is a metamethod which is called by the `-` operator.".into(),
|
||||||
|
Metamethod::Mul => "This is a metamethod which is called by the `*` operator.".into(),
|
||||||
|
Metamethod::Div => "This is a metamethod which is called by the `/` operator.".into(),
|
||||||
|
Metamethod::Mod => "This is a metamethod which is called by the `%` operator.".into(),
|
||||||
|
Metamethod::Pow => "This is a metamethod which is called by the `^` operator.".into(),
|
||||||
|
Metamethod::Unm => "This is a metamethod which is called by the `-` operator.".into(),
|
||||||
|
Metamethod::ToString => {
|
||||||
|
"This is a metamethod which can be called by the `tostring` built-in function.".into()
|
||||||
|
}
|
||||||
|
Metamethod::Pairs => {
|
||||||
|
"This is a metamethod which can be called by the `pairs` built-in function.".into()
|
||||||
|
}
|
||||||
|
Metamethod::Ipairs => {
|
||||||
|
"This is a metamethod which can be called by the `ipairs` built-in function.".into()
|
||||||
|
}
|
||||||
|
_ => format!("This is a metamethod and cannot be called directly."),
|
||||||
|
};
|
||||||
|
|
||||||
|
func.attrs.push(parse_quote!(#[doc = ""]));
|
||||||
|
func.attrs.push(parse_quote!(#[doc = #s]));
|
||||||
|
}
|
||||||
|
|
||||||
fn inject_fallback_new(registry: &mut LuaRegistry) -> Result<()> {
|
fn inject_fallback_new(registry: &mut LuaRegistry) -> Result<()> {
|
||||||
let ty = ®istry.ty;
|
let ty = ®istry.ty;
|
||||||
let lua = format!(
|
let lua = format!(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user