mirror of
https://github.com/hexedtech/jni-toolbox.git
synced 2024-11-22 07:24:53 +01:00
fix: return type void in result
This commit is contained in:
parent
3a09386878
commit
1d00db2648
2 changed files with 46 additions and 10 deletions
|
@ -6,12 +6,13 @@ use syn::{ReturnType, Type};
|
|||
pub(crate) struct ReturnOptions {
|
||||
pub(crate) ty: Option<Box<Type>>,
|
||||
pub(crate) result: bool,
|
||||
pub(crate) void: bool,
|
||||
}
|
||||
|
||||
impl ReturnOptions {
|
||||
pub(crate) fn parse_signature(ret: &ReturnType) -> Result<Self, syn::Error> {
|
||||
match ret {
|
||||
syn::ReturnType::Default => Ok(Self { ty: None, result: false }),
|
||||
syn::ReturnType::Default => Ok(Self { ty: None, result: false, void: true }),
|
||||
syn::ReturnType::Type(_tok, ty) => match *ty.clone() {
|
||||
syn::Type::Path(path) => {
|
||||
let Some(last) = path.path.segments.last() else {
|
||||
|
@ -25,14 +26,14 @@ impl ReturnOptions {
|
|||
syn::PathArguments::AngleBracketed(ref generics) => for generic in generics.args.iter() {
|
||||
match generic {
|
||||
syn::GenericArgument::Lifetime(_) => continue,
|
||||
syn::GenericArgument::Type(ty) => return Ok(Self { ty: Some(Box::new(ty.clone())), result: true }),
|
||||
syn::GenericArgument::Type(ty) => return Ok(Self { ty: Some(Box::new(ty.clone())), result: true, void: is_void(ty) }),
|
||||
_ => return Err(syn::Error::new(Span::call_site(), "unexpected type in Result")),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Self { ty: Some(Box::new(Type::Path(path.clone()))), result: false })
|
||||
Ok(Self { ty: Some(Box::new(Type::Path(path.clone()))), result: false, void: false })
|
||||
},
|
||||
_ => Err(syn::Error::new(Span::call_site(), "unsupported return type")),
|
||||
},
|
||||
|
@ -41,8 +42,29 @@ impl ReturnOptions {
|
|||
|
||||
pub(crate) fn tokens(&self) -> TokenStream {
|
||||
match &self.ty { // TODO why do we need to invoke syn::Token! macro ???
|
||||
Some(t) => ReturnType::Type(syn::Token![->](Span::call_site()), t.clone()).to_token_stream(),
|
||||
Some(t) => quote::quote!( -> <#t as jni_toolbox::IntoJava<'local>>::T ),
|
||||
None => ReturnType::Default.to_token_stream(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_void(ty: &syn::Type) -> bool {
|
||||
match ty {
|
||||
Type::Array(_) => false,
|
||||
Type::BareFn(_) => false,
|
||||
Type::Group(g) => is_void(&g.elem),
|
||||
Type::ImplTrait(_) => false,
|
||||
Type::Infer(_) => false,
|
||||
Type::Macro(_) => false,
|
||||
Type::Never(_) => true,
|
||||
Type::Paren(p) => is_void(&p.elem),
|
||||
Type::Path(p) => p.path.segments.is_empty(),
|
||||
Type::Ptr(_) => false,
|
||||
Type::Reference(_) => false,
|
||||
Type::Slice(_) => false,
|
||||
Type::TraitObject(_) => false,
|
||||
Type::Tuple(x) => x.elems.is_empty(),
|
||||
Type::Verbatim(_) => false,
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ pub(crate) fn generate_jni_wrapper(attrs: TokenStream, input: TokenStream) -> Re
|
|||
|
||||
let attrs = AttrsOptions::parse_attr(attrs)?;
|
||||
let ret = ReturnOptions::parse_signature(&fn_item.sig.output)?;
|
||||
let return_expr = if ret.ty.is_none() {
|
||||
let return_expr = if ret.void {
|
||||
quote::quote!( () )
|
||||
} else if attrs.return_pointer {
|
||||
quote::quote!( std::ptr::null_mut() )
|
||||
|
@ -49,7 +49,7 @@ pub(crate) fn generate_jni_wrapper(attrs: TokenStream, input: TokenStream) -> Re
|
|||
// V----------------------------------V
|
||||
quote::quote! {
|
||||
{
|
||||
use jni_toolbox::{JniToolboxError, FromJava};
|
||||
use jni_toolbox::{JniToolboxError, FromJava, IntoJava};
|
||||
#transforming
|
||||
match #fn_name_inner(#forwarding) {
|
||||
Ok(ret) => ret,
|
||||
|
@ -65,7 +65,7 @@ pub(crate) fn generate_jni_wrapper(attrs: TokenStream, input: TokenStream) -> Re
|
|||
// V----------------------------------V
|
||||
quote::quote! {
|
||||
{
|
||||
use jni_toolbox::{JniToolboxError, FromJava};
|
||||
use jni_toolbox::{JniToolboxError, FromJava, IntoJava};
|
||||
// NOTE: this should be SAFE! the cloned env reference lives less than the actual one, we just lack a
|
||||
// way to get it back from the called function and thus resort to unsafe cloning
|
||||
let mut env_copy = unsafe { #env_ident.unsafe_clone() };
|
||||
|
@ -84,7 +84,14 @@ pub(crate) fn generate_jni_wrapper(attrs: TokenStream, input: TokenStream) -> Re
|
|||
},
|
||||
},
|
||||
}
|
||||
Ok(ret) => ret,
|
||||
Ok(ret) => match ret.into_java(&mut env_copy) {
|
||||
Ok(fin) => return fin,
|
||||
Err(e) => {
|
||||
// TODO should we panic instead?
|
||||
let _ = env_copy.throw_new("java/lang/RuntimeException", format!("{e:?}"));
|
||||
return #return_expr;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -93,9 +100,16 @@ pub(crate) fn generate_jni_wrapper(attrs: TokenStream, input: TokenStream) -> Re
|
|||
// V----------------------------------V
|
||||
quote::quote! {
|
||||
{
|
||||
use jni_toolbox::{JniToolboxError, FromJava};
|
||||
use jni_toolbox::{JniToolboxError, FromJava, IntoJava};
|
||||
#transforming
|
||||
#fn_name_inner(#forwarding)
|
||||
match #fn_name_inner(#forwarding).into_java(&mut #env_ident) {
|
||||
Ok(res) => return res,
|
||||
Err(e) => {
|
||||
// TODO should we panic instead?
|
||||
let _ = #env_ident.throw_new("java/lang/RuntimeException", format!("{e:?}"));
|
||||
return #return_expr;
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
// ^----------------------------------^
|
||||
|
|
Loading…
Reference in a new issue