From f7ed6fcecf39d1b51bc5ff04dee79c0e570ffd75 Mon Sep 17 00:00:00 2001 From: Jonathan Pobst Date: Mon, 11 May 2020 10:34:03 -0500 Subject: [PATCH] [generator] Honor 'api-since' element to fill ApiAvailableSince property. --- .../Unit-Tests/XmlApiImporterTests.cs | 126 +++++++++++++++++- tests/generator-Tests/Unit-Tests/XmlTests.cs | 2 +- .../XmlApiImporter.cs | 33 ++++- 3 files changed, 153 insertions(+), 8 deletions(-) diff --git a/tests/generator-Tests/Unit-Tests/XmlApiImporterTests.cs b/tests/generator-Tests/Unit-Tests/XmlApiImporterTests.cs index c30cbae94..b0d6f3f49 100644 --- a/tests/generator-Tests/Unit-Tests/XmlApiImporterTests.cs +++ b/tests/generator-Tests/Unit-Tests/XmlApiImporterTests.cs @@ -19,6 +19,35 @@ public void CreateClass_EnsureValidName () Assert.AreEqual ("_3", klass.Name); } + [Test] + public void CreateClass_CorrectApiSince () + { + var xml = XDocument.Parse (""); + var klass = XmlApiImporter.CreateClass (xml.Root, xml.Root.Element ("class"), opt); + + Assert.AreEqual (7, klass.ApiAvailableSince); + } + + [Test] + public void CreateClass_CorrectApiSinceFromPackage () + { + // Make sure we inherit it from . + var xml = XDocument.Parse (""); + var klass = XmlApiImporter.CreateClass (xml.Root, xml.Root.Element ("class"), opt); + + Assert.AreEqual (7, klass.ApiAvailableSince); + } + + [Test] + public void CreateClass_CorrectApiSinceOverridePackage () + { + // Make sure we inherit it from . + var xml = XDocument.Parse (""); + var klass = XmlApiImporter.CreateClass (xml.Root, xml.Root.Element ("class"), opt); + + Assert.AreEqual (9, klass.ApiAvailableSince); + } + [Test] public void CreateCtor_EnsureValidName () { @@ -28,11 +57,30 @@ public void CreateCtor_EnsureValidName () Assert.AreEqual ("_3", klass.Ctors[0].Name); } + [Test] + public void CreateCtor_CorrectApiSince () + { + var xml = XDocument.Parse (""); + var klass = XmlApiImporter.CreateClass (xml.Root, xml.Root.Element ("class"), opt); + + Assert.AreEqual (7, klass.Ctors [0].ApiAvailableSince); + } + + [Test] + public void CreateCtor_CorrectApiSinceFromClass () + { + var xml = XDocument.Parse (""); + var klass = XmlApiImporter.CreateClass (xml.Root, xml.Root.Element ("class"), opt); + + Assert.AreEqual (7, klass.Ctors [0].ApiAvailableSince); + } + [Test] public void CreateField_StudlyCaseName () { + var klass = new TestClass ("object", "MyNamespace.MyType"); var xml = XDocument.Parse (""); - var field = XmlApiImporter.CreateField (xml.Root); + var field = XmlApiImporter.CreateField (klass, xml.Root); Assert.AreEqual ("DesEdeCbc", field.Name); } @@ -40,8 +88,9 @@ public void CreateField_StudlyCaseName () [Test] public void CreateField_EnsureValidName () { + var klass = new TestClass ("object", "MyNamespace.MyType"); var xml = XDocument.Parse (""); - var field = XmlApiImporter.CreateField (xml.Root); + var field = XmlApiImporter.CreateField (klass, xml.Root); Assert.AreEqual ("_3desEdeCbc", field.Name); } @@ -49,8 +98,9 @@ public void CreateField_EnsureValidName () [Test] public void CreateField_HandleDollarSign () { + var klass = new TestClass ("object", "MyNamespace.MyType"); var xml = XDocument.Parse (""); - var field = XmlApiImporter.CreateField (xml.Root); + var field = XmlApiImporter.CreateField (klass, xml.Root); Assert.AreEqual ("A_3", field.Name); } @@ -58,12 +108,33 @@ public void CreateField_HandleDollarSign () [Test] public void CreateField_HandleDollarSignNumber () { + var klass = new TestClass ("object", "MyNamespace.MyType"); var xml = XDocument.Parse (""); - var field = XmlApiImporter.CreateField (xml.Root); + var field = XmlApiImporter.CreateField (klass, xml.Root); Assert.AreEqual ("_3", field.Name); } + [Test] + public void CreateField_CorrectApiVersion () + { + var klass = new TestClass ("object", "MyNamespace.MyType"); + var xml = XDocument.Parse (""); + var field = XmlApiImporter.CreateField (klass, xml.Root); + + Assert.AreEqual (7, field.ApiAvailableSince); + } + + [Test] + public void CreateField_CorrectApiVersionFromClass () + { + var klass = new TestClass ("object", "MyNamespace.MyType") { ApiAvailableSince = 7 }; + var xml = XDocument.Parse (""); + var field = XmlApiImporter.CreateField (klass, xml.Root); + + Assert.AreEqual (7, field.ApiAvailableSince); + } + [Test] public void CreateInterface_EnsureValidName () { @@ -73,6 +144,35 @@ public void CreateInterface_EnsureValidName () Assert.AreEqual ("I_3", iface.Name); } + [Test] + public void CreateInterface_CorrectApiSince () + { + var xml = XDocument.Parse (""); + var iface = XmlApiImporter.CreateClass (xml.Root, xml.Root.Element ("interface"), opt); + + Assert.AreEqual (7, iface.ApiAvailableSince); + } + + [Test] + public void CreateInterface_CorrectApiSinceFromPackage () + { + // Make sure we inherit it from . + var xml = XDocument.Parse (""); + var iface = XmlApiImporter.CreateClass (xml.Root, xml.Root.Element ("interface"), opt); + + Assert.AreEqual (7, iface.ApiAvailableSince); + } + + [Test] + public void CreateInterface_CorrectApiSinceOverridePackage () + { + // Make sure we inherit it from . + var xml = XDocument.Parse (""); + var iface = XmlApiImporter.CreateInterface (xml.Root, xml.Root.Element ("interface"), opt); + + Assert.AreEqual (9, iface.ApiAvailableSince); + } + [Test] public void CreateMethod_EnsureValidName () { @@ -91,6 +191,24 @@ public void CreateMethod_EnsureValidNameHyphen () Assert.AreEqual ("_3", klass.Methods [0].Name); } + [Test] + public void CreateMethod_CorrectApiSince () + { + var xml = XDocument.Parse (""); + var klass = XmlApiImporter.CreateClass (xml.Root, xml.Root.Element ("class"), opt); + + Assert.AreEqual (7, klass.Methods [0].ApiAvailableSince); + } + + [Test] + public void CreateMethod_CorrectApiSinceFromClass () + { + var xml = XDocument.Parse (""); + var klass = XmlApiImporter.CreateClass (xml.Root, xml.Root.Element ("class"), opt); + + Assert.AreEqual (7, klass.Methods [0].ApiAvailableSince); + } + [Test] public void CreateParameter_EnsureValidName () { diff --git a/tests/generator-Tests/Unit-Tests/XmlTests.cs b/tests/generator-Tests/Unit-Tests/XmlTests.cs index 878d7511f..44a1b55dc 100644 --- a/tests/generator-Tests/Unit-Tests/XmlTests.cs +++ b/tests/generator-Tests/Unit-Tests/XmlTests.cs @@ -171,7 +171,7 @@ public void Field () { var element = package.Element ("class"); var @class = XmlApiImporter.CreateClass (package, element, options); - var field = XmlApiImporter.CreateField (element.Element ("field")); + var field = XmlApiImporter.CreateField (@class, element.Element ("field")); Assert.IsTrue (field.Validate (options, new GenericParameterDefinitionList (), new CodeGeneratorContext ()), "field.Validate failed!"); Assert.AreEqual ("Value", field.Name); diff --git a/tools/generator/Java.Interop.Tools.Generator.Importers/XmlApiImporter.cs b/tools/generator/Java.Interop.Tools.Generator.Importers/XmlApiImporter.cs index fbbc562b2..f35afe4c5 100644 --- a/tools/generator/Java.Interop.Tools.Generator.Importers/XmlApiImporter.cs +++ b/tools/generator/Java.Interop.Tools.Generator.Importers/XmlApiImporter.cs @@ -25,6 +25,8 @@ public static ClassGen CreateClass (XElement pkg, XElement elem, CodeGenerationO !options.SupportNestedInterfaceTypes }; + FillApiSince (klass, pkg, elem); + foreach (var child in elem.Elements ()) { switch (child.Name.LocalName) { case "implements": @@ -39,7 +41,7 @@ public static ClassGen CreateClass (XElement pkg, XElement elem, CodeGenerationO klass.Ctors.Add (CreateCtor (klass, child)); break; case "field": - klass.AddField (CreateField (child)); + klass.AddField (CreateField (klass, child)); break; case "typeParameters": break; // handled at GenBaseSupport @@ -55,6 +57,7 @@ public static ClassGen CreateClass (XElement pkg, XElement elem, CodeGenerationO public static Ctor CreateCtor (GenBase declaringType, XElement elem) { var ctor = new Ctor (declaringType) { + ApiAvailableSince = declaringType.ApiAvailableSince, CustomAttributes = elem.XGetAttribute ("customAttributes"), Deprecated = elem.Deprecated (), GenericArguments = elem.GenericArguments (), @@ -90,12 +93,15 @@ public static Ctor CreateCtor (GenBase declaringType, XElement elem) ctor.Name = EnsureValidIdentifer (ctor.Name); + FillApiSince (ctor, elem); + return ctor; } - public static Field CreateField (XElement elem) + public static Field CreateField (GenBase declaringType, XElement elem) { var field = new Field { + ApiAvailableSince = declaringType.ApiAvailableSince, DeprecatedComment = elem.XGetAttribute ("deprecated"), IsAcw = true, IsDeprecated = elem.XGetAttribute ("deprecated") != "not deprecated", @@ -124,6 +130,8 @@ public static Field CreateField (XElement elem) field.Name = EnsureValidIdentifer (field.Name); } + FillApiSince (field, elem); + return field; } @@ -205,6 +213,8 @@ public static InterfaceGen CreateInterface (XElement pkg, XElement elem, CodeGen !options.SupportNestedInterfaceTypes }; + FillApiSince (iface, pkg, elem); + foreach (var child in elem.Elements ()) { switch (child.Name.LocalName) { case "implements": @@ -216,7 +226,7 @@ public static InterfaceGen CreateInterface (XElement pkg, XElement elem, CodeGen iface.AddMethod (CreateMethod (iface, child)); break; case "field": - iface.AddField (CreateField (child)); + iface.AddField (CreateField (iface, child)); break; case "typeParameters": break; // handled at GenBaseSupport @@ -232,6 +242,7 @@ public static InterfaceGen CreateInterface (XElement pkg, XElement elem, CodeGen public static Method CreateMethod (GenBase declaringType, XElement elem) { var method = new Method (declaringType) { + ApiAvailableSince = declaringType.ApiAvailableSince, ArgsType = elem.Attribute ("argsType")?.Value, CustomAttributes = elem.XGetAttribute ("customAttributes"), Deprecated = elem.Deprecated (), @@ -279,6 +290,8 @@ public static Method CreateMethod (GenBase declaringType, XElement elem) method.FillReturnType (); + FillApiSince (method, elem); + return method; } @@ -350,6 +363,20 @@ static XElement GetPreviousClass (XNode n, string nameValue) return e; } + // The array here allows members to inherit defaults from their parent, but + // override them if they were added later. + // For example: + // - + // - + // - + // Elements need to be passed in the above order. (package, class, member) + static void FillApiSince (ApiVersionsSupport.IApiAvailability model, params XElement[] elems) + { + foreach (var elem in elems) + if (int.TryParse (elem.XGetAttribute ("api-since"), out var result)) + model.ApiAvailableSince = result; + } + static bool IsObfuscatedName (int threshold, string name) { if (name.StartsWith ("R.", StringComparison.Ordinal))