Skip to content

Commit

Permalink
Deprecated return by reference
Browse files Browse the repository at this point in the history
The ways of emit warnings is a terrible hack.
This is because there is no way to emit warnings
from macros in stable Rust.

Follow these steps to emit warnings.
- Detect whether reference types are used in derive_methods().
- Expand the call to deprecated_reference_return!() macro to user code.
  • Loading branch information
B-head committed May 1, 2022
1 parent 552b7a8 commit c3f5fe8
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 16 deletions.
7 changes: 7 additions & 0 deletions gdnative-core/src/export/macros.rs
Expand Up @@ -22,6 +22,13 @@ macro_rules! godot_wrap_method_if_deref {
};
}

#[doc(hidden)]
#[macro_export]
#[deprecated = "This function does not actually pass by reference to the Godot engine. You can clarify by writing #[export(deref_return)]."]
macro_rules! deprecated_reference_return {
() => {};
}

#[doc(hidden)]
#[macro_export]
macro_rules! godot_wrap_method_inner {
Expand Down
2 changes: 2 additions & 0 deletions gdnative-core/src/export/mod.rs
Expand Up @@ -26,6 +26,8 @@ pub(crate) mod type_tag;

pub mod user_data;

#[allow(deprecated)]
pub use crate::deprecated_reference_return;
pub use crate::godot_wrap_method;
pub use class::*;
pub use class_builder::*;
Expand Down
2 changes: 1 addition & 1 deletion gdnative-derive/src/lib.rs
Expand Up @@ -50,7 +50,7 @@ mod variant;
/// impl gdnative::export::NativeClassMethods for Foo {
/// fn register(builder: &ClassBuilder<Self>) {
/// use gdnative::export::*;
/// builder.method("foo", gdnative::export::godot_wrap_method!(Foo, fn foo(&self, _owner: &Reference, bar: i64) -> i64))
/// builder.method("foo", gdnative::export::godot_wrap_method!(Foo, false, fn foo(&self, _owner: &Reference, bar: i64) -> i64))
/// .with_rpc_mode(RpcMode::Disabled)
/// .done_stateless();
/// }
Expand Down
42 changes: 27 additions & 15 deletions gdnative-derive/src/methods.rs
Expand Up @@ -86,7 +86,7 @@ pub(crate) fn derive_methods(item_impl: ItemImpl) -> TokenStream2 {
let name = sig.ident;
let name_string = args.name_override.unwrap_or_else(|| name.to_string());
let ret_span = sig.output.span();
let ret_ty = match sig.output {
let ret_ty = match &sig.output {
syn::ReturnType::Default => quote_spanned!(ret_span => ()),
syn::ReturnType::Type(_, ty) => quote_spanned!( ret_span => #ty ),
};
Expand Down Expand Up @@ -128,6 +128,16 @@ pub(crate) fn derive_methods(item_impl: ItemImpl) -> TokenStream2 {
}
});

let deprecated = if let syn::ReturnType::Type(_, ty) = &sig.output {
if !is_deref_return && matches!(**ty, syn::Type::Reference(_)) {
quote_spanned!(ret_span=> ::gdnative::export::deprecated_reference_return!();)
} else {
quote_spanned!(ret_span=>)
}
} else {
quote_spanned!(ret_span=>)
};

quote_spanned!( sig_span=>
{
let method = ::gdnative::export::godot_wrap_method!(
Expand All @@ -139,6 +149,8 @@ pub(crate) fn derive_methods(item_impl: ItemImpl) -> TokenStream2 {
#builder.method(#name_string, method)
.with_rpc_mode(#rpc)
.done_stateless();

#deprecated
}
)
})
Expand Down Expand Up @@ -204,19 +216,19 @@ fn impl_gdnative_expose(ast: ItemImpl) -> (ItemImpl, ClassMethodExport) {
let _export_args = export_args.get_or_insert_with(ExportArgs::default);
use syn::{punctuated::Punctuated, Lit, Meta, NestedMeta};
let nested_meta_iter = match attr.parse_meta() {
Err(err) => {
errors.push(err);
return false;
}
Err(err) => {
errors.push(err);
return false;
}
Ok(Meta::NameValue(name_value)) => {
let span = name_value.span();
let msg = "NameValue syntax is not valid";
errors.push(syn::Error::new(span, msg));
errors.push(syn::Error::new(span, msg));
return false;
}
}
Ok(Meta::Path(_)) => {
Punctuated::<NestedMeta, syn::token::Comma>::new().into_iter()
}
}
Ok(Meta::List(list)) => list.nested.into_iter(),
};
for nested_meta in nested_meta_iter {
Expand All @@ -239,15 +251,15 @@ fn impl_gdnative_expose(ast: ItemImpl) -> (ItemImpl, ClassMethodExport) {
(&name_value.path, Some(&name_value.lit))
}
},
};
};
if path.is_ident("rpc") {
// rpc mode
// rpc mode
match lit {
None => {
errors.push(syn::Error::new(
errors.push(syn::Error::new(
nested_meta.span(),
"name parameter requires string value",
));
));
}
Some(Lit::Str(str)) => {
let value = str.value();
Expand All @@ -273,13 +285,13 @@ fn impl_gdnative_expose(ast: ItemImpl) -> (ItemImpl, ClassMethodExport) {
}
}
} else if path.is_ident("name") {
// name override
// name override
match lit {
None => {
errors.push(syn::Error::new(
errors.push(syn::Error::new(
nested_meta.span(),
"name parameter requires string value",
));
));
}
Some(Lit::Str(str)) => {
if name_override.replace(str.value()).is_some() {
Expand Down

0 comments on commit c3f5fe8

Please sign in to comment.