Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/Java.Interop.Tools.Generator/Enumification/ConstantEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ namespace Java.Interop.Tools.Generator.Enumification
public class ConstantEntry
{
public ConstantAction Action { get; set; }
public int ApiLevel { get; set; }
public AndroidSdkVersion ApiLevel { get; set; }
public string? JavaSignature { get; set; }
public string? Value { get; set; }
public string? EnumFullType { get; set; }
public string? EnumMember { get; set; }
public FieldAction FieldAction { get; set; }
public bool IsFlags { get; set; }
public int? DeprecatedSince { get; set; }
public AndroidSdkVersion? DeprecatedSince { get; set; }

public string EnumNamespace {
get {
Expand Down Expand Up @@ -100,7 +100,7 @@ static ConstantEntry FromVersion1String (CsvParser parser, bool transientMode)
{
var entry = new ConstantEntry {
Action = ConstantAction.Enumify,
ApiLevel = parser.GetFieldAsInt (0),
ApiLevel = parser.GetFieldAsAndroidSdkVersion (0),
EnumFullType = parser.GetField (1),
EnumMember = parser.GetField (2),
JavaSignature = parser.GetField (3),
Expand Down Expand Up @@ -128,14 +128,14 @@ static ConstantEntry FromVersion2String (CsvParser parser)
{
var entry = new ConstantEntry {
Action = FromConstantActionString (parser.GetField (0)),
ApiLevel = parser.GetFieldAsInt (1),
ApiLevel = parser.GetFieldAsAndroidSdkVersion (1),
JavaSignature = parser.GetField (2),
Value = parser.GetField (3),
EnumFullType = parser.GetField (4),
EnumMember = parser.GetField (5),
FieldAction = FromFieldActionString (parser.GetField (6)),
IsFlags = parser.GetField (7).ToLowerInvariant () == "flags",
DeprecatedSince = parser.GetFieldAsNullableInt32 (8)
DeprecatedSince = parser.GetFieldAsNullableAndroidSdkVersion (8)
};

entry.NormalizeJavaSignature ();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace Java.Interop.Tools.Generator.Enumification
public class MethodMapEntry
{
public MethodAction Action { get; set; }
public int ApiLevel { get; set; }
public AndroidSdkVersion ApiLevel { get; set; }
public string? JavaPackage { get; set; }
public string? JavaType { get; set; }
public string? JavaName { get; set; }
Expand Down Expand Up @@ -66,7 +66,7 @@ static MethodMapEntry FromVersion1String (CsvParser parser)
{
var entry = new MethodMapEntry {
Action = MethodAction.Enumify,
ApiLevel = parser.GetFieldAsInt (0),
ApiLevel = parser.GetFieldAsAndroidSdkVersion (0),
JavaPackage = parser.GetField (1),
JavaType = parser.GetField (2),
JavaName = parser.GetField (3),
Expand All @@ -86,7 +86,7 @@ static MethodMapEntry FromVersion2String (CsvParser parser)
{
var entry = new MethodMapEntry {
Action = FromMethodActionString (parser.GetField (0)),
ApiLevel = parser.GetFieldAsInt (1),
ApiLevel = parser.GetFieldAsAndroidSdkVersion (1),
JavaPackage = parser.GetField (2),
JavaType = parser.GetField (3),
JavaName = parser.GetField (4),
Expand Down
6 changes: 4 additions & 2 deletions src/Java.Interop.Tools.Generator/Extensions/XmlExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
using System.Xml.Linq;
using System.Xml.XPath;

using Java.Interop.Tools.Generator;

namespace Xamarin.Android.Tools
{
static class XmlExtensions
Expand All @@ -13,11 +15,11 @@ static class XmlExtensions
public static string? XGetAttribute (this XPathNavigator nav, string name, string ns)
=> nav.GetAttribute (name, ns)?.Trim ();

public static int? XGetAttributeAsInt (this XElement element, string name)
public static AndroidSdkVersion? XGetAttributeAsAndroidSdkVersion (this XElement element, string name)
{
var value = element.XGetAttribute (name);

if (int.TryParse (value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result))
if (AndroidSdkVersion.TryParse (value, out var result))
return result;

return null;
Expand Down
16 changes: 8 additions & 8 deletions src/Java.Interop.Tools.Generator/Metadata/FixupXmlDocument.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public FixupXmlDocument (XDocument fixupDocument)
public void Apply (ApiXmlDocument apiDocument, string apiLevelString, int productVersion)
{
// Defaulting to 0 here is fine
int.TryParse (apiLevelString, out var apiLevel);
AndroidSdkVersion.TryParse (apiLevelString, out var apiLevel);

var metadataChildren = FixupDocument.XPathSelectElements ("/metadata/*");

Expand Down Expand Up @@ -193,22 +193,22 @@ public IList<NamespaceTransform> GetNamespaceTransforms ()
return list;
}

bool ShouldSkip (XElement node, int apiLevel, int productVersion)
bool ShouldSkip (XElement node, AndroidSdkVersion apiLevel, int productVersion)
{
if (apiLevel > 0) {
var since = node.XGetAttributeAsInt ("api-since");
var until = node.XGetAttributeAsInt ("api-until");
var since = node.XGetAttributeAsAndroidSdkVersion ("api-since");
var until = node.XGetAttributeAsAndroidSdkVersion ("api-until");

if (since is int since_int && since_int > apiLevel)
if (since is AndroidSdkVersion since_int && since_int > apiLevel)
return true;
else if (until is int until_int && until_int < apiLevel)
else if (until is AndroidSdkVersion until_int && until_int < apiLevel)
return true;
}

if (productVersion > 0) {
var product_version = node.XGetAttributeAsInt ("product-version");
var product_version = node.XGetAttributeAsAndroidSdkVersion ("product-version");

if (product_version is int version && version > productVersion)
if (product_version is AndroidSdkVersion version && version > productVersion)
return true;

}
Expand Down
126 changes: 126 additions & 0 deletions src/Java.Interop.Tools.Generator/Utilities/AndroidSdkVersion.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@

using System;
using System.Diagnostics.CodeAnalysis;

namespace Java.Interop.Tools.Generator;

public struct AndroidSdkVersion : IComparable, IComparable<AndroidSdkVersion>, IEquatable<AndroidSdkVersion>
{
public int ApiLevel { get; private set; }
public int MinorRelease { get; private set; }

public AndroidSdkVersion (int major, int minor = 0)
{
ApiLevel = major;
MinorRelease = minor;
}

int IComparable.CompareTo (object? value)
{
var other = value as AndroidSdkVersion?;
if (other == null) {
return 1;
}
return CompareTo (other.Value);
}

public int CompareTo (AndroidSdkVersion value)
{
int r = ApiLevel.CompareTo (value.ApiLevel);
if (r == 0) {
r = MinorRelease.CompareTo (value.MinorRelease);
}
return r;
}

public override int GetHashCode ()
=> ApiLevel ^ MinorRelease;

public override bool Equals (object? value)
{
var other = value as AndroidSdkVersion?;
if (other == null) {
return false;
}
return Equals (other.Value);
}

public bool Equals (AndroidSdkVersion value)
{
return value.ApiLevel == ApiLevel && value.MinorRelease == MinorRelease;
}

public override string ToString ()
=> MinorRelease == 0
? ApiLevel.ToString ()
: $"{ApiLevel}.{MinorRelease}";

// public static implicit operator ApiLevel (int value)
// => new ApiLevel (value);

public static bool operator < (AndroidSdkVersion lhs, AndroidSdkVersion rhs)
=> lhs.CompareTo (rhs) < 0;
public static bool operator <= (AndroidSdkVersion lhs, AndroidSdkVersion rhs)
=> lhs.CompareTo (rhs) <= 0;
public static bool operator > (AndroidSdkVersion lhs, AndroidSdkVersion rhs)
=> lhs.CompareTo (rhs) > 0;
public static bool operator >= (AndroidSdkVersion lhs, AndroidSdkVersion rhs)
=> lhs.CompareTo (rhs) >= 0;
public static bool operator == (AndroidSdkVersion lhs, AndroidSdkVersion rhs)
=> lhs.Equals (rhs);
public static bool operator != (AndroidSdkVersion lhs, AndroidSdkVersion rhs)
=> !lhs.Equals (rhs);

public static bool operator < (AndroidSdkVersion lhs, int rhs)
=> lhs.ApiLevel.CompareTo (rhs) < 0;
public static bool operator <= (AndroidSdkVersion lhs, int rhs)
=> lhs.ApiLevel.CompareTo (rhs) <= 0;
public static bool operator > (AndroidSdkVersion lhs, int rhs)
=> lhs.ApiLevel.CompareTo (rhs) > 0;
public static bool operator >= (AndroidSdkVersion lhs, int rhs)
=> lhs.ApiLevel.CompareTo (rhs) >= 0;
public static bool operator == (AndroidSdkVersion lhs, int rhs)
=> lhs.ApiLevel.Equals (rhs);
public static bool operator != (AndroidSdkVersion lhs, int rhs)
=> !lhs.ApiLevel.Equals (rhs);

public static bool operator < (int lhs, AndroidSdkVersion rhs)
=> lhs.CompareTo (rhs.ApiLevel) < 0;
public static bool operator <= (int lhs, AndroidSdkVersion rhs)
=> lhs.CompareTo (rhs.ApiLevel) <= 0;
public static bool operator > (int lhs, AndroidSdkVersion rhs)
=> lhs.CompareTo (rhs.ApiLevel) > 0;
public static bool operator >= (int lhs, AndroidSdkVersion rhs)
=> lhs.CompareTo (rhs.ApiLevel) >= 0;
public static bool operator == (int lhs, AndroidSdkVersion rhs)
=> lhs.Equals (rhs.ApiLevel);
public static bool operator != (int lhs, AndroidSdkVersion rhs)
=> !lhs.Equals (rhs.ApiLevel);

public static bool TryParse (string? value, out AndroidSdkVersion apiLevel)
{
if (value == null) {
apiLevel = default;
return false;
}
if (Version.TryParse (value, out var v)) {
apiLevel = new AndroidSdkVersion (v.Major, v.Minor);
return true;
}
if (int.TryParse (value, out var major)) {
apiLevel = new AndroidSdkVersion (major);
return true;
}
apiLevel = default;
return false;
}

public static AndroidSdkVersion Parse (string? value)
{
AndroidSdkVersion v;
if (TryParse (value, out v)) {
return v;
}
throw new NotSupportedException ($"Could not parse `{value}` as an ApiLevel.");
}
}
8 changes: 4 additions & 4 deletions src/Java.Interop.Tools.Generator/Utilities/CsvParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,16 @@ public string GetField (int index)
return fields [index].Trim ();
}

public int GetFieldAsInt (int index)
public AndroidSdkVersion GetFieldAsAndroidSdkVersion (int index)
{
return int.Parse (GetField (index));
return AndroidSdkVersion.Parse (GetField (index));
}

public int? GetFieldAsNullableInt32 (int index)
public AndroidSdkVersion? GetFieldAsNullableAndroidSdkVersion (int index)
{
var value = GetField (index);

if (int.TryParse (value, out var val))
if (AndroidSdkVersion.TryParse (value, out var val))
return val;

return default;
Expand Down
47 changes: 35 additions & 12 deletions src/Java.Interop.Tools.Generator/Utilities/NamingConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,49 @@ public static class NamingConverter
/// <summary>
/// Converts a 'merge.SourceFile' attribute to an API level. (ex. "..\..\bin\BuildDebug\api\api-28.xml.in")
/// </summary>
public static int ParseApiLevel (string? value)
public static AndroidSdkVersion ParseApiLevel (string? value)
{
var result = ExtractApiLevel (value);
if (!result.HasValue ())
return default;

return result switch {
"R" => new AndroidSdkVersion (30),
"S" => new AndroidSdkVersion (31),
_ => AndroidSdkVersion.Parse (result)
};
}

static string? ExtractApiLevel (string? value)
{
if (!value.HasValue ())
return 0;
return null;

var hyphen = value.IndexOf ('-');
var period = value.IndexOf ('.', hyphen);
var hyphen = value.IndexOf ('-');
if (hyphen < 0 || (hyphen+1) >= value.Length)
return null;

var result = value.Substring (hyphen + 1, period - hyphen - 1);
int end = hyphen + 1;
if (char.IsAsciiDigit (value [end++])) {
for ( ; end < value.Length; ++end) {
var n = value [end + 1];
if (!char.IsAsciiDigit (n) && n != '.')
break;
}
} else {
// codename; expect ALLCAPS
for ( ; end < value.Length; ++end) {
if (!char.IsAsciiLetterUpper (value [end]))
break;
}
}

return result switch {
"R" => 30,
"S" => 31,
_ => int.Parse (result)
};
return value.Substring (hyphen + 1, end - hyphen - 1);
}

// The 'merge.SourceFile' attribute may be on the element, or only on its parent. For example,
// a new 'class' added will only put the attribute on the '<class>' element and not its children <method>s.
public static int ParseApiLevel (XElement element)
public static AndroidSdkVersion ParseApiLevel (XElement element)
{
var loop = element;

Expand All @@ -39,7 +62,7 @@ public static int ParseApiLevel (XElement element)
loop = loop.Parent;
}

return 0;
return default;
}

public static string ConvertNamespaceToCSharp (string v)
Expand Down
6 changes: 4 additions & 2 deletions src/utils/XmlExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
using System.Xml.Linq;
using System.Xml.XPath;

using Java.Interop.Tools.Generator;

namespace Xamarin.Android.Tools {

static class XmlExtensions {
Expand All @@ -21,14 +23,14 @@ public static string XGetAttribute (this XPathNavigator nav, string name, string
return attr != null ? attr.Trim () : null;
}

public static int? XGetAttributeAsIntOrNull (this XElement element, string name)
public static AndroidSdkVersion? XGetAttributeAsAndroidSdkVersionOrNull (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))
if (AndroidSdkVersion.TryParse (attr.Value, out var val))
return val;

return null;
Expand Down
Loading