diff --git a/build-tools/Java.Interop.Sdk/Sdk/Sdk.props b/build-tools/Java.Interop.Sdk/Sdk/Sdk.props
new file mode 100644
index 000000000..ff58e1577
--- /dev/null
+++ b/build-tools/Java.Interop.Sdk/Sdk/Sdk.props
@@ -0,0 +1,6 @@
+
+
+ ;
+ :
+
+
diff --git a/build-tools/Java.Interop.Sdk/Sdk/Sdk.targets b/build-tools/Java.Interop.Sdk/Sdk/Sdk.targets
new file mode 100644
index 000000000..92ef90e2a
--- /dev/null
+++ b/build-tools/Java.Interop.Sdk/Sdk/Sdk.targets
@@ -0,0 +1,218 @@
+
+
+
+
+ True
+
+
+ True
+
+
+
+
+ $(OutputPath)$(AssemblyName).jar
+
+
+
+
+ _BuildJavaCompileForManagedBinding;
+ _GenerateApiDescription;
+ _GenerateManagedBinding;
+ _CleanupManagedBinding;
+
+
+ _JavaCreateJcws;
+ _JavaCreateOutputJar;
+
+
+
+
+
+
+
+
+
+
+ <_GeneratorPath>$(UtilityOutputFullPath)generator.dll
+ <_JavaIntermediateDir>$(IntermediateOutputPath)_ji\
+ <_JavaManagedBindingInput>$(_JavaIntermediateDir)o.jar
+ <_JavaManagedBindingDir>$(_JavaIntermediateDir)mcw\
+ <_JavaJcwClassesDir>$(_JavaIntermediateDir)classes\
+ <_JavaJcwSourcesDir>$(_JavaIntermediateDir)java\
+
+
+
+
+ <_JavaCompileForBindingInputs
+ Condition=" '%(JavaCompile.Bind)' == 'True' "
+ Include="@(JavaCompile)"
+ />
+
+
+
+
+
+ <_JavacRefs Include="$(ToolOutputFullPath)java-interop.jar" />
+ <_JavacRefs Include="@(JavaReference)" />
+ <_JavacRefsWithForwardSlash Include="@(_JavacRefs->Replace('%5c', '/'))" />
+
+
+
+
+
+ <_ClassesDir>$(_JavaIntermediateDir)\bound-classes
+ <_ResponseFile>$(_JavaIntermediateDir)r.txt
+ <_Classpath>@(_JavacRefsWithForwardSlash, '$(JavaPathSeparator)')
+
+
+
+ <_Response Include="-classpath" />
+ <_Response Include=""$(_Classpath)"" />
+ <_Response Include="@(_JavaCompileForBindingInputs->Replace('%5c', '/'))" />
+
+
+
+
+
+
+
+
+
+
+
+ <_ClassParseInputs
+ Condition=" Exists($(_JavaManagedBindingInput))"
+ Include="$(_JavaManagedBindingInput)"
+ />
+ <_ClassParseInputs
+ Condition=" '%(JavaReference.Bind)' == 'True' "
+ Include="@(JavaReference)"
+ />
+
+
+
+
+
+
+ <_ClassParse>"$(UtilityOutputFullPath)class-parse.dll"
+ <_Inputs>@(_ClassParseInputs, ' ')
+ <_Output>"-o=$(_JavaManagedBindingDir)api.xml"
+
+
+
+
+
+
+
+ "$(_GeneratorPath)"
+ <_GenFlags>--public --global
+ <_Out>-o "$(_JavaManagedBindingDir)."
+ <_Codegen>--codegen-target=JavaInterop1
+ <_Assembly>"--assembly=$(AssemblyName)"
+ <_TypeMap>--type-map-report=$(_JavaManagedBindingDir)type-mapping.txt
+ <_Api>$(_JavaManagedBindingDir)api.xml
+ <_Dirs>"--enumdir=$(_JavaManagedBindingDir)."
+ <_FullIntermediateOutputPath>$([System.IO.Path]::GetFullPath('$(_JavaManagedBindingDir)'))
+ <_LangFeatures>--lang-features=nullable-reference-types,default-interface-methods,nested-interface-types,interface-constants
+
+
+
+ <_RefAsmDir Include="@(ReferencePathWithRefAssemblies->'%(RootDir)%(Directory).'->Distinct())" />
+ <_Lib Include="@(_RefAsmDir->'-L "%(Identity)"')" />
+ <_JavaBaseRef Include="@(ReferencePathWithRefAssemblies)"
+ Condition=" '%(FileName)' == 'Java.Base' "
+ />
+ <_Ref Include="@(_JavaBaseRef->'-r "%(FullPath)"')" />
+
+
+
+
+
+
+
+
+
+
+ $(DefineConstants);$([System.String]::Copy('$(_GeneratedDefineConstants)').Replace ('%24(DefineConstants);', ''))
+
+
+
+
+
+
+
+
+
+
+ <_RefAsmDirs Include="@(ReferencePathWithRefAssemblies->'%(RootDir)%(Directory).'->Distinct())" />
+
+
+ <_JcwGen>"$(UtilityOutputFullPath)/jcw-gen.dll"
+ <_Target>--codegen-target JavaInterop1
+ <_Output>-o "$(_JavaJcwSourcesDir)."
+ <_Libpath>@(_RefAsmDirs->'-L "%(Identity)"', ' ')
+
+
+
+
+
+
+
+ <_JavaGeneratedJcwSource Include="$(_JavaJcwSourcesDir)**\*.java" />
+
+
+
+
+
+
+
+ <_ResponseFile>$(_JavaIntermediateDir)r.txt
+ <_Classpath>@(_JavacRefsWithForwardSlash, '$(JavaPathSeparator)')
+
+
+ <_Source Include="@(JavaCompile->Replace('%5c', '/'))" />
+ <_Source Include="@(_JavaGeneratedJcwSource->Replace('%5c', '/'))" />
+
+
+
+
+
+
+
+
diff --git a/tests/Java.Base-Tests/Java.Base-Tests.csproj b/tests/Java.Base-Tests/Java.Base-Tests.csproj
index 78111a2d7..e1f4b2bc4 100644
--- a/tests/Java.Base-Tests/Java.Base-Tests.csproj
+++ b/tests/Java.Base-Tests/Java.Base-Tests.csproj
@@ -8,10 +8,12 @@
false
+
$(TestOutputFullPath)
+ $(OutputPath)java.base-tests.jar
@@ -26,6 +28,15 @@
+
+
+
+
+
+
+
+
+
diff --git a/tests/Java.Base-Tests/Java.Base-Tests.targets b/tests/Java.Base-Tests/Java.Base-Tests.targets
index 3312b41b6..8c119d541 100644
--- a/tests/Java.Base-Tests/Java.Base-Tests.targets
+++ b/tests/Java.Base-Tests/Java.Base-Tests.targets
@@ -1,49 +1,2 @@
-
-
- <_BuildJavaBaseTestsJarInputs Include="$(TargetPath)" />
- <_BuildJavaBaseTestsJarInputs Include="$(MSBuildThisFileFullPath)" />
- <_BuildJavaBaseTestsJarInputs Include="$(MSBuildThisFileFullPath)" />
- <_BuildJavaBaseTestsJarInputs Include="java\**\*.java" />
-
-
-
-
-
-
-
- <_RefAsmDirs Include="@(ReferencePathWithRefAssemblies->'%(RootDir)%(Directory).'->Distinct())" />
-
-
- <_JcwGen>"$(UtilityOutputFullPath)/jcw-gen.dll"
- <_Target>--codegen-target JavaInterop1
- <_Output>-o "$(IntermediateOutputPath)/java"
- <_Libpath>@(_RefAsmDirs->'-L "%(Identity)"', ' ')
-
-
-
-
-
-
- <_JcwSource Include="$(IntermediateOutputPath)java\**\*.java;java\**\*.java" />
-
-
-
-
-
-
- <_JcwSourceReal Include="$(IntermediateOutputPath)java\**\*.java;java\**\*.java" />
-
-
-
-
-
diff --git a/tests/Java.Base-Tests/Java.Base/InterfaceMethodInheritanceTests.cs b/tests/Java.Base-Tests/Java.Base/InterfaceMethodInheritanceTests.cs
new file mode 100644
index 000000000..dc49dfd27
--- /dev/null
+++ b/tests/Java.Base-Tests/Java.Base/InterfaceMethodInheritanceTests.cs
@@ -0,0 +1,26 @@
+using System;
+
+using Java.Interop;
+
+using NUnit.Framework;
+
+namespace Java.BaseTests {
+
+ [TestFixture]
+ public class InterfaceMethodInheritanceTests : JavaVMFixture {
+
+ [Test]
+ public void InterfaceMethod ()
+ {
+ using var iface = global::Net.Dot.Jni.Test.HasInterfaceMethodInheritance.Create ();
+ var m = iface!.M ();
+ Assert.AreEqual ("HasInterfaceMethodInheritance.m", m);
+ var n = iface!.N ();
+ Assert.AreEqual ("HasInterfaceMethodInheritance.n", n);
+ var o = iface!.O ();
+ Assert.AreEqual ("HasInterfaceMethodInheritance.o", o);
+ var p = iface!.P ();
+ Assert.AreEqual ("HasInterfaceMethodInheritance.p", p);
+ }
+ }
+}
diff --git a/tests/Java.Base-Tests/java/net/dot/jni/test/HasInterfaceMethodInheritance.java b/tests/Java.Base-Tests/java/net/dot/jni/test/HasInterfaceMethodInheritance.java
new file mode 100644
index 000000000..ffb2824c0
--- /dev/null
+++ b/tests/Java.Base-Tests/java/net/dot/jni/test/HasInterfaceMethodInheritance.java
@@ -0,0 +1,26 @@
+package net.dot.jni.test;
+
+public class HasInterfaceMethodInheritance implements InterfaceMethodInheritance {
+ private HasInterfaceMethodInheritance() {
+ }
+
+ public static InterfaceMethodInheritance create() {
+ return new HasInterfaceMethodInheritance();
+ }
+
+ public String m() {
+ return "HasInterfaceMethodInheritance.m";
+ }
+
+ public String n() {
+ return "HasInterfaceMethodInheritance.n";
+ }
+
+ public String o() {
+ return "HasInterfaceMethodInheritance.o";
+ }
+
+ public String p() {
+ return "HasInterfaceMethodInheritance.p";
+ }
+}
diff --git a/tests/Java.Base-Tests/java/net/dot/jni/test/InterfaceMethodInheritance.java b/tests/Java.Base-Tests/java/net/dot/jni/test/InterfaceMethodInheritance.java
new file mode 100644
index 000000000..e27d3fa50
--- /dev/null
+++ b/tests/Java.Base-Tests/java/net/dot/jni/test/InterfaceMethodInheritance.java
@@ -0,0 +1,9 @@
+package net.dot.jni.test;
+
+/* package */ interface BaseInterface {
+ String m();
+}
+
+public interface InterfaceMethodInheritance extends BaseInterface, PublicInterface {
+ String n();
+}
diff --git a/tests/Java.Base-Tests/java/net/dot/jni/test/PublicInterface.java b/tests/Java.Base-Tests/java/net/dot/jni/test/PublicInterface.java
new file mode 100644
index 000000000..9ce0a1f98
--- /dev/null
+++ b/tests/Java.Base-Tests/java/net/dot/jni/test/PublicInterface.java
@@ -0,0 +1,9 @@
+package net.dot.jni.test;
+
+/* package */ interface InternalInterface {
+ String o();
+}
+
+public interface PublicInterface extends InternalInterface {
+ String p();
+}
diff --git a/tests/generator-Tests/Unit-Tests/DefaultInterfaceMethodsTests.cs b/tests/generator-Tests/Unit-Tests/DefaultInterfaceMethodsTests.cs
index 9b94acd88..7269620a0 100644
--- a/tests/generator-Tests/Unit-Tests/DefaultInterfaceMethodsTests.cs
+++ b/tests/generator-Tests/Unit-Tests/DefaultInterfaceMethodsTests.cs
@@ -514,5 +514,41 @@ public void CompatVirtualMethod_Interface ()
Assert.True (writer.ToString ().NormalizeLineEndings ().Contains ("catch (Java.Lang.NoSuchMethodError) { throw new Java.Lang.AbstractMethodError (__id); }".NormalizeLineEndings ()), $"was: `{writer}`");
}
+
+ [Test]
+ public void FixDefaultInterfaceMethodStackOverflow ()
+ {
+ // The bug was that this causes a stack overflow, but this also tests
+ // that the OverriddenInterfaceMethod is now correctly set in the interface method.
+ var xml = """
+
+
+
+
+
+
+
+
+
+
+ """;
+
+ var gens = ParseApiDefinition (xml);
+
+ foreach (var iface in gens.OfType ()) {
+ generator.Context.ContextTypes.Push (iface);
+ generator.WriteType (iface, string.Empty, new GenerationInfo ("", "", "MyAssembly"));
+ generator.Context.ContextTypes.Pop ();
+ }
+
+ var klass1 = gens.Single (g => g.Name == "IInternalConfigurator");
+ var klass2 = gens.Single (g => g.Name == "IConfigurator");
+
+ Assert.AreEqual (1, klass1.Methods.Count);
+ Assert.AreEqual (1, klass2.Methods.Count);
+
+ Assert.AreNotSame (klass1.Methods [0], klass2.Methods [0]);
+ Assert.AreSame (klass1.Methods [0].OverriddenInterfaceMethod, klass2.Methods [0]);
+ }
}
}
diff --git a/tests/generator-Tests/expected.ji/AccessModifiers/Xamarin.Test.IExtendedInterface.cs b/tests/generator-Tests/expected.ji/AccessModifiers/Xamarin.Test.IExtendedInterface.cs
index 3ea50e6bd..83d01f24a 100644
--- a/tests/generator-Tests/expected.ji/AccessModifiers/Xamarin.Test.IExtendedInterface.cs
+++ b/tests/generator-Tests/expected.ji/AccessModifiers/Xamarin.Test.IExtendedInterface.cs
@@ -11,7 +11,7 @@ public partial interface IExtendedInterface : IJavaPeerable {
[global::Java.Interop.JniMethodSignature ("extendedMethod", "()V")]
void ExtendedMethod ();
- // Metadata.xml XPath method reference: path="/api/package[@name='xamarin.test']/interface[@name='BaseInterface']/method[@name='baseMethod' and count(parameter)=0]"
+ // Metadata.xml XPath method reference: path="/api/package[@name='xamarin.test']/interface[@name='ExtendedInterface']/method[@name='baseMethod' and count(parameter)=0]"
[global::Java.Interop.JniMethodSignature ("baseMethod", "()V")]
void BaseMethod ();
@@ -46,7 +46,7 @@ public unsafe void BaseMethod ()
{
const string __id = "baseMethod.()V";
try {
- _members_xamarin_test_BaseInterface.InstanceMethods.InvokeAbstractVoidMethod (__id, this, null);
+ _members_xamarin_test_ExtendedInterface.InstanceMethods.InvokeAbstractVoidMethod (__id, this, null);
} finally {
}
}
diff --git a/tests/generator-Tests/expected.xaji/AccessModifiers/Xamarin.Test.IExtendedInterface.cs b/tests/generator-Tests/expected.xaji/AccessModifiers/Xamarin.Test.IExtendedInterface.cs
index 04ab7fd4f..b569b5075 100644
--- a/tests/generator-Tests/expected.xaji/AccessModifiers/Xamarin.Test.IExtendedInterface.cs
+++ b/tests/generator-Tests/expected.xaji/AccessModifiers/Xamarin.Test.IExtendedInterface.cs
@@ -12,7 +12,7 @@ public partial interface IExtendedInterface : IJavaObject, IJavaPeerable {
[Register ("extendedMethod", "()V", "GetExtendedMethodHandler:Xamarin.Test.IExtendedInterfaceInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null")]
void ExtendedMethod ();
- // Metadata.xml XPath method reference: path="/api/package[@name='xamarin.test']/interface[@name='BaseInterface']/method[@name='baseMethod' and count(parameter)=0]"
+ // Metadata.xml XPath method reference: path="/api/package[@name='xamarin.test']/interface[@name='ExtendedInterface']/method[@name='baseMethod' and count(parameter)=0]"
[Register ("baseMethod", "()V", "GetBaseMethodHandler:Xamarin.Test.IExtendedInterfaceInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null")]
void BaseMethod ();
@@ -95,7 +95,7 @@ public unsafe void BaseMethod ()
{
const string __id = "baseMethod.()V";
try {
- _members_xamarin_test_BaseInterface.InstanceMethods.InvokeAbstractVoidMethod (__id, this, null);
+ _members_xamarin_test_ExtendedInterface.InstanceMethods.InvokeAbstractVoidMethod (__id, this, null);
} finally {
}
}
diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/InterfaceGen.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/InterfaceGen.cs
index f86750e54..7f36d0cff 100644
--- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/InterfaceGen.cs
+++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/InterfaceGen.cs
@@ -69,8 +69,9 @@ public override void FixupAccessModifiers (CodeGenerationOptions opt)
var baseType = opt.SymbolTable.Lookup (implementedInterface);
if (baseType is InterfaceGen interfaceGen && interfaceGen.RawVisibility != "public") {
// Copy over "private" methods
- interfaceGen.Methods.Where (m => !Methods.Contains (m)).ToList ().ForEach (Methods.Add);
-
+ foreach (var method in interfaceGen.Methods.ToList ())
+ if (!Methods.Any (m => m.Matches (method)))
+ Methods.Add (method.Clone (this));
} else {
break;
}
diff --git a/tools/jnimarshalmethod-gen/App.cs b/tools/jnimarshalmethod-gen/App.cs
index 6771fc452..7479706e3 100644
--- a/tools/jnimarshalmethod-gen/App.cs
+++ b/tools/jnimarshalmethod-gen/App.cs
@@ -786,8 +786,12 @@ public static bool NeedsMarshalMethod (this MethodDefinition md, DirectoryAssemb
if (iface.IsGenericType)
continue;
+ var location = iface.Assembly.Location;
+ var ad = string.IsNullOrEmpty (location)
+ ? resolver.Resolve (iface.Assembly.GetName ().Name)
+ : resolver.GetAssembly (location);
+
var ifaceMap = method.DeclaringType.GetInterfaceMap (iface);
- var ad = resolver.GetAssembly (iface.Assembly.Location);
var id = ad.MainModule.GetType (iface.GetCecilName ());
if (id == null) {