11using System ;
2+ using System . Collections . Generic ;
3+ using System . Linq ;
24using System . Text ;
3- using System . Xml . Linq ;
45using Android . Runtime ;
6+ using Java . Interop . Tools . Cecil ;
57using Java . Interop . Tools . Diagnostics ;
68using Java . Interop . Tools . JavaCallableWrappers . CallableWrapperMembers ;
79using Java . Interop . Tools . TypeNameMappings ;
@@ -18,25 +20,19 @@ public static CallableWrapperField CreateField (MethodDefinition method, string
1820 ?? throw new ArgumentException ( $ "Could not get JNI signature for method `{ method . Name } `", nameof ( method ) ) ;
1921 var annotations = JavaCallableWrapperGenerator . GetAnnotationsString ( "\t " , method . CustomAttributes , resolver ) ;
2022
21- return new CallableWrapperField (
22- fieldName : fieldName ,
23- typeName : type_name ,
24- visibility : visibility ,
25- isStatic : method . IsStatic ,
26- initializerName : method . Name ,
27- annotations : annotations ) ;
23+ return new CallableWrapperField ( fieldName , type_name , visibility , method . Name ) {
24+ IsStatic = method . IsStatic ,
25+ Annotations = annotations
26+ } ;
2827 }
2928
3029 // Temporary conversion function
3130 public static CallableWrapperField CreateField ( JavaCallableWrapperGenerator . JavaFieldInfo field )
3231 {
33- return new CallableWrapperField (
34- fieldName : field . FieldName ,
35- typeName : field . TypeName ,
36- visibility : field . GetJavaAccess ( ) ,
37- isStatic : field . IsStatic ,
38- initializerName : field . InitializerName ,
39- annotations : field . Annotations ) ;
32+ return new CallableWrapperField ( field . FieldName , field . TypeName , field . GetJavaAccess ( ) , field . InitializerName ) {
33+ IsStatic = field . IsStatic ,
34+ Annotations = field . Annotations
35+ } ;
4036 }
4137
4238 public static CallableWrapperMethod CreateMethod ( MethodDefinition method , RegisterAttribute register , IMetadataResolver cache , bool shouldBeDynamicallyRegistered = true )
@@ -190,21 +186,132 @@ public static CallableWrapperConstructor CreateConstructor (JavaCallableWrapperG
190186 // Temporary conversion function
191187 public static CallableWrapperType CreateType ( JavaCallableWrapperGenerator generator )
192188 {
193- var type = new CallableWrapperType ( generator . name , generator . package ) {
194- Type = generator . type ,
195- Cache = generator . cache ,
189+ var partial_assembly_qualified_name = generator . type . GetPartialAssemblyQualifiedName ( generator . cache ) ;
190+
191+ var type = new CallableWrapperType ( generator . name , generator . package , partial_assembly_qualified_name ) {
196192 IsAbstract = generator . type . IsAbstract ,
197193 ApplicationJavaClass = generator . ApplicationJavaClass ,
198- Generator = generator ,
199194 HasDynamicallyRegisteredMethods = generator . HasDynamicallyRegisteredMethods ,
200195 GenerateOnCreateOverrides = generator . GenerateOnCreateOverrides ,
201196 MonoRuntimeInitialization = generator . MonoRuntimeInitialization ,
197+ IsApplication = JavaNativeTypeManager . IsApplication ( generator . type , generator . cache ) ,
198+ IsInstrumentation = JavaNativeTypeManager . IsInstrumentation ( generator . type , generator . cache ) ,
202199 } ;
203200
201+ type . Annotations . AddRange ( CreateTypeAnnotations ( generator . type , generator . cache ) ) ;
202+
203+ // Extends
204+ var extendsType = GetJavaTypeName ( generator . type . BaseType , generator . cache ) ;
205+
206+ if ( extendsType == "android.app.Application" && generator . ApplicationJavaClass != null && ! string . IsNullOrEmpty ( generator . ApplicationJavaClass ) )
207+ extendsType = generator . ApplicationJavaClass ;
208+
209+ type . ExtendsType = extendsType ;
210+
211+ // Implemented interfaces
212+ foreach ( var ifaceInfo in generator . type . Interfaces ) {
213+ var iface = generator . cache . Resolve ( ifaceInfo . InterfaceType ) ;
214+
215+ if ( ! JavaCallableWrapperGenerator . GetTypeRegistrationAttributes ( iface ) . Any ( ) )
216+ continue ;
217+
218+ type . ImplementedInterfaces . Add ( GetJavaTypeName ( iface , generator . cache ) ) ;
219+ }
220+
221+ // Type constructors
222+ foreach ( var ctor in generator . ctors ) {
223+ if ( string . IsNullOrEmpty ( ctor . Params ) && type . IsApplication )
224+ continue ;
225+
226+ var ct = CreateConstructor ( ctor ) ;
227+
228+ ct . Name = type . Name ;
229+ ct . CannotRegisterInStaticConstructor = type . CannotRegisterInStaticConstructor ;
230+ ct . PartialAssemblyQualifiedName = type . PartialAssemblyQualifiedName ;
231+
232+ type . Constructors . Add ( ct ) ;
233+ }
234+
235+ // Application constructor
236+ if ( CreateApplicationConstructor ( type . Name , generator . type , generator . cache ) is CallableWrapperApplicationConstructor app_ctor )
237+ type . ApplicationConstructor = app_ctor ;
238+
239+ // Exported fields
240+ foreach ( var field in generator . exported_fields )
241+ type . Fields . Add ( CreateField ( field ) ) ;
242+
243+ // Methods
244+ foreach ( var method in generator . methods )
245+ type . Methods . Add ( CreateMethod ( method ) ) ;
246+
247+ // Nested types
204248 if ( generator . children is not null )
205249 foreach ( var nested in generator . children )
206250 type . NestedTypes . Add ( CreateType ( nested ) ) ;
207251
208252 return type ;
209253 }
254+
255+ static string GetJavaTypeName ( TypeReference r , IMetadataResolver cache )
256+ {
257+ TypeDefinition d = cache . Resolve ( r ) ;
258+ string ? jniName = JavaNativeTypeManager . ToJniName ( d , cache ) ;
259+ if ( jniName == null ) {
260+ Diagnostic . Error ( 4201 , Localization . Resources . JavaCallableWrappers_XA4201 , r . FullName ) ;
261+ throw new InvalidOperationException ( "--nrt:jniName-- Should not be reached" ) ;
262+ }
263+ return jniName . Replace ( '/' , '.' ) . Replace ( '$' , '.' ) ;
264+ }
265+
266+ public static IEnumerable < CallableWrapperTypeAnnotation > CreateTypeAnnotations ( TypeDefinition type , IMetadataResolver resolver )
267+ {
268+ foreach ( var ca in type . CustomAttributes ) {
269+ var annotation = CreateTypeAnnotation ( ca , resolver ) ;
270+
271+ if ( annotation is not null )
272+ yield return annotation ;
273+ }
274+ }
275+
276+ public static CallableWrapperTypeAnnotation ? CreateTypeAnnotation ( CustomAttribute ca , IMetadataResolver resolver )
277+ {
278+ var catype = resolver . Resolve ( ca . AttributeType ) ;
279+ var tca = catype . CustomAttributes . FirstOrDefault ( a => a . AttributeType . FullName == "Android.Runtime.AnnotationAttribute" ) ;
280+
281+ if ( tca is null )
282+ return null ;
283+
284+ var name_object = tca . ConstructorArguments [ 0 ] . Value ;
285+
286+ // Should never be hit
287+ if ( name_object is not string name )
288+ throw new ArgumentException ( $ "Expected a string for the first argument of the { nameof ( RegisterAttribute ) } constructor.", nameof ( ca ) ) ;
289+
290+ var annotation = new CallableWrapperTypeAnnotation ( name ) ;
291+
292+ foreach ( var p in ca . Properties ) {
293+ var pd = catype . Properties . FirstOrDefault ( pp => pp . Name == p . Name ) ;
294+ var reg = pd != null ? pd . CustomAttributes . FirstOrDefault ( pdca => pdca . AttributeType . FullName == "Android.Runtime.RegisterAttribute" ) : null ;
295+
296+ var key = reg != null ? ( string ) reg . ConstructorArguments [ 0 ] . Value : p . Name ;
297+ var value = ManagedValueToJavaSource ( p . Argument . Value ) ;
298+
299+ annotation . Properties . Add ( new System . Collections . Generic . KeyValuePair < string , string > ( key , value ) ) ;
300+ }
301+
302+ return annotation ;
303+ }
304+
305+ // FIXME: this is hacky. Is there any existing code for value to source conversion?
306+ static string ManagedValueToJavaSource ( object value )
307+ {
308+ if ( value is string )
309+ return "\" " + value . ToString ( ) . Replace ( "\" " , "\" \" " ) + '"' ;
310+ else if ( value . GetType ( ) . FullName == "Java.Lang.Class" )
311+ return value . ToString ( ) + ".class" ;
312+ else if ( value is bool )
313+ return ( ( bool ) value ) ? "true" : "false" ;
314+ else
315+ return value . ToString ( ) ;
316+ }
210317}
0 commit comments