diff --git a/src/utils/XmlExtensions.cs b/src/utils/XmlExtensions.cs
index 6a8d4b2ef..a72eb8f92 100644
--- a/src/utils/XmlExtensions.cs
+++ b/src/utils/XmlExtensions.cs
@@ -20,5 +20,18 @@ public static string XGetAttribute (this XPathNavigator nav, string name, string
var attr = nav.GetAttribute (name, ns);
return attr != null ? attr.Trim () : null;
}
+
+ public static int? XGetAttributeAsIntOrNull (this XElement element, string name)
+ {
+ var attr = element.Attribute (name);
+
+ if (attr?.Value is null)
+ return null;
+
+ if (int.TryParse (attr.Value, out var val))
+ return val;
+
+ return null;
+ }
}
}
diff --git a/tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs b/tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs
index 7f937b6a6..bbb9724c2 100644
--- a/tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs
+++ b/tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs
@@ -531,6 +531,86 @@ public void ObsoleteBoundMethodAbstractDeclaration ()
Assert.True (writer.ToString ().Contains ("[global::System.Obsolete (@\"This is so old!\")]"), writer.ToString ());
}
+ [Test]
+ public void ObsoletedOSPlatformAttributeSupport ()
+ {
+ var xml = @"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ";
+
+ options.UseObsoletedOSPlatformAttributes = true;
+
+ 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 [ObsoletedOSPlatform] was written
+ Assert.True (writer.ToString ().Contains ("[global::System.Runtime.Versioning.ObsoletedOSPlatform (\"android25.0\", @\"This is a class deprecated since 25!\")]"), writer.ToString ());
+ Assert.True (writer.ToString ().Contains ("[global::System.Runtime.Versioning.ObsoletedOSPlatform (\"android25.0\", @\"This is a field deprecated since 25!\")]"), writer.ToString ());
+ Assert.True (writer.ToString ().Contains ("[global::System.Runtime.Versioning.ObsoletedOSPlatform (\"android25.0\", @\"This is a constructor deprecated since 25!\")]"), writer.ToString ());
+ Assert.True (writer.ToString ().Contains ("[global::System.Runtime.Versioning.ObsoletedOSPlatform (\"android25.0\", @\"This is a method deprecated since 25!\")]"), writer.ToString ());
+ Assert.True (writer.ToString ().Contains ("[global::System.Runtime.Versioning.ObsoletedOSPlatform (\"android25.0\", @\"This is a property getter deprecated since 25! This is a property setter deprecated since 25!\")]"), writer.ToString ());
+ }
+
+ [Test]
+ public void ObsoletedOSPlatformAttributeUnneededSupport ()
+ {
+ var xml = @"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ";
+
+ options.UseObsoletedOSPlatformAttributes = true;
+
+ 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 ();
+
+ // These should use [Obsolete] because they have always been obsolete in all currently supported versions (21+)
+ Assert.True (writer.ToString ().Contains ("[global::System.Obsolete (@\"This is a class deprecated since 19!\")]"), writer.ToString ());
+ Assert.True (writer.ToString ().Contains ("[global::System.Obsolete (@\"This is a field deprecated since 0!\")]"), writer.ToString ());
+ Assert.True (writer.ToString ().Contains ("[global::System.Obsolete (@\"This is a constructor deprecated since empty string!\")]"), writer.ToString ());
+
+ // This should not have a message because the default "deprecated" message isn't useful
+ Assert.True (writer.ToString ().Contains ("[global::System.Runtime.Versioning.ObsoletedOSPlatform (\"android25.0\")]"), writer.ToString ());
+ Assert.True (writer.ToString ().Contains ("[global::System.Runtime.Versioning.ObsoletedOSPlatform (\"android22.0\")]"), writer.ToString ());
+
+ // This should use [Obsolete] because the 'deprecated-since' attribute could not be parsed
+ Assert.True (writer.ToString ().Contains ("[global::System.Obsolete (@\"This method has an invalid deprecated-since!\")]"), writer.ToString ());
+ }
+
[Test]
[NonParallelizable] // We are setting a static property on Report
public void WarnIfTypeNameMatchesNamespace ()
diff --git a/tools/generator/CodeGenerationOptions.cs b/tools/generator/CodeGenerationOptions.cs
index eb722f12d..68eb6d0b8 100644
--- a/tools/generator/CodeGenerationOptions.cs
+++ b/tools/generator/CodeGenerationOptions.cs
@@ -66,6 +66,7 @@ public SymbolTable SymbolTable {
public bool SupportNestedInterfaceTypes { get; set; }
public bool SupportNullableReferenceTypes { get; set; }
public bool UseShallowReferencedTypes { get; set; }
+ public bool UseObsoletedOSPlatformAttributes { get; set; }
public bool RemoveConstSugar => BuildingCoreAssembly;
bool? buildingCoreAssembly;
diff --git a/tools/generator/CodeGenerator.cs b/tools/generator/CodeGenerator.cs
index 880d91daf..753f05138 100644
--- a/tools/generator/CodeGenerator.cs
+++ b/tools/generator/CodeGenerator.cs
@@ -83,6 +83,7 @@ static void Run (CodeGeneratorOptions options, DirectoryAssemblyResolver resolve
SupportDefaultInterfaceMethods = options.SupportDefaultInterfaceMethods,
SupportNestedInterfaceTypes = options.SupportNestedInterfaceTypes,
SupportNullableReferenceTypes = options.SupportNullableReferenceTypes,
+ UseObsoletedOSPlatformAttributes = options.UseObsoletedOSPlatformAttributes,
};
var resolverCache = new TypeDefinitionCache ();
diff --git a/tools/generator/CodeGeneratorOptions.cs b/tools/generator/CodeGeneratorOptions.cs
index 1d6ec1324..08395d154 100644
--- a/tools/generator/CodeGeneratorOptions.cs
+++ b/tools/generator/CodeGeneratorOptions.cs
@@ -53,6 +53,7 @@ public CodeGeneratorOptions ()
public bool SupportNestedInterfaceTypes { get; set; }
public bool SupportNullableReferenceTypes { get; set; }
public bool UseLegacyJavaResolver { get; set; }
+ public bool UseObsoletedOSPlatformAttributes { get; set; }
public XmldocStyle XmldocStyle { get; set; } = XmldocStyle.IntelliSense;
@@ -102,12 +103,13 @@ public static CodeGeneratorOptions Parse (string[] args)
"SDK Platform {VERSION}/API level.",
v => opts.ApiLevel = v },
{ "lang-features=",
- "For internal use. (Flags: interface-constants,default-interface-methods,nullable-reference-types)",
+ "For internal use. (Flags: interface-constants,default-interface-methods,nested-interface-types,nullable-reference-types,obsoleted-platform-attributes)",
v => {
opts.SupportInterfaceConstants = v?.Contains ("interface-constants") == true;
opts.SupportDefaultInterfaceMethods = v?.Contains ("default-interface-methods") == true;
opts.SupportNestedInterfaceTypes = v?.Contains ("nested-interface-types") == true;
opts.SupportNullableReferenceTypes = v?.Contains ("nullable-reference-types") == true;
+ opts.UseObsoletedOSPlatformAttributes = v?.Contains ("obsoleted-platform-attributes") == true;
}},
{ "preserve-enums",
"For internal use.",
diff --git a/tools/generator/Java.Interop.Tools.Generator.Importers/XmlApiImporter.cs b/tools/generator/Java.Interop.Tools.Generator.Importers/XmlApiImporter.cs
index fbca66cee..2e773df60 100644
--- a/tools/generator/Java.Interop.Tools.Generator.Importers/XmlApiImporter.cs
+++ b/tools/generator/Java.Interop.Tools.Generator.Importers/XmlApiImporter.cs
@@ -155,6 +155,7 @@ public static Ctor CreateCtor (GenBase declaringType, XElement elem, CodeGenerat
ApiAvailableSince = declaringType.ApiAvailableSince,
CustomAttributes = elem.XGetAttribute ("customAttributes"),
Deprecated = elem.Deprecated (),
+ DeprecatedSince = elem.XGetAttributeAsIntOrNull ("deprecated-since"),
GenericArguments = elem.GenericArguments (),
Name = elem.XGetAttribute ("name"),
Visibility = elem.Visibility ()
@@ -200,6 +201,7 @@ public static Field CreateField (GenBase declaringType, XElement elem, CodeGener
var field = new Field {
ApiAvailableSince = declaringType.ApiAvailableSince,
DeprecatedComment = elem.XGetAttribute ("deprecated"),
+ DeprecatedSince = elem.XGetAttributeAsIntOrNull ("deprecated-since"),
IsAcw = true,
IsDeprecated = elem.XGetAttribute ("deprecated") != "not deprecated",
IsDeprecatedError = elem.XGetAttribute ("deprecated-error") == "true",
@@ -237,6 +239,7 @@ public static Field CreateField (GenBase declaringType, XElement elem, CodeGener
public static GenBaseSupport CreateGenBaseSupport (XElement pkg, XElement elem, CodeGenerationOptions opt, bool isInterface)
{
var support = new GenBaseSupport {
+ DeprecatedSince = elem.XGetAttributeAsIntOrNull ("deprecated-since"),
IsAcw = true,
IsDeprecated = elem.XGetAttribute ("deprecated") != "not deprecated",
IsGeneratable = true,
@@ -348,6 +351,7 @@ public static Method CreateMethod (GenBase declaringType, XElement elem, CodeGen
ArgsType = elem.Attribute ("argsType")?.Value,
CustomAttributes = elem.XGetAttribute ("customAttributes"),
Deprecated = elem.Deprecated (),
+ DeprecatedSince = elem.XGetAttributeAsIntOrNull ("deprecated-since"),
ExplicitInterface = elem.XGetAttribute ("explicitInterface"),
EventName = elem.Attribute ("eventName")?.Value,
GenerateAsyncWrapper = elem.Attribute ("generateAsyncWrapper") != null,
diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Field.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Field.cs
index ac0206cba..6f38240c7 100644
--- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Field.cs
+++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/Field.cs
@@ -9,6 +9,7 @@ public class Field : ApiVersionsSupport.IApiAvailability, ISourceLineInfo
public string Annotation { get; set; }
public int ApiAvailableSince { get; set; }
public string DeprecatedComment { get; set; }
+ public int? DeprecatedSince { get; set; }
public bool IsAcw { get; set; }
public bool IsDeprecated { get; set; }
public bool IsDeprecatedError { get; set; }
diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs
index 6d55000fc..5331bbf2b 100644
--- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs
+++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBase.cs
@@ -251,6 +251,8 @@ public bool ContainsProperty (string name, bool check_ifaces, bool check_base_if
public string DeprecatedComment => support.DeprecatedComment;
+ public int? DeprecatedSince => support.DeprecatedSince;
+
IEnumerable Descendants (IList gens)
{
foreach (var directDescendants in gens.Where (x => x.BaseGen == this)) {
diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBaseSupport.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBaseSupport.cs
index 57526908a..75258cb6d 100644
--- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBaseSupport.cs
+++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/GenBaseSupport.cs
@@ -7,6 +7,7 @@ public class GenBaseSupport
public bool IsAcw { get; set; }
public bool IsDeprecated { get; set; }
public string DeprecatedComment { get; set; }
+ public int? DeprecatedSince { get; set; }
public bool IsGeneratable { get; set; }
public bool IsGeneric { get; set; }
public bool IsObfuscated { get; set; }
diff --git a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/MethodBase.cs b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/MethodBase.cs
index ee10dc45f..09fb19072 100644
--- a/tools/generator/Java.Interop.Tools.Generator.ObjectModel/MethodBase.cs
+++ b/tools/generator/Java.Interop.Tools.Generator.ObjectModel/MethodBase.cs
@@ -18,6 +18,7 @@ protected MethodBase (GenBase declaringType)
public string AssemblyName { get; set; }
public GenBase DeclaringType { get; }
public string Deprecated { get; set; }
+ public int? DeprecatedSince { get; set; }
public GenericParameterDefinitionList GenericArguments { get; set; }
public bool IsAcw { get; set; }
public bool IsValid { get; private set; }
diff --git a/tools/generator/SourceWriters/Attributes/ObsoleteAttr.cs b/tools/generator/SourceWriters/Attributes/ObsoleteAttr.cs
index 152bce266..b00ef5008 100644
--- a/tools/generator/SourceWriters/Attributes/ObsoleteAttr.cs
+++ b/tools/generator/SourceWriters/Attributes/ObsoleteAttr.cs
@@ -14,21 +14,19 @@ public class ObsoleteAttr : AttributeWriter
public ObsoleteAttr (string message = null, bool isError = false)
{
- Message = message;
+ Message = message?.Replace ("\"", "\"\"").Trim ();
IsError = isError;
}
public override void WriteAttribute (CodeWriter writer)
{
- var parts = new List ();
+ var content = string.Empty;
- if (Message != null)
- parts.Add ($"@\"{Message}\"");
+ if (Message != null || IsError)
+ content += $"@\"{Message}\"";
if (IsError)
- parts.Add ("error: true");
-
- var content = string.Join (", ", parts.ToArray ());
+ content += ", error: true";
if (content.HasValue ())
writer.WriteLine ($"[global::System.Obsolete ({content})]");
diff --git a/tools/generator/SourceWriters/Attributes/ObsoletedOSPlatformAttr.cs b/tools/generator/SourceWriters/Attributes/ObsoletedOSPlatformAttr.cs
new file mode 100644
index 000000000..eecb0a87d
--- /dev/null
+++ b/tools/generator/SourceWriters/Attributes/ObsoletedOSPlatformAttr.cs
@@ -0,0 +1,25 @@
+using System;
+using Xamarin.SourceWriter;
+
+namespace generator.SourceWriters
+{
+ public class ObsoletedOSPlatformAttr : AttributeWriter
+ {
+ public string Message { get; set; }
+ public int Version { get; }
+
+ public ObsoletedOSPlatformAttr (string message, int version)
+ {
+ Message = message;
+ Version = version;
+ }
+
+ public override void WriteAttribute (CodeWriter writer)
+ {
+ if (Message.HasValue ())
+ writer.WriteLine ($"[global::System.Runtime.Versioning.ObsoletedOSPlatform (\"android{Version}.0\", @\"{Message.Replace ("\"", "\"\"")}\")]");
+ else
+ writer.WriteLine ($"[global::System.Runtime.Versioning.ObsoletedOSPlatform (\"android{Version}.0\")]");
+ }
+ }
+}
diff --git a/tools/generator/SourceWriters/BoundClass.cs b/tools/generator/SourceWriters/BoundClass.cs
index 38337dbe3..76ca86db8 100644
--- a/tools/generator/SourceWriters/BoundClass.cs
+++ b/tools/generator/SourceWriters/BoundClass.cs
@@ -44,7 +44,7 @@ public BoundClass (ClassGen klass, CodeGenerationOptions opt, CodeGeneratorConte
klass.JavadocInfo?.AddJavadocs (Comments);
Comments.Add ($"// Metadata.xml XPath class reference: path=\"{klass.MetadataXPathReference}\"");
- SourceWriterExtensions.AddObsolete (Attributes, klass.DeprecatedComment, klass.IsDeprecated);
+ SourceWriterExtensions.AddObsolete (Attributes, klass.DeprecatedComment, opt, forceDeprecate: klass.IsDeprecated, deprecatedSince: klass.DeprecatedSince);
SourceWriterExtensions.AddSupportedOSPlatform (Attributes, klass, opt);
diff --git a/tools/generator/SourceWriters/BoundConstructor.cs b/tools/generator/SourceWriters/BoundConstructor.cs
index ed7ad3ca4..9440abf0a 100644
--- a/tools/generator/SourceWriters/BoundConstructor.cs
+++ b/tools/generator/SourceWriters/BoundConstructor.cs
@@ -33,7 +33,7 @@ public BoundConstructor (ClassGen klass, Ctor constructor, bool useBase, CodeGen
Attributes.Add (new RegisterAttr (".ctor", constructor.JniSignature, string.Empty, additionalProperties: constructor.AdditionalAttributeString ()));
}
- SourceWriterExtensions.AddObsolete (Attributes, constructor.Deprecated);
+ SourceWriterExtensions.AddObsolete (Attributes, constructor.Deprecated, opt, deprecatedSince: constructor.DeprecatedSince);
if (constructor.CustomAttributes != null)
Attributes.Add (new CustomAttr (constructor.CustomAttributes));
diff --git a/tools/generator/SourceWriters/BoundField.cs b/tools/generator/SourceWriters/BoundField.cs
index 6c4a66347..620c3134a 100644
--- a/tools/generator/SourceWriters/BoundField.cs
+++ b/tools/generator/SourceWriters/BoundField.cs
@@ -31,7 +31,7 @@ public BoundField (GenBase type, Field field, CodeGenerationOptions opt)
if (field.IsEnumified)
Attributes.Add (new GeneratedEnumAttr ());
- SourceWriterExtensions.AddObsolete (Attributes, field.DeprecatedComment, field.IsDeprecated, isError: field.IsDeprecatedError);
+ SourceWriterExtensions.AddObsolete (Attributes, field.DeprecatedComment, opt, field.IsDeprecated, isError: field.IsDeprecatedError, deprecatedSince: field.DeprecatedSince);
if (field.Annotation.HasValue ())
Attributes.Add (new CustomAttr (field.Annotation));
diff --git a/tools/generator/SourceWriters/BoundFieldAsProperty.cs b/tools/generator/SourceWriters/BoundFieldAsProperty.cs
index aecf5d1a6..9277a1828 100644
--- a/tools/generator/SourceWriters/BoundFieldAsProperty.cs
+++ b/tools/generator/SourceWriters/BoundFieldAsProperty.cs
@@ -47,7 +47,7 @@ public BoundFieldAsProperty (GenBase type, Field field, CodeGenerationOptions op
Attributes.Add (new RegisterAttr (field.JavaName, additionalProperties: field.AdditionalAttributeString ()));
}
- SourceWriterExtensions.AddObsolete (Attributes, field.DeprecatedComment, field.IsDeprecated, isError: field.IsDeprecatedError);
+ SourceWriterExtensions.AddObsolete (Attributes, field.DeprecatedComment, opt, field.IsDeprecated, isError: field.IsDeprecatedError, deprecatedSince: field.DeprecatedSince);
SetVisibility (field.Visibility);
UseExplicitPrivateKeyword = true;
diff --git a/tools/generator/SourceWriters/BoundInterface.cs b/tools/generator/SourceWriters/BoundInterface.cs
index 9dc62a407..5ca02cf8f 100644
--- a/tools/generator/SourceWriters/BoundInterface.cs
+++ b/tools/generator/SourceWriters/BoundInterface.cs
@@ -43,7 +43,7 @@ public BoundInterface (InterfaceGen iface, CodeGenerationOptions opt, CodeGenera
iface.JavadocInfo?.AddJavadocs (Comments);
Comments.Add ($"// Metadata.xml XPath interface reference: path=\"{iface.MetadataXPathReference}\"");
- SourceWriterExtensions.AddObsolete (Attributes, iface.DeprecatedComment, iface.IsDeprecated);
+ SourceWriterExtensions.AddObsolete (Attributes, iface.DeprecatedComment, opt, iface.IsDeprecated, deprecatedSince: iface.DeprecatedSince);
if (!iface.IsConstSugar (opt)) {
var signature = string.IsNullOrWhiteSpace (iface.Namespace)
diff --git a/tools/generator/SourceWriters/BoundInterfaceMethodDeclaration.cs b/tools/generator/SourceWriters/BoundInterfaceMethodDeclaration.cs
index 8d452ac34..502efac0e 100644
--- a/tools/generator/SourceWriters/BoundInterfaceMethodDeclaration.cs
+++ b/tools/generator/SourceWriters/BoundInterfaceMethodDeclaration.cs
@@ -34,7 +34,7 @@ public BoundInterfaceMethodDeclaration (Method method, string adapter, CodeGener
if (method.DeclaringType.IsGeneratable)
Comments.Add ($"// Metadata.xml XPath method reference: path=\"{method.GetMetadataXPathReference (method.DeclaringType)}\"");
- SourceWriterExtensions.AddObsolete (Attributes, method.Deprecated);
+ SourceWriterExtensions.AddObsolete (Attributes, method.Deprecated, opt, deprecatedSince: method.DeprecatedSince);
if (method.IsReturnEnumified)
Attributes.Add (new GeneratedEnumAttr (true));
diff --git a/tools/generator/SourceWriters/BoundMethod.cs b/tools/generator/SourceWriters/BoundMethod.cs
index 806efe655..2146dd436 100644
--- a/tools/generator/SourceWriters/BoundMethod.cs
+++ b/tools/generator/SourceWriters/BoundMethod.cs
@@ -74,7 +74,7 @@ public BoundMethod (GenBase type, Method method, CodeGenerationOptions opt, bool
if (method.DeclaringType.IsGeneratable)
Comments.Add ($"// Metadata.xml XPath method reference: path=\"{method.GetMetadataXPathReference (method.DeclaringType)}\"");
- SourceWriterExtensions.AddObsolete (Attributes, method.Deprecated);
+ SourceWriterExtensions.AddObsolete (Attributes, method.Deprecated, opt, deprecatedSince: method.DeprecatedSince);
if (method.IsReturnEnumified)
Attributes.Add (new GeneratedEnumAttr (true));
diff --git a/tools/generator/SourceWriters/BoundMethodAbstractDeclaration.cs b/tools/generator/SourceWriters/BoundMethodAbstractDeclaration.cs
index bbae48799..d76b4e90d 100644
--- a/tools/generator/SourceWriters/BoundMethodAbstractDeclaration.cs
+++ b/tools/generator/SourceWriters/BoundMethodAbstractDeclaration.cs
@@ -53,7 +53,7 @@ public BoundMethodAbstractDeclaration (GenBase gen, Method method, CodeGeneratio
if (method.DeclaringType.IsGeneratable)
Comments.Add ($"// Metadata.xml XPath method reference: path=\"{method.GetMetadataXPathReference (method.DeclaringType)}\"");
- SourceWriterExtensions.AddObsolete (Attributes, method.Deprecated);
+ SourceWriterExtensions.AddObsolete (Attributes, method.Deprecated, opt, deprecatedSince: method.DeprecatedSince);
SourceWriterExtensions.AddSupportedOSPlatform (Attributes, method, opt);
diff --git a/tools/generator/SourceWriters/BoundMethodExtensionStringOverload.cs b/tools/generator/SourceWriters/BoundMethodExtensionStringOverload.cs
index dfae18351..4ad132b19 100644
--- a/tools/generator/SourceWriters/BoundMethodExtensionStringOverload.cs
+++ b/tools/generator/SourceWriters/BoundMethodExtensionStringOverload.cs
@@ -26,7 +26,7 @@ public BoundMethodExtensionStringOverload (Method method, CodeGenerationOptions
SetVisibility (method.Visibility);
ReturnType = new TypeReferenceWriter (opt.GetTypeReferenceName (method.RetVal).Replace ("Java.Lang.ICharSequence", "string").Replace ("global::string", "string"));
- SourceWriterExtensions.AddObsolete (Attributes, method.Deprecated);
+ SourceWriterExtensions.AddObsolete (Attributes, method.Deprecated, opt, deprecatedSince: method.DeprecatedSince);
SourceWriterExtensions.AddSupportedOSPlatform (Attributes, method, opt);
diff --git a/tools/generator/SourceWriters/BoundMethodStringOverload.cs b/tools/generator/SourceWriters/BoundMethodStringOverload.cs
index 80e47b452..e60f9acb6 100644
--- a/tools/generator/SourceWriters/BoundMethodStringOverload.cs
+++ b/tools/generator/SourceWriters/BoundMethodStringOverload.cs
@@ -24,7 +24,7 @@ public BoundMethodStringOverload (Method method, CodeGenerationOptions opt)
SetVisibility (method.Visibility);
ReturnType = new TypeReferenceWriter (opt.GetTypeReferenceName (method.RetVal).Replace ("Java.Lang.ICharSequence", "string").Replace ("global::string", "string"));
- SourceWriterExtensions.AddObsolete (Attributes, method.Deprecated);
+ SourceWriterExtensions.AddObsolete (Attributes, method.Deprecated, opt, deprecatedSince: method.DeprecatedSince);
SourceWriterExtensions.AddSupportedOSPlatform (Attributes, method, opt);
diff --git a/tools/generator/SourceWriters/BoundProperty.cs b/tools/generator/SourceWriters/BoundProperty.cs
index 41209eb2b..240b86a95 100644
--- a/tools/generator/SourceWriters/BoundProperty.cs
+++ b/tools/generator/SourceWriters/BoundProperty.cs
@@ -75,7 +75,8 @@ public BoundProperty (GenBase gen, Property property, CodeGenerationOptions opt,
// Unlike [Register], [Obsolete] cannot be put on property accessors, so we can apply them only under limited condition...
if (property.Getter.Deprecated != null && (property.Setter == null || property.Setter.Deprecated != null)) {
var message = property.Getter.Deprecated.Trim () + (property.Setter != null && property.Setter.Deprecated != property.Getter.Deprecated ? " " + property.Setter.Deprecated.Trim () : null);
- SourceWriterExtensions.AddObsolete (Attributes, message);
+ var since = property.Getter?.DeprecatedSince ?? property.Setter?.DeprecatedSince;
+ SourceWriterExtensions.AddObsolete (Attributes, message, opt, deprecatedSince: since);
}
SourceWriterExtensions.AddSupportedOSPlatform (Attributes, property.Getter, opt);
diff --git a/tools/generator/SourceWriters/Extensions/SourceWriterExtensions.cs b/tools/generator/SourceWriters/Extensions/SourceWriterExtensions.cs
index 3488bd3e8..7535f9488 100644
--- a/tools/generator/SourceWriters/Extensions/SourceWriterExtensions.cs
+++ b/tools/generator/SourceWriters/Extensions/SourceWriterExtensions.cs
@@ -301,13 +301,36 @@ public static void AddSupportedOSPlatform (List attributes, Api
}
- public static void AddObsolete (List attributes, string message, bool forceDeprecate = false, bool isError = false)
+ public static void AddObsolete (List attributes, string message, CodeGenerationOptions opt, bool forceDeprecate = false, bool isError = false, int? deprecatedSince = null)
{
// Bail if we're not obsolete
if ((!forceDeprecate && !message.HasValue ()) || message == "not deprecated")
return;
- attributes.Add (new ObsoleteAttr (message: message?.Replace ("\"", "\"\"").Trim (), isError: isError));
+ // Check if we should use [ObsoletedOSPlatform] instead of [Obsolete]
+ if (AddObsoletedOSPlatformAttribute (attributes, message, deprecatedSince, opt))
+ return;
+
+ attributes.Add (new ObsoleteAttr (message, isError));
+ }
+
+ // Returns true if attribute was applied
+ static bool AddObsoletedOSPlatformAttribute (List attributes, string message, int? deprecatedSince, CodeGenerationOptions opt)
+ {
+ if (!opt.UseObsoletedOSPlatformAttributes)
+ return false;
+
+ // If it was obsoleted in a version earlier than we support (like 15), use a regular [Obsolete] instead
+ if (!deprecatedSince.HasValue || deprecatedSince <= 21)
+ return false;
+
+ // This is the default Android message, but it isn't useful so remove it
+ if (message == "deprecated")
+ message = string.Empty;
+
+ attributes.Add (new ObsoletedOSPlatformAttr (message, deprecatedSince.Value));
+
+ return true;
}
public static void WriteMethodInvokerBody (CodeWriter writer, Method method, CodeGenerationOptions opt, string contextThis)
diff --git a/tools/generator/SourceWriters/InterfaceMemberAlternativeClass.cs b/tools/generator/SourceWriters/InterfaceMemberAlternativeClass.cs
index 4f1c92c38..8d99cb8e9 100644
--- a/tools/generator/SourceWriters/InterfaceMemberAlternativeClass.cs
+++ b/tools/generator/SourceWriters/InterfaceMemberAlternativeClass.cs
@@ -42,7 +42,7 @@ public InterfaceMemberAlternativeClass (InterfaceGen iface, CodeGenerationOption
Attributes.Add (new RegisterAttr (iface.RawJniName, noAcw: true, additionalProperties: iface.AdditionalAttributeString ()) { AcwLast = true });
if (should_obsolete)
- SourceWriterExtensions.AddObsolete (Attributes, $"Use the '{iface.FullName}' type. This class will be removed in a future release.");
+ SourceWriterExtensions.AddObsolete (Attributes, $"Use the '{iface.FullName}' type. This class will be removed in a future release.", opt);
Constructors.Add (new ConstructorWriter { Name = Name, IsInternal = true });
@@ -53,7 +53,7 @@ public InterfaceMemberAlternativeClass (InterfaceGen iface, CodeGenerationOption
Fields.Add (new PeerMembersField (opt, iface.RawJniName, Name, false));
if (!iface.HasManagedName && !opt.SupportInterfaceConstants)
- sibling_classes.Add (new InterfaceConstsForwardClass (iface));
+ sibling_classes.Add (new InterfaceConstsForwardClass (iface, opt));
}
void AddMethods (InterfaceGen iface, bool shouldObsolete, CodeGenerationOptions opt)
@@ -171,7 +171,7 @@ public void WriteSiblingClasses (CodeWriter writer)
public class InterfaceConstsForwardClass : ClassWriter
{
- public InterfaceConstsForwardClass (InterfaceGen iface)
+ public InterfaceConstsForwardClass (InterfaceGen iface, CodeGenerationOptions opt)
{
Name = iface.Name.Substring (1) + "Consts";
Inherits = iface.Name.Substring (1);
@@ -180,7 +180,7 @@ public InterfaceConstsForwardClass (InterfaceGen iface)
IsAbstract = true;
Attributes.Add (new RegisterAttr (iface.RawJniName, noAcw: true, additionalProperties: iface.AdditionalAttributeString ()));
- SourceWriterExtensions.AddObsolete (Attributes, $"Use the '{iface.Name.Substring (1)}' type. This type will be removed in a future release.", isError: true);
+ SourceWriterExtensions.AddObsolete (Attributes, $"Use the '{iface.Name.Substring (1)}' type. This type will be removed in a future release.", opt, isError: true);
Constructors.Add (new ConstructorWriter {
Name = Name,
diff --git a/tools/generator/SourceWriters/MethodCallback.cs b/tools/generator/SourceWriters/MethodCallback.cs
index c1107d3e5..f292d89f8 100644
--- a/tools/generator/SourceWriters/MethodCallback.cs
+++ b/tools/generator/SourceWriters/MethodCallback.cs
@@ -43,7 +43,7 @@ public MethodCallback (GenBase type, Method method, CodeGenerationOptions option
IsStatic = true;
IsPrivate = method.IsInterfaceDefaultMethod;
- SourceWriterExtensions.AddObsolete (Attributes, null, forceDeprecate: !string.IsNullOrWhiteSpace (method.Deprecated));
+ SourceWriterExtensions.AddObsolete (Attributes, null, opt, forceDeprecate: !string.IsNullOrWhiteSpace (method.Deprecated), deprecatedSince: method.DeprecatedSince);
SourceWriterExtensions.AddSupportedOSPlatform (Attributes, method, opt);
@@ -135,7 +135,7 @@ public GetDelegateHandlerMethod (Method method, CodeGenerationOptions opt)
IsStatic = true;
IsPrivate = method.IsInterfaceDefaultMethod;
- SourceWriterExtensions.AddObsolete (Attributes, null, forceDeprecate: !string.IsNullOrWhiteSpace (method.Deprecated));
+ SourceWriterExtensions.AddObsolete (Attributes, null, opt, forceDeprecate: !string.IsNullOrWhiteSpace (method.Deprecated), deprecatedSince: method.DeprecatedSince);
SourceWriterExtensions.AddSupportedOSPlatform (Attributes, method, opt);
}