@@ -25,40 +25,9 @@ public enum JavaPeerStyle {
2525 JavaInterop1 ,
2626 }
2727
28- public class OverriddenMethodDescriptor
28+ public abstract class JavaCallableMethodClassifier
2929 {
30- static readonly char [ ] methodDescSplitChars = new char [ ] { ':' } ;
31-
32- public string JavaPackageName { get ; }
33- public string NativeName { get ; }
34- public string JniSignature { get ; }
35- public string Connector { get ; }
36- public string ManagedTypeName { get ; }
37- public string OriginalDescString { get ; }
38-
39- public OverriddenMethodDescriptor ( string javaPackageName , string methodDescription , string fallbackManagedTypeName )
40- {
41- OriginalDescString = methodDescription ;
42- JavaPackageName = javaPackageName ;
43- string [ ] parts = methodDescription . Split ( methodDescSplitChars , 4 ) ;
44-
45- if ( parts . Length < 2 ) {
46- throw new InvalidOperationException ( $ "Unexpected format for method description. Expected at least 2 parts, got { parts . Length } from: '{ methodDescription } '") ;
47- }
48-
49- NativeName = parts [ 0 ] ;
50- JniSignature = parts [ 1 ] ;
51- if ( parts . Length > 2 ) {
52- Connector = parts [ 2 ] ;
53- if ( parts . Length > 3 ) {
54- ManagedTypeName = TypeDefinitionRocks . CecilTypeNameToReflectionTypeName ( parts [ 3 ] ) ;
55- }
56- }
57-
58- if ( String . IsNullOrEmpty ( ManagedTypeName ) ) {
59- ManagedTypeName = fallbackManagedTypeName ;
60- }
61- }
30+ public abstract bool ShouldBeDynamicallyRegistered ( TypeDefinition topType , MethodDefinition registeredMethod , MethodDefinition implementedMethod , CustomAttribute registerAttribute ) ;
6231 }
6332
6433 public class JavaCallableWrapperGenerator {
@@ -95,36 +64,47 @@ public string GetJavaAccess ()
9564 List < Signature > methods = new List < Signature > ( ) ;
9665 List < Signature > ctors = new List < Signature > ( ) ;
9766 List < JavaCallableWrapperGenerator > children ;
98- List < OverriddenMethodDescriptor > overriddenMethodDescriptors ;
67+
9968 readonly IMetadataResolver cache ;
69+ readonly JavaCallableMethodClassifier methodClassifier ;
10070
10171 [ Obsolete ( "Use the TypeDefinitionCache overload for better performance." ) ]
10272 public JavaCallableWrapperGenerator ( TypeDefinition type , Action < string , object [ ] > log )
103- : this ( type , null , log , resolver : null )
73+ : this ( type , log , resolver : null , methodClassifier : null )
10474 { }
10575
10676 public JavaCallableWrapperGenerator ( TypeDefinition type , Action < string , object [ ] > log , TypeDefinitionCache cache )
107- : this ( type , log , ( IMetadataResolver ) cache )
77+ : this ( type , log , ( IMetadataResolver ) cache , methodClassifier : null )
78+ { }
79+
80+ public JavaCallableWrapperGenerator ( TypeDefinition type , Action < string , object [ ] > log , TypeDefinitionCache cache , JavaCallableMethodClassifier methodClassifier )
81+ : this ( type , log , ( IMetadataResolver ) cache , methodClassifier )
10882 {
10983 }
11084
11185 public JavaCallableWrapperGenerator ( TypeDefinition type , Action < string , object [ ] > log , IMetadataResolver resolver )
112- : this ( type , null , log , resolver )
86+ : this ( type , log , resolver , methodClassifier : null )
87+ { }
88+
89+ public JavaCallableWrapperGenerator ( TypeDefinition type , Action < string , object [ ] > log , IMetadataResolver resolver , JavaCallableMethodClassifier methodClassifier )
90+ : this ( type , null , log , resolver , methodClassifier )
11391 {
11492 if ( type . HasNestedTypes ) {
11593 children = new List < JavaCallableWrapperGenerator > ( ) ;
11694 AddNestedTypes ( type ) ;
11795 }
11896 }
11997
120- public IList < OverriddenMethodDescriptor > OverriddenMethodDescriptors => overriddenMethodDescriptors ;
12198 public string ApplicationJavaClass { get ; set ; }
12299 public JavaPeerStyle CodeGenerationTarget { get ; set ; }
123100
124101 public bool GenerateOnCreateOverrides { get ; set ; }
125102
126103 public bool HasExport { get ; private set ; }
127104
105+ // If there are no methods, we need to generate "empty" registration because of backward compatibility
106+ public bool HasDynamicallyRegisteredMethods => methods . Count == 0 || methods . Any ( ( Signature sig ) => sig . IsDynamicallyRegistered ) ;
107+
128108 /// <summary>
129109 /// The Java source code to be included in Instrumentation.onCreate
130110 ///
@@ -152,8 +132,9 @@ void AddNestedTypes (TypeDefinition type)
152132 HasExport |= children . Any ( t => t . HasExport ) ;
153133 }
154134
155- JavaCallableWrapperGenerator ( TypeDefinition type , string outerType , Action < string , object [ ] > log , IMetadataResolver resolver )
135+ JavaCallableWrapperGenerator ( TypeDefinition type , string outerType , Action < string , object [ ] > log , IMetadataResolver resolver , JavaCallableMethodClassifier methodClassifier = null )
156136 {
137+ this . methodClassifier = methodClassifier ;
157138 this . type = type ;
158139 this . log = log ;
159140 this . cache = resolver ?? new TypeDefinitionCache ( ) ;
@@ -366,12 +347,13 @@ internal static RegisterAttribute ToRegisterAttribute (CustomAttribute attr)
366347 // attr.Resolve ();
367348 RegisterAttribute r = null ;
368349 if ( attr . ConstructorArguments . Count == 1 )
369- r = new RegisterAttribute ( ( string ) attr . ConstructorArguments [ 0 ] . Value ) ;
350+ r = new RegisterAttribute ( ( string ) attr . ConstructorArguments [ 0 ] . Value , attr ) ;
370351 else if ( attr . ConstructorArguments . Count == 3 )
371352 r = new RegisterAttribute (
372353 ( string ) attr . ConstructorArguments [ 0 ] . Value ,
373354 ( string ) attr . ConstructorArguments [ 1 ] . Value ,
374- ( string ) attr . ConstructorArguments [ 2 ] . Value ) ;
355+ ( string ) attr . ConstructorArguments [ 2 ] . Value ,
356+ attr ) ;
375357 if ( r != null ) {
376358 var v = attr . Properties . FirstOrDefault ( p => p . Name == "DoNotGenerateAcw" ) ;
377359 r . DoNotGenerateAcw = v . Name == null ? false : ( bool ) v . Argument . Value ;
@@ -384,7 +366,7 @@ internal static RegisterAttribute RegisterFromJniTypeSignatureAttribute (CustomA
384366 // attr.Resolve ();
385367 RegisterAttribute r = null ;
386368 if ( attr . ConstructorArguments . Count == 1 )
387- r = new RegisterAttribute ( ( string ) attr . ConstructorArguments [ 0 ] . Value ) ;
369+ r = new RegisterAttribute ( ( string ) attr . ConstructorArguments [ 0 ] . Value , attr ) ;
388370 if ( r != null ) {
389371 var v = attr . Properties . FirstOrDefault ( p => p . Name == "GenerateJavaPeer" ) ;
390372 if ( v . Name == null ) {
@@ -403,7 +385,8 @@ internal static RegisterAttribute RegisterFromJniMethodSignatureAttribute (Custo
403385 if ( attr . ConstructorArguments . Count == 2 )
404386 r = new RegisterAttribute ( ( string ) attr . ConstructorArguments [ 0 ] . Value ,
405387 ( string ) attr . ConstructorArguments [ 1 ] . Value ,
406- "" ) ;
388+ "" ,
389+ attr ) ;
407390 return r ;
408391 }
409392
@@ -467,7 +450,8 @@ void AddMethod (MethodDefinition registeredMethod, MethodDefinition implementedM
467450 if ( attr . Name . Contains ( "-impl" ) || ( attr . Name . Length > 7 && attr . Name [ attr . Name . Length - 8 ] == '-' ) )
468451 Diagnostic . Error ( 4217 , LookupSource ( implementedMethod ) , Localization . Resources . JavaCallableWrappers_XA4217 , attr . Name ) ;
469452
470- var msig = new Signature ( implementedMethod , attr ) ;
453+ bool shouldBeDynamicallyRegistered = methodClassifier ? . ShouldBeDynamicallyRegistered ( type , registeredMethod , implementedMethod , attr . OriginAttribute ) ?? true ;
454+ var msig = new Signature ( implementedMethod , attr , shouldBeDynamicallyRegistered ) ;
471455 if ( ! registeredMethod . IsConstructor && ! methods . Any ( m => m . Name == msig . Name && m . Params == msig . Params ) )
472456 methods . Add ( msig ) ;
473457 }
@@ -542,21 +526,38 @@ public void Generate (TextWriter writer)
542526
543527 GenerateHeader ( writer ) ;
544528
545- writer . WriteLine ( "/** @hide */" ) ;
546- writer . WriteLine ( " \t public static final String __md_methods;" ) ;
547- if ( children != null ) {
548- foreach ( var i in Enumerable . Range ( 1 , children . Count ) )
549- writer . WriteLine ( "\t static final String __md_{0}_methods;" , i ) ;
529+ bool needCtor = false ;
530+ if ( HasDynamicallyRegisteredMethods ) {
531+ needCtor = true ;
532+ writer . WriteLine ( "/** @hide */" ) ;
533+ writer . WriteLine ( "\t public static final String __md_methods;" ) ;
550534 }
551- writer . WriteLine ( "\t static {" ) ;
552- GenerateRegisterType ( writer , this , "__md_methods" ) ;
535+
553536 if ( children != null ) {
554- for ( int i = 0 ; i < children . Count ; ++ i ) {
555- string methods = string . Format ( "__md_{0}_methods" , i + 1 ) ;
556- GenerateRegisterType ( writer , children [ i ] , methods ) ;
537+ for ( int i = 0 ; i < children . Count ; i ++ ) {
538+ if ( ! children [ i ] . HasDynamicallyRegisteredMethods ) {
539+ continue ;
540+ }
541+ needCtor = true ;
542+ writer . WriteLine ( "\t static final String __md_{0}_methods;" , i + 1 ) ;
557543 }
558544 }
559- writer . WriteLine ( "\t }" ) ;
545+
546+ if ( needCtor ) {
547+ writer . WriteLine ( "\t static {" ) ;
548+
549+ if ( HasDynamicallyRegisteredMethods ) {
550+ GenerateRegisterType ( writer , this , "__md_methods" ) ;
551+ }
552+
553+ if ( children != null ) {
554+ for ( int i = 0 ; i < children . Count ; ++ i ) {
555+ string methods = string . Format ( "__md_{0}_methods" , i + 1 ) ;
556+ GenerateRegisterType ( writer , children [ i ] , methods ) ;
557+ }
558+ }
559+ writer . WriteLine ( "\t }" ) ;
560+ }
560561
561562 GenerateBody ( writer ) ;
562563
@@ -710,16 +711,18 @@ void GenerateBody (TextWriter sw)
710711
711712 void GenerateRegisterType ( TextWriter sw , JavaCallableWrapperGenerator self , string field )
712713 {
713- if ( overriddenMethodDescriptors == null ) {
714- overriddenMethodDescriptors = new List < OverriddenMethodDescriptor > ( ) ;
714+ if ( ! self . HasDynamicallyRegisteredMethods ) {
715+ return ;
715716 }
716717
717718 sw . WriteLine ( "\t \t {0} = " , field ) ;
718719 string managedTypeName = self . type . GetPartialAssemblyQualifiedName ( cache ) ;
719720 string javaTypeName = $ "{ package } .{ name } ";
721+
720722 foreach ( Signature method in self . methods ) {
721- sw . WriteLine ( "\t \t \t \" {0}\\ n\" +" , method . Method ) ;
722- overriddenMethodDescriptors . Add ( new OverriddenMethodDescriptor ( javaTypeName , method . Method , managedTypeName ) ) ;
723+ if ( method . IsDynamicallyRegistered ) {
724+ sw . WriteLine ( "\t \t \t \" {0}\\ n\" +" , method . Method ) ;
725+ }
723726 }
724727 sw . WriteLine ( "\t \t \t \" \" ;" ) ;
725728 if ( CannotRegisterInStaticConstructor ( self . type ) )
@@ -772,12 +775,13 @@ bool CannotRegisterInStaticConstructor (TypeDefinition type)
772775
773776 class Signature {
774777
775- public Signature ( MethodDefinition method , RegisterAttribute register ) : this ( method , register , null , null ) { }
778+ public Signature ( MethodDefinition method , RegisterAttribute register , bool shouldBeDynamicallyRegistered = true ) : this ( method , register , null , null , shouldBeDynamicallyRegistered ) { }
776779
777- public Signature ( MethodDefinition method , RegisterAttribute register , string managedParameters , string outerType )
780+ public Signature ( MethodDefinition method , RegisterAttribute register , string managedParameters , string outerType , bool shouldBeDynamicallyRegistered = true )
778781 : this ( register . Name , register . Signature , register . Connector , managedParameters , outerType , null )
779782 {
780783 Annotations = JavaCallableWrapperGenerator . GetAnnotationsString ( "\t " , method . CustomAttributes ) ;
784+ IsDynamicallyRegistered = shouldBeDynamicallyRegistered ;
781785 }
782786
783787 public Signature ( MethodDefinition method , ExportAttribute export , IMetadataResolver cache )
@@ -880,6 +884,7 @@ public string ThrowsDeclaration {
880884 public readonly string Method ;
881885 public readonly bool IsExport ;
882886 public readonly bool IsStatic ;
887+ public readonly bool IsDynamicallyRegistered = true ;
883888 public readonly string [ ] ThrownTypeNames ;
884889 public readonly string Annotations ;
885890 }
0 commit comments