Fix macros breaking auto completion in IDEs

This commit is contained in:
William Venner 2022-01-22 19:36:41 +00:00
parent 92072ef93f
commit 3e708a0c0d
4 changed files with 61 additions and 45 deletions

6
Cargo.lock generated
View File

@ -135,7 +135,7 @@ dependencies = [
[[package]]
name = "gmod"
version = "12.0.0"
version = "12.0.1"
dependencies = [
"cfg_table 1.0.0",
"cstr",
@ -144,7 +144,7 @@ dependencies = [
"fn_abi",
"fn_has_this",
"fn_type_alias",
"gmod-macros 2.0.0",
"gmod-macros 2.0.1",
"gmserverplugin",
"lazy_static",
"libloading",
@ -165,7 +165,7 @@ dependencies = [
[[package]]
name = "gmod-macros"
version = "2.0.0"
version = "2.0.1"
dependencies = [
"proc-macro2",
"quote",

View File

@ -1,6 +1,6 @@
[package]
name = "gmod-macros"
version = "2.0.0"
version = "2.0.1"
authors = ["William Venner <william@venner.io>"]
edition = "2021"
license = "MIT"

View File

@ -8,6 +8,16 @@ use proc_macro::TokenStream;
use quote::ToTokens;
use syn::ItemFn;
macro_rules! wrap_compile_error {
($input:ident, $code:expr) => {{
let orig_tokens = $input.clone();
match (|| -> Result<TokenStream, syn::Error> { $code })() {
Ok(tokens) => tokens,
Err(_) => return orig_tokens
}
}};
}
fn check_lua_function(input: &mut ItemFn) {
assert!(input.sig.asyncness.is_none(), "Cannot be async");
assert!(input.sig.constness.is_none(), "Cannot be const");
@ -24,66 +34,72 @@ fn genericify_return(item_fn: &mut ItemFn) {
#[proc_macro_attribute]
pub fn gmod13_open(_attr: TokenStream, tokens: TokenStream) -> TokenStream {
let mut input = parse_macro_input!(tokens as ItemFn);
wrap_compile_error!(tokens, {
let mut input = syn::parse::<ItemFn>(tokens)?;
let lua_ident = format_ident!("{}", match &input.sig.inputs[0] {
syn::FnArg::Typed(arg) => arg.pat.to_token_stream().to_string(),
_ => unreachable!(),
});
let lua_ident = format_ident!("{}", match &input.sig.inputs[0] {
syn::FnArg::Typed(arg) => arg.pat.to_token_stream().to_string(),
_ => unreachable!(),
});
// Capture the Lua state
input.block.stmts.insert(0, syn::parse2(quote!(::gmod::lua::__set_state__internal(#lua_ident);)).unwrap());
// Capture the Lua state
input.block.stmts.insert(0, syn::parse2(quote!(::gmod::lua::__set_state__internal(#lua_ident);)).unwrap());
// Load lua_shared
input.block.stmts.insert(0, syn::parse2(quote!(#[allow(unused_unsafe)] unsafe { ::gmod::lua::load() })).unwrap());
// Load lua_shared
input.block.stmts.insert(0, syn::parse2(quote!(#[allow(unused_unsafe)] unsafe { ::gmod::lua::load() })).unwrap());
// Make sure it's valid
check_lua_function(&mut input);
// Make sure it's valid
check_lua_function(&mut input);
// No mangling
input.attrs.push(parse_quote!(#[no_mangle]));
// No mangling
input.attrs.push(parse_quote!(#[no_mangle]));
// Make the return type nice and dynamic
genericify_return(&mut input);
// Make the return type nice and dynamic
genericify_return(&mut input);
input.into_token_stream().into()
Ok(input.into_token_stream().into())
})
}
#[proc_macro_attribute]
pub fn gmod13_close(_attr: TokenStream, tokens: TokenStream) -> TokenStream {
let mut input = parse_macro_input!(tokens as ItemFn);
wrap_compile_error!(tokens, {
let mut input = syn::parse::<ItemFn>(tokens)?;
// Make sure it's valid
check_lua_function(&mut input);
// Make sure it's valid
check_lua_function(&mut input);
// No mangling
input.attrs.push(parse_quote!(#[no_mangle]));
// No mangling
input.attrs.push(parse_quote!(#[no_mangle]));
// Shutdown gmcl thread if it's running
#[cfg(feature = "gmcl")] {
let stmts = std::mem::take(&mut input.block.stmts);
input.block.stmts = vec![syn::parse2(quote!({
let ret = (|| {#(#stmts);*})();
::gmod::gmcl::restore_stdout();
ret
})).unwrap()];
}
// Shutdown gmcl thread if it's running
#[cfg(feature = "gmcl")] {
let stmts = std::mem::take(&mut input.block.stmts);
input.block.stmts = vec![syn::parse2(quote!({
let ret = (|| {#(#stmts);*})();
::gmod::gmcl::restore_stdout();
ret
})).unwrap()];
}
// Make the return type nice and dynamic
genericify_return(&mut input);
// Make the return type nice and dynamic
genericify_return(&mut input);
input.into_token_stream().into()
Ok(input.into_token_stream().into())
})
}
#[proc_macro_attribute]
pub fn lua_function(_attr: TokenStream, tokens: TokenStream) -> TokenStream {
let mut input = parse_macro_input!(tokens as ItemFn);
wrap_compile_error!(tokens, {
let mut input = syn::parse::<ItemFn>(tokens)?;
// Make sure it's valid
check_lua_function(&mut input);
// Make sure it's valid
check_lua_function(&mut input);
// Make the return type nice and dynamic
genericify_return(&mut input);
// Make the return type nice and dynamic
genericify_return(&mut input);
input.into_token_stream().into()
Ok(input.into_token_stream().into())
})
}

View File

@ -1,6 +1,6 @@
[package]
name = "gmod"
version = "12.0.0"
version = "12.0.1"
authors = ["William Venner <william@venner.io>"]
edition = "2021"
license = "MIT"
@ -16,7 +16,7 @@ server-plugin = ["gmserverplugin"]
gmcl = ["gmod-macros/gmcl"]
[dependencies]
gmod-macros = { version = "2.0.0", path = "../gmod-macros" }
gmod-macros = { version = "2.0.1", path = "../gmod-macros" }
gmserverplugin = { version = "1", optional = true }
libloading = "0"