Skip to content
This repository was archived by the owner on Jul 6, 2026. It is now read-only.

Commit a7e09b7

Browse files
authored
[generator] Extend skipInvokerMethods support to interfaces. (#1202)
Context: 73ebad2 Context: dotnet/android-libraries#779 Commit 73ebad2 added support for the metadata attribute `//class[@skipInvokerMethods]`, which allowed us to suppress generation of invoker methods for a class. The AndroidX Media3 binding in dotnet/android-libraries#779 hits a similar issue wherein we generate incorrect generics on an invoker type. However, this is an invoker type for an *`interface`*, not a `class`. Extend our `skipInvokerMethods` support so that it can be used as `//interface[@skipInvokerMethods]` as well.
1 parent 14a9470 commit a7e09b7

8 files changed

Lines changed: 49 additions & 14 deletions

File tree

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,32 @@ public void SkipInvokerMethodsMetadata ()
352352
Assert.False(writer.ToString().Contains("public abstract Com.Xamarin.Android.MyBaseClass DoStuff ();"),$"was: `{writer}`");
353353
}
354354

355+
[Test]
356+
publicvoidSkipInterfaceInvokerMethodsMetadata()
357+
{
358+
varxml=@"<api>
359+
<package name='java.lang' jni-name='java/lang'>
360+
<class abstract='false' deprecated='not deprecated' final='false' name='Object' static='false' visibility='public' jni-signature='Ljava/lang/Object;' />
361+
</package>
362+
<package name='com.xamarin.android' jni-name='com/xamarin/android'>
363+
<interface abstract='true' deprecated='not deprecated' extends='java.lang.Object' extends-generic-aware='java.lang.Object' jni-extends='Ljava/lang/Object;' final='false' name='MyInterface' static='false' visibility='public' jni-signature='Lcom/xamarin/android/MyInterface;' skipInvokerMethods='com/xamarin/android/MyInterface.countAffectedRows()I'>
364+
<method abstract='true' deprecated='not deprecated' final='false' name='countAffectedRows' jni-signature='()I' bridge='false' native='false' return='int' jni-return='I' static='false' synchronized='false' synthetic='false' visibility='public'></method>
365+
</interface>
366+
</package>
367+
</api>";
368+
369+
vargens=ParseApiDefinition(xml);
370+
variface=gens.Single(g =>g.Name=="IMyInterface");
371+
372+
generator.Context.ContextTypes.Push(iface);
373+
generator.WriteType(iface,string.Empty,newGenerationInfo("","","MyAssembly"));
374+
generator.Context.ContextTypes.Pop();
375+
376+
// Ensure the invoker for 'countAffectedRows' isn't generated
377+
Assert.False(writer.ToString().Contains("static Delegate cb_countAffectedRows;"),$"was: `{writer}`");
378+
Assert.False(writer.ToString().Contains("InvokeAbstractInt32Method"),$"was: `{writer}`");
379+
}
380+
355381
[Test]
356382
publicvoidCompatVirtualMethod_Class()
357383
{

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

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

120-
if(elem.Attribute("skipInvokerMethods")?.Valueisstringskip)
121-
foreach(varminskip.Split(newchar[]{',',' ','\n','\r'},StringSplitOptions.RemoveEmptyEntries))
122-
klass.SkippedInvokerMethods.Add(m);
123-
124120
FillApiSince(klass,pkg,elem);
125121
SetLineInfo(klass,elem,options);
126122

@@ -264,6 +260,10 @@ public static GenBaseSupport CreateGenBaseSupport (XElement pkg, XElement elem,
264260
Visibility=elem.XGetAttribute("visibility")
265261
};
266262

263+
if(elem.Attribute("skipInvokerMethods")?.Valueisstringskip)
264+
foreach(varminskip.Split(newchar[]{',',' ','\n','\r'},StringSplitOptions.RemoveEmptyEntries))
265+
support.SkippedInvokerMethods.Add(m);
266+
267267
if(support.IsDeprecated){
268268
support.DeprecatedComment=elem.XGetAttribute("deprecated");
269269

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

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

1615
publicList<Ctor>Ctors{get;privateset;}=newList<Ctor>();
1716

@@ -356,8 +355,6 @@ public override void ResetValidation ()
356355
base.ResetValidation();
357356
}
358357

359-
publicHashSet<string>SkippedInvokerMethods=>skipped_invoker_methods??=newHashSet<string>();
360-
361358
publicoverridestringToNative(CodeGenerationOptionsopt,stringvarname,Dictionary<string,string>mappings=null)
362359
{
363360
if(opt.CodeGenerationTarget==CodeGenerationTarget.JavaInterop1){

‎tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -854,6 +854,8 @@ bool ReturnTypeMatches (Method m, Method mm)
854854

855855
publicboolShouldGenerateAnnotationAttribute=>IsAnnotation;
856856

857+
publicHashSet<string>SkippedInvokerMethods=>support.SkippedInvokerMethods;
858+
857859
publicvoidStripNonBindables(CodeGenerationOptionsopt)
858860
{
859861
// Strip out default interface methods if not desired

‎tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBaseSupport.cs‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
usingSystem;
2+
usingSystem.Collections.Generic;
23

34
namespaceMonoDroid.Generation
45
{
56
publicclassGenBaseSupport
67
{
8+
HashSet<string>skipped_invoker_methods;
9+
710
publicstringAnnotatedVisibility{get;set;}
811
publicboolIsAcw{get;set;}
912
publicboolIsDeprecated{get;set;}
@@ -21,6 +24,8 @@ public class GenBaseSupport
2124
publicstringVisibility{get;set;}
2225
publicGenericParameterDefinitionListTypeParameters{get;set;}
2326

27+
publicHashSet<string>SkippedInvokerMethods=>skipped_invoker_methods??=newHashSet<string>();
28+
2429
publicvirtualboolOnValidate(CodeGenerationOptionsopt)
2530
{
2631
// See com.google.inject.internal.util package for this case.

‎tools/generator/Java.Interop.Tools.Generator.ObjectModel/Method.cs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,8 @@ public string GetMetadataXPathReference (GenBase declaringType) =>
193193

194194
publicstringGetSignature()=>$"n_{JavaName}:{JniSignature}:{ConnectorName}";
195195

196+
publicstringGetSkipInvokerSignature()=>$"{DeclaringType.RawJniName}.{JavaName}{JniSignature}";
197+
196198
publicboolIsEventHandlerWithHandledProperty=>RetVal.JavaName=="boolean"&&EventName!="";
197199

198200
publicoverrideboolIsGeneric=>base.IsGeneric||RetVal.IsGeneric;

‎tools/generator/SourceWriters/ClassInvokerClass.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ void AddPropertyInvokers (ClassGen klass, IEnumerable<Property> properties, Hash
103103
voidAddMethodInvokers(ClassGenklass,IEnumerable<Method>methods,HashSet<string>members,HashSet<string>skipInvokers,InterfaceGengen,CodeGenerationOptionsopt)
104104
{
105105
foreach(varminmethods){
106-
if(skipInvokers.Contains($"{m.DeclaringType.RawJniName}.{m.JavaName}{m.JniSignature}"))
106+
if(skipInvokers.Contains(m.GetSkipInvokerSignature()))
107107
continue;
108108

109109
varsig=m.GetSignature();

‎tools/generator/SourceWriters/InterfaceInvokerClass.cs‎

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public InterfaceInvokerClass (InterfaceGen iface, CodeGenerationOptions opt, Cod
6969

7070
Constructors.Add(newInterfaceInvokerConstructor(opt,iface,context));
7171

72-
AddMemberInvokers(iface,newHashSet<string>(),opt,context);
72+
AddMemberInvokers(iface,newHashSet<string>(),iface.SkippedInvokerMethods,opt,context);
7373
}
7474

7575
staticHashSet<InterfaceGen>GetCompleteImplementedInterfaces(HashSet<InterfaceGen>ifaces,InterfaceGentoplevel)
@@ -81,15 +81,15 @@ static HashSet<InterfaceGen> GetCompleteImplementedInterfaces (HashSet<Interface
8181
returnifaces;
8282
}
8383

84-
voidAddMemberInvokers(InterfaceGeniface,HashSet<string>members,CodeGenerationOptionsopt,CodeGeneratorContextcontext)
84+
voidAddMemberInvokers(InterfaceGeniface,HashSet<string>members,HashSet<string>skipInvokers,CodeGenerationOptionsopt,CodeGeneratorContextcontext)
8585
{
8686
AddPropertyInvokers(iface,iface.Properties.Where(p =>!p.Getter.IsStatic&&!p.Getter.IsInterfaceDefaultMethod),members,opt,context);
87-
AddMethodInvokers(iface,iface.Methods.Where(m =>!m.IsStatic&&!m.IsInterfaceDefaultMethod),members,opt,context);
87+
AddMethodInvokers(iface,iface.Methods.Where(m =>!m.IsStatic&&!m.IsInterfaceDefaultMethod),members,skipInvokers,opt,context);
8888
AddCharSequenceEnumerators(iface);
8989

9090
foreach(variiniface.GetAllDerivedInterfaces()){
9191
AddPropertyInvokers(iface,i.Properties.Where(p =>!p.Getter.IsStatic&&!p.Getter.IsInterfaceDefaultMethod),members,opt,context);
92-
AddMethodInvokers(iface,i.Methods.Where(m =>!m.IsStatic&&!m.IsInterfaceDefaultMethod&&!iface.IsCovariantMethod(m)&&!(i.FullName.StartsWith("Java.Lang.ICharSequence",StringComparison.Ordinal)&&m.Name.EndsWith("Formatted",StringComparison.Ordinal))),members,opt,context);
92+
AddMethodInvokers(iface,i.Methods.Where(m =>!m.IsStatic&&!m.IsInterfaceDefaultMethod&&!iface.IsCovariantMethod(m)&&!(i.FullName.StartsWith("Java.Lang.ICharSequence",StringComparison.Ordinal)&&m.Name.EndsWith("Formatted",StringComparison.Ordinal))),members,skipInvokers,opt,context);
9393
AddCharSequenceEnumerators(i);
9494
}
9595
}
@@ -113,10 +113,13 @@ void AddPropertyInvokers (InterfaceGen iface, IEnumerable<Property> properties,
113113
Properties.Add(newInterfaceInvokerProperty(iface,prop,opt,context));
114114
}
115115
}
116-
117-
voidAddMethodInvokers(InterfaceGeniface,IEnumerable<Method>methods,HashSet<string>members,CodeGenerationOptionsopt,CodeGeneratorContextcontext)
116+
117+
voidAddMethodInvokers(InterfaceGeniface,IEnumerable<Method>methods,HashSet<string>members,HashSet<string>skipInvokers,CodeGenerationOptionsopt,CodeGeneratorContextcontext)
118118
{
119119
foreach(varminmethods){
120+
if(skipInvokers.Contains(m.GetSkipInvokerSignature()))
121+
continue;
122+
120123
varsig=m.GetSignature();
121124

122125
if(members.Contains(sig))

0 commit comments

Comments
 (0)