From e67782a014c0ac493b803db41f8e060da212fcac Mon Sep 17 00:00:00 2001 From: Monnoroch Date: Sat, 28 Jul 2018 21:29:51 +0100 Subject: [PATCH] Clean up generator templates code. - Better API - Better naming - Cleaner code - Improved performance --- generator/src/generate.rs | 701 +++++++++++++++++++------------------- generator/src/lib.rs | 5 +- generator/src/prepare.rs | 213 ++++++------ 3 files changed, 444 insertions(+), 475 deletions(-) diff --git a/generator/src/generate.rs b/generator/src/generate.rs index a90ed37..4579f8b 100644 --- a/generator/src/generate.rs +++ b/generator/src/generate.rs @@ -2,27 +2,28 @@ use super::assert_tokens_equals; use proc_macro2::*; use std::iter; +use std::iter::FromIterator; -#[derive(Debug, Clone)] -pub struct ClassMethodGeneratorDefinition { +#[derive(Debug)] +pub struct ClassMethod { pub name: Ident, pub java_name: Literal, pub return_type: TokenStream, pub argument_names: Vec, pub argument_types: Vec, - pub public: TokenStream, + pub public: bool, } -#[derive(Debug, Clone)] -pub struct InterfaceMethodGeneratorDefinition { +#[derive(Debug)] +pub struct InterfaceMethod { pub name: Ident, pub return_type: TokenStream, pub argument_names: Vec, pub argument_types: Vec, } -#[derive(Debug, Clone)] -pub struct InterfaceMethodImplementationGeneratorDefinition { +#[derive(Debug)] +pub struct InterfaceMethodImplementation { pub name: Ident, pub return_type: TokenStream, pub argument_names: Vec, @@ -30,8 +31,8 @@ pub struct InterfaceMethodImplementationGeneratorDefinition { pub class_cast: TokenStream, } -#[derive(Debug, Clone)] -pub struct NativeMethodGeneratorDefinition { +#[derive(Debug)] +pub struct NativeMethod { pub name: Ident, pub rust_name: Ident, pub java_name: Ident, @@ -39,84 +40,100 @@ pub struct NativeMethodGeneratorDefinition { pub argument_names: Vec, pub argument_types: Vec, pub argument_types_no_lifetime: Vec, - pub public: TokenStream, + pub public: bool, pub code: Group, } -#[derive(Debug, Clone)] -pub struct ConstructorGeneratorDefinition { +#[derive(Debug)] +pub struct Constructor { pub name: Ident, pub argument_names: Vec, pub argument_types: Vec, - pub public: TokenStream, + pub public: bool, } -#[derive(Debug, Clone)] -pub struct InterfaceImplementationGeneratorDefinition { +#[derive(Debug)] +pub struct InterfaceImplementation { pub interface: TokenStream, - pub methods: Vec, + pub methods: Vec, } -#[derive(Debug, Clone)] -pub struct ClassGeneratorDefinition { +#[derive(Debug)] +pub struct Class { pub class: Ident, - pub public: TokenStream, + pub public: bool, pub super_class: TokenStream, pub transitive_extends: Vec, - pub implements: Vec, + pub implements: Vec, pub signature: Literal, pub full_signature: Literal, - pub constructors: Vec, - pub methods: Vec, - pub static_methods: Vec, - pub native_methods: Vec, - pub static_native_methods: Vec, + pub constructors: Vec, + pub methods: Vec, + pub static_methods: Vec, + pub native_methods: Vec, + pub static_native_methods: Vec, } -#[derive(Debug, Clone)] -pub struct InterfaceGeneratorDefinition { +#[derive(Debug)] +pub struct Interface { pub interface: Ident, - pub public: TokenStream, + pub public: bool, pub extends: Vec, - pub methods: Vec, + pub methods: Vec, } -#[derive(Debug, Clone)] +#[derive(Debug)] pub enum GeneratorDefinition { - Class(ClassGeneratorDefinition), - Interface(InterfaceGeneratorDefinition), + Interface(Interface), + Class(Class), } -impl PartialEq for GeneratorDefinition { - fn eq(&self, other: &Self) -> bool { - format!("{:?}", self) == format!("{:?}", other) - } -} - -impl Eq for GeneratorDefinition {} - -#[derive(Debug, PartialEq, Eq, Clone)] +#[derive(Debug)] pub struct GeneratorData { pub definitions: Vec, } -pub fn generate(data: GeneratorData) -> TokenStream { - let mut tokens = TokenStream::new(); - for definition in data.definitions { - tokens.extend(generate_definition(definition)); - } - tokens +pub fn generate(data: &GeneratorData) -> TokenStream { + TokenStream::from_iter( + data.definitions + .iter() + .map(generate_definition) + .flat_map(|tokens| tokens.into_iter()), + ) } -fn generate_definition(definition: GeneratorDefinition) -> TokenStream { +fn generate_definition(definition: &GeneratorDefinition) -> TokenStream { match definition { - GeneratorDefinition::Class(class) => generate_class_definition(class), - GeneratorDefinition::Interface(interface) => generate_interface_definition(interface), + GeneratorDefinition::Interface(interface) => generate_interface(interface), + GeneratorDefinition::Class(class) => generate_class(class), + } +} + +fn generate_interface(definition: &Interface) -> TokenStream { + let Interface { + interface, + public, + extends, + methods, + } = definition; + let extends = if extends.is_empty() { + quote!{} + } else { + quote!{: #(#extends<'a>)+*} + }; + let methods = methods.iter().map(generate_interface_method); + let public = generate_public(*public); + quote! { + #public trait #interface<'a> #extends { + #( + #methods + )* + } } } -fn generate_interface_method(method: InterfaceMethodGeneratorDefinition) -> TokenStream { - let InterfaceMethodGeneratorDefinition { +fn generate_interface_method(method: &InterfaceMethod) -> TokenStream { + let InterfaceMethod { name, return_type, argument_names, @@ -131,8 +148,199 @@ fn generate_interface_method(method: InterfaceMethodGeneratorDefinition) -> Toke } } -fn generate_class_method(method: ClassMethodGeneratorDefinition) -> TokenStream { - let ClassMethodGeneratorDefinition { +fn generate_class(definition: &Class) -> TokenStream { + let Class { + class, + public, + super_class, + transitive_extends, + implements, + signature, + full_signature, + constructors, + methods, + static_methods, + native_methods, + static_native_methods, + } = definition; + let multiplied_class = iter::repeat(&class); + let transitive_extends_1 = transitive_extends.iter(); + let transitive_extends = transitive_extends.iter(); + let methods = methods.iter().map(generate_class_method); + let static_methods = static_methods.iter().map(generate_static_class_method); + let native_method_functions = native_methods + .iter() + .map(|method| generate_class_native_method_function(method, &class)); + let static_native_method_functions = static_native_methods + .iter() + .map(|method| generate_static_class_native_method_function(method, &class)); + let native_methods = native_methods.iter().map(generate_class_native_method); + let static_native_methods = static_native_methods + .iter() + .map(generate_static_class_native_method); + let constructors = constructors.iter().map(generate_constructor); + let implementations = implements + .iter() + .map(|interface| generate_interface_implementation(interface, &class)); + let public = generate_public(*public); + quote! { + #[derive(Debug)] + #public struct #class<'env> { + object: #super_class<'env>, + } + + impl<'a> ::rust_jni::JavaType for #class<'a> { + #[doc(hidden)] + type __JniType = <::rust_jni::java::lang::Object<'a> as ::rust_jni::JavaType>::__JniType; + + #[doc(hidden)] + fn __signature() -> &'static str { + #full_signature + } + } + + impl<'a> ::rust_jni::__generator::ToJni for #class<'a> { + unsafe fn __to_jni(&self) -> Self::__JniType { + self.raw_object() + } + } + + impl<'a> ::rust_jni::__generator::FromJni<'a> for #class<'a> { + unsafe fn __from_jni(env: &'a ::rust_jni::JniEnv<'a>, value: Self::__JniType) -> Self { + Self { + object: <#super_class as ::rust_jni::__generator::FromJni<'a>>::__from_jni(env, value), + } + } + } + + impl<'a> ::rust_jni::Cast<'a, #class<'a>> for #class<'a> { + #[doc(hidden)] + fn cast<'b>(&'b self) -> &'b #class<'a> { + self + } + } + + #( + impl<'a> ::rust_jni::Cast<'a, #transitive_extends<'a>> for #multiplied_class<'a> { + #[doc(hidden)] + fn cast<'b>(&'b self) -> &'b #transitive_extends_1<'a> { + self + } + } + )* + + impl<'a> ::std::ops::Deref for #class<'a> { + type Target = #super_class<'a>; + + fn deref(&self) -> &Self::Target { + &self.object + } + } + + impl<'a> #class<'a> { + pub fn get_class(env: &'a ::rust_jni::JniEnv<'a>, token: &::rust_jni::NoException<'a>) + -> ::rust_jni::JavaResult<'a, ::rust_jni::java::lang::Class<'a>> { + ::rust_jni::java::lang::Class::find(env, #signature, token) + } + + pub fn clone(&self, token: &::rust_jni::NoException<'a>) -> ::rust_jni::JavaResult<'a, Self> + where + Self: Sized, + { + self.object + .clone(token) + .map(|object| Self { object }) + } + + pub fn to_string(&self, token: &::rust_jni::NoException<'a>) + -> ::rust_jni::JavaResult<'a, ::rust_jni::java::lang::String<'a>> { + self.object.to_string(token) + } + + #( + #constructors + )* + + #( + #methods + )* + + #( + #static_methods + )* + + #( + #native_methods + )* + + #( + #static_native_methods + )* + } + + // TODO: put them into an anonymous module. + + #( + #native_method_functions + )* + + #( + #static_native_method_functions + )* + + impl<'a> ::std::fmt::Display for #class<'a> { + fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + self.object.fmt(formatter) + } + } + + impl<'a, T> PartialEq for #class<'a> where T: ::rust_jni::Cast<'a, ::rust_jni::java::lang::Object<'a>> { + fn eq(&self, other: &T) -> bool { + self.object.eq(other) + } + } + + impl<'a> Eq for #class<'a> {} + + #( + #implementations + )* + } +} + +fn generate_constructor(method: &Constructor) -> TokenStream { + let Constructor { + name, + public, + argument_names, + argument_types, + } = method; + let argument_names_1 = argument_names.iter(); + let argument_names = argument_names.iter(); + let argument_types_1 = argument_types.iter(); + let argument_types = argument_types.iter(); + let public = generate_public(*public); + quote!{ + #public fn #name( + env: &'a ::rust_jni::JniEnv<'a>, + #(#argument_names: #argument_types,)* + token: &::rust_jni::NoException<'a>, + ) -> ::rust_jni::JavaResult<'a, Self> { + // Safe because the method name and arguments are correct. + unsafe { + ::rust_jni::__generator::call_constructor:: + ( + env, + (#(#argument_names_1,)*), + token, + ) + } + } + } +} + +fn generate_class_method(method: &ClassMethod) -> TokenStream { + let ClassMethod { name, java_name, return_type, @@ -140,8 +348,11 @@ fn generate_class_method(method: ClassMethodGeneratorDefinition) -> TokenStream argument_names, argument_types, } = method; - let argument_names_1 = argument_names.clone(); - let argument_types_1 = argument_types.clone(); + let argument_names_1 = argument_names.iter(); + let argument_names = argument_names.iter(); + let argument_types_1 = argument_types.iter(); + let argument_types = argument_types.iter(); + let public = generate_public(*public); quote!{ #public fn #name( &self, @@ -164,8 +375,8 @@ fn generate_class_method(method: ClassMethodGeneratorDefinition) -> TokenStream } } -fn generate_static_class_method(method: ClassMethodGeneratorDefinition) -> TokenStream { - let ClassMethodGeneratorDefinition { +fn generate_static_class_method(method: &ClassMethod) -> TokenStream { + let ClassMethod { name, java_name, return_type, @@ -173,8 +384,11 @@ fn generate_static_class_method(method: ClassMethodGeneratorDefinition) -> Token argument_names, argument_types, } = method; - let argument_names_1 = argument_names.clone(); - let argument_types_1 = argument_types.clone(); + let argument_names_1 = argument_names.iter(); + let argument_names = argument_names.iter(); + let argument_types_1 = argument_types.iter(); + let argument_types = argument_types.iter(); + let public = generate_public(*public); quote!{ #public fn #name( env: &'a ::rust_jni::JniEnv<'a>, @@ -197,8 +411,8 @@ fn generate_static_class_method(method: ClassMethodGeneratorDefinition) -> Token } } -fn generate_class_native_method(method: NativeMethodGeneratorDefinition) -> TokenStream { - let NativeMethodGeneratorDefinition { +fn generate_class_native_method(method: &NativeMethod) -> TokenStream { + let NativeMethod { rust_name, return_type, public, @@ -207,6 +421,7 @@ fn generate_class_native_method(method: NativeMethodGeneratorDefinition) -> Toke code, .. } = method; + let public = generate_public(*public); quote!{ #public fn #rust_name( &self, @@ -218,8 +433,8 @@ fn generate_class_native_method(method: NativeMethodGeneratorDefinition) -> Toke } } -fn generate_static_class_native_method(method: NativeMethodGeneratorDefinition) -> TokenStream { - let NativeMethodGeneratorDefinition { +fn generate_static_class_native_method(method: &NativeMethod) -> TokenStream { + let NativeMethod { rust_name, return_type, public, @@ -228,6 +443,7 @@ fn generate_static_class_native_method(method: NativeMethodGeneratorDefinition) code, .. } = method; + let public = generate_public(*public); quote!{ #public fn #rust_name( env: &'a ::rust_jni::JniEnv<'a>, @@ -239,11 +455,8 @@ fn generate_static_class_native_method(method: NativeMethodGeneratorDefinition) } } -fn generate_class_native_method_function( - method: NativeMethodGeneratorDefinition, - class_name: &Ident, -) -> TokenStream { - let NativeMethodGeneratorDefinition { +fn generate_class_native_method_function(method: &NativeMethod, class_name: &Ident) -> TokenStream { + let NativeMethod { rust_name, java_name, return_type, @@ -251,10 +464,12 @@ fn generate_class_native_method_function( argument_types_no_lifetime, .. } = method; - let argument_names_1 = argument_names.clone(); - let argument_names_2 = argument_names.clone(); - let argument_names_3 = argument_names.clone(); - let argument_types_no_lifetime_1 = argument_types_no_lifetime.clone(); + let argument_names_1 = argument_names.iter(); + let argument_names_2 = argument_names.iter(); + let argument_names_3 = argument_names.iter(); + let argument_names = argument_names.iter(); + let argument_types_no_lifetime_1 = argument_types_no_lifetime.iter(); + let argument_types_no_lifetime = argument_types_no_lifetime.iter(); quote!{ #[no_mangle] #[doc(hidden)] @@ -297,10 +512,10 @@ fn generate_class_native_method_function( } fn generate_static_class_native_method_function( - method: NativeMethodGeneratorDefinition, + method: &NativeMethod, class_name: &Ident, ) -> TokenStream { - let NativeMethodGeneratorDefinition { + let NativeMethod { name, rust_name, java_name, @@ -309,10 +524,12 @@ fn generate_static_class_native_method_function( argument_types_no_lifetime, .. } = method; - let argument_names_1 = argument_names.clone(); - let argument_names_2 = argument_names.clone(); - let argument_names_3 = argument_names.clone(); - let argument_types_no_lifetime_1 = argument_types_no_lifetime.clone(); + let argument_names_1 = argument_names.iter(); + let argument_names_2 = argument_names.iter(); + let argument_names_3 = argument_names.iter(); + let argument_names = argument_names.iter(); + let argument_types_no_lifetime_1 = argument_types_no_lifetime.iter(); + let argument_types_no_lifetime = argument_types_no_lifetime.iter(); let class_mismatch_error = format!( "Native method {} does not belong to class {}", name.to_string(), @@ -368,45 +585,16 @@ fn generate_static_class_native_method_function( } } -fn generate_constructor(method: ConstructorGeneratorDefinition) -> TokenStream { - let ConstructorGeneratorDefinition { - name, - public, - argument_names, - argument_types, - } = method; - let argument_names_1 = argument_names.clone(); - let argument_types_1 = argument_types.clone(); - quote!{ - #public fn #name( - env: &'a ::rust_jni::JniEnv<'a>, - #(#argument_names: #argument_types,)* - token: &::rust_jni::NoException<'a>, - ) -> ::rust_jni::JavaResult<'a, Self> { - // Safe because the method name and arguments are correct. - unsafe { - ::rust_jni::__generator::call_constructor:: - ( - env, - (#(#argument_names_1,)*), - token, - ) - } - } - } -} - -fn generate_interface_method_implementation( - method: InterfaceMethodImplementationGeneratorDefinition, -) -> TokenStream { - let InterfaceMethodImplementationGeneratorDefinition { +fn generate_interface_method_implementation(method: &InterfaceMethodImplementation) -> TokenStream { + let InterfaceMethodImplementation { name, argument_names, argument_types, return_type, class_cast, } = method; - let argument_names_1 = argument_names.clone(); + let argument_names_1 = argument_names.iter(); + let argument_names = argument_names.iter(); quote!{ fn #name( &self, @@ -421,16 +609,11 @@ fn generate_interface_method_implementation( } fn generate_interface_implementation( - interface: InterfaceImplementationGeneratorDefinition, + interface: &InterfaceImplementation, class: &Ident, ) -> TokenStream { - let InterfaceImplementationGeneratorDefinition { - interface, methods, .. - } = interface; - let methods = methods - .into_iter() - .map(generate_interface_method_implementation) - .collect::>(); + let InterfaceImplementation { interface, methods } = interface; + let methods = methods.iter().map(generate_interface_method_implementation); quote! { impl<'a> #interface<'a> for #class<'a> { #( @@ -440,207 +623,11 @@ fn generate_interface_implementation( } } -fn generate_class_definition(definition: ClassGeneratorDefinition) -> TokenStream { - let ClassGeneratorDefinition { - class, - public, - super_class, - transitive_extends, - implements, - signature, - full_signature, - constructors, - methods, - static_methods, - native_methods, - static_native_methods, - .. - } = definition; - let multiplied_class = iter::repeat(class.clone()); - let multiplied_class_1 = multiplied_class.clone(); - let transitive_extends_1 = transitive_extends.clone(); - let methods = methods - .into_iter() - .map(generate_class_method) - .collect::>(); - let static_methods = static_methods - .into_iter() - .map(generate_static_class_method) - .collect::>(); - let native_method_functions = native_methods - .clone() - .into_iter() - .map(|method| generate_class_native_method_function(method, &class)) - .collect::>(); - let static_native_method_functions = static_native_methods - .clone() - .into_iter() - .map(|method| generate_static_class_native_method_function(method, &class)) - .collect::>(); - let native_methods = native_methods - .into_iter() - .map(generate_class_native_method) - .collect::>(); - let static_native_methods = static_native_methods - .into_iter() - .map(generate_static_class_native_method) - .collect::>(); - let constructors = constructors - .into_iter() - .map(generate_constructor) - .collect::>(); - let implementations = implements - .into_iter() - .map(|interface| generate_interface_implementation(interface, &class)) - .collect::>(); - quote! { - #[derive(Debug)] - #public struct #class<'env> { - object: #super_class<'env>, - } - - impl<'a> ::rust_jni::JavaType for #class<'a> { - #[doc(hidden)] - type __JniType = <::rust_jni::java::lang::Object<'a> as ::rust_jni::JavaType>::__JniType; - - #[doc(hidden)] - fn __signature() -> &'static str { - #full_signature - } - } - - impl<'a> ::rust_jni::__generator::ToJni for #class<'a> { - unsafe fn __to_jni(&self) -> Self::__JniType { - self.raw_object() - } - } - - impl<'a> ::rust_jni::__generator::FromJni<'a> for #class<'a> { - unsafe fn __from_jni(env: &'a ::rust_jni::JniEnv<'a>, value: Self::__JniType) -> Self { - Self { - object: <#super_class as ::rust_jni::__generator::FromJni<'a>>::__from_jni(env, value), - } - } - } - - impl<'a> ::rust_jni::Cast<'a, #class<'a>> for #class<'a> { - #[doc(hidden)] - fn cast<'b>(&'b self) -> &'b #class<'a> { - self - } - } - - #( - impl<'a> ::rust_jni::Cast<'a, #transitive_extends<'a>> for #multiplied_class_1<'a> { - #[doc(hidden)] - fn cast<'b>(&'b self) -> &'b #transitive_extends_1<'a> { - self - } - } - )* - - impl<'a> ::std::ops::Deref for #class<'a> { - type Target = #super_class<'a>; - - fn deref(&self) -> &Self::Target { - &self.object - } - } - - impl<'a> #class<'a> { - pub fn get_class(env: &'a ::rust_jni::JniEnv<'a>, token: &::rust_jni::NoException<'a>) - -> ::rust_jni::JavaResult<'a, ::rust_jni::java::lang::Class<'a>> { - ::rust_jni::java::lang::Class::find(env, #signature, token) - } - - pub fn clone(&self, token: &::rust_jni::NoException<'a>) -> ::rust_jni::JavaResult<'a, Self> - where - Self: Sized, - { - self.object - .clone(token) - .map(|object| Self { object }) - } - - pub fn to_string(&self, token: &::rust_jni::NoException<'a>) - -> ::rust_jni::JavaResult<'a, ::rust_jni::java::lang::String<'a>> { - self.object.to_string(token) - } - - #( - #constructors - )* - - #( - #methods - )* - - #( - #static_methods - )* - - #( - #native_methods - )* - - #( - #static_native_methods - )* - } - - // TODO: put them into an anonymous module. - - #( - #native_method_functions - )* - - #( - #static_native_method_functions - )* - - impl<'a> ::std::fmt::Display for #class<'a> { - fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - self.object.fmt(formatter) - } - } - - impl<'a, T> PartialEq for #class<'a> where T: ::rust_jni::Cast<'a, ::rust_jni::java::lang::Object<'a>> { - fn eq(&self, other: &T) -> bool { - self.object.eq(other) - } - } - - impl<'a> Eq for #class<'a> {} - - #( - #implementations - )* - } -} - -fn generate_interface_definition(definition: InterfaceGeneratorDefinition) -> TokenStream { - let InterfaceGeneratorDefinition { - interface, - public, - extends, - methods, - .. - } = definition; - let extends = if extends.is_empty() { - TokenStream::new() +fn generate_public(public: bool) -> TokenStream { + if public { + quote!{pub} } else { - quote!{: #(#extends<'a>)+*} - }; - let methods = methods - .into_iter() - .map(generate_interface_method) - .collect::>(); - quote! { - #public trait #interface<'a> #extends { - #( - #methods - )* - } + quote!{} } } @@ -654,15 +641,15 @@ mod generate_tests { definitions: vec![], }; let expected = quote!{}; - assert_tokens_equals(generate(input), expected); + assert_tokens_equals(generate(&input), expected); } #[test] fn one_class() { let input = GeneratorData { - definitions: vec![GeneratorDefinition::Class(ClassGeneratorDefinition { + definitions: vec![GeneratorDefinition::Class(Class { class: Ident::new("test1", Span::call_site()), - public: quote!{test_public}, + public: true, super_class: quote!{c::d::test2}, transitive_extends: vec![quote!{c::d::test2}], implements: vec![], @@ -677,7 +664,7 @@ mod generate_tests { }; let expected = quote!{ #[derive(Debug)] - test_public struct test1<'env> { + pub struct test1<'env> { object: c::d::test2<'env>, } @@ -762,23 +749,23 @@ mod generate_tests { impl<'a> Eq for test1<'a> {} }; - assert_tokens_equals(generate(input), expected); + assert_tokens_equals(generate(&input), expected); } #[test] fn one_class_implements() { let input = GeneratorData { - definitions: vec![GeneratorDefinition::Class(ClassGeneratorDefinition { + definitions: vec![GeneratorDefinition::Class(Class { class: Ident::new("test1", Span::call_site()), - public: quote!{test_public}, + public: true, super_class: quote!{c::d::test2}, transitive_extends: vec![quote!{c::d::test2}], implements: vec![ - InterfaceImplementationGeneratorDefinition { + InterfaceImplementation { interface: quote!{e::f::test3}, methods: vec![], }, - InterfaceImplementationGeneratorDefinition { + InterfaceImplementation { interface: quote!{e::f::test4}, methods: vec![], }, @@ -794,7 +781,7 @@ mod generate_tests { }; let expected = quote!{ #[derive(Debug)] - test_public struct test1<'env> { + pub struct test1<'env> { object: c::d::test2<'env>, } @@ -885,66 +872,62 @@ mod generate_tests { impl<'a> e::f::test4<'a> for test1<'a> { } }; - assert_tokens_equals(generate(input), expected); + assert_tokens_equals(generate(&input), expected); } #[test] fn one_interface() { let input = GeneratorData { - definitions: vec![GeneratorDefinition::Interface( - InterfaceGeneratorDefinition { - interface: Ident::new("test1", Span::call_site()), - public: quote!{test_public}, - extends: vec![], - methods: vec![], - }, - )], + definitions: vec![GeneratorDefinition::Interface(Interface { + interface: Ident::new("test1", Span::call_site()), + public: true, + extends: vec![], + methods: vec![], + })], }; let expected = quote!{ - test_public trait test1<'a> { + pub trait test1<'a> { } }; - assert_tokens_equals(generate(input), expected); + assert_tokens_equals(generate(&input), expected); } #[test] fn one_interface_extends() { let input = GeneratorData { - definitions: vec![GeneratorDefinition::Interface( - InterfaceGeneratorDefinition { - interface: Ident::new("test1", Span::call_site()), - public: TokenStream::new(), - extends: vec![quote!{c::d::test2}, quote!{e::f::test3}], - methods: vec![], - }, - )], + definitions: vec![GeneratorDefinition::Interface(Interface { + interface: Ident::new("test1", Span::call_site()), + public: false, + extends: vec![quote!{c::d::test2}, quote!{e::f::test3}], + methods: vec![], + })], }; let expected = quote!{ trait test1<'a> : c::d::test2<'a> + e::f::test3<'a> { } }; - assert_tokens_equals(generate(input), expected); + assert_tokens_equals(generate(&input), expected); } #[test] fn multiple() { let input = GeneratorData { definitions: vec![ - GeneratorDefinition::Interface(InterfaceGeneratorDefinition { + GeneratorDefinition::Interface(Interface { interface: Ident::new("test_if1", Span::call_site()), - public: TokenStream::new(), + public: false, extends: vec![], methods: vec![], }), - GeneratorDefinition::Interface(InterfaceGeneratorDefinition { + GeneratorDefinition::Interface(Interface { interface: Ident::new("test_if2", Span::call_site()), - public: TokenStream::new(), + public: false, extends: vec![], methods: vec![], }), - GeneratorDefinition::Class(ClassGeneratorDefinition { + GeneratorDefinition::Class(Class { class: Ident::new("test1", Span::call_site()), - public: TokenStream::new(), + public: false, super_class: quote!{c::d::test3}, transitive_extends: vec![quote!{c::d::test3}], implements: vec![], @@ -956,9 +939,9 @@ mod generate_tests { native_methods: vec![], static_native_methods: vec![], }), - GeneratorDefinition::Class(ClassGeneratorDefinition { + GeneratorDefinition::Class(Class { class: Ident::new("test2", Span::call_site()), - public: TokenStream::new(), + public: false, super_class: quote!{c::d::test4}, transitive_extends: vec![quote!{c::d::test4}], implements: vec![], @@ -1151,6 +1134,6 @@ mod generate_tests { impl<'a> Eq for test2<'a> {} }; - assert_tokens_equals(generate(input), expected); + assert_tokens_equals(generate(&input), expected); } } diff --git a/generator/src/lib.rs b/generator/src/lib.rs index 31a8960..7af9346 100644 --- a/generator/src/lib.rs +++ b/generator/src/lib.rs @@ -22,12 +22,11 @@ use proc_macro2::*; /// TODO(#76): examples. #[proc_macro] pub fn java_generate(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - let input: TokenStream = input.into(); - java_generate_impl(input).into() + java_generate_impl(input.into()).into() } fn java_generate_impl(input: TokenStream) -> TokenStream { - generate(to_generator_data(parse_java_definition(input))) + generate(&to_generator_data(parse_java_definition(input))) } #[cfg(test)] diff --git a/generator/src/prepare.rs b/generator/src/prepare.rs index be78c89..4d2119e 100644 --- a/generator/src/prepare.rs +++ b/generator/src/prepare.rs @@ -1,4 +1,4 @@ -use generate::*; +use generate::{self, GeneratorData, GeneratorDefinition}; use java_name::*; use parse::*; use proc_macro2::*; @@ -26,14 +26,6 @@ fn populate_interface_extends(interface_extends: &mut HashMap TokenStream { - if public { - quote!{pub} - } else { - TokenStream::new() - } -} - fn annotation_value(annotations: &[Annotation], name: &str) -> Option { let values = annotations .iter() @@ -65,7 +57,7 @@ fn annotation_value_ident(annotations: &[Annotation], name: &str) -> Option ClassMethodGeneratorDefinition { +fn to_generator_method(method: JavaClassMethod) -> generate::ClassMethod { let JavaClassMethod { name, public, @@ -74,9 +66,8 @@ fn to_generator_method(method: JavaClassMethod) -> ClassMethodGeneratorDefinitio annotations, .. } = method; - let public = public_token(public); let java_name = Literal::string(&name.to_string()); - ClassMethodGeneratorDefinition { + generate::ClassMethod { name: annotation_value_ident(&annotations, "RustName").unwrap_or(name), java_name, public, @@ -92,9 +83,7 @@ fn to_generator_method(method: JavaClassMethod) -> ClassMethodGeneratorDefinitio } } -fn to_generator_interface_method( - method: JavaInterfaceMethod, -) -> InterfaceMethodGeneratorDefinition { +fn to_generator_interface_method(method: JavaInterfaceMethod) -> generate::InterfaceMethod { let JavaInterfaceMethod { name, return_type, @@ -102,7 +91,7 @@ fn to_generator_interface_method( annotations, .. } = method; - InterfaceMethodGeneratorDefinition { + generate::InterfaceMethod { name: annotation_value_ident(&annotations, "RustName").unwrap_or(name), return_type: return_type.as_rust_type(), argument_names: arguments @@ -121,7 +110,7 @@ fn to_generator_interface_method_implementation( class_methods: &Vec, interface: &JavaName, super_class: &TokenStream, -) -> InterfaceMethodImplementationGeneratorDefinition { +) -> generate::InterfaceMethodImplementation { let JavaInterfaceMethod { name, return_type, @@ -135,7 +124,7 @@ fn to_generator_interface_method_implementation( && class_method.arguments == arguments }); let interface = interface.clone().with_double_colons(); - InterfaceMethodImplementationGeneratorDefinition { + generate::InterfaceMethodImplementation { name: annotation_value_ident(&annotations, "RustName").unwrap_or(name), return_type: return_type.as_rust_type(), argument_names: arguments @@ -157,7 +146,7 @@ fn to_generator_interface_method_implementation( fn to_generator_native_method( method: JavaNativeMethod, class_name: &JavaName, -) -> NativeMethodGeneratorDefinition { +) -> generate::NativeMethod { let JavaNativeMethod { name, public, @@ -167,7 +156,6 @@ fn to_generator_native_method( annotations, .. } = method; - let public = public_token(public); let signatures = arguments .iter() .map(|argument| &argument.data_type) @@ -183,7 +171,7 @@ fn to_generator_native_method( Span::call_site(), ); let rust_name = annotation_value_ident(&annotations, "RustName").unwrap_or(name.clone()); - NativeMethodGeneratorDefinition { + generate::NativeMethod { name, rust_name, java_name, @@ -205,16 +193,15 @@ fn to_generator_native_method( } } -fn to_generator_constructor(constructor: JavaConstructor) -> ConstructorGeneratorDefinition { +fn to_generator_constructor(constructor: JavaConstructor) -> generate::Constructor { let JavaConstructor { public, arguments, annotations, .. } = constructor; - let public = public_token(public); let name = Ident::new("init", Span::call_site()); - ConstructorGeneratorDefinition { + generate::Constructor { name: annotation_value_ident(&annotations, "RustName").unwrap_or(name), public, argument_names: arguments @@ -356,7 +343,6 @@ pub fn to_generator_data(definitions: JavaDefinitions) -> GeneratorData { .. } = definition; let definition_name = name.clone().name(); - let public = public_token(public); match definition { JavaDefinitionKind::Class(class) => { let JavaClass { @@ -396,7 +382,7 @@ pub fn to_generator_data(definitions: JavaDefinitions) -> GeneratorData { implements.sort_by(|left, right| left.to_string().cmp(&right.to_string())); let mut implements = implements .into_iter() - .map(|name| InterfaceImplementationGeneratorDefinition { + .map(|name| generate::InterfaceImplementation { interface: name.clone().with_double_colons(), methods: definitions .definitions @@ -468,7 +454,7 @@ pub fn to_generator_data(definitions: JavaDefinitions) -> GeneratorData { .cloned() .map(|method| to_generator_native_method(method, &name)) .collect(); - GeneratorDefinition::Class(ClassGeneratorDefinition { + GeneratorDefinition::Class(generate::Class { class: definition_name, public, super_class, @@ -492,7 +478,7 @@ pub fn to_generator_data(definitions: JavaDefinitions) -> GeneratorData { .cloned() .map(to_generator_interface_method) .collect(); - GeneratorDefinition::Interface(InterfaceGeneratorDefinition { + GeneratorDefinition::Interface(generate::Interface { interface: definition_name, public, methods, @@ -514,7 +500,7 @@ mod to_generator_data_tests { #[test] fn empty() { - assert_eq!( + assert_generator_data_equals( to_generator_data(JavaDefinitions { definitions: vec![], metadata: Metadata { @@ -523,13 +509,13 @@ mod to_generator_data_tests { }), GeneratorData { definitions: vec![], - } + }, ); } #[test] fn metadata_only() { - assert_eq!( + assert_generator_data_equals( to_generator_data(JavaDefinitions { definitions: vec![], metadata: Metadata { @@ -555,13 +541,13 @@ mod to_generator_data_tests { }), GeneratorData { definitions: vec![], - } + }, ); } #[test] fn one_class() { - assert_eq!( + assert_generator_data_equals( to_generator_data(JavaDefinitions { definitions: vec![JavaDefinition { name: JavaName(quote!{a b test1}), @@ -579,9 +565,9 @@ mod to_generator_data_tests { }, }), GeneratorData { - definitions: vec![GeneratorDefinition::Class(ClassGeneratorDefinition { + definitions: vec![GeneratorDefinition::Class(generate::Class { class: Ident::new("test1", Span::call_site()), - public: TokenStream::new(), + public: false, super_class: quote!{::c::d::test2}, transitive_extends: vec![quote!{::c::d::test2}], implements: vec![], @@ -593,13 +579,13 @@ mod to_generator_data_tests { static_native_methods: vec![], constructors: vec![], })], - } + }, ); } #[test] fn one_class_no_extends() { - assert_eq!( + assert_generator_data_equals( to_generator_data(JavaDefinitions { definitions: vec![JavaDefinition { name: JavaName(quote!{a b test1}), @@ -617,9 +603,9 @@ mod to_generator_data_tests { }, }), GeneratorData { - definitions: vec![GeneratorDefinition::Class(ClassGeneratorDefinition { + definitions: vec![GeneratorDefinition::Class(generate::Class { class: Ident::new("test1", Span::call_site()), - public: TokenStream::new(), + public: false, super_class: quote!{::java::lang::Object}, transitive_extends: vec![quote!{::java::lang::Object}], implements: vec![], @@ -631,13 +617,13 @@ mod to_generator_data_tests { static_native_methods: vec![], constructors: vec![], })], - } + }, ); } #[test] fn one_class_extends_recursive() { - assert_eq!( + assert_generator_data_equals( to_generator_data(JavaDefinitions { definitions: vec![ JavaDefinition { @@ -684,9 +670,9 @@ mod to_generator_data_tests { }), GeneratorData { definitions: vec![ - GeneratorDefinition::Class(ClassGeneratorDefinition { + GeneratorDefinition::Class(generate::Class { class: Ident::new("test2", Span::call_site()), - public: TokenStream::new(), + public: false, super_class: quote!{::e::f::test3}, transitive_extends: vec![ quote!{::e::f::test3}, @@ -702,9 +688,9 @@ mod to_generator_data_tests { static_native_methods: vec![], constructors: vec![], }), - GeneratorDefinition::Class(ClassGeneratorDefinition { + GeneratorDefinition::Class(generate::Class { class: Ident::new("test1", Span::call_site()), - public: TokenStream::new(), + public: false, super_class: quote!{::c::d::test2}, transitive_extends: vec![ quote!{::c::d::test2}, @@ -722,13 +708,13 @@ mod to_generator_data_tests { constructors: vec![], }), ], - } + }, ); } #[test] fn one_class_implements() { - assert_eq!( + assert_generator_data_equals( to_generator_data(JavaDefinitions { definitions: vec![ JavaDefinition { @@ -766,23 +752,23 @@ mod to_generator_data_tests { }), GeneratorData { definitions: vec![ - GeneratorDefinition::Interface(InterfaceGeneratorDefinition { + GeneratorDefinition::Interface(generate::Interface { interface: Ident::new("test4", Span::call_site()), - public: TokenStream::new(), + public: false, extends: vec![], methods: vec![], }), - GeneratorDefinition::Class(ClassGeneratorDefinition { + GeneratorDefinition::Class(generate::Class { class: Ident::new("test1", Span::call_site()), - public: TokenStream::new(), + public: false, super_class: quote!{::java::lang::Object}, transitive_extends: vec![quote!{::java::lang::Object}], implements: vec![ - InterfaceImplementationGeneratorDefinition { + generate::InterfaceImplementation { interface: quote!{::e::f::test3}, methods: vec![], }, - InterfaceImplementationGeneratorDefinition { + generate::InterfaceImplementation { interface: quote!{::e::f::test4}, methods: vec![], }, @@ -796,13 +782,13 @@ mod to_generator_data_tests { constructors: vec![], }), ], - } + }, ); } #[test] fn one_class_implements_recursive() { - assert_eq!( + assert_generator_data_equals( to_generator_data(JavaDefinitions { definitions: vec![ JavaDefinition { @@ -850,27 +836,27 @@ mod to_generator_data_tests { }), GeneratorData { definitions: vec![ - GeneratorDefinition::Interface(InterfaceGeneratorDefinition { + GeneratorDefinition::Interface(generate::Interface { interface: Ident::new("test3", Span::call_site()), - public: TokenStream::new(), + public: false, extends: vec![quote!{::e::f::test4}], methods: vec![], }), - GeneratorDefinition::Class(ClassGeneratorDefinition { + GeneratorDefinition::Class(generate::Class { class: Ident::new("test1", Span::call_site()), - public: TokenStream::new(), + public: false, super_class: quote!{::java::lang::Object}, transitive_extends: vec![quote!{::java::lang::Object}], implements: vec![ - InterfaceImplementationGeneratorDefinition { + generate::InterfaceImplementation { interface: quote!{::e::f::test3}, methods: vec![], }, - InterfaceImplementationGeneratorDefinition { + generate::InterfaceImplementation { interface: quote!{::e::f::test4}, methods: vec![], }, - InterfaceImplementationGeneratorDefinition { + generate::InterfaceImplementation { interface: quote!{::g::h::test5}, methods: vec![], }, @@ -884,13 +870,13 @@ mod to_generator_data_tests { constructors: vec![], }), ], - } + }, ); } #[test] fn one_class_implements_recursive_duplicated() { - assert_eq!( + assert_generator_data_equals( to_generator_data(JavaDefinitions { definitions: vec![ JavaDefinition { @@ -930,29 +916,29 @@ mod to_generator_data_tests { }), GeneratorData { definitions: vec![ - GeneratorDefinition::Interface(InterfaceGeneratorDefinition { + GeneratorDefinition::Interface(generate::Interface { interface: Ident::new("test4", Span::call_site()), - public: TokenStream::new(), + public: false, extends: vec![], methods: vec![], }), - GeneratorDefinition::Interface(InterfaceGeneratorDefinition { + GeneratorDefinition::Interface(generate::Interface { interface: Ident::new("test3", Span::call_site()), - public: TokenStream::new(), + public: false, extends: vec![quote!{::g::h::test4}], methods: vec![], }), - GeneratorDefinition::Class(ClassGeneratorDefinition { + GeneratorDefinition::Class(generate::Class { class: Ident::new("test1", Span::call_site()), - public: TokenStream::new(), + public: false, super_class: quote!{::java::lang::Object}, transitive_extends: vec![quote!{::java::lang::Object}], implements: vec![ - InterfaceImplementationGeneratorDefinition { + generate::InterfaceImplementation { interface: quote!{::e::f::test3}, methods: vec![], }, - InterfaceImplementationGeneratorDefinition { + generate::InterfaceImplementation { interface: quote!{::g::h::test4}, methods: vec![], }, @@ -966,13 +952,13 @@ mod to_generator_data_tests { constructors: vec![], }), ], - } + }, ); } #[test] fn one_class_public() { - assert_eq!( + assert_generator_data_equals( to_generator_data(JavaDefinitions { definitions: vec![JavaDefinition { name: JavaName(quote!{a b test1}), @@ -990,9 +976,9 @@ mod to_generator_data_tests { }, }), GeneratorData { - definitions: vec![GeneratorDefinition::Class(ClassGeneratorDefinition { + definitions: vec![GeneratorDefinition::Class(generate::Class { class: Ident::new("test1", Span::call_site()), - public: quote!{pub}, + public: true, super_class: quote!{::java::lang::Object}, transitive_extends: vec![quote!{::java::lang::Object}], implements: vec![], @@ -1004,13 +990,13 @@ mod to_generator_data_tests { static_native_methods: vec![], constructors: vec![], })], - } + }, ); } #[test] fn one_interface() { - assert_eq!( + assert_generator_data_equals( to_generator_data(JavaDefinitions { definitions: vec![JavaDefinition { name: JavaName(quote!{a b test1}), @@ -1025,21 +1011,19 @@ mod to_generator_data_tests { }, }), GeneratorData { - definitions: vec![GeneratorDefinition::Interface( - InterfaceGeneratorDefinition { - interface: Ident::new("test1", Span::call_site()), - public: TokenStream::new(), - extends: vec![], - methods: vec![], - }, - )], - } + definitions: vec![GeneratorDefinition::Interface(generate::Interface { + interface: Ident::new("test1", Span::call_site()), + public: false, + extends: vec![], + methods: vec![], + })], + }, ); } #[test] fn one_interface_extends() { - assert_eq!( + assert_generator_data_equals( to_generator_data(JavaDefinitions { definitions: vec![ JavaDefinition { @@ -1084,26 +1068,26 @@ mod to_generator_data_tests { }), GeneratorData { definitions: vec![ - GeneratorDefinition::Interface(InterfaceGeneratorDefinition { + GeneratorDefinition::Interface(generate::Interface { interface: Ident::new("test3", Span::call_site()), - public: TokenStream::new(), + public: false, extends: vec![], methods: vec![], }), - GeneratorDefinition::Interface(InterfaceGeneratorDefinition { + GeneratorDefinition::Interface(generate::Interface { interface: Ident::new("test1", Span::call_site()), - public: TokenStream::new(), + public: false, extends: vec![quote!{::c::d::test2}, quote!{::e::f::test3}], methods: vec![], }), ], - } + }, ); } #[test] fn one_interface_public() { - assert_eq!( + assert_generator_data_equals( to_generator_data(JavaDefinitions { definitions: vec![JavaDefinition { name: JavaName(quote!{a b test1}), @@ -1118,21 +1102,19 @@ mod to_generator_data_tests { }, }), GeneratorData { - definitions: vec![GeneratorDefinition::Interface( - InterfaceGeneratorDefinition { - interface: Ident::new("test1", Span::call_site()), - public: quote!{pub}, - extends: vec![], - methods: vec![], - }, - )], - } + definitions: vec![GeneratorDefinition::Interface(generate::Interface { + interface: Ident::new("test1", Span::call_site()), + public: true, + extends: vec![], + methods: vec![], + })], + }, ); } #[test] fn multiple() { - assert_eq!( + assert_generator_data_equals( to_generator_data(JavaDefinitions { definitions: vec![ JavaDefinition { @@ -1180,21 +1162,21 @@ mod to_generator_data_tests { }), GeneratorData { definitions: vec![ - GeneratorDefinition::Interface(InterfaceGeneratorDefinition { + GeneratorDefinition::Interface(generate::Interface { interface: Ident::new("test_if1", Span::call_site()), - public: TokenStream::new(), + public: false, extends: vec![], methods: vec![], }), - GeneratorDefinition::Interface(InterfaceGeneratorDefinition { + GeneratorDefinition::Interface(generate::Interface { interface: Ident::new("test_if2", Span::call_site()), - public: TokenStream::new(), + public: false, extends: vec![], methods: vec![], }), - GeneratorDefinition::Class(ClassGeneratorDefinition { + GeneratorDefinition::Class(generate::Class { class: Ident::new("test1", Span::call_site()), - public: TokenStream::new(), + public: false, super_class: quote!{::java::lang::Object}, transitive_extends: vec![quote!{::java::lang::Object}], implements: vec![], @@ -1206,9 +1188,9 @@ mod to_generator_data_tests { static_native_methods: vec![], constructors: vec![], }), - GeneratorDefinition::Class(ClassGeneratorDefinition { + GeneratorDefinition::Class(generate::Class { class: Ident::new("test2", Span::call_site()), - public: TokenStream::new(), + public: false, super_class: quote!{::java::lang::Object}, transitive_extends: vec![quote!{::java::lang::Object}], implements: vec![], @@ -1221,7 +1203,12 @@ mod to_generator_data_tests { constructors: vec![], }), ], - } + }, ); } } + +#[cfg(test)] +fn assert_generator_data_equals(left: GeneratorData, right: GeneratorData) { + assert_eq!(format!("{:?}", left), format!("{:?}", right),); +}