2020
2121namespace Java . Interop . Tools . JavaCallableWrappers {
2222
23+ public enum JavaPeerStyle {
24+ XAJavaInterop1 ,
25+ JavaInterop1 ,
26+ }
27+
2328 public class JavaCallableWrapperGenerator {
2429
2530 class JavaFieldInfo {
@@ -76,6 +81,7 @@ public JavaCallableWrapperGenerator (TypeDefinition type, Action<string, object[
7681 }
7782
7883 public string ApplicationJavaClass { get ; set ; }
84+ public JavaPeerStyle CodeGenerationTarget { get ; set ; }
7985
8086 public bool GenerateOnCreateOverrides { get ; set ; }
8187
@@ -101,7 +107,7 @@ void AddNestedTypes (TypeDefinition type)
101107 continue ;
102108 if ( ! JavaNativeTypeManager . IsNonStaticInnerClass ( nt , cache ) )
103109 continue ;
104- children . Add ( new JavaCallableWrapperGenerator ( nt , JavaNativeTypeManager . ToJniName ( type ) , log , cache ) ) ;
110+ children . Add ( new JavaCallableWrapperGenerator ( nt , JavaNativeTypeManager . ToJniName ( type , cache ) , log , cache ) ) ;
105111 if ( nt . HasNestedTypes )
106112 AddNestedTypes ( nt ) ;
107113 }
@@ -117,7 +123,7 @@ void AddNestedTypes (TypeDefinition type)
117123 if ( type . IsEnum || type . IsInterface || type . IsValueType )
118124 Diagnostic . Error ( 4200 , LookupSource ( type ) , Localization . Resources . JavaCallableWrappers_XA4200 , type . FullName ) ;
119125
120- string jniName = JavaNativeTypeManager . ToJniName ( type ) ;
126+ string jniName = JavaNativeTypeManager . ToJniName ( type , resolver ) ;
121127 if ( jniName == null )
122128 Diagnostic . Error ( 4201 , LookupSource ( type ) , Localization . Resources . JavaCallableWrappers_XA4201 , type . FullName ) ;
123129 if ( ! string . IsNullOrEmpty ( outerType ) ) {
@@ -157,7 +163,7 @@ void AddNestedTypes (TypeDefinition type)
157163 r . FullName ) ;
158164 return d ;
159165 } )
160- . Where ( d => GetRegisterAttributes ( d ) . Any ( ) )
166+ . Where ( d => GetTypeRegistrationAttributes ( d ) . Any ( ) )
161167 . SelectMany ( d => d . Methods )
162168 . Where ( m => ! m . IsStatic ) ) {
163169 AddMethod ( imethod , imethod ) ;
@@ -168,7 +174,7 @@ void AddNestedTypes (TypeDefinition type)
168174 } ;
169175 foreach ( var bt in type . GetBaseTypes ( cache ) ) {
170176 ctorTypes . Add ( bt ) ;
171- RegisterAttribute rattr = GetRegisterAttributes ( bt ) . FirstOrDefault ( ) ;
177+ RegisterAttribute rattr = GetMethodRegistrationAttributes ( bt ) . FirstOrDefault ( ) ;
172178 if ( rattr != null && rattr . DoNotGenerateAcw )
173179 break ;
174180 }
@@ -271,7 +277,7 @@ void AddConstructor (MethodDefinition ctor, TypeDefinition type, string outerTyp
271277 return ;
272278 }
273279
274- RegisterAttribute rattr = GetRegisterAttributes ( ctor ) . FirstOrDefault ( ) ;
280+ RegisterAttribute rattr = GetMethodRegistrationAttributes ( ctor ) . FirstOrDefault ( ) ;
275281 if ( rattr != null ) {
276282 if ( ctors . Any ( c => c . JniSignature == rattr . Signature ) )
277283 return ;
@@ -335,6 +341,34 @@ internal static RegisterAttribute ToRegisterAttribute (CustomAttribute attr)
335341 return r ;
336342 }
337343
344+ internal static RegisterAttribute RegisterFromJniTypeSignatureAttribute ( CustomAttribute attr )
345+ {
346+ // attr.Resolve ();
347+ RegisterAttribute r = null ;
348+ if ( attr . ConstructorArguments . Count == 1 )
349+ r = new RegisterAttribute ( ( string ) attr . ConstructorArguments [ 0 ] . Value ) ;
350+ if ( r != null ) {
351+ var v = attr . Properties . FirstOrDefault ( p => p . Name == "GenerateJavaPeer" ) ;
352+ if ( v . Name == null ) {
353+ r . DoNotGenerateAcw = false ;
354+ } else if ( v . Name == "GenerateJavaPeer" ) {
355+ r . DoNotGenerateAcw = ! ( bool ) v . Argument . Value ;
356+ }
357+ }
358+ return r ;
359+ }
360+
361+ internal static RegisterAttribute RegisterFromJniMethodSignatureAttribute ( CustomAttribute attr )
362+ {
363+ // attr.Resolve ();
364+ RegisterAttribute r = null ;
365+ if ( attr . ConstructorArguments . Count == 2 )
366+ r = new RegisterAttribute ( ( string ) attr . ConstructorArguments [ 0 ] . Value ,
367+ ( string ) attr . ConstructorArguments [ 1 ] . Value ,
368+ "" ) ;
369+ return r ;
370+ }
371+
338372 ExportAttribute ToExportAttribute ( CustomAttribute attr , IMemberDefinition declaringMember )
339373 {
340374 var name = attr . ConstructorArguments . Count > 0 ? ( string ) attr . ConstructorArguments [ 0 ] . Value : declaringMember . Name ;
@@ -351,9 +385,24 @@ internal static ExportFieldAttribute ToExportFieldAttribute (CustomAttribute att
351385 return new ExportFieldAttribute ( ( string ) attr . ConstructorArguments [ 0 ] . Value ) ;
352386 }
353387
354- static IEnumerable < RegisterAttribute > GetRegisterAttributes ( Mono . Cecil . ICustomAttributeProvider p )
388+ internal static IEnumerable < RegisterAttribute > GetTypeRegistrationAttributes ( Mono . Cecil . ICustomAttributeProvider p )
355389 {
356- return GetAttributes < RegisterAttribute > ( p , a => ToRegisterAttribute ( a ) ) ;
390+ foreach ( var a in GetAttributes < RegisterAttribute > ( p , a => ToRegisterAttribute ( a ) ) ) {
391+ yield return a ;
392+ }
393+ foreach ( var c in p . GetCustomAttributes ( "Java.Interop.JniTypeSignatureAttribute" ) ) {
394+ yield return RegisterFromJniTypeSignatureAttribute ( c ) ;
395+ }
396+ }
397+
398+ static IEnumerable < RegisterAttribute > GetMethodRegistrationAttributes ( Mono . Cecil . ICustomAttributeProvider p )
399+ {
400+ foreach ( var a in GetAttributes < RegisterAttribute > ( p , a => ToRegisterAttribute ( a ) ) ) {
401+ yield return a ;
402+ }
403+ foreach ( var c in p . GetCustomAttributes ( "Java.Interop.JniMethodSignatureAttribute" ) ) {
404+ yield return RegisterFromJniMethodSignatureAttribute ( c ) ;
405+ }
357406 }
358407
359408 IEnumerable < ExportAttribute > GetExportAttributes ( IMemberDefinition p )
@@ -375,7 +424,7 @@ static IEnumerable<TAttribute> GetAttributes<TAttribute> (Mono.Cecil.ICustomAttr
375424 void AddMethod ( MethodDefinition registeredMethod , MethodDefinition implementedMethod )
376425 {
377426 if ( registeredMethod != null )
378- foreach ( RegisterAttribute attr in GetRegisterAttributes ( registeredMethod ) ) {
427+ foreach ( RegisterAttribute attr in GetMethodRegistrationAttributes ( registeredMethod ) ) {
379428 // Check for Kotlin-mangled methods that cannot be overridden
380429 if ( attr . Name . Contains ( "-impl" ) || ( attr . Name . Length > 7 && attr . Name [ attr . Name . Length - 8 ] == '-' ) )
381430 Diagnostic . Error ( 4217 , LookupSource ( implementedMethod ) , Localization . Resources . JavaCallableWrappers_XA4217 , attr . Name ) ;
@@ -544,19 +593,27 @@ void GenerateHeader (TextWriter sw)
544593
545594 sw . WriteLine ( "public " + ( type . IsAbstract ? "abstract " : "" ) + "class " + name ) ;
546595
547- string extendsType = GetJavaTypeName ( type . BaseType ) ;
596+ string extendsType = GetJavaTypeName ( type . BaseType , cache ) ;
548597 if ( extendsType == "android.app.Application" && ! string . IsNullOrEmpty ( ApplicationJavaClass ) )
549598 extendsType = ApplicationJavaClass ;
550599 sw . WriteLine ( "\t extends " + extendsType ) ;
551600 sw . WriteLine ( "\t implements" ) ;
552- sw . Write ( "\t \t mono.android.IGCUserPeer" ) ;
601+ sw . Write ( "\t \t " ) ;
602+ switch ( CodeGenerationTarget ) {
603+ case JavaPeerStyle . JavaInterop1 :
604+ sw . Write ( "com.xamarin.java_interop.GCUserPeerable" ) ;
605+ break ;
606+ default :
607+ sw . Write ( "mono.android.IGCUserPeer" ) ;
608+ break ;
609+ }
553610 IEnumerable < TypeDefinition > ifaces = type . Interfaces . Select ( ifaceInfo => ifaceInfo . InterfaceType )
554611 . Select ( r => r . Resolve ( ) )
555- . Where ( d => GetRegisterAttributes ( d ) . Any ( ) ) ;
612+ . Where ( d => GetTypeRegistrationAttributes ( d ) . Any ( ) ) ;
556613 if ( ifaces . Any ( ) ) {
557614 foreach ( TypeDefinition iface in ifaces ) {
558615 sw . WriteLine ( "," ) ;
559- sw . Write ( "\t \t {0}" , GetJavaTypeName ( iface ) ) ;
616+ sw . Write ( "\t \t {0}" , GetJavaTypeName ( iface , cache ) ) ;
560617 }
561618 }
562619 sw . WriteLine ( ) ;
@@ -590,16 +647,23 @@ void GenerateBody (TextWriter sw)
590647 w . WriteLine ( "\t \t super.onCreate (arguments);" ) ;
591648 } ) ;
592649
650+ string addRef = "monodroidAddReference" ;
651+ string clearRefs = "monodroidClearReferences" ;
652+ if ( CodeGenerationTarget == JavaPeerStyle . JavaInterop1 ) {
653+ addRef = "jiAddManagedReference" ;
654+ clearRefs = "jiClearManagedReferences" ;
655+ }
656+
593657 sw . WriteLine ( ) ;
594658 sw . WriteLine ( "\t private java.util.ArrayList refList;" ) ;
595- sw . WriteLine ( "\t public void monodroidAddReference (java.lang.Object obj)" ) ;
659+ sw . WriteLine ( $ "\t public void { addRef } (java.lang.Object obj)") ;
596660 sw . WriteLine ( "\t {" ) ;
597661 sw . WriteLine ( "\t \t if (refList == null)" ) ;
598662 sw . WriteLine ( "\t \t \t refList = new java.util.ArrayList ();" ) ;
599663 sw . WriteLine ( "\t \t refList.add (obj);" ) ;
600664 sw . WriteLine ( "\t }" ) ;
601665 sw . WriteLine ( ) ;
602- sw . WriteLine ( "\t public void monodroidClearReferences ()" ) ;
666+ sw . WriteLine ( $ "\t public void { clearRefs } ()") ;
603667 sw . WriteLine ( "\t {" ) ;
604668 sw . WriteLine ( "\t \t if (refList != null)" ) ;
605669 sw . WriteLine ( "\t \t \t refList.clear ();" ) ;
@@ -612,9 +676,19 @@ void GenerateRegisterType (TextWriter sw, JavaCallableWrapperGenerator self, str
612676 foreach ( Signature method in self . methods )
613677 sw . WriteLine ( "\t \t \t \" {0}\\ n\" +" , method . Method ) ;
614678 sw . WriteLine ( "\t \t \t \" \" ;" ) ;
615- if ( ! CannotRegisterInStaticConstructor ( self . type ) )
616- sw . WriteLine ( "\t \t mono.android.Runtime.register (\" {0}\" , {1}.class, {2});" ,
617- self . type . GetPartialAssemblyQualifiedName ( cache ) , self . name , field ) ;
679+ if ( CannotRegisterInStaticConstructor ( self . type ) )
680+ return ;
681+ string format = null ;
682+ switch ( CodeGenerationTarget ) {
683+ case JavaPeerStyle . JavaInterop1 :
684+ format = "com.xamarin.java_interop.ManagedPeer.registerNativeMembers ({1}.class, \" {0}\" , {2});" ;
685+ break ;
686+ default :
687+ format = "mono.android.Runtime.register (\" {0}\" , {1}.class, {2});" ;
688+ break ;
689+ }
690+ sw . Write ( "\t \t " ) ;
691+ sw . WriteLine ( format , self . type . GetPartialAssemblyQualifiedName ( cache ) , self . name , field ) ;
618692 }
619693
620694 void GenerateFooter ( TextWriter sw )
@@ -636,10 +710,10 @@ static string GetJavaAccess (MethodAttributes access)
636710 }
637711 }
638712
639- static string GetJavaTypeName ( TypeReference r )
713+ static string GetJavaTypeName ( TypeReference r , IMetadataResolver cache )
640714 {
641715 TypeDefinition d = r . Resolve ( ) ;
642- string jniName = JavaNativeTypeManager . ToJniName ( d ) ;
716+ string jniName = JavaNativeTypeManager . ToJniName ( d , cache ) ;
643717 if ( jniName == null )
644718 Diagnostic . Error ( 4201 , Localization . Resources . JavaCallableWrappers_XA4201 , r . FullName ) ;
645719 return jniName . Replace ( '/' , '.' ) . Replace ( '$' , '.' ) ;
@@ -780,8 +854,19 @@ void GenerateConstructor (Signature ctor, TextWriter sw)
780854 sw . WriteLine ( "\t \t android.util.Log.i(\" MonoDroid-Timing\" , \" {0}..ctor({1}): time: \" +java.lang.System.currentTimeMillis());" , name , ctor . Params ) ;
781855#endif
782856 if ( ! CannotRegisterInStaticConstructor ( type ) ) {
783- sw . WriteLine ( "\t \t if (getClass () == {0}.class)" , name ) ;
784- sw . WriteLine ( "\t \t \t mono.android.TypeManager.Activate (\" {0}\" , \" {1}\" , this, new java.lang.Object[] {{ {2} }});" , type . GetPartialAssemblyQualifiedName ( cache ) , ctor . ManagedParameters , ctor . ActivateCall ) ;
857+ string format = null ;
858+ switch ( CodeGenerationTarget ) {
859+ case JavaPeerStyle . JavaInterop1 :
860+ format = "com.xamarin.java_interop.ManagedPeer.construct (this, \" {0}\" , \" {1}\" , new java.lang.Object[] {{ {2} }});" ;
861+ break ;
862+ default :
863+ format = "mono.android.TypeManager.Activate (\" {0}\" , \" {1}\" , this, new java.lang.Object[] {{ {2} }});" ;
864+ break ;
865+ }
866+ sw . WriteLine ( "\t \t if (getClass () == {0}.class) {" , name ) ;
867+ sw . Write ( "\t \t \t " ) ;
868+ sw . WriteLine ( format , type . GetPartialAssemblyQualifiedName ( cache ) , ctor . ManagedParameters , ctor . ActivateCall ) ;
869+ sw . WriteLine ( "\t \t }" ) ;
785870 }
786871 sw . WriteLine ( "\t }" ) ;
787872 }
0 commit comments