diff --git a/src/rgen/Microsoft.Macios.Generator/Availability/PlatformAvailability.cs b/src/rgen/Microsoft.Macios.Generator/Availability/PlatformAvailability.cs index 075951107a33..594c434a38dd 100644 --- a/src/rgen/Microsoft.Macios.Generator/Availability/PlatformAvailability.cs +++ b/src/rgen/Microsoft.Macios.Generator/Availability/PlatformAvailability.cs @@ -29,14 +29,14 @@ namespace Microsoft.Macios.Generator.Availability; /// The supported version of the platform. If null, that means that the user did not add a SupportedOSPlatform /// attribute. /// - public Version? SupportedVersion { get; } + public PlatformSupportVersion? SupportedVersion { get; } - readonly SortedDictionary unsupported = new (); + readonly SortedDictionary unsupported = new (); /// /// Dictionary that contains all the obsoleted versions and their optional data. /// - public IReadOnlyDictionary UnsupportedVersions => unsupported; + public IReadOnlyDictionary UnsupportedVersions => unsupported; readonly SortedDictionary obsoleted = new (); @@ -53,11 +53,12 @@ public bool IsSupported { // a platform is supported if: // 1. The supported version is not null, either the default version or a specific one // 2. The default version is not in the unsupported list - return SupportedVersion is not null && !unsupported.ContainsKey (defaultVersion); + return SupportedVersion is not null + && !unsupported.ContainsKey (PlatformSupportVersion.ImplicitDefault) + && !unsupported.ContainsKey (PlatformSupportVersion.ExplicitDefault); } } - /// /// Returns if a version is the default version. /// @@ -65,9 +66,8 @@ public bool IsSupported { /// True if the version is default. public static bool IsDefaultVersion (Version version) => version == defaultVersion; - - PlatformAvailability (ApplePlatform platform, Version? supportedVersion, - SortedDictionary unsupportedVersions, + PlatformAvailability (ApplePlatform platform, PlatformSupportVersion? supportedVersion, + SortedDictionary unsupportedVersions, SortedDictionary obsoletedVersions) { Platform = platform; @@ -126,11 +126,9 @@ public PlatformAvailability MergeWithParent (PlatformAvailability? parent) // 2. if supported in the platform, we will always pick the larges version between // the two. Now, because we might be unsupported - var supportedVersion = (parent.Value.SupportedVersion > SupportedVersion) - ? parent.Value.SupportedVersion - : SupportedVersion; + var supportedVersion = PlatformSupportVersion.Max (parent.Value.SupportedVersion, SupportedVersion); if (supportedVersion is not null) - builder.AddSupportedVersion (new (supportedVersion, SupportKind.Explicit)); + builder.AddSupportedVersion (supportedVersion.Value); // similar to the unsupported versions, if the parent has obsolete ones, we will add them foreach (var (version, obsoleteInfo) in parent.Value.obsoleted) { @@ -148,7 +146,7 @@ public PlatformAvailability MergeWithParent (PlatformAvailability? parent) public bool Equals (PlatformAvailability other) { var obsoleteComparer = new DictionaryComparer (); - var unsupportedComparer = new DictionaryComparer (); + var unsupportedComparer = new DictionaryComparer (); var x = Equals (SupportedVersion, other.SupportedVersion); return Platform == other.Platform && @@ -184,9 +182,9 @@ public override string ToString () { var sb = new StringBuilder ("{ "); sb.Append ($"Platform: '{Platform}', "); - sb.Append ($"Supported: '{SupportedVersion?.ToString ()}', "); + sb.Append ($"Supported: '{SupportedVersion?.Version.ToString ()}', "); sb.Append ("Unsupported: ["); - sb.AppendJoin (", ", unsupported.Select (v => $"'{v.Key}': '{v.Value?.ToString () ?? "null"}'")); + sb.AppendJoin (", ", unsupported.Select (v => $"'{v.Key.Version}': '{v.Value?.ToString () ?? "null"}'")); sb.Append ("], Obsoleted: ["); sb.AppendJoin (", ", obsoleted.Select (v => $"'{v.Key}': ('{v.Value.Message?.ToString () ?? "null"}', '{v.Value.Url?.ToString () ?? "null"}')")); sb.Append ("] }"); diff --git a/src/rgen/Microsoft.Macios.Generator/Availability/PlatformSupportVersion.cs b/src/rgen/Microsoft.Macios.Generator/Availability/PlatformSupportVersion.cs index e6966fd4cb57..3cbcd1b8c9c7 100644 --- a/src/rgen/Microsoft.Macios.Generator/Availability/PlatformSupportVersion.cs +++ b/src/rgen/Microsoft.Macios.Generator/Availability/PlatformSupportVersion.cs @@ -8,7 +8,8 @@ namespace Microsoft.Macios.Generator.Availability; /// /// Represents a platform support version, combining a version number and a support kind. /// -public readonly record struct PlatformSupportVersion { +public readonly record struct PlatformSupportVersion : IComparable { + /// /// Gets the version number. /// @@ -60,12 +61,17 @@ public PlatformSupportVersion (Version version) : this (version, SupportKind.Exp /// The platform support version with the highest precedence. If the kinds are the same, it returns the one with the greater version. /// If the kinds are different, it returns the one with the higher kind value. /// - public static PlatformSupportVersion Max (PlatformSupportVersion v1, PlatformSupportVersion v2) + public static PlatformSupportVersion? Max (PlatformSupportVersion? v1, PlatformSupportVersion? v2) { - if (v1.Kind == v2.Kind) { - return v1.Version >= v2.Version ? v1 : v2; + if (v1 is null) + return v2; + if (v2 is null) + return v1; + + if (v1.Value.Kind == v2.Value.Kind) { + return v1.Value.Version >= v2.Value.Version ? v1 : v2; } - return (int) v1.Kind > (int) v2.Kind ? v1 : v2; + return (int) v1.Value.Kind > (int) v2.Value.Kind ? v1 : v2; } /// @@ -77,11 +83,68 @@ public static PlatformSupportVersion Max (PlatformSupportVersion v1, PlatformSup /// The platform support version with the lowest version if the kinds are the same. /// If the kinds are different, it returns the one with the higher kind value. /// - public static PlatformSupportVersion Min (PlatformSupportVersion v1, PlatformSupportVersion v2) + public static PlatformSupportVersion? Min (PlatformSupportVersion? v1, PlatformSupportVersion? v2) { - if (v1.Kind == v2.Kind) { - return v1.Version <= v2.Version ? v1 : v2; + if (v1 is null) + return v2; + if (v2 is null) + return v1; + if (v1.Value.Kind == v2.Value.Kind) { + return v1.Value.Version <= v2.Value.Version ? v1 : v2; } - return (int) v1.Kind > (int) v2.Kind ? v1 : v2; + return (int) v1.Value.Kind > (int) v2.Value.Kind ? v1 : v2; + } + + /// + public int CompareTo (PlatformSupportVersion other) + { + var versionComparison = Version.CompareTo (other.Version); + if (versionComparison != 0) + return versionComparison; + return Kind.CompareTo (other.Kind); + } + + /// + /// Compares two instances to determine if the left is less than the right. + /// + /// The first to compare. + /// The second to compare. + /// true if the left instance is less than the right instance; otherwise, false. + public static bool operator < (PlatformSupportVersion left, PlatformSupportVersion right) + { + return left.CompareTo (right) < 0; + } + + /// + /// Compares two instances to determine if the left is greater than the right. + /// + /// The first to compare. + /// The second to compare. + /// true if the left instance is greater than the right instance; otherwise, false. + public static bool operator > (PlatformSupportVersion left, PlatformSupportVersion right) + { + return left.CompareTo (right) > 0; + } + + /// + /// Compares two instances to determine if the left is less than or equal to the right. + /// + /// The first to compare. + /// The second to compare. + /// true if the left instance is less than or equal to the right instance; otherwise, false. + public static bool operator <= (PlatformSupportVersion left, PlatformSupportVersion right) + { + return left.CompareTo (right) <= 0; + } + + /// + /// Compares two instances to determine if the left is greater than or equal to the right. + /// + /// The first to compare. + /// The second to compare. + /// true if the left instance is greater than or equal to the right instance; otherwise, false. + public static bool operator >= (PlatformSupportVersion left, PlatformSupportVersion right) + { + return left.CompareTo (right) >= 0; } } diff --git a/src/rgen/Microsoft.Macios.Generator/IO/TabbedStringBuilderAvailability.cs b/src/rgen/Microsoft.Macios.Generator/IO/TabbedStringBuilderAvailability.cs index f3d6732c15ad..9870b04abd9f 100644 --- a/src/rgen/Microsoft.Macios.Generator/IO/TabbedStringBuilderAvailability.cs +++ b/src/rgen/Microsoft.Macios.Generator/IO/TabbedStringBuilderAvailability.cs @@ -15,15 +15,15 @@ public static TabbedWriter AppendMemberAvailability (this TabbedWr foreach (var availability in allPlatformsAvailability.PlatformAvailabilities) { var platformName = availability.Platform.AsString ().ToLower (); if (availability.SupportedVersion is not null) { - var versionStr = (PlatformAvailability.IsDefaultVersion (availability.SupportedVersion)) + var versionStr = (PlatformAvailability.IsDefaultVersion (availability.SupportedVersion.Value.Version)) ? string.Empty - : availability.SupportedVersion.ToString (); + : availability.SupportedVersion.Value.Version.ToString (); self.WriteLine ($"[SupportedOSPlatform (\"{platformName}{versionStr}\")]"); } // loop over the unsupported versions of the platform foreach (var (version, message) in availability.UnsupportedVersions) { - var versionStr = (PlatformAvailability.IsDefaultVersion (version)) ? string.Empty : version.ToString (); + var versionStr = (PlatformAvailability.IsDefaultVersion (version.Version)) ? string.Empty : version.Version.ToString (); if (message is null) { self.WriteLine ($"[UnsupportedOSPlatform (\"{platformName}{versionStr}\")]"); } else { @@ -61,15 +61,15 @@ public static async Task> AppendMemberAvailabilityAsy foreach (var availability in allPlatformsAvailability.PlatformAvailabilities) { var platformName = availability.Platform.AsString ().ToLower (); if (availability.SupportedVersion is not null) { - var versionStr = (PlatformAvailability.IsDefaultVersion (availability.SupportedVersion)) + var versionStr = (PlatformAvailability.IsDefaultVersion (availability.SupportedVersion.Value.Version)) ? string.Empty - : availability.SupportedVersion.ToString (); + : availability.SupportedVersion.Value.Version.ToString (); await self.WriteLineAsync ($"[SupportedOSPlatform (\"{platformName}{versionStr}\")]"); } // loop over the unsupported versions of the platform foreach (var (version, message) in availability.UnsupportedVersions) { - var versionStr = (PlatformAvailability.IsDefaultVersion (version)) ? string.Empty : version.ToString (); + var versionStr = (PlatformAvailability.IsDefaultVersion (version.Version)) ? string.Empty : version.Version.ToString (); if (message is null) { await self.WriteLineAsync ($"[UnsupportedOSPlatform (\"{platformName}{versionStr}\")]"); } else { diff --git a/tests/rgen/Microsoft.Macios.Generator.Tests/Availability/PlatformAvailabilityTests.cs b/tests/rgen/Microsoft.Macios.Generator.Tests/Availability/PlatformAvailabilityTests.cs index 9b4a78eeec10..d8863d65b962 100644 --- a/tests/rgen/Microsoft.Macios.Generator.Tests/Availability/PlatformAvailabilityTests.cs +++ b/tests/rgen/Microsoft.Macios.Generator.Tests/Availability/PlatformAvailabilityTests.cs @@ -22,7 +22,8 @@ public void SupportPlatform (ApplePlatform platform, string attributePlatformNam var attrData = new SupportedOSPlatformData (attributePlatformName); builder.Add (attrData); var availability = builder.ToImmutable (); - Assert.Equal (availability.SupportedVersion, new Version ()); + Assert.NotNull (availability.SupportedVersion); + Assert.Equal (availability.SupportedVersion.Value.Version, new Version ()); } [Theory] @@ -52,7 +53,8 @@ public void SupportPlatformWithPlatformAttributeWithVersion (ApplePlatform platf builder.Add (attrData); var expectedVersion = Version.Parse (version); var availability = builder.ToImmutable (); - Assert.Equal (expectedVersion, availability.SupportedVersion); + Assert.NotNull (availability.SupportedVersion); + Assert.Equal (expectedVersion, availability.SupportedVersion.Value.Version); } [Theory] @@ -73,7 +75,8 @@ public void SupportPlatformAndThenAddHigherVersion (ApplePlatform platform, stri var expectedVersion = Version.Parse (version); // should be most specific version var availability = builder.ToImmutable (); - Assert.Equal (expectedVersion, availability.SupportedVersion); + Assert.NotNull (availability.SupportedVersion); + Assert.Equal (expectedVersion, availability.SupportedVersion.Value.Version); } [Theory] @@ -94,7 +97,8 @@ public void SupportPlatformSeveralVersionsPickHigherVersion (ApplePlatform platf var expected = Version.Parse (expectedVersion); var availability = builder.ToImmutable (); - Assert.Equal (expected, availability.SupportedVersion); + Assert.NotNull (availability.SupportedVersion); + Assert.Equal (expected, availability.SupportedVersion.Value.Version); } [Theory] @@ -107,11 +111,10 @@ public void UnsupportPlatform (ApplePlatform platform, string attributePlatformN var builder = PlatformAvailability.CreateBuilder (platform); var attrData = new UnsupportedOSPlatformData (attributePlatformName); builder.Add (attrData); - var defaultVersion = new Version (); var availability = builder.ToImmutable (); - Assert.Contains (defaultVersion, availability.UnsupportedVersions.Keys); + Assert.Contains (PlatformSupportVersion.ExplicitDefault, availability.UnsupportedVersions.Keys); Assert.Single (availability.UnsupportedVersions); - Assert.Null (availability.UnsupportedVersions [defaultVersion]); + Assert.Null (availability.UnsupportedVersions [PlatformSupportVersion.ExplicitDefault]); } [Theory] @@ -124,11 +127,10 @@ public void UnsupportPlatformWithMessage (ApplePlatform platform, string attribu var builder = PlatformAvailability.CreateBuilder (platform); var attrData = new UnsupportedOSPlatformData (attributePlatformName, message); builder.Add (attrData); - var defaultVersion = new Version (); var availability = builder.ToImmutable (); - Assert.Contains (defaultVersion, availability.UnsupportedVersions.Keys); + Assert.Contains (PlatformSupportVersion.ExplicitDefault, availability.UnsupportedVersions.Keys); Assert.Single (availability.UnsupportedVersions); - Assert.Equal (message, availability.UnsupportedVersions [defaultVersion]); + Assert.Equal (message, availability.UnsupportedVersions [PlatformSupportVersion.ExplicitDefault]); } [Theory] @@ -145,11 +147,10 @@ public void UnsupportVersionAndPlatform (ApplePlatform platform, string attribut var platformAttrData = new UnsupportedOSPlatformData (platform.AsString ().ToLower (), message); builder.Add (versionAttrData); builder.Add (platformAttrData); - var defaultVersion = new Version (); var availability = builder.ToImmutable (); - Assert.Contains (defaultVersion, availability.UnsupportedVersions.Keys); + Assert.Contains (PlatformSupportVersion.ExplicitDefault, availability.UnsupportedVersions.Keys); Assert.Single (availability.UnsupportedVersions); - Assert.Equal (message, availability.UnsupportedVersions [defaultVersion]); + Assert.Equal (message, availability.UnsupportedVersions [PlatformSupportVersion.ExplicitDefault]); } [Theory] @@ -182,8 +183,8 @@ public void SupportAndUnsupportPlatform (ApplePlatform platform, string? message var availability = builder.ToImmutable (); Assert.Null (availability.SupportedVersion); Assert.Single (availability.UnsupportedVersions); - Assert.Contains (new Version (), availability.UnsupportedVersions.Keys); - Assert.Equal (message, availability.UnsupportedVersions [new Version ()]); + Assert.Contains (PlatformSupportVersion.ExplicitDefault, availability.UnsupportedVersions.Keys); + Assert.Equal (message, availability.UnsupportedVersions [PlatformSupportVersion.ExplicitDefault]); } [Theory] @@ -213,8 +214,8 @@ public void UnsupportSeveralVersionAndPlatform (ApplePlatform platform, string [ var availability = builder.ToImmutable (); Assert.Single (availability.UnsupportedVersions); - Assert.Contains (new Version (), availability.UnsupportedVersions.Keys); - Assert.Equal (message, availability.UnsupportedVersions [new Version ()]); + Assert.Contains (PlatformSupportVersion.ExplicitDefault, availability.UnsupportedVersions.Keys); + Assert.Equal (message, availability.UnsupportedVersions [PlatformSupportVersion.ExplicitDefault]); } [Theory] @@ -239,10 +240,13 @@ public void UnsupportedSeveralVersions (ApplePlatform platform, string [] versio } var availability = builder.ToImmutable (); + // get all the versions we added + var unsupported = availability.UnsupportedVersions.Keys + .Select (x => x.Version).ToArray (); // assert that the version is present foreach (var v in versions) { var currentVersion = Version.Parse (v); - Assert.Contains (currentVersion, availability.UnsupportedVersions.Keys); + Assert.Contains (currentVersion, unsupported); } }