From c2f4169d3e69c4c9353091946afb13e1981fd6a9 Mon Sep 17 00:00:00 2001 From: Jonathan Pobst Date: Mon, 12 Dec 2022 09:21:41 -0600 Subject: [PATCH] [generator] Support [Obsolete]/[SupportedOSPlatform] attributes for enum members. --- .../Unit-Tests/EnumGeneratorTests.cs | 87 +++++++++++++++++-- .../EnumGenerator.cs | 29 ++++--- .../Extensions/SourceWriterExtensions.cs | 8 +- 3 files changed, 103 insertions(+), 21 deletions(-) diff --git a/tests/generator-Tests/Unit-Tests/EnumGeneratorTests.cs b/tests/generator-Tests/Unit-Tests/EnumGeneratorTests.cs index 0e870a88b..3053258ff 100644 --- a/tests/generator-Tests/Unit-Tests/EnumGeneratorTests.cs +++ b/tests/generator-Tests/Unit-Tests/EnumGeneratorTests.cs @@ -1,24 +1,26 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Reflection; using System.Text; using Java.Interop.Tools.Generator.Enumification; using MonoDroid.Generation; using NUnit.Framework; using NUnit.Framework.Internal; +using Xamarin.Android.Binder; namespace generatortests { [TestFixture] - class EnumGeneratorTests + class EnumGeneratorTests : CodeGeneratorTestBase { - protected EnumGenerator generator; - protected StringBuilder builder; - protected StringWriter writer; + protected new EnumGenerator generator; + + protected override CodeGenerationTarget Target => CodeGenerationTarget.XAJavaInterop1; [SetUp] - public void SetUp () + public new void SetUp () { builder = new StringBuilder (); writer = new StringWriter (builder); @@ -60,7 +62,78 @@ public void WriteEnumWithGens () Assert.AreEqual (GetExpected (nameof (WriteEnumWithGens)), writer.ToString ().NormalizeLineEndings ()); } - protected string GetExpected (string testName) + [Test] + public void ObsoletedOSPlatformAttributeSupport () + { + var xml = @" + + + + + + + + + "; + + options.UseObsoletedOSPlatformAttributes = true; + + var enu = CreateEnum (); + var gens = ParseApiDefinition (xml); + + generator.WriteEnumeration (options, enu, gens.ToArray ()); + + // Ensure [ObsoletedOSPlatform] and [SupportedOSPlatform] are written + Assert.True (writer.ToString ().NormalizeLineEndings ().Contains ("[global::System.Runtime.Versioning.SupportedOSPlatformAttribute(\"android30.0\")][global::System.Runtime.Versioning.ObsoletedOSPlatform(\"android31.0\")]WithExcluded=1"), writer.ToString ()); + } + + [Test] + public void ObsoleteAttributeSupport () + { + var xml = @" + + + + + + + + + "; + + var enu = CreateEnum (); + var gens = ParseApiDefinition (xml); + + generator.WriteEnumeration (options, enu, gens.ToArray ()); + + // Ensure [Obsolete] is written + Assert.True (writer.ToString ().NormalizeLineEndings ().Contains ("[global::System.Obsolete(@\"deprecated\")]WithExcluded=1"), writer.ToString ()); + } + + [Test] + public void ObsoleteFieldButNotEnumAttributeSupport () + { + var xml = @" + + + + + + + + + "; + + var enu = CreateEnum (); + var gens = ParseApiDefinition (xml); + + generator.WriteEnumeration (options, enu, gens.ToArray ()); + + // [Obsolete] should not be written because the value isn't deprecated, just the _field_ is deprecated because we want people to use the enum instead + Assert.False (writer.ToString ().NormalizeLineEndings ().Contains ("[global::System.Obsolete(@\"deprecated\")]WithExcluded=1"), writer.ToString ()); + } + + protected new string GetExpected (string testName) { var root = Path.GetDirectoryName (Assembly.GetExecutingAssembly ().Location); @@ -71,7 +144,7 @@ protected string GetExpected (string testName) { var enu = new EnumMappings.EnumDescription { Members = new List { - new ConstantEntry { EnumMember = "WithExcluded", Value = "1", JavaSignature = "android/app/ActivityManager.RECENT_IGNORE_UNAVAILABLE" }, + new ConstantEntry { EnumMember = "WithExcluded", Value = "1", JavaSignature = "android/app/ActivityManager.RECENT_IGNORE_UNAVAILABLE", ApiLevel = 30 }, new ConstantEntry { EnumMember = "IgnoreUnavailable", Value = "2", JavaSignature = "android/app/ActivityManager.RECENT_WITH_EXCLUDED" } }, BitField = false, diff --git a/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/EnumGenerator.cs b/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/EnumGenerator.cs index 6835198b9..f611a5ccf 100644 --- a/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/EnumGenerator.cs +++ b/tools/generator/Java.Interop.Tools.Generator.CodeGeneration/EnumGenerator.cs @@ -50,10 +50,20 @@ EnumWriter CreateWriter (CodeGenerationOptions opt, KeyValuePair gens) + WeakReference cache_found_class; + + (GenBase Cls, Field Field)? FindManagedMember (EnumDescription desc, ConstantEntry constant, IEnumerable gens) { if (desc.FieldsRemoved) return null; - var jniMember = member.JavaSignature; + var jniMember = constant.JavaSignature; + if (string.IsNullOrWhiteSpace (jniMember)) { // enum values like "None" falls here. return null; } - return FindManagedMember (jniMember, gens); - } - WeakReference cache_found_class; + ParseJniMember (jniMember, out var package, out var type, out var member); - string FindManagedMember (string jniMember, IEnumerable gens) - { - string package, type, member; - ParseJniMember (jniMember, out package, out type, out member); var fullJavaType = (string.IsNullOrEmpty (package) ? "" : package + ".") + type; var cls = cache_found_class != null ? cache_found_class.Target as GenBase : null; @@ -96,7 +103,7 @@ string FindManagedMember (string jniMember, IEnumerable gens) // The field was not found e.g. removed by metadata fixup. return null; } - return cls.FullName + "." + fld.Name; + return (cls, fld); } internal void ParseJniMember (string jniMember, out string package, out string type, out string member) diff --git a/tools/generator/SourceWriters/Extensions/SourceWriterExtensions.cs b/tools/generator/SourceWriters/Extensions/SourceWriterExtensions.cs index 7535f9488..71d3f1b9e 100644 --- a/tools/generator/SourceWriters/Extensions/SourceWriterExtensions.cs +++ b/tools/generator/SourceWriters/Extensions/SourceWriterExtensions.cs @@ -293,12 +293,14 @@ public static void AddParameterListCallArgs (List body, ParameterList pa } public static void AddSupportedOSPlatform (List attributes, ApiVersionsSupport.IApiAvailability member, CodeGenerationOptions opt) + => AddSupportedOSPlatform (attributes, member.ApiAvailableSince, opt); + + public static void AddSupportedOSPlatform (List attributes, int since, CodeGenerationOptions opt) { // There's no sense in writing say 'android15' because we do not support older APIs, // so those APIs will be available in all of our versions. - if (member.ApiAvailableSince > 21 && opt.CodeGenerationTarget == Xamarin.Android.Binder.CodeGenerationTarget.XAJavaInterop1) - attributes.Add (new SupportedOSPlatformAttr (member.ApiAvailableSince)); - + if (since > 21 && opt.CodeGenerationTarget == Xamarin.Android.Binder.CodeGenerationTarget.XAJavaInterop1) + attributes.Add (new SupportedOSPlatformAttr (since)); } public static void AddObsolete (List attributes, string message, CodeGenerationOptions opt, bool forceDeprecate = false, bool isError = false, int? deprecatedSince = null)