Skip to content

Commit a2951e9

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

File tree

4 files changed

+246
-142
lines changed

4 files changed

+246
-142
lines changed

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

Lines changed: 128 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,21 @@ 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) {
24+
IsStatic = method.IsStatic,
25+
InitializerName = method.Name,
26+
Annotations = annotations
27+
};
2828
}
2929

3030
// Temporary conversion function
3131
public static CallableWrapperField CreateField (JavaCallableWrapperGenerator.JavaFieldInfo field)
3232
{
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);
33+
return new CallableWrapperField (field.FieldName, field.TypeName, field.GetJavaAccess ()) {
34+
IsStatic = field.IsStatic,
35+
InitializerName = field.InitializerName,
36+
Annotations = field.Annotations
37+
};
4038
}
4139

4240
public static CallableWrapperMethod CreateMethod (MethodDefinition method, RegisterAttribute register, IMetadataResolver cache, bool shouldBeDynamicallyRegistered = true)
@@ -190,21 +188,132 @@ public static CallableWrapperConstructor CreateConstructor (JavaCallableWrapperG
190188
// Temporary conversion function
191189
public static CallableWrapperType CreateType (JavaCallableWrapperGenerator generator)
192190
{
193-
var type = new CallableWrapperType (generator.name, generator.package) {
194-
Type = generator.type,
195-
Cache = generator.cache,
191+
var partial_assembly_qualified_name = generator.type.GetPartialAssemblyQualifiedName (generator.cache);
192+
193+
var type = new CallableWrapperType (generator.name, generator.package, partial_assembly_qualified_name) {
196194
IsAbstract = generator.type.IsAbstract,
197195
ApplicationJavaClass = generator.ApplicationJavaClass,
198-
Generator = generator,
199196
HasDynamicallyRegisteredMethods = generator.HasDynamicallyRegisteredMethods,
200197
GenerateOnCreateOverrides = generator.GenerateOnCreateOverrides,
201198
MonoRuntimeInitialization = generator.MonoRuntimeInitialization,
199+
IsApplication = JavaNativeTypeManager.IsApplication (generator.type, generator.cache),
200+
IsInstrumentation = JavaNativeTypeManager.IsInstrumentation (generator.type, generator.cache),
202201
};
203202

203+
type.Annotations.AddRange (CreateTypeAnnotations (generator.type, generator.cache));
204+
205+
// Extends
206+
var extendsType = GetJavaTypeName (generator.type.BaseType, generator.cache);
207+
208+
if (extendsType == "android.app.Application" && generator.ApplicationJavaClass != null && !string.IsNullOrEmpty (generator.ApplicationJavaClass))
209+
extendsType = generator.ApplicationJavaClass;
210+
211+
type.ExtendsType = extendsType;
212+
213+
// Implemented interfaces
214+
foreach (var ifaceInfo in generator.type.Interfaces) {
215+
var iface = generator.cache.Resolve (ifaceInfo.InterfaceType);
216+
217+
if (!JavaCallableWrapperGenerator.GetTypeRegistrationAttributes (iface).Any ())
218+
continue;
219+
220+
type.ImplementedInterfaces.Add (GetJavaTypeName (iface, generator.cache));
221+
}
222+
223+
// Type constructors
224+
foreach (var ctor in generator.ctors) {
225+
if (string.IsNullOrEmpty (ctor.Params) && type.IsApplication)
226+
continue;
227+
228+
var ct = CreateConstructor (ctor);
229+
230+
ct.Name = type.Name;
231+
ct.CannotRegisterInStaticConstructor = type.CannotRegisterInStaticConstructor;
232+
ct.PartialAssemblyQualifiedName = type.PartialAssemblyQualifiedName ;
233+
234+
type.Constructors.Add (ct);
235+
}
236+
237+
// Application constructor
238+
if (CreateApplicationConstructor (type.Name, generator.type, generator.cache) is CallableWrapperApplicationConstructor app_ctor)
239+
type.ApplicationConstructor = app_ctor;
240+
241+
// Exported fields
242+
foreach (var field in generator.exported_fields)
243+
type.Fields.Add (CreateField (field));
244+
245+
// Methods
246+
foreach (var method in generator.methods)
247+
type.Methods.Add (CreateMethod (method));
248+
249+
// Nested types
204250
if (generator.children is not null)
205251
foreach (var nested in generator.children)
206252
type.NestedTypes.Add (CreateType (nested));
207253

208254
return type;
209255
}
256+
257+
static string GetJavaTypeName (TypeReference r, IMetadataResolver cache)
258+
{
259+
TypeDefinition d = cache.Resolve (r);
260+
string? jniName = JavaNativeTypeManager.ToJniName (d, cache);
261+
if (jniName == null) {
262+
Diagnostic.Error (4201, Localization.Resources.JavaCallableWrappers_XA4201, r.FullName);
263+
throw new InvalidOperationException ("--nrt:jniName-- Should not be reached");
264+
}
265+
return jniName.Replace ('/', '.').Replace ('$', '.');
266+
}
267+
268+
public static IEnumerable<CallableWrapperTypeAnnotation> CreateTypeAnnotations (TypeDefinition type, IMetadataResolver resolver)
269+
{
270+
foreach (var ca in type.CustomAttributes) {
271+
var annotation = CreateTypeAnnotation (ca, resolver);
272+
273+
if (annotation is not null)
274+
yield return annotation;
275+
}
276+
}
277+
278+
public static CallableWrapperTypeAnnotation? CreateTypeAnnotation (CustomAttribute ca, IMetadataResolver resolver)
279+
{
280+
var catype = resolver.Resolve (ca.AttributeType);
281+
var tca = catype.CustomAttributes.FirstOrDefault (a => a.AttributeType.FullName == "Android.Runtime.AnnotationAttribute");
282+
283+
if (tca is null)
284+
return null;
285+
286+
var name_object = tca.ConstructorArguments [0].Value;
287+
288+
// Should never be hit
289+
if (name_object is not string name)
290+
throw new ArgumentException ($"Expected a string for the first argument of the {nameof (RegisterAttribute)} constructor.", nameof (ca));
291+
292+
var annotation = new CallableWrapperTypeAnnotation (name);
293+
294+
foreach (var p in ca.Properties) {
295+
var pd = catype.Properties.FirstOrDefault (pp => pp.Name == p.Name);
296+
var reg = pd != null ? pd.CustomAttributes.FirstOrDefault (pdca => pdca.AttributeType.FullName == "Android.Runtime.RegisterAttribute") : null;
297+
298+
var key = reg != null ? (string) reg.ConstructorArguments [0].Value : p.Name;
299+
var value = ManagedValueToJavaSource (p.Argument.Value);
300+
301+
annotation.Properties.Add (new System.Collections.Generic.KeyValuePair<string, string> (key, value));
302+
}
303+
304+
return annotation;
305+
}
306+
307+
// FIXME: this is hacky. Is there any existing code for value to source conversion?
308+
static string ManagedValueToJavaSource (object value)
309+
{
310+
if (value is string)
311+
return "\"" + value.ToString ().Replace ("\"", "\"\"") + '"';
312+
else if (value.GetType ().FullName == "Java.Lang.Class")
313+
return value.ToString () + ".class";
314+
else if (value is bool)
315+
return ((bool) value) ? "true" : "false";
316+
else
317+
return value.ToString ();
318+
}
210319
}

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

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,21 @@ 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)
1515
{
1616
FieldName = fieldName;
1717
TypeName = typeName;
1818
Visibility = visibility;
19-
IsStatic = isStatic;
20-
InitializerName = initializerName;
21-
Annotations = annotations;
2219
}
2320

24-
public void Generate (TextWriter sw)
21+
public void Generate (TextWriter sw, CallableWrapperWriterOptions options)
2522
{
2623
sw.WriteLine ();
2724

0 commit comments

Comments
 (0)