Skip to content

Commit db551f5

Browse files
committed
Complete generating Java source code from intermediate model.
1 parent 10d6639 commit db551f5

File tree

4 files changed

+244
-141
lines changed

4 files changed

+244
-141
lines changed

src/Java.Interop.Tools.JavaCallableWrappers/Adapters/CecilImporter.cs

Lines changed: 126 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
24
using System.Text;
3-
using System.Xml.Linq;
45
using Android.Runtime;
6+
using Java.Interop.Tools.Cecil;
57
using Java.Interop.Tools.Diagnostics;
68
using Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers;
79
using 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
}

src/Java.Interop.Tools.JavaCallableWrappers/CallableWrapperMembers/CallableWrapperField.cs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,22 @@ namespace Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers;
44

55
class CallableWrapperField
66
{
7-
public string FieldName { get; }
8-
public string TypeName { get; }
9-
public string Visibility { get; }
10-
public bool IsStatic { get; }
11-
public string InitializerName { get; }
12-
public string? Annotations { get; }
13-
14-
public CallableWrapperField (string fieldName, string typeName, string visibility, bool isStatic, string initializerName, string? annotations)
7+
public string FieldName { get; set; }
8+
public string TypeName { get; set; }
9+
public string Visibility { get; set; }
10+
public bool IsStatic { get; set; }
11+
public string InitializerName { get; set; }
12+
public string? Annotations { get; set; }
13+
14+
public CallableWrapperField (string fieldName, string typeName, string visibility, string initializerName)
1515
{
1616
FieldName = fieldName;
1717
TypeName = typeName;
1818
Visibility = visibility;
19-
IsStatic = isStatic;
2019
InitializerName = initializerName;
21-
Annotations = annotations;
2220
}
2321

24-
public void Generate (TextWriter sw)
22+
public void Generate (TextWriter sw, CallableWrapperWriterOptions options)
2523
{
2624
sw.WriteLine ();
2725

0 commit comments

Comments
 (0)