Skip to content

Commit

Permalink
Recognize MacCatalyst as a superset of iOS (#55550)
Browse files Browse the repository at this point in the history
Recognize MacCatalyst as a superset of iOS and apply platform guard attributes that will inform the analyzer of the relationship.
  • Loading branch information
jeffhandley authored Jul 13, 2021
1 parent ce09822 commit 14854e2
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 14 deletions.
15 changes: 11 additions & 4 deletions src/libraries/System.Private.CoreLib/src/System/OperatingSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@

using System.Diagnostics;
using System.Runtime.Serialization;
using System.Runtime.Versioning;

namespace System
{
public sealed class OperatingSystem : ISerializable, ICloneable
{
#if TARGET_UNIX && !TARGET_OSX
#if TARGET_UNIX && !TARGET_OSX && !TARGET_MACCATALYST && !TARGET_IOS
private static readonly string s_osPlatformName = Interop.Sys.GetUnixName();
#endif

Expand Down Expand Up @@ -102,6 +103,10 @@ public static bool IsOSPlatform(string platform)
return platform.Equals("WINDOWS", StringComparison.OrdinalIgnoreCase);
#elif TARGET_OSX
return platform.Equals("OSX", StringComparison.OrdinalIgnoreCase) || platform.Equals("MACOS", StringComparison.OrdinalIgnoreCase);
#elif TARGET_MACCATALYST
return platform.Equals("MACCATALYST", StringComparison.OrdinalIgnoreCase) || platform.Equals("IOS", StringComparison.OrdinalIgnoreCase);
#elif TARGET_IOS
return platform.Equals("IOS", StringComparison.OrdinalIgnoreCase);
#elif TARGET_UNIX
return platform.Equals(s_osPlatformName, StringComparison.OrdinalIgnoreCase);
#else
Expand Down Expand Up @@ -173,18 +178,20 @@ public static bool IsAndroidVersionAtLeast(int major, int minor = 0, int build =
=> IsAndroid() && IsOSVersionAtLeast(major, minor, build, revision);

/// <summary>
/// Indicates whether the current application is running on iOS.
/// Indicates whether the current application is running on iOS or MacCatalyst.
/// </summary>
[SupportedOSPlatformGuard("maccatalyst")]
public static bool IsIOS() =>
#if TARGET_IOS
#if TARGET_IOS || TARGET_MACCATALYST
true;
#else
false;
#endif

/// <summary>
/// Check for the iOS version (returned by 'libobjc.get_operatingSystemVersion') with a >= version comparison. Used to guard APIs that were added in the given iOS release.
/// Check for the iOS/MacCatalyst version (returned by 'libobjc.get_operatingSystemVersion') with a >= version comparison. Used to guard APIs that were added in the given iOS release.
/// </summary>
[SupportedOSPlatformGuard("maccatalyst")]
public static bool IsIOSVersionAtLeast(int major, int minor = 0, int build = 0)
=> IsIOS() && IsOSVersionAtLeast(major, minor, build, 0);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,23 @@ public static void OSX_Is_Treated_as_macOS()
[Fact, PlatformSpecific(TestPlatforms.MacCatalyst)]
public static void TestIsOSVersionAtLeast_MacCatalyst() => TestIsOSVersionAtLeast("MacCatalyst");

[Fact, PlatformSpecific(TestPlatforms.MacCatalyst)]
public static void MacCatalyst_Is_Also_iOS()
{
Assert.True(OperatingSystem.IsOSPlatform("IOS"));
Assert.True(OperatingSystem.IsIOS());

AssertVersionChecks(true, (major, minor, build, revision) => OperatingSystem.IsOSPlatformVersionAtLeast("IOS", major, minor, build, revision));
AssertVersionChecks(true, (major, minor, build) => OperatingSystem.IsOSPlatformVersionAtLeast("IOS", major, minor, build));
}

[Fact, PlatformSpecific(TestPlatforms.iOS)]
public static void IOS_Is_Not_Also_MacCatalyst()
{
Assert.False(OperatingSystem.IsOSPlatform("MacCatalyst"));
Assert.False(OperatingSystem.IsMacCatalyst());
}

[Fact, PlatformSpecific(TestPlatforms.tvOS)]
public static void TestIsOSPlatform_TvOS() => TestIsOSPlatform("tvOS", OperatingSystem.IsTvOS);

Expand All @@ -146,13 +163,13 @@ public static void OSX_Is_Treated_as_macOS()

private static void TestIsOSPlatform(string currentOSName, Func<bool> currentOSCheck)
{
foreach (string platfromName in AllKnownPlatformNames)
foreach (string platformName in AllKnownPlatformNames)
{
bool expected = currentOSName.Equals(platfromName, StringComparison.OrdinalIgnoreCase);
bool expected = currentOSName.Equals(platformName, StringComparison.OrdinalIgnoreCase);

Assert.Equal(expected, OperatingSystem.IsOSPlatform(platfromName));
Assert.Equal(expected, OperatingSystem.IsOSPlatform(platfromName.ToUpper()));
Assert.Equal(expected, OperatingSystem.IsOSPlatform(platfromName.ToLower()));
Assert.Equal(expected, OperatingSystem.IsOSPlatform(platformName));
Assert.Equal(expected, OperatingSystem.IsOSPlatform(platformName.ToUpper()));
Assert.Equal(expected, OperatingSystem.IsOSPlatform(platformName.ToLower()));
}

Assert.True(currentOSCheck());
Expand All @@ -176,13 +193,13 @@ private static void TestIsOSPlatform(string currentOSName, Func<bool> currentOSC

private static void TestIsOSVersionAtLeast(string currentOSName)
{
foreach (string platfromName in AllKnownPlatformNames)
foreach (string platformName in AllKnownPlatformNames)
{
bool isCurrentOS = currentOSName.Equals(platfromName, StringComparison.OrdinalIgnoreCase);
bool isCurrentOS = currentOSName.Equals(platformName, StringComparison.OrdinalIgnoreCase);

AssertVersionChecks(isCurrentOS, (major, minor, build, revision) => OperatingSystem.IsOSPlatformVersionAtLeast(platfromName, major, minor, build, revision));
AssertVersionChecks(isCurrentOS, (major, minor, build, revision) => OperatingSystem.IsOSPlatformVersionAtLeast(platfromName.ToLower(), major, minor, build, revision));
AssertVersionChecks(isCurrentOS, (major, minor, build, revision) => OperatingSystem.IsOSPlatformVersionAtLeast(platfromName.ToUpper(), major, minor, build, revision));
AssertVersionChecks(isCurrentOS, (major, minor, build, revision) => OperatingSystem.IsOSPlatformVersionAtLeast(platformName, major, minor, build, revision));
AssertVersionChecks(isCurrentOS, (major, minor, build, revision) => OperatingSystem.IsOSPlatformVersionAtLeast(platformName.ToLower(), major, minor, build, revision));
AssertVersionChecks(isCurrentOS, (major, minor, build, revision) => OperatingSystem.IsOSPlatformVersionAtLeast(platformName.ToUpper(), major, minor, build, revision));
}

AssertVersionChecks(currentOSName.Equals("Android", StringComparison.OrdinalIgnoreCase), OperatingSystem.IsAndroidVersionAtLeast);
Expand Down
2 changes: 2 additions & 0 deletions src/libraries/System.Runtime/ref/System.Runtime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4965,7 +4965,9 @@ public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, S
public static bool IsFreeBSDVersionAtLeast(int major, int minor = 0, int build = 0, int revision = 0) { throw null; }
public static bool IsAndroid() { throw null; }
public static bool IsAndroidVersionAtLeast(int major, int minor = 0, int build = 0, int revision = 0) { throw null; }
[System.Runtime.Versioning.SupportedOSPlatformGuardAttribute("maccatalyst")]
public static bool IsIOS() { throw null; }
[System.Runtime.Versioning.SupportedOSPlatformGuardAttribute("maccatalyst")]
public static bool IsIOSVersionAtLeast(int major, int minor = 0, int build = 0) { throw null; }
public static bool IsMacOS() { throw null; }
public static bool IsMacOSVersionAtLeast(int major, int minor = 0, int build = 0) { throw null; }
Expand Down

0 comments on commit 14854e2

Please sign in to comment.