Skip to content

Commit 0418719

Browse files
committed
[marshal-methods] Add marshal methods classification code
Add code which classifies methods selected by `JavaCallableWrapperGenerator` and decides whether they are to be registered dynamically or using the future native code marshal methods. If a type `JavaCallableWrapperGenerator` is processing is found to not have any dynamically registered methods, then the code to register them is no longer generated.
1 parent 7716ae5 commit 0418719

File tree

2 files changed

+68
-66
lines changed

2 files changed

+68
-66
lines changed

src/Java.Interop.NamingCustomAttributes/Android.Runtime/RegisterAttribute.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
using System;
22

3+
using Mono.Cecil;
4+
35
namespace Android.Runtime {
46

57
[AttributeUsage (AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Method | AttributeTargets.Property)]
@@ -12,18 +14,21 @@ sealed class RegisterAttribute : Attribute, Java.Interop.IJniNameProviderAttribu
1214
string name;
1315
string signature;
1416

15-
public RegisterAttribute (string name)
17+
public RegisterAttribute (string name, CustomAttribute originAttribute)
1618
{
1719
this.name = name;
20+
OriginAttribute = originAttribute;
1821
}
1922

20-
public RegisterAttribute (string name, string signature, string connector)
21-
: this (name)
23+
public RegisterAttribute (string name, string signature, string connector, CustomAttribute originAttribute)
24+
: this (name, originAttribute)
2225
{
2326
this.connector = connector;
2427
this.signature = signature;
2528
}
2629

30+
public CustomAttribute OriginAttribute { get; }
31+
2732
public string Connector {
2833
get { return connector; }
2934
set { connector = value; }

src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/JavaCallableWrapperGenerator.cs

Lines changed: 60 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -25,40 +25,9 @@ public enum JavaPeerStyle {
2525
JavaInterop1,
2626
}
2727

28-
public class OverriddenMethodDescriptor
28+
public interface IJCWMethodClassifier
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+
bool ShouldBeDynamicallyRegistered (MethodDefinition registeredMethod, MethodDefinition implementedMethod, CustomAttribute registerAttribute);
6231
}
6332

6433
public class JavaCallableWrapperGenerator {
@@ -95,36 +64,38 @@ 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 IJCWMethodClassifier methodClassifier;
10070

10171
[Obsolete ("Use the TypeDefinitionCache overload for better performance.")]
10272
public JavaCallableWrapperGenerator (TypeDefinition type, Action<string, object []> log)
10373
: this (type, null, log, resolver: null)
10474
{ }
10575

106-
public JavaCallableWrapperGenerator (TypeDefinition type, Action<string, object[]> log, TypeDefinitionCache cache)
107-
: this (type, log, (IMetadataResolver) cache)
76+
public JavaCallableWrapperGenerator (TypeDefinition type, Action<string, object[]> log, TypeDefinitionCache cache, IJCWMethodClassifier methodClassifier = null)
77+
: this (type, log, (IMetadataResolver) cache, methodClassifier)
10878
{
10979
}
11080

111-
public JavaCallableWrapperGenerator (TypeDefinition type, Action<string, object[]> log, IMetadataResolver resolver)
112-
: this (type, null, log, resolver)
81+
public JavaCallableWrapperGenerator (TypeDefinition type, Action<string, object[]> log, IMetadataResolver resolver, IJCWMethodClassifier methodClassifier = null)
82+
: this (type, null, log, resolver, methodClassifier)
11383
{
11484
if (type.HasNestedTypes) {
11585
children = new List<JavaCallableWrapperGenerator> ();
11686
AddNestedTypes (type);
11787
}
11888
}
11989

120-
public IList<OverriddenMethodDescriptor> OverriddenMethodDescriptors => overriddenMethodDescriptors;
12190
public string ApplicationJavaClass { get; set; }
12291
public JavaPeerStyle CodeGenerationTarget { get; set; }
12392

12493
public bool GenerateOnCreateOverrides { get; set; }
12594

12695
public bool HasExport { get; private set; }
12796

97+
public bool HasDynamicallyRegisteredMethods => methods.Any ((Signature sig) => sig.IsDynamicallyRegistered);
98+
12899
/// <summary>
129100
/// The Java source code to be included in Instrumentation.onCreate
130101
///
@@ -152,8 +123,9 @@ void AddNestedTypes (TypeDefinition type)
152123
HasExport |= children.Any (t => t.HasExport);
153124
}
154125

155-
JavaCallableWrapperGenerator (TypeDefinition type, string outerType, Action<string, object[]> log, IMetadataResolver resolver)
126+
JavaCallableWrapperGenerator (TypeDefinition type, string outerType, Action<string, object[]> log, IMetadataResolver resolver, IJCWMethodClassifier methodClassifier = null)
156127
{
128+
this.methodClassifier = methodClassifier;
157129
this.type = type;
158130
this.log = log;
159131
this.cache = resolver ?? new TypeDefinitionCache ();
@@ -366,12 +338,13 @@ internal static RegisterAttribute ToRegisterAttribute (CustomAttribute attr)
366338
// attr.Resolve ();
367339
RegisterAttribute r = null;
368340
if (attr.ConstructorArguments.Count == 1)
369-
r = new RegisterAttribute ((string) attr.ConstructorArguments [0].Value);
341+
r = new RegisterAttribute ((string) attr.ConstructorArguments [0].Value, attr);
370342
else if (attr.ConstructorArguments.Count == 3)
371343
r = new RegisterAttribute (
372344
(string) attr.ConstructorArguments [0].Value,
373345
(string) attr.ConstructorArguments [1].Value,
374-
(string) attr.ConstructorArguments [2].Value);
346+
(string) attr.ConstructorArguments [2].Value,
347+
attr);
375348
if (r != null) {
376349
var v = attr.Properties.FirstOrDefault (p => p.Name == "DoNotGenerateAcw");
377350
r.DoNotGenerateAcw = v.Name == null ? false : (bool) v.Argument.Value;
@@ -384,7 +357,7 @@ internal static RegisterAttribute RegisterFromJniTypeSignatureAttribute (CustomA
384357
// attr.Resolve ();
385358
RegisterAttribute r = null;
386359
if (attr.ConstructorArguments.Count == 1)
387-
r = new RegisterAttribute ((string) attr.ConstructorArguments [0].Value);
360+
r = new RegisterAttribute ((string) attr.ConstructorArguments [0].Value, attr);
388361
if (r != null) {
389362
var v = attr.Properties.FirstOrDefault (p => p.Name == "GenerateJavaPeer");
390363
if (v.Name == null) {
@@ -403,7 +376,8 @@ internal static RegisterAttribute RegisterFromJniMethodSignatureAttribute (Custo
403376
if (attr.ConstructorArguments.Count == 2)
404377
r = new RegisterAttribute ((string) attr.ConstructorArguments [0].Value,
405378
(string) attr.ConstructorArguments [1].Value,
406-
"");
379+
"",
380+
attr);
407381
return r;
408382
}
409383

@@ -467,7 +441,8 @@ void AddMethod (MethodDefinition registeredMethod, MethodDefinition implementedM
467441
if (attr.Name.Contains ("-impl") || (attr.Name.Length > 7 && attr.Name[attr.Name.Length - 8] == '-'))
468442
Diagnostic.Error (4217, LookupSource (implementedMethod), Localization.Resources.JavaCallableWrappers_XA4217, attr.Name);
469443

470-
var msig = new Signature (implementedMethod, attr);
444+
bool shouldBeDynamicallyRegistered = methodClassifier?.ShouldBeDynamicallyRegistered (registeredMethod, implementedMethod, attr.OriginAttribute) ?? false;
445+
var msig = new Signature (implementedMethod, attr, shouldBeDynamicallyRegistered);
471446
if (!registeredMethod.IsConstructor && !methods.Any (m => m.Name == msig.Name && m.Params == msig.Params))
472447
methods.Add (msig);
473448
}
@@ -542,21 +517,38 @@ public void Generate (TextWriter writer)
542517

543518
GenerateHeader (writer);
544519

545-
writer.WriteLine ("/** @hide */");
546-
writer.WriteLine ("\tpublic static final String __md_methods;");
520+
bool needCtor = false;
521+
if (HasDynamicallyRegisteredMethods) {
522+
needCtor = true;
523+
writer.WriteLine ("/** @hide */");
524+
writer.WriteLine ("\tpublic static final String __md_methods;");
525+
}
526+
547527
if (children != null) {
548-
foreach (var i in Enumerable.Range (1, children.Count))
528+
for (int i = 0; i < children.Count; i++) {
529+
if (!children[i].HasDynamicallyRegisteredMethods) {
530+
continue;
531+
}
532+
needCtor = true;
549533
writer.WriteLine ("\tstatic final String __md_{0}_methods;", i);
534+
}
550535
}
551-
writer.WriteLine ("\tstatic {");
552-
GenerateRegisterType (writer, this, "__md_methods");
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);
536+
537+
if (needCtor) {
538+
writer.WriteLine ("\tstatic {");
539+
540+
if (HasDynamicallyRegisteredMethods) {
541+
GenerateRegisterType (writer, this, "__md_methods");
542+
}
543+
544+
if (children != null) {
545+
for (int i = 0; i < children.Count; ++i) {
546+
string methods = string.Format ("__md_{0}_methods", i + 1);
547+
GenerateRegisterType (writer, children [i], methods);
548+
}
557549
}
550+
writer.WriteLine ("\t}");
558551
}
559-
writer.WriteLine ("\t}");
560552

561553
GenerateBody (writer);
562554

@@ -710,16 +702,19 @@ void GenerateBody (TextWriter sw)
710702

711703
void GenerateRegisterType (TextWriter sw, JavaCallableWrapperGenerator self, string field)
712704
{
713-
if (overriddenMethodDescriptors == null) {
714-
overriddenMethodDescriptors = new List<OverriddenMethodDescriptor> ();
705+
string managedTypeName = self.type.GetPartialAssemblyQualifiedName (cache);
706+
string javaTypeName = $"{package}.{name}";
707+
708+
if (!self.HasDynamicallyRegisteredMethods) {
709+
return;
715710
}
716711

717712
sw.WriteLine ("\t\t{0} = ", field);
718-
string managedTypeName = self.type.GetPartialAssemblyQualifiedName (cache);
719-
string javaTypeName = $"{package}.{name}";
713+
720714
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));
715+
if (method.IsDynamicallyRegistered) {
716+
sw.WriteLine ("\t\t\t\"{0}\\n\" +", method.Method);
717+
}
723718
}
724719
sw.WriteLine ("\t\t\t\"\";");
725720
if (CannotRegisterInStaticConstructor (self.type))
@@ -772,12 +767,13 @@ bool CannotRegisterInStaticConstructor (TypeDefinition type)
772767

773768
class Signature {
774769

775-
public Signature (MethodDefinition method, RegisterAttribute register) : this (method, register, null, null) {}
770+
public Signature (MethodDefinition method, RegisterAttribute register, bool shouldBeDynamicallyRegistered = true) : this (method, register, null, null, shouldBeDynamicallyRegistered) {}
776771

777-
public Signature (MethodDefinition method, RegisterAttribute register, string managedParameters, string outerType)
772+
public Signature (MethodDefinition method, RegisterAttribute register, string managedParameters, string outerType, bool shouldBeDynamicallyRegistered = true)
778773
: this (register.Name, register.Signature, register.Connector, managedParameters, outerType, null)
779774
{
780775
Annotations = JavaCallableWrapperGenerator.GetAnnotationsString ("\t", method.CustomAttributes);
776+
IsDynamicallyRegistered = shouldBeDynamicallyRegistered;
781777
}
782778

783779
public Signature (MethodDefinition method, ExportAttribute export, IMetadataResolver cache)
@@ -880,6 +876,7 @@ public string ThrowsDeclaration {
880876
public readonly string Method;
881877
public readonly bool IsExport;
882878
public readonly bool IsStatic;
879+
public readonly bool IsDynamicallyRegistered = true;
883880
public readonly string [] ThrownTypeNames;
884881
public readonly string Annotations;
885882
}

0 commit comments

Comments
 (0)