Skip to content

Commit 1dd91b5

Browse files
committed
[generator] Add support for 'skipInvokerMethods' metadata.
1 parent c694313 commit 1dd91b5

File tree

4 files changed

+46
-6
lines changed

4 files changed

+46
-6
lines changed

tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,36 @@ public void ManagedOverrideInterfaceProperty_Reabstract ()
322322
Assert.True (writer.ToString ().Contains ("abstract int Name {"), $"was: `{writer}`");
323323
}
324324

325+
[Test]
326+
public void SkipInvokerMethodsMetadata ()
327+
{
328+
var xml = @"<api>
329+
<package name='java.lang' jni-name='java/lang'>
330+
<class abstract='false' deprecated='not deprecated' final='false' name='Object' static='false' visibility='public' jni-signature='Ljava/lang/Object;' />
331+
</package>
332+
<package name='com.xamarin.android' jni-name='com/xamarin/android'>
333+
<class abstract='true' deprecated='not deprecated' extends='java.lang.Object' extends-generic-aware='java.lang.Object' jni-extends='Ljava/lang/Object;' final='false' name='MyBaseClass' static='false' visibility='public' jni-signature='Lcom/xamarin/android/MyBaseClass;'>
334+
<method abstract='true' deprecated='not deprecated' final='false' name='doStuff' jni-signature='()Lcom/xamarin/android/MyBaseClass;' bridge='false' native='false' return='com.xamarin.android.MyBaseClass' jni-return='Lcom/xamarin/android/MyBaseClass;' static='false' synchronized='false' synthetic='false' visibility='public'></method>
335+
</class>
336+
<class abstract='true' deprecated='not deprecated' extends='com.xamarin.android.MyBaseClass' extends-generic-aware='com.xamarin.android.MyBaseClass' jni-extends='Lcom/xamarin/android/MyBaseClass;' final='false' name='MyClass' static='false' visibility='public' jni-signature='Lcom/xamarin/android/MyClass;' skipInvokerMethods='com/xamarin/android/MyBaseClass.doStuff()Lcom/xamarin/android/MyBaseClass;'>
337+
<method abstract='true' deprecated='not deprecated' final='false' name='doStuff' jni-signature='()Lcom/xamarin/android/MyClass;' bridge='false' native='false' return='com.xamarin.android.MyClass' jni-return='Lcom/xamarin/android/MyClass;' static='false' synchronized='false' synthetic='false' visibility='public' managedOverride='override' return-not-null='true'></method>
338+
</class>
339+
</package>
340+
</api>";
341+
342+
var gens = ParseApiDefinition (xml);
343+
var klass = gens.Single (g => g.Name == "MyClass");
344+
345+
generator.Context.ContextTypes.Push (klass);
346+
generator.WriteType (klass, string.Empty, new GenerationInfo ("", "", "MyAssembly"));
347+
generator.Context.ContextTypes.Pop ();
348+
349+
// `override abstract` causes both invoker methods to get generated. We use metadata
350+
// to suppress the base class's method to prevent a conflict.
351+
Assert.True (writer.ToString ().Contains ("public override abstract Com.Xamarin.Android.MyClass DoStuff ();"), $"was: `{writer}`");
352+
Assert.False (writer.ToString ().Contains ("public abstract Com.Xamarin.Android.MyBaseClass DoStuff ();"), $"was: `{writer}`");
353+
}
354+
325355
[Test]
326356
public void WriteDuplicateInterfaceEventArgs ()
327357
{

tools/generator/Java.Interop.Tools.Generator.Importers/XmlApiImporter.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@ public static ClassGen CreateClass (XElement pkg, XElement elem, CodeGenerationO
116116
!options.SupportNestedInterfaceTypes
117117
};
118118

119+
if (elem.Attribute ("skipInvokerMethods")?.Value is string skip)
120+
foreach (var m in skip.Split (new char [] { ',' }))
121+
klass.SkippedInvokerMethods.Add (m);
122+
119123
FillApiSince (klass, pkg, elem);
120124
SetLineInfo (klass, elem, options);
121125

tools/generator/Java.Interop.Tools.Generator.ObjectModel/ClassGen.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ namespace MonoDroid.Generation
1111
public class ClassGen : GenBase
1212
{
1313
bool fill_explicit_implementation_started;
14+
HashSet<string> skipped_invoker_methods;
1415

1516
public List<Ctor> Ctors { get; private set; } = new List<Ctor> ();
1617

@@ -355,6 +356,8 @@ public override void ResetValidation ()
355356
base.ResetValidation ();
356357
}
357358

359+
public HashSet<string> SkippedInvokerMethods => skipped_invoker_methods ??= new HashSet<string> ();
360+
358361
public override string ToNative (CodeGenerationOptions opt, string varname, Dictionary<string, string> mappings = null)
359362
{
360363
if (opt.CodeGenerationTarget == CodeGenerationTarget.JavaInterop1) {

tools/generator/SourceWriters/ClassInvokerClass.cs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,21 +64,21 @@ public ClassInvokerClass (ClassGen klass, CodeGenerationOptions opt)
6464
Properties.Add (new ThresholdTypeGetter ());
6565
}
6666

67-
AddMemberInvokers (klass, opt, new HashSet<string> ());
67+
AddMemberInvokers (klass, opt, new HashSet<string> (), klass.SkippedInvokerMethods);
6868
}
6969

70-
void AddMemberInvokers (ClassGen klass, CodeGenerationOptions opt, HashSet<string> members)
70+
void AddMemberInvokers (ClassGen klass, CodeGenerationOptions opt, HashSet<string> members, HashSet<string> skipInvokers)
7171
{
7272
AddPropertyInvokers (klass, klass.Properties, members, opt);
73-
AddMethodInvokers (klass, klass.Methods, members, null, opt);
73+
AddMethodInvokers (klass, klass.Methods, members, skipInvokers, null, opt);
7474

7575
foreach (var iface in klass.GetAllDerivedInterfaces ()) {
7676
AddPropertyInvokers (klass, iface.Properties.Where (p => !klass.ContainsProperty (p.Name, false, false)), members, opt);
77-
AddMethodInvokers (klass, iface.Methods.Where (m => (opt.SupportDefaultInterfaceMethods || !m.IsInterfaceDefaultMethod) && !klass.ContainsMethod (m, false, false) && !klass.IsCovariantMethod (m) && !klass.ExplicitlyImplementedInterfaceMethods.Contains (m.GetSignature ())), members, iface, opt);
77+
AddMethodInvokers (klass, iface.Methods.Where (m => (opt.SupportDefaultInterfaceMethods || !m.IsInterfaceDefaultMethod) && !klass.ContainsMethod (m, false, false) && !klass.IsCovariantMethod (m) && !klass.ExplicitlyImplementedInterfaceMethods.Contains (m.GetSignature ())), members, skipInvokers, iface, opt);
7878
}
7979

8080
if (klass.BaseGen != null && klass.BaseGen.FullName != "Java.Lang.Object")
81-
AddMemberInvokers (klass.BaseGen, opt, members);
81+
AddMemberInvokers (klass.BaseGen, opt, members, skipInvokers);
8282
}
8383

8484
void AddPropertyInvokers (ClassGen klass, IEnumerable<Property> properties, HashSet<string> members, CodeGenerationOptions opt)
@@ -100,9 +100,12 @@ void AddPropertyInvokers (ClassGen klass, IEnumerable<Property> properties, Hash
100100
}
101101
}
102102

103-
void AddMethodInvokers (ClassGen klass, IEnumerable<Method> methods, HashSet<string> members, InterfaceGen gen, CodeGenerationOptions opt)
103+
void AddMethodInvokers (ClassGen klass, IEnumerable<Method> methods, HashSet<string> members, HashSet<string> skipInvokers, InterfaceGen gen, CodeGenerationOptions opt)
104104
{
105105
foreach (var m in methods) {
106+
if (skipInvokers.Contains ($"{m.DeclaringType.RawJniName}.{m.JavaName}{m.JniSignature}"))
107+
continue;
108+
106109
var sig = m.GetSignature ();
107110

108111
if (members.Contains (sig))

0 commit comments

Comments
 (0)