From 3090eca84dada6395daa1a6693f23d3b1636b532 Mon Sep 17 00:00:00 2001 From: Sebastien Pouliot Date: Thu, 15 Oct 2020 08:57:47 -0400 Subject: [PATCH] [tests][intro] Detect cases where [Unavailable] is mis-used (#9871) For each platform the presence of `[Unavailable]` should mean there are no other availability (introduced, deprecated or obsoleted) attributes on the same member. Also check if the type is unavailable. In that case no member should, for that platform, have other availability attributes. Also fix failures - all in WatchKit which was removed from iOS. --- src/WatchKit/iOS/WKAccessibility.cs | 2 +- .../iOS/WKAccessibilityImageRegion.cs | 1 - src/WatchKit/iOS/WKErrorCode.cs | 1 - src/WatchKit/iOS/WKInterfaceButton.cs | 1 - src/WatchKit/iOS/WKInterfaceController.cs | 1 - src/WatchKit/iOS/WKInterfaceDate.cs | 1 - src/WatchKit/iOS/WKInterfaceDevice.cs | 1 - src/WatchKit/iOS/WKInterfaceGroup.cs | 1 - src/WatchKit/iOS/WKInterfaceImage.cs | 1 - src/WatchKit/iOS/WKInterfaceLabel.cs | 1 - src/WatchKit/iOS/WKInterfaceMap.cs | 1 - src/WatchKit/iOS/WKInterfaceObject.cs | 1 - src/WatchKit/iOS/WKInterfaceSeparator.cs | 1 - src/WatchKit/iOS/WKInterfaceSlider.cs | 1 - src/WatchKit/iOS/WKInterfaceSwitch.cs | 1 - src/WatchKit/iOS/WKInterfaceTable.cs | 1 - src/WatchKit/iOS/WKInterfaceTimer.cs | 1 - src/WatchKit/iOS/WKMenuItemIcon.cs | 1 - src/WatchKit/iOS/WKTextInputMode.cs | 1 - .../WKUserNotificationInterfaceController.cs | 1 - .../iOS/WKUserNotificationInterfaceType.cs | 2 +- src/watchkit.cs | 140 +++++++----------- tests/introspection/ApiAvailabilityTest.cs | 75 ++++++++-- 23 files changed, 113 insertions(+), 125 deletions(-) diff --git a/src/WatchKit/iOS/WKAccessibility.cs b/src/WatchKit/iOS/WKAccessibility.cs index 6819aecdfd..62be304e61 100644 --- a/src/WatchKit/iOS/WKAccessibility.cs +++ b/src/WatchKit/iOS/WKAccessibility.cs @@ -5,7 +5,7 @@ using System.ComponentModel; using ObjCRuntime; namespace WatchKit { - [Introduced (PlatformName.iOS, 8,2, PlatformArchitecture.All)] + [Unavailable (PlatformName.iOS, PlatformArchitecture.All)] [Obsolete (Constants.WatchKitRemoved)] [EditorBrowsable (EditorBrowsableState.Never)] diff --git a/src/WatchKit/iOS/WKAccessibilityImageRegion.cs b/src/WatchKit/iOS/WKAccessibilityImageRegion.cs index 2a8978c3a6..401fb9b6b2 100644 --- a/src/WatchKit/iOS/WKAccessibilityImageRegion.cs +++ b/src/WatchKit/iOS/WKAccessibilityImageRegion.cs @@ -8,7 +8,6 @@ using ObjCRuntime; namespace WatchKit { [Register ("WKAccessibilityImageRegion", SkipRegistration = true)] - [Introduced (PlatformName.iOS, 8,2, PlatformArchitecture.All)] [Unavailable (PlatformName.iOS, PlatformArchitecture.All)] [Obsolete (Constants.WatchKitRemoved)] [EditorBrowsable (EditorBrowsableState.Never)] diff --git a/src/WatchKit/iOS/WKErrorCode.cs b/src/WatchKit/iOS/WKErrorCode.cs index 07537e5760..cfe4ea2633 100644 --- a/src/WatchKit/iOS/WKErrorCode.cs +++ b/src/WatchKit/iOS/WKErrorCode.cs @@ -6,7 +6,6 @@ using Foundation; using ObjCRuntime; namespace WatchKit { - [Introduced (PlatformName.iOS, 8,2, PlatformArchitecture.All)] [Unavailable (PlatformName.iOS, PlatformArchitecture.All)] [Obsolete (Constants.WatchKitRemoved)] [EditorBrowsable (EditorBrowsableState.Never)] diff --git a/src/WatchKit/iOS/WKInterfaceButton.cs b/src/WatchKit/iOS/WKInterfaceButton.cs index dfd99fdd0b..01aa65ff3e 100644 --- a/src/WatchKit/iOS/WKInterfaceButton.cs +++ b/src/WatchKit/iOS/WKInterfaceButton.cs @@ -7,7 +7,6 @@ using ObjCRuntime; namespace WatchKit { [Register ("WKInterfaceButton", SkipRegistration = true)] - [Introduced (PlatformName.iOS, 8,2, PlatformArchitecture.All)] [Unavailable (PlatformName.iOS, PlatformArchitecture.All)] [Obsolete (Constants.WatchKitRemoved)] [EditorBrowsable (EditorBrowsableState.Never)] diff --git a/src/WatchKit/iOS/WKInterfaceController.cs b/src/WatchKit/iOS/WKInterfaceController.cs index 7102c542fe..d455c00793 100644 --- a/src/WatchKit/iOS/WKInterfaceController.cs +++ b/src/WatchKit/iOS/WKInterfaceController.cs @@ -10,7 +10,6 @@ using UIKit; namespace WatchKit { [Register ("WKInterfaceController", SkipRegistration = true)] - [Introduced (PlatformName.iOS, 8,2, PlatformArchitecture.All)] [Unavailable (PlatformName.iOS, PlatformArchitecture.All)] [Obsolete (Constants.WatchKitRemoved)] [EditorBrowsable (EditorBrowsableState.Never)] diff --git a/src/WatchKit/iOS/WKInterfaceDate.cs b/src/WatchKit/iOS/WKInterfaceDate.cs index c693576133..c55dd93ea8 100644 --- a/src/WatchKit/iOS/WKInterfaceDate.cs +++ b/src/WatchKit/iOS/WKInterfaceDate.cs @@ -7,7 +7,6 @@ using ObjCRuntime; namespace WatchKit { [Register ("WKInterfaceDate", SkipRegistration = true)] - [Introduced (PlatformName.iOS, 8,2, PlatformArchitecture.All)] [Unavailable (PlatformName.iOS, PlatformArchitecture.All)] [Obsolete (Constants.WatchKitRemoved)] [EditorBrowsable (EditorBrowsableState.Never)] diff --git a/src/WatchKit/iOS/WKInterfaceDevice.cs b/src/WatchKit/iOS/WKInterfaceDevice.cs index c7b3d7c27c..06329fdf47 100644 --- a/src/WatchKit/iOS/WKInterfaceDevice.cs +++ b/src/WatchKit/iOS/WKInterfaceDevice.cs @@ -10,7 +10,6 @@ using UIKit; namespace WatchKit { [Register ("WKInterfaceDevice", SkipRegistration = true)] - [Introduced (PlatformName.iOS, 8,2, PlatformArchitecture.All)] [Unavailable (PlatformName.iOS, PlatformArchitecture.All)] [Obsolete (Constants.WatchKitRemoved)] [EditorBrowsable (EditorBrowsableState.Never)] diff --git a/src/WatchKit/iOS/WKInterfaceGroup.cs b/src/WatchKit/iOS/WKInterfaceGroup.cs index 91edd13bac..d741520c60 100644 --- a/src/WatchKit/iOS/WKInterfaceGroup.cs +++ b/src/WatchKit/iOS/WKInterfaceGroup.cs @@ -7,7 +7,6 @@ using ObjCRuntime; namespace WatchKit { [Register ("WKInterfaceGroup", SkipRegistration = true)] - [Introduced (PlatformName.iOS, 8,2, PlatformArchitecture.All)] [Unavailable (PlatformName.iOS, PlatformArchitecture.All)] [Obsolete (Constants.WatchKitRemoved)] [EditorBrowsable (EditorBrowsableState.Never)] diff --git a/src/WatchKit/iOS/WKInterfaceImage.cs b/src/WatchKit/iOS/WKInterfaceImage.cs index 282d778fb2..f21958714d 100644 --- a/src/WatchKit/iOS/WKInterfaceImage.cs +++ b/src/WatchKit/iOS/WKInterfaceImage.cs @@ -7,7 +7,6 @@ using ObjCRuntime; namespace WatchKit { [Register ("WKInterfaceImage", SkipRegistration = true)] - [Introduced (PlatformName.iOS, 8,2, PlatformArchitecture.All)] [Unavailable (PlatformName.iOS, PlatformArchitecture.All)] [Obsolete (Constants.WatchKitRemoved)] [EditorBrowsable (EditorBrowsableState.Never)] diff --git a/src/WatchKit/iOS/WKInterfaceLabel.cs b/src/WatchKit/iOS/WKInterfaceLabel.cs index fede124a83..8a208a61cf 100644 --- a/src/WatchKit/iOS/WKInterfaceLabel.cs +++ b/src/WatchKit/iOS/WKInterfaceLabel.cs @@ -7,7 +7,6 @@ using ObjCRuntime; namespace WatchKit { [Register ("WKInterfaceLabel", SkipRegistration = true)] - [Introduced (PlatformName.iOS, 8,2, PlatformArchitecture.All)] [Unavailable (PlatformName.iOS, PlatformArchitecture.All)] [Obsolete (Constants.WatchKitRemoved)] [EditorBrowsable (EditorBrowsableState.Never)] diff --git a/src/WatchKit/iOS/WKInterfaceMap.cs b/src/WatchKit/iOS/WKInterfaceMap.cs index 722782e805..1c64f33a59 100644 --- a/src/WatchKit/iOS/WKInterfaceMap.cs +++ b/src/WatchKit/iOS/WKInterfaceMap.cs @@ -8,7 +8,6 @@ using ObjCRuntime; namespace WatchKit { [Register ("WKInterfaceMap", SkipRegistration = true)] - [Introduced (PlatformName.iOS, 8,2, PlatformArchitecture.All)] [Unavailable (PlatformName.iOS, PlatformArchitecture.All)] [Obsolete (Constants.WatchKitRemoved)] [EditorBrowsable (EditorBrowsableState.Never)] diff --git a/src/WatchKit/iOS/WKInterfaceObject.cs b/src/WatchKit/iOS/WKInterfaceObject.cs index f3d5ef47a6..faed3fc5e2 100644 --- a/src/WatchKit/iOS/WKInterfaceObject.cs +++ b/src/WatchKit/iOS/WKInterfaceObject.cs @@ -9,7 +9,6 @@ using UIKit; namespace WatchKit { [Register ("WKInterfaceObject", SkipRegistration = true)] - [Introduced (PlatformName.iOS, 8,2, PlatformArchitecture.All)] [Unavailable (PlatformName.iOS, PlatformArchitecture.All)] [Obsolete (Constants.WatchKitRemoved)] [EditorBrowsable (EditorBrowsableState.Never)] diff --git a/src/WatchKit/iOS/WKInterfaceSeparator.cs b/src/WatchKit/iOS/WKInterfaceSeparator.cs index 81b2ebd2f6..e7074cbe86 100644 --- a/src/WatchKit/iOS/WKInterfaceSeparator.cs +++ b/src/WatchKit/iOS/WKInterfaceSeparator.cs @@ -7,7 +7,6 @@ using ObjCRuntime; namespace WatchKit { [Register ("WKInterfaceSeparator", SkipRegistration = true)] - [Introduced (PlatformName.iOS, 8,2, PlatformArchitecture.All)] [Unavailable (PlatformName.iOS, PlatformArchitecture.All)] [Obsolete (Constants.WatchKitRemoved)] [EditorBrowsable (EditorBrowsableState.Never)] diff --git a/src/WatchKit/iOS/WKInterfaceSlider.cs b/src/WatchKit/iOS/WKInterfaceSlider.cs index dbfd37ca53..885524cba6 100644 --- a/src/WatchKit/iOS/WKInterfaceSlider.cs +++ b/src/WatchKit/iOS/WKInterfaceSlider.cs @@ -7,7 +7,6 @@ using ObjCRuntime; namespace WatchKit { [Register ("WKInterfaceSlider", SkipRegistration = true)] - [Introduced (PlatformName.iOS, 8,2, PlatformArchitecture.All)] [Unavailable (PlatformName.iOS, PlatformArchitecture.All)] [Obsolete (Constants.WatchKitRemoved)] [EditorBrowsable (EditorBrowsableState.Never)] diff --git a/src/WatchKit/iOS/WKInterfaceSwitch.cs b/src/WatchKit/iOS/WKInterfaceSwitch.cs index fe0081a8ba..8f0b4a8c4c 100644 --- a/src/WatchKit/iOS/WKInterfaceSwitch.cs +++ b/src/WatchKit/iOS/WKInterfaceSwitch.cs @@ -7,7 +7,6 @@ using ObjCRuntime; namespace WatchKit { [Register ("WKInterfaceSwitch", SkipRegistration = true)] - [Introduced (PlatformName.iOS, 8,2, PlatformArchitecture.All)] [Unavailable (PlatformName.iOS, PlatformArchitecture.All)] [Obsolete (Constants.WatchKitRemoved)] [EditorBrowsable (EditorBrowsableState.Never)] diff --git a/src/WatchKit/iOS/WKInterfaceTable.cs b/src/WatchKit/iOS/WKInterfaceTable.cs index dbc2bb7d9b..8633ce0bfb 100644 --- a/src/WatchKit/iOS/WKInterfaceTable.cs +++ b/src/WatchKit/iOS/WKInterfaceTable.cs @@ -7,7 +7,6 @@ using ObjCRuntime; namespace WatchKit { [Register ("WKInterfaceTable", SkipRegistration = true)] - [Introduced (PlatformName.iOS, 8,2, PlatformArchitecture.All)] [Unavailable (PlatformName.iOS, PlatformArchitecture.All)] [Obsolete (Constants.WatchKitRemoved)] [EditorBrowsable (EditorBrowsableState.Never)] diff --git a/src/WatchKit/iOS/WKInterfaceTimer.cs b/src/WatchKit/iOS/WKInterfaceTimer.cs index 8808558355..cc1288d2ce 100644 --- a/src/WatchKit/iOS/WKInterfaceTimer.cs +++ b/src/WatchKit/iOS/WKInterfaceTimer.cs @@ -7,7 +7,6 @@ using ObjCRuntime; namespace WatchKit { [Register ("WKInterfaceTimer", SkipRegistration = true)] - [Introduced (PlatformName.iOS, 8,2, PlatformArchitecture.All)] [Unavailable (PlatformName.iOS, PlatformArchitecture.All)] [Obsolete (Constants.WatchKitRemoved)] [EditorBrowsable (EditorBrowsableState.Never)] diff --git a/src/WatchKit/iOS/WKMenuItemIcon.cs b/src/WatchKit/iOS/WKMenuItemIcon.cs index b61b4a5a1f..50f811827c 100644 --- a/src/WatchKit/iOS/WKMenuItemIcon.cs +++ b/src/WatchKit/iOS/WKMenuItemIcon.cs @@ -5,7 +5,6 @@ using System.ComponentModel; using ObjCRuntime; namespace WatchKit { - [Introduced (PlatformName.iOS, 8,2, PlatformArchitecture.All)] [Unavailable (PlatformName.iOS, PlatformArchitecture.All)] [Obsolete (Constants.WatchKitRemoved)] [EditorBrowsable (EditorBrowsableState.Never)] diff --git a/src/WatchKit/iOS/WKTextInputMode.cs b/src/WatchKit/iOS/WKTextInputMode.cs index 98fb364760..37d9b166b7 100644 --- a/src/WatchKit/iOS/WKTextInputMode.cs +++ b/src/WatchKit/iOS/WKTextInputMode.cs @@ -5,7 +5,6 @@ using System.ComponentModel; using ObjCRuntime; namespace WatchKit { - [Introduced (PlatformName.iOS, 8,2, PlatformArchitecture.All)] [Unavailable (PlatformName.iOS, PlatformArchitecture.All)] [Obsolete (Constants.WatchKitRemoved)] [EditorBrowsable (EditorBrowsableState.Never)] diff --git a/src/WatchKit/iOS/WKUserNotificationInterfaceController.cs b/src/WatchKit/iOS/WKUserNotificationInterfaceController.cs index 14aa559f2b..9b1c885405 100644 --- a/src/WatchKit/iOS/WKUserNotificationInterfaceController.cs +++ b/src/WatchKit/iOS/WKUserNotificationInterfaceController.cs @@ -7,7 +7,6 @@ using ObjCRuntime; namespace WatchKit { [Register ("WKUserNotificationInterfaceController", SkipRegistration = true)] - [Introduced (PlatformName.iOS, 8,2, PlatformArchitecture.All)] [Unavailable (PlatformName.iOS, PlatformArchitecture.All)] [Obsolete (Constants.WatchKitRemoved)] [EditorBrowsable (EditorBrowsableState.Never)] diff --git a/src/WatchKit/iOS/WKUserNotificationInterfaceType.cs b/src/WatchKit/iOS/WKUserNotificationInterfaceType.cs index befcbed2f4..502b6f7c4d 100644 --- a/src/WatchKit/iOS/WKUserNotificationInterfaceType.cs +++ b/src/WatchKit/iOS/WKUserNotificationInterfaceType.cs @@ -5,7 +5,7 @@ using System.ComponentModel; using ObjCRuntime; namespace WatchKit { - [Introduced (PlatformName.iOS, 8,2, PlatformArchitecture.All)] + [Unavailable (PlatformName.iOS, PlatformArchitecture.All)] [Obsolete (Constants.WatchKitRemoved)] [EditorBrowsable (EditorBrowsableState.Never)] diff --git a/src/watchkit.cs b/src/watchkit.cs index a84c075710..f7b404aab4 100644 --- a/src/watchkit.cs +++ b/src/watchkit.cs @@ -26,7 +26,6 @@ using System; using System.ComponentModel; namespace WatchKit { - [iOS (8,2)] [Unavailable (PlatformName.iOS)] [BaseType (typeof (NSObject))] [Abstract] // To use this class, subclass it @@ -51,28 +50,23 @@ namespace WatchKit { [Export ("didDeactivate")] void DidDeactivate (); -#if WATCH [Export ("didAppear")] void DidAppear (); [Export ("willDisappear")] void WillDisappear (); -#endif [Export ("table:didSelectRowAtIndex:")] void DidSelectRow (WKInterfaceTable table, nint rowIndex); - [Deprecated (PlatformName.iOS, 10,0, message: "Use 'UNUserNotificationCenterDelegate' instead.")] [Deprecated (PlatformName.WatchOS, 3,0, message: "Use 'UNUserNotificationCenterDelegate' instead.")] [Export ("handleActionWithIdentifier:forRemoteNotification:")] void HandleRemoteNotificationAction ([NullAllowed] string identifier, NSDictionary remoteNotification); - [Deprecated (PlatformName.iOS, 10,0, message: "Use 'UNUserNotificationCenterDelegate' instead.")] [Deprecated (PlatformName.WatchOS, 3,0, message: "Use 'UNUserNotificationCenterDelegate' instead.")] [Export ("handleActionWithIdentifier:forLocalNotification:")] void HandleLocalNotificationAction ([NullAllowed] string identifier, UILocalNotification localNotification); - [iOS (10,0)] [NoWatch] [Export ("handleActionWithIdentifier:forNotification:")] void HandleAction ([NullAllowed] string identifier, UNNotification notification); @@ -156,7 +150,7 @@ namespace WatchKit { // This NSDictionary is OK, it is arbitrary and user specific void UpdateUserActivity (string type, [NullAllowed] NSDictionary userInfo, [NullAllowed] NSUrl webpageURL); - [Watch (5,0)][ NoiOS] + [Watch (5,0)] [Export ("updateUserActivity:")] void UpdateUserActivity (NSUserActivity userActivity); @@ -168,7 +162,6 @@ namespace WatchKit { [Async] void PresentTextInputController ([NullAllowed] string [] suggestions, WKTextInputMode inputMode, Action completion); - [iOS (9,0)] [Export ("presentTextInputControllerWithSuggestionsForLanguage:allowedInputMode:completion:")] [Async] void PresentTextInputController ([NullAllowed] Func suggestionsHandler, WKTextInputMode inputMode, Action completion); @@ -181,7 +174,7 @@ namespace WatchKit { [Static, Export ("reloadRootControllersWithNames:contexts:")] void ReloadRootControllers (string [] names, [NullAllowed] NSObject [] contexts); - [Watch (4,0)][NoiOS] + [Watch (4,0)] [Static] [Export ("reloadRootPageControllersWithNames:contexts:orientation:pageIndex:")] void ReloadRootPageControllers (string[] names, [NullAllowed] NSObject[] contexts, WKPageOrientation orientation, nint pageIndex); @@ -192,7 +185,6 @@ namespace WatchKit { NSString ErrorDomain { get; } #endif -#if WATCH [Export ("dismissMediaPlayerController")] void DismissMediaPlayerController (); @@ -235,46 +227,45 @@ namespace WatchKit { [Export ("pickerDidSettle:")] void PickerDidSettle (WKInterfacePicker picker); - [NoiOS] +#if WATCH [Export ("presentMediaPlayerControllerWithURL:options:completion:")] [Async (ResultType = typeof (WKPresentMediaPlayerResult))] void PresentMediaPlayerController (NSUrl url, [NullAllowed] NSDictionary options, Action completion); #endif - [Watch (3,0)][NoiOS] + [Watch (3,0)] [Export ("crownSequencer", ArgumentSemantic.Strong)] WKCrownSequencer CrownSequencer { get; } - [Watch (4,0)][NoiOS] + [Watch (4,0)] [Export ("scrollToObject:atScrollPosition:animated:")] void ScrollTo (WKInterfaceObject @object, WKInterfaceScrollPosition scrollPosition, bool animated); - [Watch (4,0)][NoiOS] + [Watch (4,0)] [Export ("interfaceDidScrollToTop")] void InterfaceDidScrollToTop (); - [Watch (4,0)][NoiOS] + [Watch (4,0)] [Export ("interfaceOffsetDidScrollToTop")] void InterfaceOffsetDidScrollToTop (); - [Watch (4,0)][NoiOS] + [Watch (4,0)] [Export ("interfaceOffsetDidScrollToBottom")] void InterfaceOffsetDidScrollToBottom (); - [Watch (5,0), NoiOS] + [Watch (5,0)] [Export ("contentSafeAreaInsets")] UIEdgeInsets ContentSafeAreaInsets { get; } - [Watch (5,0), NoiOS] + [Watch (5,0)] [Export ("systemMinimumLayoutMargins")] NSDirectionalEdgeInsets SystemMinimumLayoutMargins { get; } - [Watch (5,0), NoiOS] + [Watch (5,0)] [Export ("tableScrollingHapticFeedbackEnabled")] bool TableScrollingHapticFeedbackEnabled { [Bind ("isTableScrollingHapticFeedbackEnabled")] get; set; } } - [iOS (8,2)] [Unavailable (PlatformName.iOS)] [BaseType (typeof (WKInterfaceController))] [DisableDefaultCtor] // DesignatedInitializer below @@ -284,48 +275,44 @@ namespace WatchKit { [Export ("init")] IntPtr Constructor (); - [Deprecated (PlatformName.iOS, 10,0, message: "Use 'DidReceiveNotification' instead.")] [Deprecated (PlatformName.WatchOS, 3,0, message: "Use 'DidReceiveNotification' instead.")] [Export ("didReceiveRemoteNotification:withCompletion:")] void DidReceiveRemoteNotification (NSDictionary remoteNotification, Action completionHandler); - [Deprecated (PlatformName.iOS, 10,0, message: "Use 'DidReceiveNotification' instead.")] [Deprecated (PlatformName.WatchOS, 3,0, message: "Use 'DidReceiveNotification' instead.")] [Export ("didReceiveLocalNotification:withCompletion:")] void DidReceiveLocalNotification (UILocalNotification localNotification, Action completionHandler); [Deprecated (PlatformName.WatchOS, 5,0, message: "Use 'DidReceiveNotification(UNNotification)' instead.")] - [Watch (3,0)][iOS (10,0)] + [Watch (3,0)] [Export ("didReceiveNotification:withCompletion:")] void DidReceiveNotification (UNNotification notification, Action completionHandler); - [NoiOS] [Deprecated (PlatformName.WatchOS, 3,0, message: "Use overload accepting an 'UNNotification' parameter.")] [Export ("suggestionsForResponseToActionWithIdentifier:forRemoteNotification:inputLanguage:")] string[] GetSuggestionsForResponseToAction (string identifier, NSDictionary remoteNotification, string inputLanguage); - [NoiOS] [Deprecated (PlatformName.WatchOS, 3,0, message: "Use overload accepting an 'UNNotification' parameter.")] [Export ("suggestionsForResponseToActionWithIdentifier:forLocalNotification:inputLanguage:")] string[] GetSuggestionsForResponseToAction (string identifier, UILocalNotification localNotification, string inputLanguage); - [Watch (3,0)][NoiOS] + [Watch (3,0)] [Export ("suggestionsForResponseToActionWithIdentifier:forNotification:inputLanguage:")] string[] GetSuggestionsForResponseToAction (string identifier, UNNotification notification, string inputLanguage); - [Watch (5,0)][NoiOS] + [Watch (5,0)] [Export ("notificationActions", ArgumentSemantic.Copy)] UNNotificationAction[] NotificationActions { get; set; } - [Watch (5,0)][NoiOS] + [Watch (5,0)] [Export ("didReceiveNotification:")] void DidReceiveNotification (UNNotification notification); - [Watch (5,0)][NoiOS] + [Watch (5,0)] [Export ("performNotificationDefaultAction")] void PerformNotificationDefaultAction (); - [Watch (5,0)][NoiOS] + [Watch (5,0)] [Export ("performDismissAction")] void PerformDismissAction (); @@ -336,7 +323,6 @@ namespace WatchKit { } - [iOS (8,2)] [Unavailable (PlatformName.iOS)] [BaseType (typeof (NSObject))] [DisableDefaultCtor] @@ -357,38 +343,29 @@ namespace WatchKit { [Export ("setHeight:")] void SetHeight (nfloat height); - [Watch (2,1), NoiOS] + [Watch (2,1)] [Export ("setSemanticContentAttribute:")] void SetSemanticContentAttribute (WKInterfaceSemanticContentAttribute semanticContentAttribute); -#if WATCH - [NoiOS] [Export ("setHorizontalAlignment:")] void SetHorizontalAlignment (WKInterfaceObjectHorizontalAlignment horizontalAlignment); - [NoiOS] [Export ("setVerticalAlignment:")] void SetVerticalAlignment (WKInterfaceObjectVerticalAlignment verticalAlignment); -#endif - [NoiOS] [Export ("setRelativeWidth:withAdjustment:")] void SetRelativeWidth (nfloat width, nfloat adjustment); - [NoiOS] [Export ("setRelativeHeight:withAdjustment:")] void SetRelativeHeight (nfloat height, nfloat adjustment); - [NoiOS] [Export ("sizeToFitWidth")] void SizeToFitWidth (); - [NoiOS] [Export ("sizeToFitHeight")] void SizeToFitHeight (); } - [iOS (8,2)] [Unavailable (PlatformName.iOS)] [Category] [BaseType (typeof (WKInterfaceObject))] @@ -414,18 +391,17 @@ namespace WatchKit { [Export ("setAccessibilityIdentifier:")] void SetAccessibilityIdentifier ([NullAllowed] string accessibilityIdentifier); - [Watch (2,0)][NoiOS] + [Watch (2,0)] [Notification] [Field ("WKAccessibilityVoiceOverStatusChanged")] NSString VoiceOverStatusChanged { get; } - [Watch (4,0)][NoiOS] + [Watch (4,0)] [Notification] [Field ("WKAccessibilityReduceMotionStatusDidChangeNotification")] NSString ReduceMotionStatusDidChangeNotification { get; } } - [iOS (8,2)] [Unavailable (PlatformName.iOS)] [BaseType (typeof (NSObject))] [DisableDefaultCtor] // does not make sense to create, it should only be used thru the singleton @@ -464,81 +440,80 @@ namespace WatchKit { [Export ("removeAllCachedImages")] void RemoveAllCachedImages (); - [iOS (9,0), Watch (2,0)] + [Watch (2,0)] [Export ("systemVersion")] string SystemVersion { get; } - [iOS (9,0), Watch (2,0)] + [Watch (2,0)] [Export ("name")] string Name { get; } - [iOS (9,0), Watch (2,0)] + [Watch (2,0)] [Export ("model")] string Model { get; } - [iOS (9,0), Watch (2,0)] + [Watch (2,0)] [Export ("localizedModel")] string LocalizedModel { get; } - [iOS (9,0)][Watch (2,0)] + [Watch (2,0)] [Export ("systemName")] string SystemName { get; } - [Watch (3,0)][NoiOS] + [Watch (3,0)] [Export ("waterResistanceRating")] WKWaterResistanceRating WaterResistanceRating { get; } - [Watch (2,0), NoiOS] + [Watch (2,0)] [Export ("playHaptic:")] void PlayHaptic (WKHapticType type); - [Watch (2,1), NoiOS] + [Watch (2,1)] [Export ("layoutDirection")] WKInterfaceLayoutDirection LayoutDirection { get; } - [Watch (2,1), NoiOS] + [Watch (2,1)] [Static] [Export ("interfaceLayoutDirectionForSemanticContentAttribute:")] WKInterfaceLayoutDirection GetInterfaceLayoutDirection (WKInterfaceSemanticContentAttribute semanticContentAttribute); - [Watch (3,0)][NoiOS] + [Watch (3,0)] [Export ("wristLocation")] WKInterfaceDeviceWristLocation WristLocation { get; } - [Watch (3,0)][NoiOS] + [Watch (3,0)] [Export ("crownOrientation")] WKInterfaceDeviceCrownOrientation CrownOrientation { get; } - [Watch (4,0)][NoiOS] + [Watch (4,0)] [Export ("batteryMonitoringEnabled")] bool BatteryMonitoringEnabled { [Bind ("isBatteryMonitoringEnabled")] get; set; } - [Watch (4,0)][NoiOS] + [Watch (4,0)] [Export ("batteryLevel")] float BatteryLevel { get; } - [Watch (4,0)][NoiOS] + [Watch (4,0)] [Export ("batteryState")] WKInterfaceDeviceBatteryState BatteryState { get; } - [Watch (6,0)][NoiOS] + [Watch (6,0)] [Export ("supportsAudioStreaming")] bool SupportsAudioStreaming { get; } - [Watch (6,2), NoiOS] + [Watch (6,2)] [NullAllowed, Export ("identifierForVendor", ArgumentSemantic.Strong)] NSUuid IdentifierForVendor { get; } - [Watch (6,1)][NoiOS] + [Watch (6,1)] [Export ("enableWaterLock")] void EnableWaterLock (); - [Watch (6,1)][NoiOS] + [Watch (6,1)] [Export ("isWaterLockEnabled")] bool IsWaterLockEnabled { get; } } - [iOS (8,2)] [Unavailable (PlatformName.iOS)] [DisableDefaultCtor] // Do not subclass or create instances of this class yourself. -> Handle is nil if init is called [BaseType (typeof (WKInterfaceObject))] @@ -565,7 +540,6 @@ namespace WatchKit { void SetEnabled (bool enabled); } - [iOS (8,2)] [Unavailable (PlatformName.iOS)] [BaseType (typeof (WKInterfaceObject))] [DisableDefaultCtor] // Do not subclass or create instances of this class yourself. -> Handle is nil if init is called @@ -585,12 +559,10 @@ namespace WatchKit { [Export ("setCornerRadius:")] void SetCornerRadius (nfloat cornerRadius); - [NoiOS] [Export ("setContentInset:")] void SetContentInset (UIEdgeInsets contentInset); } - [iOS (8,2)] [Unavailable (PlatformName.iOS)] [BaseType (typeof (WKInterfaceObject))] [DisableDefaultCtor] // Do not subclass or create instances of this class yourself. -> Handle is nil if init is called @@ -608,7 +580,6 @@ namespace WatchKit { void SetTintColor ([NullAllowed] UIColor color); } - [iOS (8,2)] [Unavailable (PlatformName.iOS)] [DisableDefaultCtor] // Do not subclass or create instances of this class yourself. -> Handle is nil if init is called [BaseType (typeof (WKInterfaceObject))] @@ -624,7 +595,6 @@ namespace WatchKit { void SetText ([NullAllowed] NSAttributedString attributedText); } - [iOS (8,2)] [Unavailable (PlatformName.iOS)] [DisableDefaultCtor] // Do not subclass or create instances of this class yourself. -> Handle is nil if init is called [BaseType (typeof (WKInterfaceObject))] @@ -639,7 +609,6 @@ namespace WatchKit { void SetCalendar ([NullAllowed] NSCalendar calendar); } - [iOS (8,2)] [Unavailable (PlatformName.iOS)] [DisableDefaultCtor] // Do not subclass or create instances of this class yourself. -> Handle is nil if init is called [BaseType (typeof (WKInterfaceObject))] @@ -658,7 +627,6 @@ namespace WatchKit { void Stop (); } - [iOS (8,2)] [Unavailable (PlatformName.iOS)] [DisableDefaultCtor] // Do not subclass or create instances of this class yourself. -> Handle is nil if init is called [BaseType (typeof (WKInterfaceObject))] @@ -685,20 +653,19 @@ namespace WatchKit { [Export ("scrollToRowAtIndex:")] void ScrollToRow (nint index); - [Watch (3,0)][NoiOS] + [Watch (3,0)] [Export ("performSegueForRow:")] void PerformSegue (nint row); - [Watch (5,1), NoiOS] + [Watch (5,1)] [Export ("curvesAtTop")] bool CurvesAtTop { get; set; } - [Watch (5,1), NoiOS] + [Watch (5,1)] [Export ("curvesAtBottom")] bool CurvesAtBottom { get; set; } } - [iOS (8,2)] [Unavailable (PlatformName.iOS)] [DisableDefaultCtor] // Do not subclass or create instances of this class yourself. -> Handle is nil if init is called [BaseType (typeof (WKInterfaceObject))] @@ -741,7 +708,6 @@ namespace WatchKit { void SetUserTrackingMode (WKInterfaceMapUserTrackingMode mode, bool animated); } - [iOS (8,2)] [Unavailable (PlatformName.iOS)] [DisableDefaultCtor] // Do not subclass or create instances of this class yourself. -> Handle is nil if init is called [BaseType (typeof (WKInterfaceObject))] @@ -750,7 +716,6 @@ namespace WatchKit { void SetColor ([NullAllowed] UIColor color); } - [iOS (8,2)] [Unavailable (PlatformName.iOS)] [DisableDefaultCtor] // Do not subclass or create instances of this class yourself. -> Handle is nil if init is called [BaseType (typeof (WKInterfaceObject))] @@ -768,7 +733,6 @@ namespace WatchKit { void SetNumberOfSteps (nint numberOfSteps); } - [iOS (8,2)] [Unavailable (PlatformName.iOS)] [DisableDefaultCtor] // Do not subclass or create instances of this class yourself. -> Handle is nil if init is called [BaseType (typeof (WKInterfaceObject))] @@ -790,7 +754,6 @@ namespace WatchKit { void SetTitle ([NullAllowed] NSAttributedString attributedTitle); } - [iOS (8,2)] [Unavailable (PlatformName.iOS)] [BaseType (typeof (NSObject))] interface WKAccessibilityImageRegion { @@ -804,21 +767,18 @@ namespace WatchKit { interface IWKImageAnimatable {} - [iOS (9,0)] [Unavailable (PlatformName.iOS)] [Protocol] interface WKImageAnimatable { - [iOS (8,2)] + [Abstract] [Export ("startAnimating")] void StartAnimating (); - [iOS (8,2)] [Abstract] [Export ("startAnimatingWithImagesInRange:duration:repeatCount:")] void StartAnimating (NSRange imageRange, double duration, nint repeatCount); - [iOS (8,2)] [Abstract] [Export ("stopAnimating")] void StopAnimating (); @@ -954,17 +914,17 @@ namespace WatchKit { void SetCurrentTime (double time); #endif - [Watch (2,0), NoiOS] + [Watch (2,0)] [Notification] [Field ("WKAudioFilePlayerItemTimeJumpedNotification")] NSString TimeJumpedNotification { get; } - [Watch (2,0), NoiOS] + [Watch (2,0)] [Notification] [Field ("WKAudioFilePlayerItemDidPlayToEndTimeNotification")] NSString DidPlayToEndTimeNotification { get; } - [Watch (2,0), NoiOS] + [Watch (2,0)] [Notification] [Field ("WKAudioFilePlayerItemFailedToPlayToEndTimeNotification")] NSString FailedToPlayToEndTimeNotification { get; } @@ -1037,23 +997,23 @@ namespace WatchKit { [Export ("globalTintColor")] UIColor GlobalTintColor { get; } - [Watch (7, 0), NoiOS] + [Watch (7, 0)] [Notification, Field ("WKApplicationDidFinishLaunchingNotification")] NSString DidFinishLaunchingNotification { get; } - [Watch (7, 0), NoiOS] + [Watch (7, 0)] [Notification, Field ("WKApplicationDidBecomeActiveNotification")] NSString DidBecomeActiveNotification { get; } - [Watch (7, 0), NoiOS] + [Watch (7, 0)] [Notification, Field ("WKApplicationWillResignActiveNotification")] NSString WillResignActiveNotification { get; } - [Watch (7, 0), NoiOS] + [Watch (7, 0)] [Notification, Field ("WKApplicationWillEnterForegroundNotification")] NSString WillEnterForegroundNotification { get; } - [Watch (7, 0), NoiOS] + [Watch (7, 0)] [Notification, Field ("WKApplicationDidEnterBackgroundNotification")] NSString DidEnterBackgroundNotification { get; } } diff --git a/tests/introspection/ApiAvailabilityTest.cs b/tests/introspection/ApiAvailabilityTest.cs index 2f7eb40016..5af5c39cf9 100644 --- a/tests/introspection/ApiAvailabilityTest.cs +++ b/tests/introspection/ApiAvailabilityTest.cs @@ -27,40 +27,36 @@ using ObjCRuntime; namespace Introspection { public class ApiAvailabilityTest : ApiBaseTest { - + protected Version Minimum { get; set; } protected Version Maximum { get; set; } - protected Func Filter { get; set; } + protected Func Filter { get; set; } + protected PlatformName Platform { get; set; } public ApiAvailabilityTest () { Maximum = Version.Parse (Constants.SdkVersion); #if __IOS__ + Platform = PlatformName.iOS; Minimum = new Version (6,0); - Filter = (AvailabilityBaseAttribute arg) => { - return (arg.AvailabilityKind != AvailabilityKind.Introduced) || (arg.Platform != PlatformName.iOS); - }; #elif __TVOS__ + Platform = PlatformName.TvOS; Minimum = new Version (9,0); - Filter = (AvailabilityBaseAttribute arg) => { - return (arg.AvailabilityKind != AvailabilityKind.Introduced) || (arg.Platform != PlatformName.TvOS); - }; #elif __WATCHOS__ + Platform = PlatformName.WatchOS; Minimum = new Version (2,0); // Need to special case watchOS 'Maximum' version for OS minor subversions (can't change Constants.SdkVersion) //Maximum = new Version (6,2,5); - Filter = (AvailabilityBaseAttribute arg) => { - return (arg.AvailabilityKind != AvailabilityKind.Introduced) || (arg.Platform != PlatformName.WatchOS); - }; #else + Platform = PlatformName.MacOSX; Minimum = new Version (10,9); // Need to special case macOS 'Maximum' version for OS minor subversions (can't change Constants.SdkVersion) // Please comment the code below if needed Maximum = new Version (10,15,5); - Filter = (AvailabilityBaseAttribute arg) => { - return (arg.AvailabilityKind != AvailabilityKind.Introduced) || (arg.Platform != PlatformName.MacOSX); - }; #endif + Filter = (AvailabilityBaseAttribute arg) => { + return (arg.AvailabilityKind != AvailabilityKind.Introduced) || (arg.Platform != Platform); + }; } bool FoundInProtocols (MemberInfo m, Type t) @@ -205,5 +201,56 @@ namespace Introspection { } return null; } + + bool IsUnavailable (ICustomAttributeProvider cap) + { + foreach (var ca in cap.GetCustomAttributes (false)) { + if (ca is UnavailableAttribute ua) { + if (ua.Platform == Platform) + return true; + } + } + return false; + } + + AvailabilityBaseAttribute GetAvailable (ICustomAttributeProvider cap) + { + foreach (var ca in cap.GetCustomAttributes (false)) { + if (ca is AvailabilityBaseAttribute aa) { + if ((aa.AvailabilityKind != AvailabilityKind.Unavailable) && (aa.Platform == Platform)) + return aa; + } + } + return null; + } + + [Test] + public void Unavailable () + { + //LogProgress = true; + Errors = 0; + foreach (Type t in Assembly.GetTypes ()) { + if (LogProgress) + Console.WriteLine ($"T: {t}"); + var tu = IsUnavailable (t); + var ta = GetAvailable (t); + if (tu && (ta != null)) + AddErrorLine ($"[FAIL] {t.FullName} is marked both [Unavailable ({Platform})] and {ta}."); + + foreach (var m in t.GetMembers (BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public)) { + if (LogProgress) + Console.WriteLine ($"M: {m}"); + + var ma = GetAvailable (t); + if (tu && (ma != null)) + AddErrorLine ($"[FAIL] {m} is marked with {ma} but the type {t.FullName} is [Unavailable ({Platform})]."); + + var mu = IsUnavailable (t); + if (mu && (ma != null)) + AddErrorLine ($"[FAIL] {m} is marked both [Unavailable ({Platform})] and {ma}."); + } + } + AssertIfErrors ("{0} API with mixed [Unavailable] and availability attributes", Errors); + } } }