Skip to content

Commit 63dcf36

Browse files
committed
[generator] Fix StackOverflow when copying DIM from package-protected interfaces.
1 parent 9d99723 commit 63dcf36

File tree

4 files changed

+43
-6
lines changed

4 files changed

+43
-6
lines changed

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

+36
Original file line numberDiff line numberDiff line change
@@ -514,5 +514,41 @@ public void CompatVirtualMethod_Interface ()
514514

515515
Assert.True (writer.ToString ().NormalizeLineEndings ().Contains ("catch (Java.Lang.NoSuchMethodError) { throw new Java.Lang.AbstractMethodError (__id); }".NormalizeLineEndings ()), $"was: `{writer}`");
516516
}
517+
518+
[Test]
519+
public void FixDefaultInterfaceMethodStackOverflow ()
520+
{
521+
// The bug was that this causes a stack overflow, but this also tests
522+
// that the OverriddenInterfaceMethod is now correctly set in the interface method.
523+
var xml = """
524+
<api>
525+
<package name='io.grpc' jni-name='io/grpc'>
526+
<interface abstract="true" deprecated="not deprecated" final="false" name="InternalConfigurator" static="false" visibility="public" jni-signature="Lio/grpc/InternalConfigurator;">
527+
<implements name="io.grpc.Configurator" name-generic-aware="io.grpc.Configurator" jni-type="Lio/grpc/Configurator;" />
528+
</interface>
529+
<interface abstract="true" deprecated="not deprecated" final="false" name="Configurator" static="false" visibility="" jni-signature="Lio/grpc/Configurator;">
530+
<method abstract="false" deprecated="not deprecated" final="false" name="configureChannelBuilder" jni-signature="V" bridge="false" native="false" return="void" jni-return="V" static="false" synchronized="false" synthetic="false" visibility="public" />
531+
</interface>
532+
</package>
533+
</api>
534+
""";
535+
536+
var gens = ParseApiDefinition (xml);
537+
538+
foreach (var iface in gens.OfType<InterfaceGen> ()) {
539+
generator.Context.ContextTypes.Push (iface);
540+
generator.WriteType (iface, string.Empty, new GenerationInfo ("", "", "MyAssembly"));
541+
generator.Context.ContextTypes.Pop ();
542+
}
543+
544+
var klass1 = gens.Single (g => g.Name == "IInternalConfigurator");
545+
var klass2 = gens.Single (g => g.Name == "IConfigurator");
546+
547+
Assert.AreEqual (1, klass1.Methods.Count);
548+
Assert.AreEqual (1, klass2.Methods.Count);
549+
550+
Assert.AreNotSame (klass1.Methods [0], klass2.Methods [0]);
551+
Assert.AreSame (klass1.Methods [0].OverriddenInterfaceMethod, klass2.Methods [0]);
552+
}
517553
}
518554
}

tests/generator-Tests/expected.ji/AccessModifiers/Xamarin.Test.IExtendedInterface.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public partial interface IExtendedInterface : IJavaPeerable {
1111
[global::Java.Interop.JniMethodSignature ("extendedMethod", "()V")]
1212
void ExtendedMethod ();
1313

14-
// Metadata.xml XPath method reference: path="/api/package[@name='xamarin.test']/interface[@name='BaseInterface']/method[@name='baseMethod' and count(parameter)=0]"
14+
// Metadata.xml XPath method reference: path="/api/package[@name='xamarin.test']/interface[@name='ExtendedInterface']/method[@name='baseMethod' and count(parameter)=0]"
1515
[global::Java.Interop.JniMethodSignature ("baseMethod", "()V")]
1616
void BaseMethod ();
1717

@@ -46,7 +46,7 @@ public unsafe void BaseMethod ()
4646
{
4747
const string __id = "baseMethod.()V";
4848
try {
49-
_members_xamarin_test_BaseInterface.InstanceMethods.InvokeAbstractVoidMethod (__id, this, null);
49+
_members_xamarin_test_ExtendedInterface.InstanceMethods.InvokeAbstractVoidMethod (__id, this, null);
5050
} finally {
5151
}
5252
}

tests/generator-Tests/expected.xaji/AccessModifiers/Xamarin.Test.IExtendedInterface.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public partial interface IExtendedInterface : IJavaObject, IJavaPeerable {
1212
[Register ("extendedMethod", "()V", "GetExtendedMethodHandler:Xamarin.Test.IExtendedInterfaceInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null")]
1313
void ExtendedMethod ();
1414

15-
// Metadata.xml XPath method reference: path="/api/package[@name='xamarin.test']/interface[@name='BaseInterface']/method[@name='baseMethod' and count(parameter)=0]"
15+
// Metadata.xml XPath method reference: path="/api/package[@name='xamarin.test']/interface[@name='ExtendedInterface']/method[@name='baseMethod' and count(parameter)=0]"
1616
[Register ("baseMethod", "()V", "GetBaseMethodHandler:Xamarin.Test.IExtendedInterfaceInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null")]
1717
void BaseMethod ();
1818

@@ -95,7 +95,7 @@ public unsafe void BaseMethod ()
9595
{
9696
const string __id = "baseMethod.()V";
9797
try {
98-
_members_xamarin_test_BaseInterface.InstanceMethods.InvokeAbstractVoidMethod (__id, this, null);
98+
_members_xamarin_test_ExtendedInterface.InstanceMethods.InvokeAbstractVoidMethod (__id, this, null);
9999
} finally {
100100
}
101101
}

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

+3-2
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,9 @@ public override void FixupAccessModifiers (CodeGenerationOptions opt)
6969
var baseType = opt.SymbolTable.Lookup (implementedInterface);
7070
if (baseType is InterfaceGen interfaceGen && interfaceGen.RawVisibility != "public") {
7171
// Copy over "private" methods
72-
interfaceGen.Methods.Where (m => !Methods.Contains (m)).ToList ().ForEach (Methods.Add);
73-
72+
foreach (var method in interfaceGen.Methods.ToList ())
73+
if (!Methods.Any (m => m.Matches (method)))
74+
Methods.Add (method.Clone (this));
7475
} else {
7576
break;
7677
}

0 commit comments

Comments
 (0)