diff --git a/tests/generator-Tests/Unit-Tests/KotlinFixupsTests.cs b/tests/generator-Tests/Unit-Tests/KotlinFixupsTests.cs
new file mode 100644
index 000000000..1e4c90081
--- /dev/null
+++ b/tests/generator-Tests/Unit-Tests/KotlinFixupsTests.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Linq;
+using System.Xml.Linq;
+using Java.Interop.Tools.Generator.Transformation;
+using MonoDroid.Generation;
+using NUnit.Framework;
+
+namespace generatortests
+{
+ [TestFixture]
+ public class KotlinFixupsTests
+ {
+ [Test]
+ public void CreateMethod_EnsureKotlinImplFix ()
+ {
+ var xml = XDocument.Parse ("");
+ var klass = XmlApiImporter.CreateClass (xml.Root, xml.Root.Element ("class"));
+
+ KotlinFixups.Fixup (new [] { (GenBase)klass }.ToList ());
+
+ Assert.AreEqual ("Add", klass.Methods [0].Name);
+ Assert.IsTrue (klass.Methods [0].IsFinal);
+ Assert.IsFalse (klass.Methods [0].IsVirtual);
+ }
+
+ [Test]
+ public void CreateMethod_EnsureKotlinHashcodeFix ()
+ {
+ var xml = XDocument.Parse ("");
+ var klass = XmlApiImporter.CreateClass (xml.Root, xml.Root.Element ("class"));
+
+ KotlinFixups.Fixup (new [] { (GenBase) klass }.ToList ());
+
+ Assert.AreEqual ("Add", klass.Methods [0].Name);
+ Assert.IsTrue (klass.Methods [0].IsFinal);
+ Assert.IsFalse (klass.Methods [0].IsVirtual);
+ }
+ }
+}
diff --git a/tests/generator-Tests/Unit-Tests/XmlApiImporterTests.cs b/tests/generator-Tests/Unit-Tests/XmlApiImporterTests.cs
index a7681be26..c8161224a 100644
--- a/tests/generator-Tests/Unit-Tests/XmlApiImporterTests.cs
+++ b/tests/generator-Tests/Unit-Tests/XmlApiImporterTests.cs
@@ -89,24 +89,6 @@ public void CreateMethod_EnsureValidNameHyphen ()
Assert.AreEqual ("_3", klass.Methods [0].Name);
}
- [Test]
- public void CreateMethod_EnsureKotlinImplFix ()
- {
- var xml = XDocument.Parse ("");
- var klass = XmlApiImporter.CreateClass (xml.Root, xml.Root.Element ("class"));
-
- Assert.AreEqual ("Add", klass.Methods [0].Name);
- }
-
- [Test]
- public void CreateMethod_EnsureKotlinHashcodeFix ()
- {
- var xml = XDocument.Parse ("");
- var klass = XmlApiImporter.CreateClass (xml.Root, xml.Root.Element ("class"));
-
- Assert.AreEqual ("Add", klass.Methods [0].Name);
- }
-
[Test]
public void CreateParameter_EnsureValidName ()
{
diff --git a/tools/generator/CodeGenerator.cs b/tools/generator/CodeGenerator.cs
index 65b795f60..11d3f5409 100644
--- a/tools/generator/CodeGenerator.cs
+++ b/tools/generator/CodeGenerator.cs
@@ -12,6 +12,7 @@
using Java.Interop.Tools.Diagnostics;
using Java.Interop.Tools.TypeNameMappings;
using MonoDroid.Generation.Utilities;
+using Java.Interop.Tools.Generator.Transformation;
namespace Xamarin.Android.Binder
{
@@ -149,6 +150,9 @@ static void Run (CodeGeneratorOptions options, DirectoryAssemblyResolver resolve
AddTypeToTable (opt, gen);
}
+ // Apply fixups
+ KotlinFixups.Fixup (gens);
+
Validate (gens, opt, new CodeGeneratorContext ());
if (api_versions_xml != null)
diff --git a/tools/generator/Java.Interop.Tools.Generator.Importers/XmlApiImporter.cs b/tools/generator/Java.Interop.Tools.Generator.Importers/XmlApiImporter.cs
index cac352a55..7e4609645 100644
--- a/tools/generator/Java.Interop.Tools.Generator.Importers/XmlApiImporter.cs
+++ b/tools/generator/Java.Interop.Tools.Generator.Importers/XmlApiImporter.cs
@@ -245,25 +245,8 @@ public static Method CreateMethod (GenBase declaringType, XElement elem)
if (elem.Attribute ("managedName") != null)
method.Name = elem.XGetAttribute ("managedName");
- else {
- var name = method.JavaName;
-
- // Kotlin generates methods that cannot be referenced in Java,
- // like `add-impl` and `add-V5j3Lk8`. We mangle them back into
- // something a user would expect by truncating anything after the hyphen.
- var index = name.IndexOf ("-impl");
-
- if (index >= 0)
- name = name.Substring (0, index);
-
- index = name.IndexOf ('-');
-
- // `add-V5j3Lk8` is always a 7 character hashcode
- if (index >= 0 && name.Length - index == 8)
- name = name.Substring (0, index);
-
- method.Name = StringRocks.MemberToPascalCase (name);
- }
+ else
+ method.Name = StringRocks.MemberToPascalCase (method.JavaName);
if (method.IsReturnEnumified) {
method.ManagedReturn = elem.XGetAttribute ("enumReturn");
diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/MethodBase.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/MethodBase.cs
index d77cccc67..4a738d501 100644
--- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/MethodBase.cs
+++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/MethodBase.cs
@@ -79,6 +79,24 @@ public string GetSignature (CodeGenerationOptions opt)
public virtual bool IsGeneric => Parameters.HasGeneric;
+ public bool IsKotlinNameMangled {
+ get {
+ // Kotlin generates methods that cannot be referenced in Java,
+ // like `add-impl` and `add-V5j3Lk8`. We will need to fix those later.
+ if (this is Method method) {
+ if (method.JavaName.IndexOf ("-impl") >= 0)
+ return true;
+
+ var index = method.JavaName.IndexOf ('-');
+
+ // `add-V5j3Lk8` is always a 7 character hashcode
+ return index >= 0 && method.JavaName.Length - index == 8;
+ }
+
+ return false;
+ }
+ }
+
public virtual bool Matches (MethodBase other)
{
if (Name != other.Name)
diff --git a/tools/generator/Java.Interop.Tools.Generator.Transformation/KotlinFixups.cs b/tools/generator/Java.Interop.Tools.Generator.Transformation/KotlinFixups.cs
new file mode 100644
index 000000000..fc901fc5c
--- /dev/null
+++ b/tools/generator/Java.Interop.Tools.Generator.Transformation/KotlinFixups.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using MonoDroid.Generation;
+using MonoDroid.Utils;
+
+namespace Java.Interop.Tools.Generator.Transformation
+{
+ public static class KotlinFixups
+ {
+ public static void Fixup (List gens)
+ {
+ foreach (var c in gens.OfType ())
+ FixupClass (c);
+ }
+
+ private static void FixupClass (ClassGen c)
+ {
+ // Kotlin mangles the name of some methods to make them
+ // inaccessible from Java, like `add-impl` and `add-V5j3Lk8`.
+ // We need to generate C# compatible names as well as prevent overriding
+ // them as we cannot generate JCW for them.
+ var invalid_methods = c.Methods.Where (m => m.IsKotlinNameMangled).ToList ();
+
+ foreach (var method in invalid_methods) {
+
+ // If the method is virtual, mark it as !virtual as it can't be overridden in Java
+ if (!method.IsFinal)
+ method.IsFinal = true;
+
+ if (method.IsVirtual)
+ method.IsVirtual = false;
+
+ // Only run this if it's the default name (ie: not a user's "managedName")
+ if (method.Name == StringRocks.MemberToPascalCase (method.JavaName).Replace ('-', '_')) {
+ // We want to remove the hyphen and anything afterwards to fix mangled names,
+ // but a previous step converted it to an underscore. Remove the final
+ // underscore and anything after it.
+ var index = method.Name.LastIndexOf ('_');
+
+ method.Name = method.Name.Substring (0, index);
+ }
+ }
+ }
+ }
+}
diff --git a/tools/generator/generator.csproj b/tools/generator/generator.csproj
index 30c8d16bd..9b3f96404 100644
--- a/tools/generator/generator.csproj
+++ b/tools/generator/generator.csproj
@@ -104,6 +104,7 @@
+