From 14854e209868749262bd58a64407b3802177542f Mon Sep 17 00:00:00 2001 From: Jeff Handley Date: Tue, 13 Jul 2021 14:33:41 -0700 Subject: [PATCH] Recognize MacCatalyst as a superset of iOS (#55550) Recognize MacCatalyst as a superset of iOS and apply platform guard attributes that will inform the analyzer of the relationship. --- .../src/System/OperatingSystem.cs | 15 ++++++-- .../tests/System/OperatingSystemTests.cs | 37 ++++++++++++++----- .../System.Runtime/ref/System.Runtime.cs | 2 + 3 files changed, 40 insertions(+), 14 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/OperatingSystem.cs b/src/libraries/System.Private.CoreLib/src/System/OperatingSystem.cs index a0e17bfb34961..ce70c49dfc147 100644 --- a/src/libraries/System.Private.CoreLib/src/System/OperatingSystem.cs +++ b/src/libraries/System.Private.CoreLib/src/System/OperatingSystem.cs @@ -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 @@ -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 @@ -173,18 +178,20 @@ public static bool IsAndroidVersionAtLeast(int major, int minor = 0, int build = => IsAndroid() && IsOSVersionAtLeast(major, minor, build, revision); /// - /// Indicates whether the current application is running on iOS. + /// Indicates whether the current application is running on iOS or MacCatalyst. /// + [SupportedOSPlatformGuard("maccatalyst")] public static bool IsIOS() => -#if TARGET_IOS +#if TARGET_IOS || TARGET_MACCATALYST true; #else false; #endif /// - /// 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. /// + [SupportedOSPlatformGuard("maccatalyst")] public static bool IsIOSVersionAtLeast(int major, int minor = 0, int build = 0) => IsIOS() && IsOSVersionAtLeast(major, minor, build, 0); diff --git a/src/libraries/System.Runtime.Extensions/tests/System/OperatingSystemTests.cs b/src/libraries/System.Runtime.Extensions/tests/System/OperatingSystemTests.cs index 6a6b1cdd6b6a2..405cf4373f9b8 100644 --- a/src/libraries/System.Runtime.Extensions/tests/System/OperatingSystemTests.cs +++ b/src/libraries/System.Runtime.Extensions/tests/System/OperatingSystemTests.cs @@ -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); @@ -146,13 +163,13 @@ public static void OSX_Is_Treated_as_macOS() private static void TestIsOSPlatform(string currentOSName, Func 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()); @@ -176,13 +193,13 @@ private static void TestIsOSPlatform(string currentOSName, Func 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); diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index 2656da8c99964..35fe09cc66295 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -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; }