From b487b5c2f99e426217c62850d57b6ff69734095a Mon Sep 17 00:00:00 2001 From: Jonathan Pobst Date: Thu, 7 Jul 2022 09:23:05 -0500 Subject: [PATCH] [generator] Add support for @explicitInterface metadata. --- .../Unit-Tests/CodeGeneratorTests.cs | 150 ++++++++++++++++++ .../XmlApiImporter.cs | 1 + .../Method.cs | 1 + .../Property.cs | 2 + .../SourceWriters/BoundAbstractProperty.cs | 1 + .../BoundInterfaceMethodDeclaration.cs | 2 + .../BoundInterfacePropertyDeclaration.cs | 1 + tools/generator/SourceWriters/BoundMethod.cs | 4 + .../BoundMethodAbstractDeclaration.cs | 1 + .../generator/SourceWriters/BoundProperty.cs | 1 + 10 files changed, 164 insertions(+) diff --git a/tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs b/tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs index d2a335a4d..b8b6137ac 100644 --- a/tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs +++ b/tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs @@ -352,6 +352,156 @@ public void InheritedInterfaceAsClass () Assert.Pass ("WriteType did not NRE"); } + + [Test] + public void ExplicitInterfaceMetadata_InterfaceMethod () + { + var xml = @" + + + + + + + + + "; + + var gens = ParseApiDefinition (xml); + var iface = gens.Single (g => g.Name == "IMyInterface"); + + generator.Context.ContextTypes.Push (iface); + generator.WriteType (iface, string.Empty, new GenerationInfo ("", "", "MyAssembly")); + generator.Context.ContextTypes.Pop (); + + // Ensure explicit interface was written + Assert.True (writer.ToString ().Contains ("int IRowCounter.CountAffectedRows ("), $"was: `{writer}`"); + } + + [Test] + public void ExplicitInterfaceMetadata_InterfaceProperty () + { + var xml = @" + + + + + + + + + "; + + var gens = ParseApiDefinition (xml); + var iface = gens.Single (g => g.Name == "IMyInterface"); + + generator.Context.ContextTypes.Push (iface); + generator.WriteType (iface, string.Empty, new GenerationInfo ("", "", "MyAssembly")); + generator.Context.ContextTypes.Pop (); + + // Ensure explicit interface was written + Assert.True (writer.ToString ().Contains ("int IHasAge.Age {"), $"was: `{writer}`"); + } + + [Test] + public void ExplicitInterfaceMetadata_ClassMethod () + { + var xml = @" + + + + + + + + + "; + + var gens = ParseApiDefinition (xml); + var iface = gens.Single (g => g.Name == "MyClass"); + + generator.Context.ContextTypes.Push (iface); + generator.WriteType (iface, string.Empty, new GenerationInfo ("", "", "MyAssembly")); + generator.Context.ContextTypes.Pop (); + + // Ensure explicit interface was written + Assert.True (writer.ToString ().Contains ("int IRowCounter.CountAffectedRows ("), $"was: `{writer}`"); + } + + [Test] + public void ExplicitInterfaceMetadata_ClassProperty () + { + var xml = @" + + + + + + + + + "; + + var gens = ParseApiDefinition (xml); + var iface = gens.Single (g => g.Name == "MyClass"); + + generator.Context.ContextTypes.Push (iface); + generator.WriteType (iface, string.Empty, new GenerationInfo ("", "", "MyAssembly")); + generator.Context.ContextTypes.Pop (); + + // Ensure explicit interface was written + Assert.True (writer.ToString ().Contains ("int IHasAge.Age {"), $"was: `{writer}`"); + } + + [Test] + public void ExplicitInterfaceMetadata_AbstractClassMethod () + { + var xml = @" + + + + + + + + + "; + + var gens = ParseApiDefinition (xml); + var iface = gens.Single (g => g.Name == "MyClass"); + + generator.Context.ContextTypes.Push (iface); + generator.WriteType (iface, string.Empty, new GenerationInfo ("", "", "MyAssembly")); + generator.Context.ContextTypes.Pop (); + + // Ensure explicit interface was written + Assert.True (writer.ToString ().Contains ("abstract int IRowCounter.CountAffectedRows ("), $"was: `{writer}`"); + } + + [Test] + public void ExplicitInterfaceMetadata_AbstractClassProperty () + { + var xml = @" + + + + + + + + + "; + + var gens = ParseApiDefinition (xml); + var iface = gens.Single (g => g.Name == "MyClass"); + + generator.Context.ContextTypes.Push (iface); + generator.WriteType (iface, string.Empty, new GenerationInfo ("", "", "MyAssembly")); + generator.Context.ContextTypes.Pop (); + + // Ensure explicit interface was written + Assert.True (writer.ToString ().Contains ("abstract int IHasAge.Age {"), $"was: `{writer}`"); + } } [TestFixture] diff --git a/tools/generator/Java.Interop.Tools.Generator.Importers/XmlApiImporter.cs b/tools/generator/Java.Interop.Tools.Generator.Importers/XmlApiImporter.cs index 3c80a0c25..fbca66cee 100644 --- a/tools/generator/Java.Interop.Tools.Generator.Importers/XmlApiImporter.cs +++ b/tools/generator/Java.Interop.Tools.Generator.Importers/XmlApiImporter.cs @@ -348,6 +348,7 @@ public static Method CreateMethod (GenBase declaringType, XElement elem, CodeGen ArgsType = elem.Attribute ("argsType")?.Value, CustomAttributes = elem.XGetAttribute ("customAttributes"), Deprecated = elem.Deprecated (), + ExplicitInterface = elem.XGetAttribute ("explicitInterface"), EventName = elem.Attribute ("eventName")?.Value, GenerateAsyncWrapper = elem.Attribute ("generateAsyncWrapper") != null, GenerateDispatchingSetter = elem.Attribute ("generateDispatchingSetter") != null, diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Method.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Method.cs index c78ca6af7..bae3faf1f 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Method.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Method.cs @@ -33,6 +33,7 @@ public Method (GenBase declaringType) : base (declaringType) public bool ReturnNotNull { get; set; } public ReturnValue RetVal { get; set; } public int SourceApiLevel { get; set; } + public string ExplicitInterface { get; set; } // it used to be private though... internal string AdjustedName => IsReturnCharSequence ? Name + "Formatted" : Name; diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Property.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Property.cs index 591002361..57b4b59a8 100644 --- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Property.cs +++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Property.cs @@ -58,5 +58,7 @@ public void AutoDetectEnumifiedOverrideProperties (AncestorDescendantCache cache } } } + + public string ExplicitInterface => Getter?.ExplicitInterface ?? Setter?.ExplicitInterface; } } diff --git a/tools/generator/SourceWriters/BoundAbstractProperty.cs b/tools/generator/SourceWriters/BoundAbstractProperty.cs index fcade1968..7e0985528 100644 --- a/tools/generator/SourceWriters/BoundAbstractProperty.cs +++ b/tools/generator/SourceWriters/BoundAbstractProperty.cs @@ -19,6 +19,7 @@ public class BoundAbstractProperty : PropertyWriter public BoundAbstractProperty (GenBase gen, Property property, CodeGenerationOptions opt) { Name = property.AdjustedName; + ExplicitInterfaceImplementation = property.ExplicitInterface; PropertyType = new TypeReferenceWriter (opt.GetTypeReferenceName (property.Getter.RetVal)); SetVisibility (property.Getter.RetVal.IsGeneric ? "protected" : property.Getter.Visibility); diff --git a/tools/generator/SourceWriters/BoundInterfaceMethodDeclaration.cs b/tools/generator/SourceWriters/BoundInterfaceMethodDeclaration.cs index 02cdece3e..5e529e7e3 100644 --- a/tools/generator/SourceWriters/BoundInterfaceMethodDeclaration.cs +++ b/tools/generator/SourceWriters/BoundInterfaceMethodDeclaration.cs @@ -22,6 +22,8 @@ public BoundInterfaceMethodDeclaration (Method method, string adapter, CodeGener this.opt = opt; Name = method.AdjustedName; + ExplicitInterfaceImplementation = method.ExplicitInterface; + ReturnType = new TypeReferenceWriter (opt.GetTypeReferenceName (method.RetVal)); IsDeclaration = true; diff --git a/tools/generator/SourceWriters/BoundInterfacePropertyDeclaration.cs b/tools/generator/SourceWriters/BoundInterfacePropertyDeclaration.cs index d80956f9b..1031b197a 100644 --- a/tools/generator/SourceWriters/BoundInterfacePropertyDeclaration.cs +++ b/tools/generator/SourceWriters/BoundInterfacePropertyDeclaration.cs @@ -16,6 +16,7 @@ public class BoundInterfacePropertyDeclaration : PropertyWriter public BoundInterfacePropertyDeclaration (GenBase gen, Property property, string adapter, CodeGenerationOptions opt) { Name = property.AdjustedName; + ExplicitInterfaceImplementation = property.ExplicitInterface; PropertyType = new TypeReferenceWriter (opt.GetTypeReferenceName (property)); IsAutoProperty = true; diff --git a/tools/generator/SourceWriters/BoundMethod.cs b/tools/generator/SourceWriters/BoundMethod.cs index eb153b296..a6ddf53b9 100644 --- a/tools/generator/SourceWriters/BoundMethod.cs +++ b/tools/generator/SourceWriters/BoundMethod.cs @@ -48,6 +48,10 @@ public BoundMethod (GenBase type, Method method, CodeGenerationOptions opt, bool if (is_explicit) ExplicitInterfaceImplementation = GetDeclaringTypeOfExplicitInterfaceMethod (method.OverriddenInterfaceMethod); + // Allow user to override our explicit interface logic + if (method.ExplicitInterface.HasValue ()) + ExplicitInterfaceImplementation = method.ExplicitInterface; + if ((IsVirtual || !IsOverride) && type.RequiresNew (method.AdjustedName, method)) IsShadow = true; diff --git a/tools/generator/SourceWriters/BoundMethodAbstractDeclaration.cs b/tools/generator/SourceWriters/BoundMethodAbstractDeclaration.cs index 2957662ea..2bdde787e 100644 --- a/tools/generator/SourceWriters/BoundMethodAbstractDeclaration.cs +++ b/tools/generator/SourceWriters/BoundMethodAbstractDeclaration.cs @@ -36,6 +36,7 @@ public BoundMethodAbstractDeclaration (GenBase gen, Method method, CodeGeneratio } Name = method.AdjustedName; + ExplicitInterfaceImplementation = method.ExplicitInterface; IsAbstract = true; IsShadow = impl.RequiresNew (method.Name, method); diff --git a/tools/generator/SourceWriters/BoundProperty.cs b/tools/generator/SourceWriters/BoundProperty.cs index 0df7ca1b9..7804d9bc1 100644 --- a/tools/generator/SourceWriters/BoundProperty.cs +++ b/tools/generator/SourceWriters/BoundProperty.cs @@ -19,6 +19,7 @@ public class BoundProperty : PropertyWriter public BoundProperty (GenBase gen, Property property, CodeGenerationOptions opt, bool withCallbacks = true, bool forceOverride = false) { Name = property.AdjustedName; + ExplicitInterfaceImplementation = property.ExplicitInterface; PropertyType = new TypeReferenceWriter (opt.GetTypeReferenceName (property.Getter.RetVal)); SetVisibility (gen is InterfaceGen ? string.Empty : property.Getter.IsAbstract && property.Getter.RetVal.IsGeneric ? "protected" : (property.Setter ?? property.Getter).Visibility);