diff --git a/docs/api/Foundation/DictionaryContainer.xml b/docs/api/Foundation/DictionaryContainer.xml deleted file mode 100644 index 25aa74135dc4..000000000000 --- a/docs/api/Foundation/DictionaryContainer.xml +++ /dev/null @@ -1,132 +0,0 @@ - - - When overridden, call the base-class constructor with a . - - - When creating a strongly-typed wrapper for NSDictionary, - subclass the DicionaryContainer and provide two constructors: - one taking an NSDictionary (to create the wrapper) and one - taking no arguments, which should call the base class with an - NSMutableDictionary. Then use one of the various Get and Set - methods exposed by this class to get and set values. This is - how a sample class would work: - - - - - - - - - The dictionary to be wrapped. - When overridden, call the base-class constructor, passing the . - - - When creating a strongly-typed wrapper for NSDictionary, - subclass the DicionaryContainer and provide two constructors: - one taking an NSDictionary (to create the wrapper) and one - taking no arguments, which should call the base class with an - NSMutableDictionary. Then use one of the various Get and Set - methods exposed by this class to get and set values. This is - how a sample class would work: - - - - - - - - - Convenience base class used by strongly-typed classes that wrap NSDictionary-based settings. - - - Many iOS and OSX APIs accept configuration options as untyped - NSDictionary values, or return untyped NSDictionary values. - The C# bindings offer strong-typed versions of those - dictionaries, which allow developers to get code completion - while passing parameters, and to extract data from return - values. The DicionaryContainer is an abstract base class that - encapsulates the common code to wrap NSDictionaries like this. - - - - When creating a strongly-typed wrapper for NSDictionary, - subclass the DicionaryContainer and provide two constructors: - one taking an NSDictionary (to create the wrapper) and one - taking no arguments, which should call the base class with an - NSMutableDictionary. Then use one of the various Get and Set - methods exposed by this class to get and set values. This is - how a sample class would work: - - - - - - - - - - \ No newline at end of file diff --git a/src/CoreFoundation/CFDictionary.cs b/src/CoreFoundation/CFDictionary.cs index 1c2d78ac315a..176409be0ef6 100644 --- a/src/CoreFoundation/CFDictionary.cs +++ b/src/CoreFoundation/CFDictionary.cs @@ -31,6 +31,7 @@ #nullable enable using System; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using Foundation; using ObjCRuntime; @@ -97,6 +98,20 @@ public static IntPtr GetValue (IntPtr theDict, IntPtr key) return CFDictionaryGetValue (theDict, key); } + [DllImport (Constants.CoreFoundationLibrary)] + unsafe extern static byte /* Boolean */ CFDictionaryGetValueIfPresent (IntPtr /* CFDictionaryRef */ theDict, IntPtr /* const void * */ key, IntPtr* /* const void * * */ value); + + /// Try to get the stored value for the specified . + /// The dictionary whose value to get. + /// The key of the value to find. + /// Upon return, the value that was found, or if the dictionary doesn't contain a value for the specified . + /// if the dictionary contains the specified , otherwise. + public unsafe static bool TryGetValue (IntPtr dictionary, IntPtr key, out IntPtr value) + { + value = default; + return CFDictionaryGetValueIfPresent (dictionary, key, (IntPtr*) Unsafe.AsPointer (ref value)) != 0; + } + [DllImport (Constants.CoreFoundationLibrary)] extern static nint CFDictionaryGetCount (IntPtr theDict); public nint Count { @@ -220,5 +235,18 @@ public static void SetValue (IntPtr theDict, IntPtr key, bool value) { SetValue (theDict, key, value ? CFBoolean.TrueHandle : CFBoolean.FalseHandle); } + + internal static void SetValue (IntPtr theDict, INativeObject? key, INativeObject? value) + { + SetValue (theDict, key.GetHandle (), value.GetHandle ()); + GC.KeepAlive (key); + GC.KeepAlive (value); + } + + internal static void SetValue (IntPtr theDict, INativeObject? key, IntPtr value) + { + SetValue (theDict, key.GetHandle (), value); + GC.KeepAlive (key); + } } } diff --git a/src/CoreVideo/CVPixelFormatDescription.cs b/src/CoreVideo/CVPixelFormatDescription.cs index 682309eccfda..6dacff7347f2 100644 --- a/src/CoreVideo/CVPixelFormatDescription.cs +++ b/src/CoreVideo/CVPixelFormatDescription.cs @@ -394,6 +394,16 @@ public CVFillExtendedPixelsCallBackDataStruct? FillExtendedPixelsCallbackStruct FillExtendedPixelsCallback = data; } } + +#if !XAMCORE_5_0 + [Obsolete ("Use 'ComponentRangeValue' instead, the property type is incorrect for this property.")] + [EditorBrowsable (EditorBrowsableState.Never)] + public CVPixelFormatComponentRange? ComponentRange { + get => null; + set { } + } +#endif // !XAMCORE_5_0 + #endif // !COREBUILD } } diff --git a/src/Foundation/DictionaryContainer.cs b/src/Foundation/DictionaryContainer.cs index aa41a4b61c0c..2ac154c6b197 100644 --- a/src/Foundation/DictionaryContainer.cs +++ b/src/Foundation/DictionaryContainer.cs @@ -28,6 +28,7 @@ using System; using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; @@ -46,289 +47,446 @@ #nullable enable namespace Foundation { - - /// + /// Convenience class to provide strongly-typed classes that wrap based settings. + /// + /// + /// Many APIs accept configuration options as untyped + /// values, or return untyped values. + /// The managed bindings offer strong-typed versions of those + /// dictionaries, which allow developers to get code completion + /// while passing parameters, and to extract data from return + /// values. The class is an abstract base class that + /// encapsulates the common code to wrap dictionaries like this. + /// + /// + /// When creating a strongly-typed wrapper for an , + /// subclass the and provide two constructors: + /// one taking an (to create the wrapper) and a default + /// costructor. They should each call the corresponding base class () constructor. + /// Then use one of the various Get and Set methods exposed by this class to get and set values. This is + /// how a sample class would work: + /// + /// + /// return GetInt32Value (boolKey); + /// set => SetInt32Value (boolKey, value); + /// } + /// }]]> + /// + /// [SupportedOSPlatform ("ios")] [SupportedOSPlatform ("maccatalyst")] [SupportedOSPlatform ("macos")] [SupportedOSPlatform ("tvos")] public abstract class DictionaryContainer { #if !COREBUILD - /// + /// Creates a new container for an empty . protected DictionaryContainer () { Dictionary = new NSMutableDictionary (); } - /// + /// Creates a new container wrapping the specified . + /// The dictionary to be wrapped. protected DictionaryContainer (NSDictionary? dictionary) { Dictionary = dictionary ?? new NSMutableDictionary (); } /// Gets the wrapped . - /// To be added. - /// To be added. + /// The wrapped . public NSDictionary Dictionary { get; private set; } - /// The type of values stored in the array identified by . - /// The identifier of the array. - /// Retrieves the array of type T associated with . - /// To be added. - /// To be added. - protected T []? GetArray (NSString key) where T : NSObject + static T? Create (NativeHandle handle) where T : DictionaryContainer, new() { - if (key is null) - throw new ArgumentNullException (nameof (key)); + if (handle == NativeHandle.Zero) + return null; + var dict = Runtime.GetNSObject (handle, owns: false); + if (dict is null) + return null; + var rv = new T (); + rv.Dictionary = dict; + return rv; + } + + /// Returns the nullable associated with . + /// The identifier of the value to get. + /// if the specified was found in the dictionary, otherwise. + protected T? GetNativeValue (NSString key) where T : class, INativeObject + { + if (!TryGetNativeValue (key, out var value)) + return null; - var value = CFDictionary.GetValue (Dictionary.Handle, key.Handle); + return Runtime.GetINativeObject (value, false); + } + + /// Returns the nullable associated with . + /// The identifier of the value to get. + /// The instance that was found (or if no value was found for the specified key). + /// This method will throw an exception if the dictionary contains a value for the specified key that is not an . + /// if the specified was found in the dictionary, otherwise. + protected bool TryGetNSObject (NSString key, [NotNullWhen (true)] out T? @object) where T : NSObject + { + @object = null; + + if (!TryGetNativeValue (key, out var handle)) + return false; + + // Don't use GetNSObject, because then we don't get any type checking. + var value = Runtime.GetNSObject (handle, false); + if (value is null) + return false; + @object = value as T; + if (@object is null) + throw new InvalidOperationException (string.Format ("The stored type for the key '{0}' is not '{1}', it's '{2}' (value: {3}).", key, typeof (T), value.GetType (), value)); + + return true; + } + + T? GetNSObject (NSString key) where T : NSObject + { + if (!TryGetNSObject (key, out var value)) + return null; + return value; + } + + /// Returns the nullable associated with . + /// The identifier of the value to get. + /// The instance that was found (or if no value was found for the specified key). + /// This method will throw an exception if the dictionary contains a value for the specified key that is not an . + /// if the specified was found in the dictionary, otherwise. + bool TryGetNSNumber (NSString key, [NotNullWhen (true)] out NSNumber? number) + { + return TryGetNSObject (key, out number); + } + + /// Returns the handle associated with . + /// The identifier of the value to get. + /// The returned handle that was found (or if no value was found for the specified key). + /// if the specified was found in the dictionary and the found value was not , otherwise. + protected bool TryGetNativeValue (NSString key, out NativeHandle value) + { + var rv = TryGetNativeValue (key.GetHandle (), out value); GC.KeepAlive (key); + return rv; + } + + /// Returns the handle associated with . + /// The identifier of the value to get. + /// The returned handle that was found (or if no value was found for the specified key). + /// if the specified was found in the dictionary and the found value was not , otherwise. + bool TryGetNativeValue (NativeHandle key, out NativeHandle value) + { + if (key == IntPtr.Zero) + throw new ArgumentNullException (nameof (key)); + + value = default; + + if (!CFDictionary.TryGetValue (Dictionary.Handle, key, out var handle)) + return false; + + value = handle; + return value != NativeHandle.Zero; + } + + /// Returns the nullable array of associated with the specified . + /// The identifier of the value to get. + /// The stored array of value if present in the dictionary, otherwise. + protected T []? GetArray (NSString key) where T : NSObject + { + if (!TryGetNativeValue (key, out var value)) + return null; + return NSArray.ArrayFromHandle (value); } + /// Returns the nullable array of associated with the specified . + /// The identifier of the value to get. + /// A callback to convert between the native object stored in the dictionary to the desired return type. + /// The stored array of value if present in the dictionary, otherwise. protected T []? GetArray (NSString key, Func creator) { - if (key is null) - throw new ArgumentNullException (nameof (key)); + if (!TryGetNativeValue (key, out var value)) + return null; - var value = CFDictionary.GetValue (Dictionary.Handle, key.Handle); - GC.KeepAlive (key); return NSArray.ArrayFromHandleFunc (value, creator); } - /// The identifier of the int. - /// Returns the nullable int associated with . - /// To be added. - /// To be added. - protected int? GetInt32Value (NSString key) + /// Retrieves the array associeted with . + /// The identifier of the value to get. + /// The array associeted with . + protected T []? GetArrayOfDictionariesValue (NSString key) where T : DictionaryContainer, new() { - if (key is null) - throw new ArgumentNullException (nameof (key)); + if (!TryGetNativeValue (key, out var value)) + return null; - NSObject value; - if (!Dictionary.TryGetValue (key, out value)) + return NSArray.ArrayFromHandleFunc (value, (handle) => Create (handle)!); + } + + /// Returns the nullable associated with the specified . + /// The identifier of the value to get. + /// The stored value if present in the dictionary, otherwise. + /// The stored value must be stored as an . + protected byte? GetByteValue (NSString key) + { + if (!TryGetNSNumber (key, out var number)) return null; - return ((NSNumber) value).Int32Value; + return number.ByteValue; } - /// The identifier of the . - /// Returns the nullable associated with . - /// To be added. - /// To be added. - protected uint? GetUInt32Value (NSString key) + /// Returns the nullable associated with the specified . + /// The identifier of the value to get. + /// The stored value if present in the dictionary, otherwise. + /// The stored value must be stored as an . + protected sbyte? GetSByteValue (NSString key) { - if (key is null) - throw new ArgumentNullException (nameof (key)); + if (!TryGetNSNumber (key, out var number)) + return null; + + return number.SByteValue; + } - NSObject value; - if (!Dictionary.TryGetValue (key, out value)) + /// Returns the nullable associated with the specified . + /// The identifier of the value to get. + /// The stored value if present in the dictionary, otherwise. + /// The stored value must be stored as an . + protected short? GetInt16Value (NSString key) + { + if (!TryGetNSNumber (key, out var number)) return null; - return ((NSNumber) value).UInt32Value; + return number.Int16Value; } - /// The identifier of the native integer. - /// Returns the nullable native integer associated with . - /// To be added. - /// To be added. - protected nint? GetNIntValue (NSString key) + /// Returns the nullable associated with the specified . + /// The identifier of the value to get. + /// The stored value if present in the dictionary, otherwise. + /// The stored value must be stored as an . + protected ushort? GetUInt16Value (NSString key) { - if (key is null) - throw new ArgumentNullException (nameof (key)); + if (!TryGetNSNumber (key, out var number)) + return null; + + return number.UInt16Value; + } - NSObject value; - if (!Dictionary.TryGetValue (key, out value)) + /// Returns the nullable associated with the specified . + /// The identifier of the value to get. + /// The stored value if present in the dictionary, otherwise. + /// The stored value must be stored as an . + protected int? GetInt32Value (NSString key) + { + if (!TryGetNSNumber (key, out var number)) return null; - return ((NSNumber) value).NIntValue; + return number.Int32Value; } - /// The identifier of the nuint - /// Returns the nullable native unsigned int associated with . - /// To be added. - /// To be added. - protected nuint? GetNUIntValue (NSString key) + /// Returns the nullable associated with the specified . + /// The identifier of the value to get. + /// The stored value if present in the dictionary, otherwise. + /// The stored value must be stored as an . + protected uint? GetUInt32Value (NSString key) { - if (key is null) - throw new ArgumentNullException (nameof (key)); + if (!TryGetNSNumber (key, out var number)) + return null; + + return number.UInt32Value; + } - NSObject value; - if (!Dictionary.TryGetValue (key, out value)) + /// Returns the nullable associated with the specified . + /// The identifier of the value to get. + /// The stored value if present in the dictionary, otherwise. + /// The stored value must be stored as an . + protected nint? GetNIntValue (NSString key) + { + if (!TryGetNSNumber (key, out var number)) return null; - return ((NSNumber) value).NUIntValue; + return number.NIntValue; } - /// The identifier of the long. - /// Returns the nullable long associated with . - /// To be added. - /// To be added. - protected long? GetLongValue (NSString key) + /// Returns the nullable associated with the specified . + /// The identifier of the value to get. + /// The stored value if present in the dictionary, otherwise. + /// The stored value must be stored as an . + protected nuint? GetNUIntValue (NSString key) { - if (key is null) - throw new ArgumentNullException (nameof (key)); + if (!TryGetNSNumber (key, out var number)) + return null; - NSObject value; - if (!Dictionary.TryGetValue (key, out value)) + return number.NUIntValue; + } + + /// Returns the nullable associated with the specified . + /// The identifier of the value to get. + /// The stored value if present in the dictionary, otherwise. + /// The stored value must be stored as an . + protected long? GetLongValue (NSString key) + { + if (!TryGetNSNumber (key, out var number)) return null; - return ((NSNumber) value).Int64Value; + return number.Int64Value; } + /// Returns the nullable associated with the specified . + /// The identifier of the value to get. + /// The stored value if present in the dictionary, otherwise. + /// The stored value must be stored as an . protected ulong? GetULongValue (NSString key) { - if (key is null) - throw new ArgumentNullException (nameof (key)); - - if (!Dictionary.TryGetValue (key, out var value)) + if (!TryGetNSNumber (key, out var number)) return null; - return ((NSNumber) value).UInt64Value; + return number.UInt64Value; } - /// The identifier of the . - /// Returns the nullable associated with . - /// To be added. - /// To be added. + /// Returns the nullable associated with the specified . + /// The identifier of the value to get. + /// The stored value if present in the dictionary, otherwise. + /// The stored value must be stored as an . protected uint? GetUIntValue (NSString key) { - if (key is null) - throw new ArgumentNullException (nameof (key)); - - NSObject value; - if (!Dictionary.TryGetValue (key, out value)) + if (!TryGetNSNumber (key, out var number)) return null; - return ((NSNumber) value).UInt32Value; + return number.UInt32Value; } - /// The identifier of the float. - /// Returns the nullable float associated with . - /// To be added. - /// To be added. + /// Returns the nullable associated with the specified . + /// The identifier of the value to get. + /// The stored value if present in the dictionary, otherwise. + /// The stored value must be stored as an . protected float? GetFloatValue (NSString key) { - if (key is null) - throw new ArgumentNullException (nameof (key)); + if (!TryGetNSNumber (key, out var number)) + return null; + + return number.FloatValue; + } - NSObject value; - if (!Dictionary.TryGetValue (key, out value)) + /// Returns the nullable associated with the specified . + /// The identifier of the value to get. + /// The stored value if present in the dictionary, otherwise. + /// The stored value must be stored as an . + protected nfloat? GetNFloatValue (NSString key) + { + if (!TryGetNSNumber (key, out var number)) return null; - return ((NSNumber) value).FloatValue; + // we only support 64-bit architectures at the moment, so this is safe + Validate64BitNFloat (); + + return (nfloat) number.DoubleValue; } - /// The identifier of the double. - /// Returns the nullable double associated with . - /// To be added. - /// To be added. + /// Returns the nullable associated with the specified . + /// The identifier of the value to get. + /// The stored value if present in the dictionary, otherwise. + /// The stored value must be stored as an . protected double? GetDoubleValue (NSString key) { - if (key is null) - throw new ArgumentNullException (nameof (key)); - - NSObject value; - if (!Dictionary.TryGetValue (key, out value)) + if (!TryGetNSNumber (key, out var number)) return null; - return ((NSNumber) value).DoubleValue; + return number.DoubleValue; } - /// The identifier of the bool. - /// Returns the nullable Boolean associated with . - /// To be added. - /// To be added. + /// Returns the nullable associated with the specified . + /// The identifier of the value to get. + /// The stored value if present in the dictionary, otherwise. protected bool? GetBoolValue (NSString key) { - if (key is null) - throw new ArgumentNullException (nameof (key)); - - var value = CFDictionary.GetValue (Dictionary.Handle, key.Handle); - GC.KeepAlive (key); - if (value == IntPtr.Zero) + if (!TryGetNativeValue (key, out var value)) return null; return CFBoolean.GetValue (value); } /// Returns the nullable DateTime associated with . - /// The identifier of the DateTime value. + /// The identifier of the value to get. + /// The stored value if present in the dictionary, otherwise. + /// The stored value must be stored as an . protected DateTime? GetDateTimeValue (NSString key) { - if (key is null) - throw new ArgumentNullException (nameof (key)); - - var value = CFDictionary.GetValue (Dictionary.Handle, key.Handle); - GC.KeepAlive (key); - if (value == IntPtr.Zero) + if (!TryGetNSObject (key, out var date)) return null; - return (DateTime) Runtime.GetNSObject (value, false)!; - } - - /// The type associated with . - /// The identifier of the reference. - /// Returns the native object associated with . - /// To be added. - /// To be added. - protected T? GetNativeValue (NSString key) where T : class, INativeObject - { - if (key is null) - throw new ArgumentNullException (nameof (key)); - - T? result = Runtime.GetINativeObject (Dictionary.LowlevelObjectForKey (key.Handle), false); - GC.KeepAlive (key); - return result; + return (DateTime) date; } + /// Returns the nullable string array associated with . + /// The identifier of the value to get. + /// The stored string array value if present in the dictionary, otherwise. protected string []? GetStringArrayValue (NSString key) { - if (key is null) - throw new ArgumentNullException (nameof (key)); + if (!TryGetNativeValue (key, out var array)) + return null; - var array = Dictionary.LowlevelObjectForKey (key.Handle); - GC.KeepAlive (key); return CFArray.StringArrayFromHandle (array)!; } - /// The identifier of the . - /// Returns the associated with . - /// To be added. - /// To be added. + /// Returns the nullable associated with . + /// The identifier of the value to get. + /// The stored if present in the dictionary, otherwise. protected NSDictionary? GetNSDictionary (NSString key) { - if (key is null) - throw new ArgumentNullException (nameof (key)); - - NSObject value; - Dictionary.TryGetValue (key, out value); - return value as NSDictionary; + return GetNSObject (key); } + /// Returns the nullable associated with . /// The type of keys in the stored dictionary. - /// The type of values in the stored dictionary. - /// The identifier of the . - /// Returns the associated with . - /// To be added. - /// To be added. + /// The type of values in the stored dictionary. + /// The identifier of the value to get. + /// The stored if present in the dictionary, otherwise. protected NSDictionary? GetNSDictionary (NSString key) where TKey : class, INativeObject where TValue : class, INativeObject + { + return GetNativeValue> (key); + } + + /// Returns an with the contents of a value type of type associated with . + /// The value type stored in the type . + /// The identifier of the value to get. + /// The value type initialized from the data in the , or if the specified is not present in this dictionary. + protected T? GetNSDataAsValueType (NSString key) where T : unmanaged + { + if (!TryGetNSObject (key, out var data)) + return null; + return data.ToValueType (); + } + + /// Sets an with the contents of a value type of type associated with . + /// The value type stored in the type . + /// The identifier of the value to get. + /// The value to store in the . + protected void SetValueTypeAsNSData (NSString key, T? value) where T : unmanaged { if (key is null) throw new ArgumentNullException (nameof (key)); - NSObject value; - Dictionary.TryGetValue (key, out value); - return value as NSDictionary; + var data = NSData.CreateFromValueType (value); + SetNativeValue (key, data); } - /// The type of associated with . - /// The identifier of the . - /// Returns the associated with . - /// To be added. - /// To be added. + /// Returns the nullable associated with . + /// The identifier of the value to get. + /// The stored if present in the dictionary, otherwise. protected T? GetStrongDictionary<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] T> (NSString key) where T : DictionaryContainer { @@ -336,12 +494,13 @@ protected DictionaryContainer (NSDictionary? dictionary) (T?) Activator.CreateInstance (typeof (T), new object [] { dict })); } - protected T? GetStrongDictionary (NSString? key, Func createStrongDictionary) + /// Returns the nullable associated with . + /// The identifier of the value to get. + /// A callback to convert between an and . + /// The stored if present in the dictionary, otherwise. + protected T? GetStrongDictionary (NSString key, Func createStrongDictionary) where T : DictionaryContainer { - if (key is null) - throw new ArgumentNullException (nameof (key)); - var dict = GetNSDictionary (key); if (dict is null) return null; @@ -349,106 +508,78 @@ protected DictionaryContainer (NSDictionary? dictionary) return createStrongDictionary (dict); } - /// The identifier of the . - /// Returns the associated with . - /// To be added. - /// To be added. + /// Returns the nullable associated with . + /// The identifier of the value to get. + /// The stored if present in the dictionary, otherwise. protected NSString? GetNSStringValue (NSString key) { - if (key is null) - throw new ArgumentNullException (nameof (key)); - - NSObject value; - Dictionary.TryGetValue (key, out value); - return value as NSString; + return GetNSObject (key); } - /// The identifier of the string. - /// Returns the string associated with . - /// To be added. - /// To be added. + /// Returns the nullable associated with . + /// The identifier of the value to get. + /// The stored if present in the dictionary, otherwise. protected string? GetStringValue (NSString key) { - if (key is null) - throw new ArgumentNullException (nameof (key)); - - NSObject value; - if (!Dictionary.TryGetValue (key, out value)) + if (!TryGetNativeValue (key, out var value)) return null; - var result = CFString.FromHandle (value.Handle); - GC.KeepAlive (value); - return result; + return CFString.FromHandle (value); } - /// The identifier of the string. - /// Returns the string associated with . - /// To be added. - /// To be added. + /// protected string? GetStringValue (string key) { - if (key is null) - throw new ArgumentNullException (nameof (key)); - - var keyHandle = CFString.CreateNative (key); - try { - return CFString.FromHandle (CFDictionary.GetValue (Dictionary.Handle, keyHandle)); - } finally { - CFString.ReleaseNative (keyHandle); - } + using var keyHandle = new TransientCFString (key); + if (TryGetNativeValue ((IntPtr) keyHandle, out var value)) + return null; + return CFString.FromHandle (value); } - /// The identifier of the . - /// Returns the nullable associated with . - /// To be added. - /// To be added. + /// Returns the nullable associated with . + /// The identifier of the value to get. + /// The stored if present in the dictionary, otherwise. protected CGRect? GetCGRectValue (NSString key) { var dictValue = GetNSDictionary (key); - CGRect value; - if (!CGRect.TryParse (dictValue, out value)) + if (!CGRect.TryParse (dictValue, out var value)) return null; return value; } - /// The identifier of the . - /// Returns the nullable associated with . - /// To be added. - /// To be added. + /// Returns the nullable associated with . + /// The identifier of the value to get. + /// The stored if present in the dictionary, otherwise. protected CGSize? GetCGSizeValue (NSString key) { var dictValue = GetNSDictionary (key); - CGSize value; - if (!CGSize.TryParse (dictValue, out value)) + if (!CGSize.TryParse (dictValue, out var value)) return null; return value; } - /// The identifier of the . - /// Returns the nullable associated with . - /// To be added. - /// To be added. + /// Returns the nullable associated with . + /// The identifier of the value to get. + /// The stored if present in the dictionary, otherwise. protected CGPoint? GetCGPointValue (NSString key) { var dictValue = GetNSDictionary (key); - CGPoint value; - if (!CGPoint.TryParse (dictValue, out value)) + if (!CGPoint.TryParse (dictValue, out var value)) return null; return value; } - /// The identifier of the . - /// Returns the nullable associated with . - /// To be added. - /// To be added. + /// Returns the nullable associated with . + /// The identifier of the value to get. + /// The stored if present in the dictionary, otherwise. protected CMTime? GetCMTimeValue (NSString key) { var dictValue = GetNSDictionary (key); if (dictValue is null) - ObjCRuntime.ThrowHelper.ThrowArgumentNullException (nameof (dictValue)); + return null; var value = CMTime.FromDictionary (dictValue); if (value.IsInvalid) return null; @@ -457,92 +588,112 @@ protected DictionaryContainer (NSDictionary? dictionary) } #if HAS_UIKIT + /// Returns the nullable associated with . + /// The identifier of the value to get. + /// The stored if present in the dictionary, otherwise. protected UIEdgeInsets? GetUIEdgeInsets (NSString key) + { + if (!TryGetNSObject (key, out var value)) + return null; + + return value.UIEdgeInsetsValue; + } +#endif + + bool NullCheckValueTypeAndRemoveKey ([NotNullWhen (true)] NSString key, [NotNullWhen (true)] T? valueType) where T : struct { if (key is null) throw new ArgumentNullException (nameof (key)); - if (!Dictionary.TryGetValue (key, out var value)) - return null; - - if (value is NSValue size) - return size.UIEdgeInsetsValue; + if (!valueType.HasValue) + RemoveValue (key); - return null; + return valueType.HasValue; } -#endif - bool NullCheckAndRemoveKey ([NotNullWhen (true)] NSString key, bool removeEntry) + bool NullCheckObjectAndRemoveKey ([NotNullWhen (true)] NSString key, [NotNullWhen (true)] object? obj) { if (key is null) throw new ArgumentNullException (nameof (key)); - if (removeEntry) + if (obj is null) RemoveValue (key); - return !removeEntry; + return obj is not null; } - /// The identifier to be associated with the array. - /// The array to be associated with . - /// Associates the array with . - /// To be added. + /// Associates the array with . + /// The identifier of the value to get. + /// The array to be associated with . Pass to remove any existing association. protected void SetArrayValue (NSString key, NSNumber []? values) { - if (NullCheckAndRemoveKey (key, values is null)) + if (NullCheckObjectAndRemoveKey (key, values)) Dictionary [key] = NSArray.FromNSObjects (values); } - /// The type stored by the array. - /// The identifier to be associated with the array. - /// The array of type to be associated with . - /// Associates the array of type with . - /// To be added. + /// Associates an array of with . + /// The identifier of the value to get. + /// The array of to be associated with . Pass to remove any existing association. protected void SetArrayValue (NSString key, T []? values) { - if (NullCheckAndRemoveKey (key, values is null)) { - var nsValues = new NSObject [values!.Length]; + if (NullCheckObjectAndRemoveKey (key, values)) { + var nsValues = new NSObject [values.Length]; for (var i = 0; i < values.Length; i++) nsValues [i] = NSObject.FromObject (values [i]); Dictionary [key] = NSArray.FromNSObjects (nsValues); } } - /// The identifier to be associated with the array. - /// The array to be associated with . - /// Associates the array with . - /// To be added. + /// Associates a array with . + /// The identifier of the value to get. + /// The to be associated with . Pass to remove any existing association. protected void SetArrayValue (NSString key, string []? values) { - if (NullCheckAndRemoveKey (key, values is null)) + if (NullCheckObjectAndRemoveKey (key, values)) Dictionary [key] = NSArray.FromStrings (values); } - /// The identifier to be associated with the array. - /// The array to be associated with . - /// Associates the array with . - /// To be added. + /// Associates an array of with . + /// The identifier of the value to get. + /// The array of to be associated with . Pass to remove any existing association. protected void SetArrayValue (NSString key, INativeObject []? values) { - if (NullCheckAndRemoveKey (key, values is null)) { - var array = CFArray.FromNativeObjects (values!); - CFMutableDictionary.SetValue (Dictionary.Handle, key.Handle, array.Handle); - GC.KeepAlive (key); - GC.KeepAlive (array); + SetArrayValue (key, values, NativeObjectExtensions.GetHandle); + } + + /// Associates an array of with . + /// The identifier of the value to get. + /// The array of to be associated with . Pass to remove any existing association. + /// A callback to convert between the array's element type to + protected void SetArrayValue (NSString key, T []? values, Func convert) + { + if (NullCheckObjectAndRemoveKey (key, values)) { + var handles = new NativeHandle [values.Length]; + for (var i = 0; i < handles.Length; i++) + handles [i] = convert (values [i]); + var array = CFArray.FromIntPtrs (handles!); + CFMutableDictionary.SetValue (Dictionary.Handle, key, array); } } + /// Associates a array with . + /// The identifier of the value to get. + /// The array to be associated with . Pass to remove any existing association. + protected void SetArrayOfDictionariesValue (NSString key, DictionaryContainer []? values) + { + SetArrayValue (key, values, DictionaryContainerHelper.GetHandle); + } + #region Sets CFBoolean value - /// The identifier associated with the Boolean. - /// The nullable Boolean to be associated with . - /// Stores the Boolean and associates it with the . - /// To be added. + /// Associates a nullable with . + /// The identifier of the value to get. + /// The nullable value to be associated with . Pass to remove any existing association. protected void SetBooleanValue (NSString key, bool? value) { - if (NullCheckAndRemoveKey (key, !value.HasValue)) { - CFMutableDictionary.SetValue (Dictionary.Handle, key.Handle, value!.Value ? CFBoolean.TrueHandle : CFBoolean.FalseHandle); - GC.KeepAlive (key); + if (NullCheckValueTypeAndRemoveKey (key, value)) { + var v = value.Value ? CFBoolean.TrueHandle : CFBoolean.FalseHandle; + CFMutableDictionary.SetValue (Dictionary.Handle, key, v); } } @@ -550,88 +701,144 @@ protected void SetBooleanValue (NSString key, bool? value) #region Sets NSNumber value - /// The identifier associated with the int. - /// The nullable int to be associated with . - /// Stores the int (or ) and associates it with the . - /// To be added. + /// Associates a nullable with . + /// The identifier of the value to get. + /// The nullable value to be associated with . Pass to remove any existing association. + protected void SetNumberValue (NSString key, byte? value) + { + if (NullCheckValueTypeAndRemoveKey (key, value)) + Dictionary [key] = new NSNumber (value.Value); + } + + /// Associates a nullable with . + /// The identifier of the value to get. + /// The nullable value to be associated with . Pass to remove any existing association. + protected void SetNumberValue (NSString key, sbyte? value) + { + if (NullCheckValueTypeAndRemoveKey (key, value)) + Dictionary [key] = new NSNumber (value.Value); + } + + /// Associates a nullable with . + /// The identifier of the value to get. + /// The nullable value to be associated with . Pass to remove any existing association. + protected void SetNumberValue (NSString key, short? value) + { + if (NullCheckValueTypeAndRemoveKey (key, value)) + Dictionary [key] = new NSNumber (value.Value); + } + + /// Associates a nullable with . + /// The identifier of the value to get. + /// The nullable value to be associated with . Pass to remove any existing association. + protected void SetNumberValue (NSString key, ushort? value) + { + if (NullCheckValueTypeAndRemoveKey (key, value)) + Dictionary [key] = new NSNumber (value.Value); + } + + /// Associates a nullable with . + /// The identifier of the value to get. + /// The nullable value to be associated with . Pass to remove any existing association. protected void SetNumberValue (NSString key, int? value) { - if (NullCheckAndRemoveKey (key, !value.HasValue)) - Dictionary [key] = new NSNumber (value!.Value); + if (NullCheckValueTypeAndRemoveKey (key, value)) + Dictionary [key] = new NSNumber (value.Value); } - /// The identifier associated with the uint. - /// The nullable unsigned int to be associated with . - /// Stores the unsigned int (or ) and associates it with the . - /// To be added. + /// Associates a nullable with . + /// The identifier of the value to get. + /// The nullable value to be associated with . Pass to remove any existing association. + protected void SetNumberValue (NSString key, uint? value) { - if (NullCheckAndRemoveKey (key, !value.HasValue)) - Dictionary [key] = new NSNumber (value!.Value); + if (NullCheckValueTypeAndRemoveKey (key, value)) + Dictionary [key] = new NSNumber (value.Value); } + /// Associates a nullable with . + /// The identifier of the value to get. + /// The nullable value to be associated with . Pass to remove any existing association. protected void SetNumberValue (NSString key, nint? value) { - if (NullCheckAndRemoveKey (key, !value.HasValue)) - Dictionary [key] = new NSNumber (value!.Value); + if (NullCheckValueTypeAndRemoveKey (key, value)) + Dictionary [key] = new NSNumber (value.Value); } + /// Associates a nullable with . + /// The identifier of the value to get. + /// The nullable value to be associated with . Pass to remove any existing association. protected void SetNumberValue (NSString key, nuint? value) { - if (NullCheckAndRemoveKey (key, !value.HasValue)) - Dictionary [key] = new NSNumber (value!.Value); + if (NullCheckValueTypeAndRemoveKey (key, value)) + Dictionary [key] = new NSNumber (value.Value); } - /// The identifier associated with the long. - /// The nullable long to be associated with . - /// Stores the long (or ) and associates it with the . - /// To be added. + /// Associates a nullable with . + /// The identifier of the value to get. + /// The nullable value to be associated with . Pass to remove any existing association. protected void SetNumberValue (NSString key, long? value) { - if (NullCheckAndRemoveKey (key, !value.HasValue)) - Dictionary [key] = new NSNumber (value!.Value); + if (NullCheckValueTypeAndRemoveKey (key, value)) + Dictionary [key] = new NSNumber (value.Value); } - /// The identifier associated with the float. - /// The nullable float to be associated with . - /// Stores the float (or ) and associates it with the . - /// To be added. + /// Associates a nullable with . + /// The identifier of the value to get. + /// The nullable value to be associated with . Pass to remove any existing association. + protected void SetNumberValue (NSString key, ulong? value) + { + if (NullCheckValueTypeAndRemoveKey (key, value)) + Dictionary [key] = new NSNumber (value.Value); + } + + /// Associates a nullable with . + /// The identifier of the value to get. + /// The nullable value to be associated with . Pass to remove any existing association. protected void SetNumberValue (NSString key, float? value) { - if (NullCheckAndRemoveKey (key, !value.HasValue)) - Dictionary [key] = new NSNumber (value!.Value); + if (NullCheckValueTypeAndRemoveKey (key, value)) + Dictionary [key] = new NSNumber (value.Value); } - /// The identifier associated with the double. - /// The nullable double to be associated with . - /// Stores the double (or ) and associates it with the . - /// To be added. + /// Associates a nullable with . + /// The identifier of the value to get. + /// The nullable value to be associated with . Pass to remove any existing association. + protected void SetNumberValue (NSString key, nfloat? value) + { + // we only support 64-bit architectures at the moment, so this is safe + Validate64BitNFloat (); + + SetNumberValue (key, (double?) value); + } + + /// Associates a nullable with . + /// The identifier of the value to get. + /// The nullable value to be associated with . Pass to remove any existing association. protected void SetNumberValue (NSString key, double? value) { - if (NullCheckAndRemoveKey (key, !value.HasValue)) - Dictionary [key] = new NSNumber (value!.Value); + if (NullCheckValueTypeAndRemoveKey (key, value)) + Dictionary [key] = new NSNumber (value.Value); } #endregion #region Sets NSString value - /// The identifier associated with the string. - /// The string to be associated with . - /// Stores the string and associates it with the . - /// To be added. + /// Associates a nullable with . + /// The identifier of the value to get. + /// The nullable value to be associated with . Pass to remove any existing association. protected void SetStringValue (NSString key, string? value) { - SetStringValue (key, value is null ? (NSString) null! : new NSString (value)); + SetStringValue (key, (NSString?) value); } - /// The identifier associated with the string. - /// The string to be associated with . - /// Stores the string and associates it with the . - /// To be added. + /// Associates a nullable with . + /// The identifier of the value to get. + /// The nullable value to be associated with . Pass to remove any existing association. protected void SetStringValue (NSString key, NSString? value) { - if (NullCheckAndRemoveKey (key, value is null)) + if (NullCheckObjectAndRemoveKey (key, value)) Dictionary [key] = value; } @@ -639,25 +846,20 @@ protected void SetStringValue (NSString key, NSString? value) #region Sets Native value - /// To be added. - /// To be added. - /// To be added. - /// To be added. - /// To be added. + /// Associates a nullable value with . + /// The identifier of the value to get. + /// The nullable value to be associated with . Pass to remove any existing association. + /// Specifies whether any existing values should be removed if is . protected void SetNativeValue (NSString key, INativeObject? value, bool removeNullValue = true) { - if (NullCheckAndRemoveKey (key, removeNullValue && value is null)) { - CFMutableDictionary.SetValue (Dictionary.Handle, key.Handle, value.GetHandle ()); - GC.KeepAlive (key); - GC.KeepAlive (value); - } + if (NullCheckObjectAndRemoveKey (key, removeNullValue ? value : key /* key is just an object that's not null */)) + CFMutableDictionary.SetValue (Dictionary.Handle, key, value); } #endregion - /// The identifier of the value to be removed. - /// Removes from the dictionary the value associated with . - /// To be added. + /// Removes from the dictionary the value associated with . + /// The identifier of the value to get. protected void RemoveValue (NSString key) { if (key is null) @@ -668,47 +870,46 @@ protected void RemoveValue (NSString key) #region Sets structs values - /// The identifier associated with the . - /// The to be associated with . - /// Stores the and associates it with the . - /// To be added. + /// Associates a nullable value with . + /// The identifier of the value to get. + /// The nullable value to be associated with . Pass to remove any existing association. protected void SetCGRectValue (NSString key, CGRect? value) { - if (NullCheckAndRemoveKey (key, !value.HasValue)) - Dictionary [key] = value!.Value.ToDictionary (); + if (NullCheckValueTypeAndRemoveKey (key, value)) + Dictionary [key] = value.Value.ToDictionary (); } - /// The identifier associated with the . - /// The to be associated with . - /// Stores the and associates it with the . - /// To be added. + /// Associates a nullable value with . + /// The identifier of the value to get. + /// The nullable value to be associated with . Pass to remove any existing association. protected void SetCGSizeValue (NSString key, CGSize? value) { - if (NullCheckAndRemoveKey (key, !value.HasValue)) - Dictionary [key] = value!.Value.ToDictionary (); + if (NullCheckValueTypeAndRemoveKey (key, value)) + Dictionary [key] = value.Value.ToDictionary (); } - /// The identifier associated with the . - /// The to be associated with . - /// Stores the and associates it with the . - /// To be added. + /// Associates a nullable value with . + /// The identifier of the value to get. + /// The nullable value to be associated with . Pass to remove any existing association. protected void SetCGPointValue (NSString key, CGPoint? value) { - if (NullCheckAndRemoveKey (key, !value.HasValue)) - Dictionary [key] = value!.Value.ToDictionary (); + if (NullCheckValueTypeAndRemoveKey (key, value)) + Dictionary [key] = value.Value.ToDictionary (); } - /// The identifier associated with the . - /// The to be associated with . - /// Stores the and associates it with the . - /// To be added. + /// Associates a nullable value with . + /// The identifier of the value to get. + /// The nullable value to be associated with . Pass to remove any existing association. protected void SetCMTimeValue (NSString key, CMTime? value) { - if (NullCheckAndRemoveKey (key, !value.HasValue)) - Dictionary [key] = value!.Value.ToDictionary (); + if (NullCheckValueTypeAndRemoveKey (key, value)) + Dictionary [key] = value.Value.ToDictionary (); } #if HAS_UIKIT + /// Associates a nullable value with . + /// The identifier of the value to get. + /// The nullable value to be associated with . Pass to remove any existing association. protected void SetUIEdgeInsets (NSString key, UIEdgeInsets? value) { SetNativeValue (key, value is null ? null : NSValue.FromUIEdgeInsets (value.Value)); @@ -716,6 +917,13 @@ protected void SetUIEdgeInsets (NSString key, UIEdgeInsets? value) #endif #endregion #endif + + unsafe static void Validate64BitNFloat () + { + var size = sizeof (nfloat); + if (size != 8) + throw new InvalidOperationException ($"Unexpected nfloat size: {size}"); + } } #if !COREBUILD diff --git a/src/ObjCRuntime/Runtime.cs b/src/ObjCRuntime/Runtime.cs index b570a9b6d639..ea6665a39ddb 100644 --- a/src/ObjCRuntime/Runtime.cs +++ b/src/ObjCRuntime/Runtime.cs @@ -1718,25 +1718,44 @@ static IntPtr CreateNSObject (IntPtr type_gchandle, IntPtr handle, NSObject.Flag return o; } + /// Wraps an unmanaged into a fully typed , or returns an existing wrapper object if one already exists. /// Type to wrap the native object as. - /// A pointer to an unmanaged NSObject or any class that derives from the Objective-C NSObject class. - /// Wraps an unmanaged IntPtr into a fully typed NSObject, or returns an existing wrapper object if one already exists. - /// An instance of the T class. - /// - /// Returns an instance of the T class even if the native object is not in the class hierarchy of T (no type checks). - /// This method will fail if there already is a managed wrapper of a different (and incompatible) type for the native object. - /// + /// A pointer to an unmanaged or any class that derives from the Objective-C class. + /// An instance of the class . + /// + /// Returns an instance of the class even if the native object is not in the class hierarchy of (no type checks). + /// This method will fail if there already is a managed wrapper of a different and incompatible type for the native object. + /// static public T? GetNSObject (IntPtr ptr) where T : NSObject { - return GetNSObject (ptr, IntPtr.Zero, default (RuntimeMethodHandle)); + return GetNSObject (ptr, IntPtr.Zero, default (RuntimeMethodHandle), false, false); + } + + /// Wraps an unmanaged into a fully typed , or returns an existing wrapper object if one already exists. + /// Type to wrap the native object as. + /// A pointer to an unmanaged or any class that derives from the Objective-C class. + /// An instance of the class . + /// + /// Contrary to , this method will throw an exception if the native object's type is not compatible with . + /// This method will fail if there already is a managed wrapper of a different and incompatible type for the native object. + /// + // Not doing "GetNSObject(IntPtr, bool checked)" because that signature very much looks like the second parameter is an "owns" parameter, a common signatures in similar methods. + public static T? GetNSObjectChecked (IntPtr ptr) where T : NSObject + { + return GetNSObject (ptr, IntPtr.Zero, default (RuntimeMethodHandle), false, true); } static T? GetNSObject (IntPtr ptr, IntPtr sel, RuntimeMethodHandle method_handle) where T : NSObject { - return GetNSObject (ptr, sel, method_handle, false); + return GetNSObject (ptr, sel, method_handle, false, false); } static T? GetNSObject (IntPtr ptr, IntPtr sel, RuntimeMethodHandle method_handle, bool evenInFinalizerQueue) where T : NSObject + { + return GetNSObject (ptr, sel, method_handle, evenInFinalizerQueue, false); + } + + static T? GetNSObject (IntPtr ptr, IntPtr sel, RuntimeMethodHandle method_handle, bool evenInFinalizerQueue, bool typeSafe) where T : NSObject { if (ptr == IntPtr.Zero) return null; @@ -1747,6 +1766,9 @@ static IntPtr CreateNSObject (IntPtr type_gchandle, IntPtr handle, NSObject.Flag if (obj is T o) return o; + if (typeSafe && obj is not null) + throw new InvalidCastException ($"Unable to cast object of type '{obj.GetType ().FullName}' to type '{typeof (T).FullName}'."); + // We either didn't find an object, or it was of the wrong type, so we need to create a new instance. // Try to get the managed type that correspond to this exact native type @@ -1771,6 +1793,13 @@ static IntPtr CreateNSObject (IntPtr type_gchandle, IntPtr handle, NSObject.Flag target_type = typeof (NSObject); } + if (typeSafe) { + obj = ConstructNSObject (ptr, target_type, MissingCtorResolution.ThrowConstructor1NotFound, sel, method_handle); + if (obj is T o2) + return o2; + throw new InvalidCastException ($"Unable to cast object of type '{obj.GetType ().FullName}' to type '{typeof (T).FullName}'."); + } + return ConstructNSObject (ptr, target_type, MissingCtorResolution.ThrowConstructor1NotFound, sel, method_handle); } diff --git a/src/Resources.Designer.cs b/src/Resources.Designer.cs index 4767a7547e2e..065b18eaa7ff 100644 --- a/src/Resources.Designer.cs +++ b/src/Resources.Designer.cs @@ -1158,5 +1158,23 @@ internal static string BI1120 { return ResourceManager.GetString("BI1120", resourceCulture); } } + + /// + /// Looks up a localized string similar to The strong enum '{0}' is not a valid strong dictionary field for the property '{1}.{2}', because its backing type is '{3}'. Only enums with backing type 'NSString' or 'NSNumber' are supported in strong dictionaries.. + /// + internal static string BI1121 { + get { + return ResourceManager.GetString("BI1121", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to find the corresponding NSNumber property for the type {0} in {1}.{2}. + /// + internal static string BI1122 { + get { + return ResourceManager.GetString("BI1122", resourceCulture); + } + } } } diff --git a/src/Resources.resx b/src/Resources.resx index 454bafab70d5..7b03d8c8373c 100644 --- a/src/Resources.resx +++ b/src/Resources.resx @@ -625,4 +625,12 @@ The type '{0}' is trying to inline the methods binding the selector '{1}' from the protocols '{2}' and '{3}', using methods with different signatures ('{4}' vs '{5}'). These methods will be ignored. + + The strong enum '{0}' is not a valid strong dictionary field for the property '{1}.{2}', because its backing type is '{3}'. Only enums with backing type 'NSString' or 'NSNumber' are supported in strong dictionaries. + + + + Unable to find the corresponding NSNumber property for the type {0} in {1}.{2} + + diff --git a/src/bgen/Enums.cs b/src/bgen/Enums.cs index 380af426cd75..ceb1ed3e13b1 100644 --- a/src/bgen/Enums.cs +++ b/src/bgen/Enums.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Text; @@ -43,6 +44,61 @@ void CopyNativeName (ICustomAttributeProvider provider) print ("[NativeName (\"{0}\")]", oa.NativeName); } +#nullable enable + bool IsEnumBackedByNativeType (Type type, [NotNullWhen (true)] out Type? backingFieldType) + { + backingFieldType = null; + + if (!type.IsEnum) + return false; + + var backingFieldTypeAttribute = AttributeManager.GetCustomAttribute (type); + if (backingFieldTypeAttribute is not null) { + backingFieldType = backingFieldTypeAttribute.BackingFieldType; + return true; + } + + foreach (var f in type.GetFields ()) { + var fa = AttributeManager.GetCustomAttribute (f); + if (fa is null) + continue; + + backingFieldType = TypeCache.NSString; + return true; + } + + // Checking for Field attributes on the enum only works if the enum is in the current api definition we're processing. + // So check for the Extensions type, with GetConstant + GetValue methods, as well. + + var extensionType = type.Assembly.GetType (type.FullName + "Extensions"); + if (extensionType is null) + return false; + + var anyPropertiesWithFields = false; + foreach (var p in type.GetProperties (BindingFlags.NonPublic | BindingFlags.Static)) { + if (!AttributeManager.HasAttribute (p)) + continue; + + anyPropertiesWithFields = true; + break; + } + if (!anyPropertiesWithFields) + return false; + + var getConstantMethod = type.GetMethod ("GetConstant", BindingFlags.Public | BindingFlags.Static, new Type [] { type }); + if (getConstantMethod is null) + return false; + + backingFieldType = getConstantMethod.ReturnType; + + var getValueMethod = type.GetMethod ("GetValue", BindingFlags.Public | BindingFlags.Static, new Type [] { backingFieldType }); + if (getValueMethod is null) + return false; + + return false; + } +#nullable disable + // caller already: // - setup the header and namespace // - call/emit PrintPlatformAttributes on the type @@ -168,8 +224,10 @@ void GenerateEnum (Type type) var field = fields.FirstOrDefault (); var fieldAttr = field.Value; - if (!TryComputeLibraryName (fieldAttr?.LibraryName, type, out library_name, out var _)) - throw ErrorHelper.CreateError (1042, /* Missing '[Field (LibraryName=value)]' for {0} (e.g."__Internal") */ type.FullName + "." + field.Key?.Name); + if (!TryComputeLibraryName (fieldAttr?.LibraryName, type, out library_name, out var _)) { + exceptions.Add (ErrorHelper.CreateError (1042, /* Missing '[Field (LibraryName=value)]' for {0} (e.g."__Internal") */ type.FullName + "." + field.Key?.Name)); + library_name = "placeholder"; + } } } diff --git a/src/bgen/Generator.cs b/src/bgen/Generator.cs index 7936a40eb12e..494e26b448de 100644 --- a/src/bgen/Generator.cs +++ b/src/bgen/Generator.cs @@ -1784,6 +1784,91 @@ void GenerateLibraryHandles () sw.Close (); } + bool TryGetNSNumberStrongDictionaryMethods (Type type, [NotNullWhen (true)] out string? getter, [NotNullWhen (true)] out string? setter) + { + setter = "SetNumberValue"; + getter = null; + + if (type == TypeCache.System_SByte || + type == TypeCache.System_Byte || + type == TypeCache.System_Int16 || + type == TypeCache.System_UInt16 || + type == TypeCache.System_Int32 || + type == TypeCache.System_UInt32 || + type == TypeCache.System_Double + ) { + getter = "Get" + type.Name + "Value"; + } else if (type == TypeCache.System_nint) { + getter = "GetNIntValue"; + } else if (type == TypeCache.System_nuint) { + getter = "GetNUIntValue"; + } else if (type == TypeCache.System_Int64) { + getter = "GetLongValue"; + } else if (type == TypeCache.System_UInt64) { + getter = "GetULongValue"; + } else if (type == TypeCache.System_Float) { + getter = "GetFloatValue"; + } else if (type == TypeCache.System_nfloat) { + getter = "GetNFloatValue"; + } else if (type == TypeCache.System_Boolean) { + getter = "GetBoolValue"; + setter = "SetBooleanValue"; + } else { + return false; + } + + return true; + } + + bool TryGetNSNumberField (Type wrappedNumberType, [NotNullWhen (true)] out string? fieldName) + { + fieldName = null; + + if (wrappedNumberType == TypeCache.System_Float) { + fieldName = "FloatValue"; + } else if (wrappedNumberType == TypeCache.System_Double) { + fieldName = "DoubleValue"; + } else if (wrappedNumberType == TypeCache.System_nfloat) { + fieldName = "NFloatValue"; + } else if (wrappedNumberType == TypeCache.System_Int32) { + fieldName = "Int32Value"; + } else if (wrappedNumberType == TypeCache.System_UInt32) { + fieldName = "UInt32Value"; + } else if (wrappedNumberType == TypeCache.System_Int64) { + fieldName = "Int64Value"; + } else if (wrappedNumberType == TypeCache.System_UInt64) { + fieldName = "UInt64Value"; + } else if (wrappedNumberType == TypeCache.System_Int16) { + fieldName = "Int16Value"; + } else if (wrappedNumberType == TypeCache.System_UInt16) { + fieldName = "UInt16Value"; + } else if (wrappedNumberType == TypeCache.System_SByte) { + fieldName = "SByteValue"; + } else if (wrappedNumberType == TypeCache.System_Byte) { + fieldName = "ByteValue"; + } else if (wrappedNumberType == TypeCache.System_Boolean) { + fieldName = "BoolValue"; + } else if (wrappedNumberType == TypeCache.System_nint) { + fieldName = "NIntValue"; + } else if (wrappedNumberType == TypeCache.System_nuint) { + fieldName = "NUIntValue"; + } else { + return false; + } + + return true; + } + + void ValidateStrongEnumBackingTypeInStrongDictionaryType (PropertyInfo property, Type enumBackingType) + { + if (enumBackingType == TypeCache.NSString) + return; + if (enumBackingType == TypeCache.NSNumber) + return; + + exceptions.Add (ErrorHelper.CreateError (1121 /* The strong enum '{0}' is not a valid strong dictionary field for the property '{1}.{2}', because its backing type is '{3}'. Only enums with backing type 'NSString' or 'NSNumber' are supported in strong dictionaries. */, property.PropertyType.Name, property.DeclaringType.FullName, property.Name, enumBackingType.FullName)); + } + // // Processes the various StrongDictionaryAttribute interfaces // @@ -1849,41 +1934,32 @@ void GenerateStrongDictionaryTypes () string castToUnderlying = ""; string castToEnum = ""; bool isNativeEnum = false; + Type? enumBackingType = null; if (pi.PropertyType.IsEnum) { - fetchType = pi.PropertyType.GetEnumUnderlyingType (); - castToUnderlying = "(" + fetchType + "?)"; - castToEnum = "(" + TypeManager.FormatType (dictType, pi.PropertyType) + "?)"; - isNativeEnum = IsNativeEnum (pi.PropertyType); + if (IsEnumBackedByNativeType (pi.PropertyType, out enumBackingType)) { + ValidateStrongEnumBackingTypeInStrongDictionaryType (pi, enumBackingType); + fetchType = enumBackingType; + } else { + fetchType = pi.PropertyType.GetEnumUnderlyingType (); + castToUnderlying = "(" + fetchType + "?)"; + castToEnum = "(" + TypeManager.FormatType (dictType, pi.PropertyType) + "?)"; + isNativeEnum = IsNativeEnum (pi.PropertyType); + } } if (pi.PropertyType.IsValueType) { - if (pi.PropertyType == TypeCache.System_Boolean) { - getter = "{1} GetBoolValue ({0})"; - setter = "SetBooleanValue ({0}, {1}value)"; - } else if (fetchType == TypeCache.System_Int32) { - getter = "{1} GetInt32Value ({0})"; - setter = "SetNumberValue ({0}, {1}value)"; - } else if (fetchType == TypeCache.System_nint) { - getter = "{1} GetNIntValue ({0})"; - setter = "SetNumberValue ({0}, {1}value)"; - } else if (fetchType == TypeCache.System_Int64) { - getter = "{1} GetLongValue ({0})"; - setter = "SetNumberValue ({0}, {1}value)"; - } else if (fetchType == TypeCache.System_UInt64) { - getter = "{1} GetULongValue ({0})"; - setter = "SetNumberValue ({0}, {1}value)"; - } else if (pi.PropertyType == TypeCache.System_Float) { - getter = "{1} GetFloatValue ({0})"; - setter = "SetNumberValue ({0}, {1}value)"; - } else if (pi.PropertyType == TypeCache.System_Double) { - getter = "{1} GetDoubleValue ({0})"; - setter = "SetNumberValue ({0}, {1}value)"; - } else if (fetchType == TypeCache.System_UInt32) { - getter = "{1} GetUInt32Value ({0})"; + if (enumBackingType is not null) { + getter = "TryGetNativeValue ({0}, out var handle) ? " + TypeManager.FormatType (null, pi.PropertyType) + "Extensions.GetNullableValue (handle) : null"; + setter = "SetNativeValue ({0}, value.HasValue ? value.Value.GetConstant () : null)"; + } else if (isNativeEnum && fetchType == TypeCache.System_Int64) { + getter = "{1} (long?) GetNIntValue ({0})"; setter = "SetNumberValue ({0}, {1}value)"; - } else if (fetchType == TypeCache.System_nuint) { - getter = "{1} GetNUIntValue ({0})"; + } else if (isNativeEnum && fetchType == TypeCache.System_UInt64) { + getter = "{1} (ulong?) GetNUIntValue ({0})"; setter = "SetNumberValue ({0}, {1}value)"; + } else if (TryGetNSNumberStrongDictionaryMethods (fetchType, out var getNSNumber, out var setNSNumber)) { + getter = "{1} " + getNSNumber + " ({0})"; + setter = setNSNumber + " ({0}, {1}value)"; } else if (fetchType == TypeCache.System_DateTime) { getter = "GetDateTimeValue ({0})"; setter = "SetNativeValue ({0}, (NSDate?) value)"; @@ -1899,15 +1975,12 @@ void GenerateStrongDictionaryTypes () } else if (Frameworks.HaveCoreMedia && fetchType == TypeCache.CMTime) { getter = "{1} GetCMTimeValue ({0})"; setter = "SetCMTimeValue ({0}, {1}value)"; - } else if (isNativeEnum && fetchType == TypeCache.System_Int64) { - getter = "{1} (long?) GetNIntValue ({0})"; - setter = "SetNumberValue ({0}, {1}value)"; - } else if (isNativeEnum && fetchType == TypeCache.System_UInt64) { - getter = "{1} (ulong?) GetNUIntValue ({0})"; - setter = "SetNumberValue ({0}, {1}value)"; } else if (fetchType == TypeCache.UIEdgeInsets) { getter = "{1} GetUIEdgeInsets ({0})"; setter = "SetUIEdgeInsets ({0}, {1}value)"; + } else if (pi.PropertyType.Name == "NMatrix3") { + getter = "{1} GetNSDataAsValueType<" + TypeManager.FormatType (null, pi.PropertyType) + "> ({0})"; + setter = "SetValueTypeAsNSData ({0}, {1}value)"; } else { exceptions.Add (new BindingException (1033, true, pi.PropertyType, dictType, pi.Name)); continue; @@ -1915,22 +1988,39 @@ void GenerateStrongDictionaryTypes () } else { if (pi.PropertyType.IsArray) { var elementType = pi.PropertyType.GetElementType (); - if (TypeManager.IsWrappedType (elementType)) { + if (TypeManager.IsDictionaryContainerType (elementType)) { + var dictElementType = TypeManager.FormatType (dictType, elementType); + getter = $"GetArrayOfDictionariesValue<{dictElementType}> ({{0}})"; + setter = "SetArrayOfDictionariesValue ({0}, value)"; + } else if (TypeCache.INativeObject.IsAssignableFrom (elementType)) { + var dictElementType = TypeManager.FormatType (dictType, elementType); + getter = "GetArray<" + dictElementType + "> ({0}, (ptr) => Runtime.GetINativeObject<" + dictElementType + "> (ptr, false)!)"; + setter = "SetArrayValue ({0}, value)"; + } else if (TypeManager.IsWrappedType (elementType)) { getter = "GetArray<" + TypeManager.FormatType (dictType, elementType) + "> ({0})"; setter = "SetArrayValue ({0}, value)"; + } else if (IsEnumBackedByNativeType (elementType, out enumBackingType)) { + ValidateStrongEnumBackingTypeInStrongDictionaryType (pi, enumBackingType); + + var enumTypeStr = TypeManager.FormatType (null, elementType); + getter = "{1} GetArray<" + enumTypeStr + "> ({0}, (ptr) => ptr == NativeHandle.Zero ? default (" + enumTypeStr + ") : " + enumTypeStr + "Extensions.GetValue (ptr))"; + setter = "SetArrayValue<" + enumTypeStr + "> ({0}, value, (element) => Runtime.RetainAndAutoreleaseNSObject (element.GetConstant ()))"; } else if (elementType.IsEnum) { - // Handle arrays of enums as arrays of NSNumbers, casted to the enum + var underlyingEnumType = elementType.GetEnumUnderlyingType (); + if (!TryGetNSNumberField (underlyingEnumType, out var fieldName)) + exceptions.Add (ErrorHelper.CreateError (1122 /* Unable to find the corresponding NSNumber property for the type {0} in {1}.{2} */, underlyingEnumType.FullName, pi.DeclaringType.FullName, pi.Name)); + + // Handle arrays of enums as arrays of NSNumbers var enumTypeStr = TypeManager.FormatType (null, elementType); - getter = "GetArray<" + enumTypeStr + - "> ({0}, (ptr)=> {{\n\tusing (var num = Runtime.GetNSObject (ptr)!){{\n\t\treturn (" + - enumTypeStr + ") num.Int32Value;\n\t}}\n}})"; - setter = "SetArrayValue<" + enumTypeStr + "> ({0}, value)"; + getter = "GetArray<" + enumTypeStr + "> ({0}, (ptr) => (" + enumTypeStr + "?) Runtime.GetNSObjectChecked (ptr)?." + fieldName + " ?? default (" + enumTypeStr + "))"; + setter = "SetArrayValue<" + enumTypeStr + "> ({0}, value, (element) => Runtime.RetainAndAutoreleaseNSObject (new NSNumber ((" + TypeManager.FormatType (null, underlyingEnumType) + ") element)))"; } else if (elementType == TypeCache.System_String) { getter = "GetArray ({0}, (ptr) => CFString.FromHandle (ptr)!)"; setter = "SetArrayValue ({0}, value)"; - } else if (elementType.Name == "CTFontDescriptor") { - getter = "GetArray ({0}, (ptr) => new CTFontDescriptor (ptr, false))"; - setter = "SetArrayValue ({0}, value)"; + } else if (TryGetNSNumberField (elementType, out var fieldName)) { + var renderedElementType = TypeManager.RenderType (elementType); + getter = "GetArray<" + renderedElementType + "> ({0}, (ptr) => (" + renderedElementType + "?) Runtime.GetNSObjectChecked (ptr)?." + fieldName + " ?? default (" + renderedElementType + "))"; + setter = "SetArrayValue<" + renderedElementType + "> ({0}, value)"; } else { exceptions.Add (new BindingException (1033, true, pi.PropertyType, dictType, pi.Name)); continue; @@ -1953,7 +2043,7 @@ void GenerateStrongDictionaryTypes () } else if (TypeManager.IsDictionaryContainerType (pi.PropertyType) || AttributeManager.HasAttribute (pi)) { var strType = pi.PropertyType.Name; getter = $"GetStrongDictionary<{strType}>({{0}}, (dict) => new {strType} (dict))"; - setter = "SetNativeValue ({0}, value.GetDictionary ())"; + setter = "SetNativeValue ({0}, value?.Dictionary)"; } else if (TypeCache.INativeObject.IsAssignableFrom (pi.PropertyType)) { getter = $"GetNativeValue<{pi.PropertyType}> ({{0}})"; setter = "SetNativeValue ({0}, value)"; @@ -6151,8 +6241,10 @@ public void Generate (Type type) if (field_exports.Count != 0) { foreach (var field_pi in field_exports.OrderBy (f => f.Name, StringComparer.Ordinal)) { var fieldAttr = AttributeManager.GetCustomAttribute (field_pi); - if (!TryComputeLibraryName (fieldAttr?.LibraryName, type, out string library_name, out string library_path)) - throw ErrorHelper.CreateError (1042, /* Missing '[Field (LibraryName=value)]' for {0} (e.g."__Internal") */ type.FullName + "." + field_pi.Name); + if (!TryComputeLibraryName (fieldAttr?.LibraryName, type, out string library_name, out string library_path)) { + exceptions.Add (ErrorHelper.CreateError (1042, /* Missing '[Field (LibraryName=value)]' for {0} (e.g."__Internal") */ type.FullName + "." + field_pi.Name)); + continue; + } string fieldTypeName; string smartEnumTypeName = null; diff --git a/src/coretext.cs b/src/coretext.cs index f277c80a0585..adaf4be45f19 100644 --- a/src/coretext.cs +++ b/src/coretext.cs @@ -15,6 +15,8 @@ namespace CoreText { + interface CTFontDescriptor : INativeObject { } + [Partial] interface CTFontManager { [Field ("kCTFontManagerRegisteredFontsChangedNotification")] diff --git a/src/corevideo.cs b/src/corevideo.cs index b83de1ae1698..8e497a400c23 100644 --- a/src/corevideo.cs +++ b/src/corevideo.cs @@ -956,6 +956,7 @@ interface CVPixelFormatKeys { NSString BitsPerComponent { get; } } +#if !XAMCORE_5_0 [Partial] interface CVPixelFormatComponentRangeKeys { [Field ("kCVPixelFormatComponentRange_VideoRange")] @@ -980,6 +981,23 @@ interface CVPixelFormatComponentRange { // there's no documentation about the type, so binding as NSObject NSObject WideRange { get; set; } } +#endif // !XAMCORE_5_0 + +#if XAMCORE_5_0 + enum CVPixelFormatComponentRange { +#else + enum CVPixelFormatComponentRangeValues { +#endif + [Field ("kCVPixelFormatComponentRange_VideoRange")] + VideoRange, + + [Field ("kCVPixelFormatComponentRange_FullRange")] + FullRange, + + [Field ("kCVPixelFormatComponentRange_WideRange")] + WideRange, + } + [StrongDictionary ("CVPixelFormatKeys", Suffix = "")] interface CVPixelFormatDescription { @@ -1019,7 +1037,17 @@ interface CVPixelFormatDescription { bool FormatContainsSenselArray { get; set; } #endif +#if XAMCORE_6_0 CVPixelFormatComponentRange ComponentRange { get; set; } +#elif XAMCORE_5_0 + CVPixelFormatComponentRange ComponentRange { get; set; } + [Export ("ComponentRange")] + [Obsolete ("Use 'ComponentRange' instead.")] + CVPixelFormatComponentRange ComponentRangeValue { get; set; } +#else + [Export ("ComponentRange")] + CVPixelFormatComponentRangeValues ComponentRangeValue { get; set; } +#endif // This can be an array of dictionaries, or a single dictionary when there's only one plane, so we have to type as 'NSObject'. NSObject Planes { get; set; } diff --git a/tests/bindings-test/ApiDefinition.cs b/tests/bindings-test/ApiDefinition.cs index df4a237e5d95..8f48ce816216 100644 --- a/tests/bindings-test/ApiDefinition.cs +++ b/tests/bindings-test/ApiDefinition.cs @@ -1,5 +1,8 @@ using System; +using System.Numerics; +using CoreGraphics; +using CoreMedia; using ObjCRuntime; using Foundation; #if __MACOS__ @@ -573,4 +576,240 @@ interface VeryGenericFactory { [Static] IVeryGenericConsumerProtocol GetConsumer (); } + + enum StrongEnum { + [Field ("StrongEnumA", LibraryName = "__Internal")] + A, + + [Field ("StrongEnumB", LibraryName = "__Internal")] + B, + + [Field ("StrongEnumC", LibraryName = "__Internal")] + C, + } + + [Partial] + interface StrongDictionaryKeys { + // simple types + [Field ("StrongDictionarySByteField", LibraryName = "__Internal")] + NSString SByteField { get; } + + [Field ("StrongDictionaryInt16Field", LibraryName = "__Internal")] + NSString Int16Field { get; } + + [Field ("StrongDictionaryInt32Field", LibraryName = "__Internal")] + NSString Int32Field { get; } + + [Field ("StrongDictionaryInt64Field", LibraryName = "__Internal")] + NSString Int64Field { get; } + + [Field ("StrongDictionaryByteField", LibraryName = "__Internal")] + NSString ByteField { get; } + + [Field ("StrongDictionaryUInt16Field", LibraryName = "__Internal")] + NSString UInt16Field { get; } + + [Field ("StrongDictionaryUInt32Field", LibraryName = "__Internal")] + NSString UInt32Field { get; } + + [Field ("StrongDictionaryUInt64Field", LibraryName = "__Internal")] + NSString UInt64Field { get; } + + [Field ("StrongDictionaryNIntField", LibraryName = "__Internal")] + NSString NIntField { get; } + + [Field ("StrongDictionaryNUIntField", LibraryName = "__Internal")] + NSString NUIntField { get; } + + [Field ("StrongDictionarySingleField", LibraryName = "__Internal")] + NSString SingleField { get; } + + [Field ("StrongDictionaryDoubleField", LibraryName = "__Internal")] + NSString DoubleField { get; } + + [Field ("StrongDictionaryNFloatField", LibraryName = "__Internal")] + NSString NFloatField { get; } + + [Field ("StrongDictionaryNSObjectField", LibraryName = "__Internal")] + NSString NSObjectField { get; } + + [Field ("StrongDictionaryBooleanField", LibraryName = "__Internal")] + NSString BooleanField { get; } + + [Field ("StrongDictionaryNSStringField", LibraryName = "__Internal")] + NSString NSStringField { get; } + + [Field ("StrongDictionaryNSDateField", LibraryName = "__Internal")] + NSString NSDateField { get; } + + [Field ("StrongDictionaryNSDictionaryField", LibraryName = "__Internal")] + NSString NSDictionaryField { get; } + + [Field ("StrongDictionaryStrongDictionaryField", LibraryName = "__Internal")] + NSString NSStrongDictionaryField { get; } + + [Field ("StrongDictionaryStrongEnumField", LibraryName = "__Internal")] + NSString StrongEnumField { get; } + + // arrays of the above + + [Field ("StrongDictionaryArrayOfSByteField", LibraryName = "__Internal")] + NSString ArrayOfSByteField { get; } + + [Field ("StrongDictionaryArrayOfInt16Field", LibraryName = "__Internal")] + NSString ArrayOfInt16Field { get; } + + [Field ("StrongDictionaryArrayOfInt32Field", LibraryName = "__Internal")] + NSString ArrayOfInt32Field { get; } + + [Field ("StrongDictionaryArrayOfInt64Field", LibraryName = "__Internal")] + NSString ArrayOfInt64Field { get; } + + [Field ("StrongDictionaryArrayOfByteField", LibraryName = "__Internal")] + NSString ArrayOfByteField { get; } + + [Field ("StrongDictionaryArrayOfUInt16Field", LibraryName = "__Internal")] + NSString ArrayOfUInt16Field { get; } + + [Field ("StrongDictionaryArrayOfUInt32Field", LibraryName = "__Internal")] + NSString ArrayOfUInt32Field { get; } + + [Field ("StrongDictionaryArrayOfUInt64Field", LibraryName = "__Internal")] + NSString ArrayOfUInt64Field { get; } + + [Field ("StrongDictionaryArrayOfNIntField", LibraryName = "__Internal")] + NSString ArrayOfNIntField { get; } + + [Field ("StrongDictionaryArrayOfNUIntField", LibraryName = "__Internal")] + NSString ArrayOfNUIntField { get; } + + [Field ("StrongDictionaryArrayOfSingleField", LibraryName = "__Internal")] + NSString ArrayOfSingleField { get; } + + [Field ("StrongDictionaryArrayOfDoubleField", LibraryName = "__Internal")] + NSString ArrayOfDoubleField { get; } + + [Field ("StrongDictionaryArrayOfNFloatField", LibraryName = "__Internal")] + NSString ArrayOfNFloatField { get; } + + [Field ("StrongDictionaryArrayOfNSObjectField", LibraryName = "__Internal")] + NSString ArrayOfNSObjectField { get; } + + [Field ("StrongDictionaryArrayOfBooleanField", LibraryName = "__Internal")] + NSString ArrayOfBooleanField { get; } + + [Field ("StrongDictionaryArrayOfNSStringField", LibraryName = "__Internal")] + NSString ArrayOfNSStringField { get; } + + [Field ("StrongDictionaryArrayOfNSDateField", LibraryName = "__Internal")] + NSString ArrayOfNSDateField { get; } + + [Field ("StrongDictionaryArrayOfNSDictionaryField", LibraryName = "__Internal")] + NSString ArrayOfNSDictionaryField { get; } + + [Field ("StrongDictionaryArrayOfStrongDictionaryField", LibraryName = "__Internal")] + NSString ArrayOfStrongDictionaryField { get; } + + [Field ("StrongDictionaryArrayOfStrongEnumField", LibraryName = "__Internal")] + NSString ArrayOfStrongEnumField { get; } + + // other fields + + [Field ("StrongDictionaryStringField", LibraryName = "__Internal")] + NSString StringField { get; } + + [Field ("StrongDictionaryDateTimeField", LibraryName = "__Internal")] + NSString DateTimeField { get; } + + [Field ("StrongDictionaryGenericNSDictionaryField", LibraryName = "__Internal")] + NSString GenericNSDictionaryField { get; } + + [Field ("StrongDictionaryArrayOfStringField", LibraryName = "__Internal")] + NSString ArrayOfStringField { get; } + + [Field ("StrongDictionaryNSDataField", LibraryName = "__Internal")] + NSString NSDataField { get; } + + [Field ("StrongDictionaryNSDataAsMatrix3Field", LibraryName = "__Internal")] + NSString NSDataAsMatrix3Field { get; } + + [Field ("StrongDictionaryCGRectField", LibraryName = "__Internal")] + NSString CGRectField { get; } + + [Field ("StrongDictionaryCGSizeField", LibraryName = "__Internal")] + NSString CGSizeField { get; } + + [Field ("StrongDictionaryCGPointField", LibraryName = "__Internal")] + NSString CGPointField { get; } + + [Field ("StrongDictionaryCMTimeField", LibraryName = "__Internal")] + NSString CMTimeField { get; } + +#if !__MACOS__ + [Field ("StrongDictionaryUIEdgeInsetsField", LibraryName = "__Internal")] + NSString UIEdgeInsetsField { get; } +#endif // !__MACOS__ + } + + [StrongDictionary ("StrongDictionaryKeys", Suffix = "")] + interface WrappedNSDictionary { + // simple types + sbyte SByteField { get; set; } + short Int16Field { get; set; } + int Int32Field { get; set; } + long Int64Field { get; set; } + byte ByteField { get; set; } + ushort UInt16Field { get; set; } + uint UInt32Field { get; set; } + ulong UInt64Field { get; set; } + nint NIntField { get; set; } + nuint NUIntField { get; set; } + float SingleField { get; set; } + double DoubleField { get; set; } + nfloat NFloatField { get; set; } + NSObject NSObjectField { get; set; } + bool BooleanField { get; set; } + NSString NSStringField { get; set; } + NSDate NSDateField { get; set; } + NSDictionary NSDictionaryField { get; set; } + WrappedNSDictionary NSStrongDictionaryField { get; set; } + StrongEnum StrongEnumField { get; set; } + + // arrays of the above + sbyte [] ArrayOfSByteField { get; set; } + short [] ArrayOfInt16Field { get; set; } + int [] ArrayOfInt32Field { get; set; } + long [] ArrayOfInt64Field { get; set; } + byte [] ArrayOfByteField { get; set; } + ushort [] ArrayOfUInt16Field { get; set; } + uint [] ArrayOfUInt32Field { get; set; } + ulong [] ArrayOfUInt64Field { get; set; } + nint [] ArrayOfNIntField { get; set; } + nuint [] ArrayOfNUIntField { get; set; } + float [] ArrayOfSingleField { get; set; } + double [] ArrayOfDoubleField { get; set; } + nfloat [] ArrayOfNFloatField { get; set; } + NSObject [] ArrayOfNSObjectField { get; set; } + bool [] ArrayOfBooleanField { get; set; } + NSString [] ArrayOfNSStringField { get; set; } + NSDate [] ArrayOfNSDateField { get; set; } + NSDictionary [] ArrayOfNSDictionaryField { get; set; } + WrappedNSDictionary [] ArrayOfStrongDictionaryField { get; set; } + StrongEnum [] ArrayOfStrongEnumField { get; set; } + + // other fields + string StringField { get; set; } + DateTime DateTimeField { get; set; } + NSDictionary GenericNSDictionaryField { get; set; } + string [] ArrayOfStringField { get; set; } + NSData NSDataField { get; set; } + NMatrix3 NSDataAsMatrix3Field { get; set; } + CGRect CGRectField { get; set; } + CGSize CGSizeField { get; set; } + CGPoint CGPointField { get; set; } + CMTime CMTimeField { get; set; } +#if !__MACOS__ + UIEdgeInsets UIEdgeInsetsField { get; set; } +#endif // !__MACOS____MACOS__ + } } diff --git a/tests/bindings-test/dotnet/shared.csproj b/tests/bindings-test/dotnet/shared.csproj index 4a6a2579af4a..a1957248ec75 100644 --- a/tests/bindings-test/dotnet/shared.csproj +++ b/tests/bindings-test/dotnet/shared.csproj @@ -6,6 +6,7 @@ ..\..\..\..\product.snk true true + true $([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)\..\..')) $(RootTestsDirectory)\bindings-test diff --git a/tests/cecil-tests/Documentation.KnownFailures.txt b/tests/cecil-tests/Documentation.KnownFailures.txt index 45bfd3766e02..55e90c845e2a 100644 --- a/tests/cecil-tests/Documentation.KnownFailures.txt +++ b/tests/cecil-tests/Documentation.KnownFailures.txt @@ -2704,6 +2704,9 @@ F:CoreVideo.CVFillExtendedPixelsCallBackDataStruct.UserInfo F:CoreVideo.CVFillExtendedPixelsCallBackDataStruct.Version F:CoreVideo.CVImageBufferAlphaChannelMode.Premultiplied F:CoreVideo.CVImageBufferAlphaChannelMode.Straight +F:CoreVideo.CVPixelFormatComponentRangeValues.FullRange +F:CoreVideo.CVPixelFormatComponentRangeValues.VideoRange +F:CoreVideo.CVPixelFormatComponentRangeValues.WideRange F:CoreVideo.CVPixelFormatType.CV16VersatileBayer F:CoreVideo.CVPixelFormatType.CV422YpCbCr8BiPlanarFullRange F:CoreVideo.CVPixelFormatType.CV422YpCbCr8BiPlanarVideoRange @@ -11419,14 +11422,6 @@ M:FileProvider.NSFileProviderUserInfo.#ctor M:FinderSync.FIFinderSync.GetValuesAsync(System.String[],Foundation.NSUrl) M:FinderSync.FIFinderSyncProtocol_Extensions.GetValuesAsync(FinderSync.IFIFinderSyncProtocol,System.String[],Foundation.NSUrl) M:FinderSync.IFIFinderSyncProtocol.GetValuesAsync(System.String[],Foundation.NSUrl) -M:Foundation.DictionaryContainer.GetArray``1(Foundation.NSString,System.Func{ObjCRuntime.NativeHandle,``0}) -M:Foundation.DictionaryContainer.GetStringArrayValue(Foundation.NSString) -M:Foundation.DictionaryContainer.GetStrongDictionary``1(Foundation.NSString,System.Func{Foundation.NSDictionary,``0}) -M:Foundation.DictionaryContainer.GetUIEdgeInsets(Foundation.NSString) -M:Foundation.DictionaryContainer.GetULongValue(Foundation.NSString) -M:Foundation.DictionaryContainer.SetNumberValue(Foundation.NSString,System.Nullable{System.IntPtr}) -M:Foundation.DictionaryContainer.SetNumberValue(Foundation.NSString,System.Nullable{System.UIntPtr}) -M:Foundation.DictionaryContainer.SetUIEdgeInsets(Foundation.NSString,System.Nullable{UIKit.UIEdgeInsets}) M:Foundation.INSCoding.CreateInstance``1(Foundation.NSCoder) M:Foundation.INSFilePresenter.AccommodatePresentedItemEviction(System.Action{Foundation.NSError}) M:Foundation.INSItemProviderReading.GetReadableTypeIdentifiers``1 @@ -21007,7 +21002,7 @@ P:CoreVideo.CVPixelFormatDescription.CGBitmapContextCompatibility P:CoreVideo.CVPixelFormatDescription.CGBitmapInfo P:CoreVideo.CVPixelFormatDescription.CGImageCompatibility P:CoreVideo.CVPixelFormatDescription.CodecType -P:CoreVideo.CVPixelFormatDescription.ComponentRange +P:CoreVideo.CVPixelFormatDescription.ComponentRangeValue P:CoreVideo.CVPixelFormatDescription.Constant P:CoreVideo.CVPixelFormatDescription.ContainsAlpha P:CoreVideo.CVPixelFormatDescription.ContainsGrayscale @@ -27161,6 +27156,7 @@ T:CoreVideo.CVOpenGLESTexture T:CoreVideo.CVOpenGLESTextureCache T:CoreVideo.CVPixelFormatComponentRange T:CoreVideo.CVPixelFormatComponentRangeKeys +T:CoreVideo.CVPixelFormatComponentRangeValues T:CoreVideo.CVPixelFormatKeys T:CoreVideo.CVPixelFormatTypeExtensions T:CoreVideo.CVVersatileBayerPattern diff --git a/tests/generator/BGenTests.cs b/tests/generator/BGenTests.cs index 4806d377e1c1..9d94fc34b92a 100644 --- a/tests/generator/BGenTests.cs +++ b/tests/generator/BGenTests.cs @@ -1495,6 +1495,7 @@ public void Issue19612 () [Test] [TestCase (Profile.iOS)] + [TestCase (Profile.MacCatalyst)] public void BackingFieldType (Profile profile) { Configuration.IgnoreIfIgnoredPlatform (profile.AsPlatform ()); @@ -1511,6 +1512,7 @@ public void BackingFieldType (Profile profile) new { BackingFieldType = "Int64", NullableType = $"System.Nullable`1", RenderedBackingFieldType = "System.Int64", SimplifiedNullableType = "System.Nullable`1" }, new { BackingFieldType = "UInt32", NullableType = $"System.Nullable`1", RenderedBackingFieldType = "System.UInt32", SimplifiedNullableType = "System.Nullable`1" }, new { BackingFieldType = "UInt64", NullableType = $"System.Nullable`1", RenderedBackingFieldType = "System.UInt64", SimplifiedNullableType = "System.Nullable`1" }, + new { BackingFieldType = "NSString", NullableType = $"Foundation.NSString", RenderedBackingFieldType = "Foundation.NSString", SimplifiedNullableType = "Foundation.NSString" }, }; foreach (var tc in testCases) { diff --git a/tests/generator/ErrorTests.cs b/tests/generator/ErrorTests.cs index 646a57660a4b..ff3cbd912ed4 100644 --- a/tests/generator/ErrorTests.cs +++ b/tests/generator/ErrorTests.cs @@ -953,5 +953,41 @@ public void ErrorDomain_NoLibraryName (Profile profile) bgen.AssertExecuteError ("build"); bgen.AssertError (1087, "Missing value for the 'LibraryName' property for the '[ErrorDomain]' attribute for ErrorDomainNS.EWithDomain (e.g. '[ErrorDomain (\"MyDomain\", LibraryName = \"__Internal\")]')"); } + + [Test] + [TestCase (Profile.MacCatalyst)] + public void StrongDictionaryErrors (Profile profile) + { + Configuration.IgnoreIfIgnoredPlatform (profile.AsPlatform ()); + + var bgen = new BGenTool (); + bgen.Profile = profile; + bgen.ProcessEnums = true; + bgen.Defines = BGenTool.GetDefaultDefines (profile); + bgen.CreateTemporaryBinding (File.ReadAllText (Path.Combine (Configuration.SourceRoot, "tests", "generator", "tests", "strongdictionary-errors.cs"))); + bgen.AssertExecuteError ("build"); + + var errorMessages = new string [] + { + "The strong enum 'NSIntegerFieldType' is not a valid strong dictionary field for the property 'BackingField.StrongDictionary.NSIntegerValue', because its backing type is 'System.IntPtr'. Only enums with backing type 'NSString' or 'NSNumber' are supported in strong dictionaries.", + "The strong enum 'NSUIntegerFieldType' is not a valid strong dictionary field for the property 'BackingField.StrongDictionary.NSUIntegerValue', because its backing type is 'System.UIntPtr'. Only enums with backing type 'NSString' or 'NSNumber' are supported in strong dictionaries.", + "The strong enum 'Int32FieldType' is not a valid strong dictionary field for the property 'BackingField.StrongDictionary.Int32Value', because its backing type is 'System.Int32'. Only enums with backing type 'NSString' or 'NSNumber' are supported in strong dictionaries.", + "The strong enum 'Int64FieldType' is not a valid strong dictionary field for the property 'BackingField.StrongDictionary.Int64Value', because its backing type is 'System.Int64'. Only enums with backing type 'NSString' or 'NSNumber' are supported in strong dictionaries.", + "The strong enum 'UInt32FieldType' is not a valid strong dictionary field for the property 'BackingField.StrongDictionary.UInt32Value', because its backing type is 'System.UInt32'. Only enums with backing type 'NSString' or 'NSNumber' are supported in strong dictionaries.", + "The strong enum 'UInt64FieldType' is not a valid strong dictionary field for the property 'BackingField.StrongDictionary.UInt64Value', because its backing type is 'System.UInt64'. Only enums with backing type 'NSString' or 'NSNumber' are supported in strong dictionaries.", + + "The strong enum 'NSIntegerFieldType[]' is not a valid strong dictionary field for the property 'BackingField.StrongDictionary.ArrayOfNSIntegerValue', because its backing type is 'System.IntPtr'. Only enums with backing type 'NSString' or 'NSNumber' are supported in strong dictionaries.", + "The strong enum 'NSUIntegerFieldType[]' is not a valid strong dictionary field for the property 'BackingField.StrongDictionary.ArrayOfNSUIntegerValue', because its backing type is 'System.UIntPtr'. Only enums with backing type 'NSString' or 'NSNumber' are supported in strong dictionaries.", + "The strong enum 'Int32FieldType[]' is not a valid strong dictionary field for the property 'BackingField.StrongDictionary.ArrayOfInt32Value', because its backing type is 'System.Int32'. Only enums with backing type 'NSString' or 'NSNumber' are supported in strong dictionaries.", + "The strong enum 'Int64FieldType[]' is not a valid strong dictionary field for the property 'BackingField.StrongDictionary.ArrayOfInt64Value', because its backing type is 'System.Int64'. Only enums with backing type 'NSString' or 'NSNumber' are supported in strong dictionaries.", + "The strong enum 'UInt32FieldType[]' is not a valid strong dictionary field for the property 'BackingField.StrongDictionary.ArrayOfUInt32Value', because its backing type is 'System.UInt32'. Only enums with backing type 'NSString' or 'NSNumber' are supported in strong dictionaries.", + "The strong enum 'UInt64FieldType[]' is not a valid strong dictionary field for the property 'BackingField.StrongDictionary.ArrayOfUInt64Value', because its backing type is 'System.UInt64'. Only enums with backing type 'NSString' or 'NSNumber' are supported in strong dictionaries.", + }; + + foreach (var msg in errorMessages) + bgen.AssertError (1121, msg); + + bgen.AssertErrorCount (errorMessages.Length); + } } } diff --git a/tests/generator/tests/backingfieldtype.cs b/tests/generator/tests/backingfieldtype.cs index fd360715fc6b..8a602e6e169f 100644 --- a/tests/generator/tests/backingfieldtype.cs +++ b/tests/generator/tests/backingfieldtype.cs @@ -44,6 +44,12 @@ enum UInt64FieldType { G, } + [BackingFieldType (typeof (NSString))] + enum NSStringFieldType { + [Field ("ZField", "__Internal")] + Z, + } + [BaseType (typeof (NSObject))] interface SomeObj { [Export ("nsIntegerField")] @@ -66,5 +72,8 @@ interface SomeObj { [Export ("uint64Field")] UInt64FieldType UInt64Field { get; set; } + + [Export ("nsStringField")] + NSStringFieldType NSStringField { get; set; } } } diff --git a/tests/generator/tests/strongdictionary-errors.cs b/tests/generator/tests/strongdictionary-errors.cs new file mode 100644 index 000000000000..5f37e38dad03 --- /dev/null +++ b/tests/generator/tests/strongdictionary-errors.cs @@ -0,0 +1,124 @@ +using System; +using Foundation; + +namespace BackingField { + [BackingFieldType (typeof (nint))] + enum NSIntegerFieldType { + [Field ("AField", "__Internal")] + A, + } + + [BackingFieldType (typeof (nuint))] + enum NSUIntegerFieldType { + [Field ("BField", "__Internal")] + B, + } + + [BackingFieldType (typeof (NSNumber))] + enum NSNumberFieldType { + [Field ("CField", "__Internal")] + C, + } + + [BackingFieldType (typeof (Int32))] + enum Int32FieldType { + [Field ("DField", "__Internal")] + D, + } + + [BackingFieldType (typeof (Int64))] + enum Int64FieldType { + [Field ("EField", "__Internal")] + E, + } + + [BackingFieldType (typeof (UInt32))] + enum UInt32FieldType { + [Field ("FField", "__Internal")] + F, + } + + [BackingFieldType (typeof (UInt64))] + enum UInt64FieldType { + [Field ("GField", "__Internal")] + G, + } + + [BackingFieldType (typeof (NSString))] + enum NSStringFieldType { + [Field ("ZField", "__Internal")] + Z, + } + + [Partial] + interface StrongDictionaryKeys { + [Field ("StrongDictionaryNSIntegerKey", "__Internal")] + NSString NSIntegerValueKey { get; } + + [Field ("StrongDictionaryNSUIntegerKey", "__Internal")] + NSString NSUIntegerValueKey { get; } + + [Field ("StrongDictionaryNSNumberKey", "__Internal")] + NSString NSNumberValueKey { get; } + + [Field ("StrongDictionaryInt32Key", "__Internal")] + NSString Int32ValueKey { get; } + + [Field ("StrongDictionaryInt64Key", "__Internal")] + NSString Int64ValueKey { get; } + + [Field ("StrongDictionaryUInt32Key", "__Internal")] + NSString UInt32ValueKey { get; } + + [Field ("StrongDictionaryUInt64Key", "__Internal")] + NSString UInt64ValueKey { get; } + + [Field ("StrongDictionaryNSStringKey", "__Internal")] + NSString NSStringValueKey { get; } + + [Field ("StrongDictionaryArrayOfNSIntegerKey", "__Internal")] + NSString ArrayOfNSIntegerValueKey { get; } + + [Field ("StrongDictionaryArrayOfNSUIntegerKey", "__Internal")] + NSString ArrayOfNSUIntegerValueKey { get; } + + [Field ("StrongDictionaryArrayOfNSNumberKey", "__Internal")] + NSString ArrayOfNSNumberValueKey { get; } + + [Field ("StrongDictionaryArrayOfInt32Key", "__Internal")] + NSString ArrayOfInt32ValueKey { get; } + + [Field ("StrongDictionaryArrayOfInt64Key", "__Internal")] + NSString ArrayOfInt64ValueKey { get; } + + [Field ("StrongDictionaryArrayOfUInt32Key", "__Internal")] + NSString ArrayOfUInt32ValueKey { get; } + + [Field ("StrongDictionaryArrayOfUInt64Key", "__Internal")] + NSString ArrayOfUInt64ValueKey { get; } + + [Field ("StrongDictionaryArrayOfNSStringKey", "__Internal")] + NSString ArrayOfNSStringValueKey { get; } + } + + [StrongDictionary ("StrongDictionaryKeys")] + interface StrongDictionary { + NSIntegerFieldType NSIntegerValue { get; } + NSUIntegerFieldType NSUIntegerValue { get; } + NSNumberFieldType NSNumberValue { get; } + Int32FieldType Int32Value { get; } + Int64FieldType Int64Value { get; } + UInt32FieldType UInt32Value { get; } + UInt64FieldType UInt64Value { get; } + NSStringFieldType NSStringValue { get; } + + NSIntegerFieldType [] ArrayOfNSIntegerValue { get; } + NSUIntegerFieldType [] ArrayOfNSUIntegerValue { get; } + NSNumberFieldType [] ArrayOfNSNumberValue { get; } + Int32FieldType [] ArrayOfInt32Value { get; } + Int64FieldType [] ArrayOfInt64Value { get; } + UInt32FieldType [] ArrayOfUInt32Value { get; } + UInt64FieldType [] ArrayOfUInt64Value { get; } + NSStringFieldType [] ArrayOfNSStringValue { get; } + } +} diff --git a/tests/monotouch-test/CoreVideo/PixelFormatDescriptionTest.cs b/tests/monotouch-test/CoreVideo/PixelFormatDescriptionTest.cs index 65d4711555c1..84a8827f9b9c 100644 --- a/tests/monotouch-test/CoreVideo/PixelFormatDescriptionTest.cs +++ b/tests/monotouch-test/CoreVideo/PixelFormatDescriptionTest.cs @@ -79,7 +79,8 @@ public void CV32ARGB () Assert.AreEqual (false, desc.ContainsGrayscale, "ContainsGrayscale"); if (TestRuntime.CheckXcodeVersion (14, 0)) Assert.IsNull (desc.FormatContainsSenselArray, "FormatContainsSenselArray"); - Assert.IsNull (desc.ComponentRange, "ComponentRange"); + if (TestRuntime.CheckXcodeVersion (16, 0)) + Assert.AreEqual (CVPixelFormatComponentRangeValues.FullRange, desc.ComponentRangeValue, "ComponentRangeValue"); Assert.IsNull (desc.Planes, "Planes"); Assert.IsNull (desc.BlockWidth, "BlockWidth"); Assert.IsNull (desc.BlockHeight, "BlockHeight"); diff --git a/tests/monotouch-test/Foundation/DictionaryContainerTest.cs b/tests/monotouch-test/Foundation/DictionaryContainerTest.cs index cd3fd4cd3f88..914162142e67 100644 --- a/tests/monotouch-test/Foundation/DictionaryContainerTest.cs +++ b/tests/monotouch-test/Foundation/DictionaryContainerTest.cs @@ -8,11 +8,21 @@ // using System; +using System.Linq; + using CoreFoundation; +using CoreGraphics; +using CoreMedia; using Foundation; using ObjCRuntime; using NUnit.Framework; +#if HAS_UIKIT +using UIKit; +#endif + +using Bindings.Test; + namespace MonoTouchFixtures.Foundation { public class DictionaryContainerPoker : DictionaryContainer { @@ -233,5 +243,372 @@ public void SetStringValue () dc.SetStringValue_ (key, null); Assert.That ((int) dc.Dictionary.Count, Is.EqualTo (0), "0"); } + + [Test] + public void WrappedNSDictionary () + { + var wrapped = new WrappedNSDictionary (); + + Assert.Multiple (() => { + Assert.IsNull (wrapped.SByteField, "SByteField"); + var valueSByteField = SByte.MaxValue; + wrapped.SByteField = valueSByteField; + Assert.AreEqual (valueSByteField, wrapped.SByteField, "SByteField - set"); + wrapped.SByteField = null; + Assert.IsNull (wrapped.SByteField, "SByteField - final"); + + Assert.IsNull (wrapped.Int16Field, "Int16Field"); + var valueInt16Field = Int16.MaxValue; + wrapped.Int16Field = valueInt16Field; + Assert.AreEqual (valueInt16Field, wrapped.Int16Field, "Int16Field - set"); + wrapped.Int16Field = null; + Assert.IsNull (wrapped.Int16Field, "Int16Field - final"); + + Assert.IsNull (wrapped.Int32Field, "Int32Field"); + var valueInt32Field = Int32.MaxValue; + wrapped.Int32Field = valueInt32Field; + Assert.AreEqual (valueInt32Field, wrapped.Int32Field, "Int32Field - set"); + wrapped.Int32Field = null; + Assert.IsNull (wrapped.Int32Field, "Int32Field - final"); + + Assert.IsNull (wrapped.Int64Field, "Int64Field"); + var valueInt64Field = Int64.MaxValue; + wrapped.Int64Field = valueInt64Field; + Assert.AreEqual (valueInt64Field, wrapped.Int64Field, "Int64Field - set"); + wrapped.Int64Field = null; + Assert.IsNull (wrapped.Int64Field, "Int64Field - final"); + + Assert.IsNull (wrapped.ByteField, "ByteField"); + var valueByteField = Byte.MaxValue; + wrapped.ByteField = valueByteField; + Assert.AreEqual (valueByteField, wrapped.ByteField, "ByteField - set"); + wrapped.ByteField = null; + Assert.IsNull (wrapped.ByteField, "ByteField - final"); + + Assert.IsNull (wrapped.UInt16Field, "UInt16Field"); + var valueUInt16Field = UInt16.MaxValue; + wrapped.UInt16Field = valueUInt16Field; + Assert.AreEqual (valueUInt16Field, wrapped.UInt16Field, "UInt16Field - set"); + wrapped.UInt16Field = null; + Assert.IsNull (wrapped.UInt16Field, "UInt16Field - final"); + + Assert.IsNull (wrapped.UInt32Field, "UInt32Field"); + var valueUInt32Field = UInt32.MaxValue; + wrapped.UInt32Field = valueUInt32Field; + Assert.AreEqual (valueUInt32Field, wrapped.UInt32Field, "UInt32Field - set"); + wrapped.UInt32Field = null; + Assert.IsNull (wrapped.UInt32Field, "UInt32Field - final"); + + Assert.IsNull (wrapped.UInt64Field, "UInt64Field"); + var valueUInt64Field = UInt64.MaxValue; + wrapped.UInt64Field = valueUInt64Field; + Assert.AreEqual (valueUInt64Field, wrapped.UInt64Field, "UInt64Field - set"); + wrapped.UInt64Field = null; + Assert.IsNull (wrapped.UInt64Field, "UInt64Field - final"); + + Assert.IsNull (wrapped.NIntField, "NIntField"); + var valueNIntField = nint.MaxValue; + wrapped.NIntField = valueNIntField; + Assert.AreEqual (valueNIntField, wrapped.NIntField, "NIntField - set"); + wrapped.NIntField = null; + Assert.IsNull (wrapped.NIntField, "NIntField - final"); + + Assert.IsNull (wrapped.NUIntField, "NUIntField"); + var valueNUIntField = nuint.MaxValue; + wrapped.NUIntField = valueNUIntField; + Assert.AreEqual (valueNUIntField, wrapped.NUIntField, "NUIntField - set"); + wrapped.NUIntField = null; + Assert.IsNull (wrapped.NUIntField, "NUIntField - final"); + + Assert.IsNull (wrapped.SingleField, "SingleField"); + var valueSingleField = Single.MaxValue; + wrapped.SingleField = valueSingleField; + Assert.AreEqual (valueSingleField, wrapped.SingleField, "SingleField - set"); + wrapped.SingleField = null; + Assert.IsNull (wrapped.SingleField, "SingleField - final"); + + Assert.IsNull (wrapped.DoubleField, "DoubleField"); + var valueDoubleField = Double.MaxValue; + wrapped.DoubleField = valueDoubleField; + Assert.AreEqual (valueDoubleField, wrapped.DoubleField, "DoubleField - set"); + wrapped.DoubleField = null; + Assert.IsNull (wrapped.DoubleField, "DoubleField - final"); + + Assert.IsNull (wrapped.NFloatField, "NFloatField"); + var valueNFloatField = nfloat.MaxValue; + wrapped.NFloatField = valueNFloatField; + Assert.AreEqual (valueNFloatField, wrapped.NFloatField, "NFloatField - set"); + wrapped.NFloatField = null; + Assert.IsNull (wrapped.NFloatField, "NFloatField - final"); + + Assert.IsNull (wrapped.NSObjectField, "NSObjectField"); + var valueNSObjectField = (NSString) "NSObjectValue"; + wrapped.NSObjectField = valueNSObjectField; + Assert.AreEqual (valueNSObjectField, wrapped.NSObjectField, "NSObjectField - set"); + wrapped.NSObjectField = null; + Assert.IsNull (wrapped.NSObjectField, "NSObjectField - final"); + + Assert.IsNull (wrapped.BooleanField, "BooleanField"); + var valueBooleanField = true; + wrapped.BooleanField = valueBooleanField; + Assert.AreEqual (valueBooleanField, wrapped.BooleanField, "BooleanField - set"); + wrapped.BooleanField = null; + Assert.IsNull (wrapped.BooleanField, "BooleanField - final"); + + Assert.IsNull (wrapped.NSStringField, "NSStringField"); + var valueNSStringField = (NSString) "NSStringValue"; + wrapped.NSStringField = valueNSStringField; + Assert.AreEqual (valueNSStringField, wrapped.NSStringField, "NSStringField - set"); + wrapped.NSStringField = null; + Assert.IsNull (wrapped.NSStringField, "NSStringField - final"); + + Assert.IsNull (wrapped.NSDateField, "NSDateField"); + var valueNSDateField = (NSDate) new DateTime (2025, 09, 01, 12, 45, 55, 23).ToUniversalTime (); + wrapped.NSDateField = valueNSDateField; + Assert.AreEqual (valueNSDateField, wrapped.NSDateField, "NSDateField - set"); + wrapped.NSDateField = null; + Assert.IsNull (wrapped.NSDateField, "NSDateField - final"); + + Assert.IsNull (wrapped.NSDictionaryField, "NSDictionaryField"); + var valueNSDictionaryField = new NSDictionary (); + wrapped.NSDictionaryField = valueNSDictionaryField; + Assert.AreEqual (valueNSDictionaryField, wrapped.NSDictionaryField, "NSDictionaryField - set"); + wrapped.NSDictionaryField = null; + Assert.IsNull (wrapped.NSDictionaryField, "NSDictionaryField - final"); + + Assert.IsNull (wrapped.NSStrongDictionaryField, "NSStrongDictionaryField"); + var valueNSStrongDictionaryField = new WrappedNSDictionary (); + wrapped.NSStrongDictionaryField = valueNSStrongDictionaryField; + Assert.AreEqual (valueNSStrongDictionaryField?.Dictionary?.ToString (), wrapped.NSStrongDictionaryField?.Dictionary?.ToString (), "NSStrongDictionaryField - set"); + wrapped.NSStrongDictionaryField = null; + Assert.IsNull (wrapped.NSStrongDictionaryField, "NSStrongDictionaryField - final"); + + Assert.IsNull (wrapped.StrongEnumField, "StrongEnumField"); + var valueStrongEnumField = StrongEnum.C; + wrapped.StrongEnumField = valueStrongEnumField; + Assert.AreEqual (valueStrongEnumField, wrapped.StrongEnumField, "StrongEnumField - set"); + wrapped.StrongEnumField = null; + Assert.IsNull (wrapped.StrongEnumField, "StrongEnumField - final"); + + Assert.IsNull (wrapped.ArrayOfSByteField, "ArrayOfSByteField"); + var valueArrayOfSByteField = new sbyte [] { 1, 2, 3 }; + wrapped.ArrayOfSByteField = valueArrayOfSByteField; + Assert.AreEqual (valueArrayOfSByteField, wrapped.ArrayOfSByteField, "ArrayOfSByteField - set"); + wrapped.ArrayOfSByteField = null; + Assert.IsNull (wrapped.ArrayOfSByteField, "ArrayOfSByteField - final"); + + Assert.IsNull (wrapped.ArrayOfInt16Field, "ArrayOfInt16Field"); + var valueArrayOfInt16Field = new short [] { 1, 2, 3 }; + wrapped.ArrayOfInt16Field = valueArrayOfInt16Field; + Assert.AreEqual (valueArrayOfInt16Field, wrapped.ArrayOfInt16Field, "ArrayOfInt16Field - set"); + wrapped.ArrayOfInt16Field = null; + Assert.IsNull (wrapped.ArrayOfInt16Field, "ArrayOfInt16Field - final"); + + Assert.IsNull (wrapped.ArrayOfInt32Field, "ArrayOfInt32Field"); + var valueArrayOfInt32Field = new int [] { 1, 2, 3 }; ; + wrapped.ArrayOfInt32Field = valueArrayOfInt32Field; + Assert.AreEqual (valueArrayOfInt32Field, wrapped.ArrayOfInt32Field, "ArrayOfInt32Field - set"); + wrapped.ArrayOfInt32Field = null; + Assert.IsNull (wrapped.ArrayOfInt32Field, "ArrayOfInt32Field - final"); + + Assert.IsNull (wrapped.ArrayOfInt64Field, "ArrayOfInt64Field"); + var valueArrayOfInt64Field = new long [] { 1, 2, 3 }; ; + wrapped.ArrayOfInt64Field = valueArrayOfInt64Field; + Assert.AreEqual (valueArrayOfInt64Field, wrapped.ArrayOfInt64Field, "ArrayOfInt64Field - set"); + wrapped.ArrayOfInt64Field = null; + Assert.IsNull (wrapped.ArrayOfInt64Field, "ArrayOfInt64Field - final"); + + Assert.IsNull (wrapped.ArrayOfByteField, "ArrayOfByteField"); + var valueArrayOfByteField = new byte [] { 1, 2, 3 }; ; + wrapped.ArrayOfByteField = valueArrayOfByteField; + Assert.AreEqual (valueArrayOfByteField, wrapped.ArrayOfByteField, "ArrayOfByteField - set"); + wrapped.ArrayOfByteField = null; + Assert.IsNull (wrapped.ArrayOfByteField, "ArrayOfByteField - final"); + + Assert.IsNull (wrapped.ArrayOfUInt16Field, "ArrayOfUInt16Field"); + var valueArrayOfUInt16Field = new ushort [] { 1, 2, 3 }; ; + wrapped.ArrayOfUInt16Field = valueArrayOfUInt16Field; + Assert.AreEqual (valueArrayOfUInt16Field, wrapped.ArrayOfUInt16Field, "ArrayOfUInt16Field - set"); + wrapped.ArrayOfUInt16Field = null; + Assert.IsNull (wrapped.ArrayOfUInt16Field, "ArrayOfUInt16Field - final"); + + Assert.IsNull (wrapped.ArrayOfUInt32Field, "ArrayOfUInt32Field"); + var valueArrayOfUInt32Field = new uint [] { 1, 2, 3 }; ; + wrapped.ArrayOfUInt32Field = valueArrayOfUInt32Field; + Assert.AreEqual (valueArrayOfUInt32Field, wrapped.ArrayOfUInt32Field, "ArrayOfUInt32Field - set"); + wrapped.ArrayOfUInt32Field = null; + Assert.IsNull (wrapped.ArrayOfUInt32Field, "ArrayOfUInt32Field - final"); + + Assert.IsNull (wrapped.ArrayOfUInt64Field, "ArrayOfUInt64Field"); + var valueArrayOfUInt64Field = new ulong [] { 1, 2, 3 }; ; + wrapped.ArrayOfUInt64Field = valueArrayOfUInt64Field; + Assert.AreEqual (valueArrayOfUInt64Field, wrapped.ArrayOfUInt64Field, "ArrayOfUInt64Field - set"); + wrapped.ArrayOfUInt64Field = null; + Assert.IsNull (wrapped.ArrayOfUInt64Field, "ArrayOfUInt64Field - final"); + + Assert.IsNull (wrapped.ArrayOfNIntField, "ArrayOfNIntField"); + var valueArrayOfNIntField = new nint [] { 1, 2, 3 }; ; + wrapped.ArrayOfNIntField = valueArrayOfNIntField; + Assert.AreEqual (valueArrayOfNIntField, wrapped.ArrayOfNIntField, "ArrayOfNIntField - set"); + wrapped.ArrayOfNIntField = null; + Assert.IsNull (wrapped.ArrayOfNIntField, "ArrayOfNIntField - final"); + + Assert.IsNull (wrapped.ArrayOfNUIntField, "ArrayOfNUIntField"); + var valueArrayOfNUIntField = new nuint [] { 1, 2, 3 }; ; + wrapped.ArrayOfNUIntField = valueArrayOfNUIntField; + Assert.AreEqual (valueArrayOfNUIntField, wrapped.ArrayOfNUIntField, "ArrayOfNUIntField - set"); + wrapped.ArrayOfNUIntField = null; + Assert.IsNull (wrapped.ArrayOfNUIntField, "ArrayOfNUIntField - final"); + + Assert.IsNull (wrapped.ArrayOfSingleField, "ArrayOfSingleField"); + var valueArrayOfSingleField = new float [] { 1, 2, 3 }; ; + wrapped.ArrayOfSingleField = valueArrayOfSingleField; + Assert.AreEqual (valueArrayOfSingleField, wrapped.ArrayOfSingleField, "ArrayOfSingleField - set"); + wrapped.ArrayOfSingleField = null; + Assert.IsNull (wrapped.ArrayOfSingleField, "ArrayOfSingleField - final"); + + Assert.IsNull (wrapped.ArrayOfDoubleField, "ArrayOfDoubleField"); + var valueArrayOfDoubleField = new double [] { 1, 2, 3 }; ; + wrapped.ArrayOfDoubleField = valueArrayOfDoubleField; + Assert.AreEqual (valueArrayOfDoubleField, wrapped.ArrayOfDoubleField, "ArrayOfDoubleField - set"); + wrapped.ArrayOfDoubleField = null; + Assert.IsNull (wrapped.ArrayOfDoubleField, "ArrayOfDoubleField - final"); + + Assert.IsNull (wrapped.ArrayOfNFloatField, "ArrayOfNFloatField"); + var valueArrayOfNFloatField = new nfloat [] { 1, 2, 3 }; ; + wrapped.ArrayOfNFloatField = valueArrayOfNFloatField; + Assert.AreEqual (valueArrayOfNFloatField, wrapped.ArrayOfNFloatField, "ArrayOfNFloatField - set"); + wrapped.ArrayOfNFloatField = null; + Assert.IsNull (wrapped.ArrayOfNFloatField, "ArrayOfNFloatField - final"); + + Assert.IsNull (wrapped.ArrayOfNSObjectField, "ArrayOfNSObjectField"); + var valueArrayOfNSObjectField = new NSObject [] { (NSString) "Array1", NSDate.Now }; + wrapped.ArrayOfNSObjectField = valueArrayOfNSObjectField; + Assert.AreEqual (valueArrayOfNSObjectField, wrapped.ArrayOfNSObjectField, "ArrayOfNSObjectField - set"); + wrapped.ArrayOfNSObjectField = null; + Assert.IsNull (wrapped.ArrayOfNSObjectField, "ArrayOfNSObjectField - final"); + + Assert.IsNull (wrapped.ArrayOfBooleanField, "ArrayOfBooleanField"); + var valueArrayOfBooleanField = new bool [] { true, false, true }; + wrapped.ArrayOfBooleanField = valueArrayOfBooleanField; + Assert.AreEqual (valueArrayOfBooleanField, wrapped.ArrayOfBooleanField, "ArrayOfBooleanField - set"); + wrapped.ArrayOfBooleanField = null; + Assert.IsNull (wrapped.ArrayOfBooleanField, "ArrayOfBooleanField - final"); + + Assert.IsNull (wrapped.ArrayOfNSStringField, "ArrayOfNSStringField"); + var valueArrayOfNSStringField = new NSString [] { (NSString) "a", (NSString) "b", (NSString) "c" }; + wrapped.ArrayOfNSStringField = valueArrayOfNSStringField; + Assert.AreEqual (valueArrayOfNSStringField, wrapped.ArrayOfNSStringField, "ArrayOfNSStringField - set"); + wrapped.ArrayOfNSStringField = null; + Assert.IsNull (wrapped.ArrayOfNSStringField, "ArrayOfNSStringField - final"); + + Assert.IsNull (wrapped.ArrayOfNSDateField, "ArrayOfNSDateField"); + var valueArrayOfNSDateField = new NSDate [] { NSDate.Now, NSDate.Now }; + wrapped.ArrayOfNSDateField = valueArrayOfNSDateField; + Assert.AreEqual (valueArrayOfNSDateField, wrapped.ArrayOfNSDateField, "ArrayOfNSDateField - set"); + wrapped.ArrayOfNSDateField = null; + Assert.IsNull (wrapped.ArrayOfNSDateField, "ArrayOfNSDateField - final"); + + Assert.IsNull (wrapped.ArrayOfNSDictionaryField, "ArrayOfNSDictionaryField"); + var valueArrayOfNSDictionaryField = new NSDictionary [] { new NSDictionary (), new NSDictionary () }; + wrapped.ArrayOfNSDictionaryField = valueArrayOfNSDictionaryField; + Assert.AreEqual (valueArrayOfNSDictionaryField, wrapped.ArrayOfNSDictionaryField, "ArrayOfNSDictionaryField - set"); + wrapped.ArrayOfNSDictionaryField = null; + Assert.IsNull (wrapped.ArrayOfNSDictionaryField, "ArrayOfNSDictionaryField - final"); + + Assert.IsNull (wrapped.ArrayOfStrongDictionaryField, "ArrayOfStrongDictionaryField"); + var valueArrayOfStrongDictionaryField = new WrappedNSDictionary [] { new WrappedNSDictionary (), new WrappedNSDictionary () }; + wrapped.ArrayOfStrongDictionaryField = valueArrayOfStrongDictionaryField; + Assert.AreEqual (string.Join (";", valueArrayOfStrongDictionaryField.Select (v => v?.Dictionary?.ToString ())), string.Join (";", wrapped.ArrayOfStrongDictionaryField.Select (v => v?.Dictionary?.ToString ())), "ArrayOfStrongDictionaryField - set"); + wrapped.ArrayOfStrongDictionaryField = null; + Assert.IsNull (wrapped.ArrayOfStrongDictionaryField, "ArrayOfStrongDictionaryField - final"); + + Assert.IsNull (wrapped.ArrayOfStrongEnumField, "ArrayOfStrongEnumField"); + var valueArrayOfStrongEnumField = new StrongEnum [] { StrongEnum.A, StrongEnum.B }; + wrapped.ArrayOfStrongEnumField = valueArrayOfStrongEnumField; + Assert.AreEqual (valueArrayOfStrongEnumField, wrapped.ArrayOfStrongEnumField, "ArrayOfStrongEnumField - set"); + wrapped.ArrayOfStrongEnumField = null; + Assert.IsNull (wrapped.ArrayOfStrongEnumField, "ArrayOfStrongEnumField - final"); + + Assert.IsNull (wrapped.StringField, "StringField"); + var valueStringField = "managed string"; + wrapped.StringField = valueStringField; + Assert.AreEqual (valueStringField, wrapped.StringField, "StringField - set"); + wrapped.StringField = null; + Assert.IsNull (wrapped.StringField, "StringField - final"); + + Assert.IsNull (wrapped.DateTimeField, "DateTimeField"); + var valueDateTimeField = new DateTime (2025, 09, 01, 12, 45, 55, 23).ToUniversalTime (); + wrapped.DateTimeField = valueDateTimeField; + Assert.AreEqual (valueDateTimeField, wrapped.DateTimeField, "DateTimeField - set"); + wrapped.DateTimeField = null; + Assert.IsNull (wrapped.DateTimeField, "DateTimeField - final"); + + Assert.IsNull (wrapped.GenericNSDictionaryField, "GenericNSDictionaryField"); + var valueGenericNSDictionaryField = new NSDictionary (); + wrapped.GenericNSDictionaryField = valueGenericNSDictionaryField; + Assert.AreEqual (valueGenericNSDictionaryField, wrapped.GenericNSDictionaryField, "GenericNSDictionaryField - set"); + wrapped.GenericNSDictionaryField = null; + Assert.IsNull (wrapped.GenericNSDictionaryField, "GenericNSDictionaryField - final"); + + Assert.IsNull (wrapped.ArrayOfStringField, "ArrayOfStringField"); + var valueArrayOfStringField = new string [] { "abc", "def", "ghi" }; + wrapped.ArrayOfStringField = valueArrayOfStringField; + Assert.AreEqual (valueArrayOfStringField, wrapped.ArrayOfStringField, "ArrayOfStringField - set"); + wrapped.ArrayOfStringField = null; + Assert.IsNull (wrapped.ArrayOfStringField, "ArrayOfStringField - final"); + + Assert.IsNull (wrapped.NSDataField, "NSDataField"); + var valueNSDataField = NSData.FromArray (new byte [] { 1, 2, 3 }); + wrapped.NSDataField = valueNSDataField; + Assert.AreEqual (valueNSDataField, wrapped.NSDataField, "NSDataField - set"); + wrapped.NSDataField = null; + Assert.IsNull (wrapped.NSDataField, "NSDataField - final"); + + Assert.IsNull (wrapped.NSDataAsMatrix3Field, "NSDataAsMatrix3Field"); + var valueNSDataAsMatrix3Field = new NMatrix3 (1, 2, 3, 4, 5, 6, 7, 8, 9); + wrapped.NSDataAsMatrix3Field = valueNSDataAsMatrix3Field; + Assert.AreEqual (valueNSDataAsMatrix3Field, wrapped.NSDataAsMatrix3Field, "NSDataAsMatrix3Field - set"); + wrapped.NSDataAsMatrix3Field = null; + Assert.IsNull (wrapped.NSDataAsMatrix3Field, "NSDataAsMatrix3Field - final"); + + Assert.IsNull (wrapped.CGRectField, "CGRectField"); + var valueCGRectField = new CGRect (1, 2, 3, 4); + wrapped.CGRectField = valueCGRectField; + Assert.AreEqual (valueCGRectField, wrapped.CGRectField, "CGRectField - set"); + wrapped.CGRectField = null; + Assert.IsNull (wrapped.CGRectField, "CGRectField - final"); + + Assert.IsNull (wrapped.CGSizeField, "CGSizeField"); + var valueCGSizeField = new CGSize (5, 6); + wrapped.CGSizeField = valueCGSizeField; + Assert.AreEqual (valueCGSizeField, wrapped.CGSizeField, "CGSizeField - set"); + wrapped.CGSizeField = null; + Assert.IsNull (wrapped.CGSizeField, "CGSizeField - final"); + + Assert.IsNull (wrapped.CGPointField, "CGPointField"); + var valueCGPointField = new CGPoint (7, 8); + wrapped.CGPointField = valueCGPointField; + Assert.AreEqual (valueCGPointField, wrapped.CGPointField, "CGPointField - set"); + wrapped.CGPointField = null; + Assert.IsNull (wrapped.CGPointField, "CGPointField - final"); + + Assert.IsNull (wrapped.CMTimeField, "CMTimeField"); + var valueCMTimeField = new CMTime (123, 2); + wrapped.CMTimeField = valueCMTimeField; + Assert.AreEqual (valueCMTimeField, wrapped.CMTimeField, "CMTimeField - set"); + wrapped.CMTimeField = null; + Assert.IsNull (wrapped.CMTimeField, "CMTimeField - final"); + +#if HAS_UIKIT + Assert.IsNull (wrapped.UIEdgeInsetsField, "UIEdgeInsetsField"); + var valueUIEdgeInsetsField = new UIEdgeInsets (9, 8, 7, 6); + wrapped.UIEdgeInsetsField = valueUIEdgeInsetsField; + Assert.AreEqual (valueUIEdgeInsetsField, wrapped.UIEdgeInsetsField, "UIEdgeInsetsField - set"); + wrapped.UIEdgeInsetsField = null; + Assert.IsNull (wrapped.UIEdgeInsetsField, "UIEdgeInsetsField - final"); +#endif // HAS_UIKIT + }); + } } } diff --git a/tests/test-libraries/libtest.m b/tests/test-libraries/libtest.m index 6da86024410f..d83a53f1b7b6 100644 --- a/tests/test-libraries/libtest.m +++ b/tests/test-libraries/libtest.m @@ -9,6 +9,68 @@ NSString *x_GlobalString = @"There's nothing cruvus here!"; +// Strong enum +NSString *StrongEnumA = @"A"; +NSString *StrongEnumB = @"B"; +NSString *StrongEnumC = @"C"; + +// Strong dictionary keys + +// simple types +NSString *StrongDictionarySByteField = @"StrongDictionarySByteField"; +NSString *StrongDictionaryInt16Field = @"StrongDictionaryInt16Field"; +NSString *StrongDictionaryInt32Field = @"StrongDictionaryInt32Field"; +NSString *StrongDictionaryInt64Field = @"StrongDictionaryInt64Field"; +NSString *StrongDictionaryByteField = @"StrongDictionaryByteField"; +NSString *StrongDictionaryUInt16Field = @"StrongDictionaryUInt16Field"; +NSString *StrongDictionaryUInt32Field = @"StrongDictionaryUInt32Field"; +NSString *StrongDictionaryUInt64Field = @"StrongDictionaryUInt64Field"; +NSString *StrongDictionaryNIntField = @"StrongDictionaryNIntField"; +NSString *StrongDictionaryNUIntField = @"StrongDictionaryNUIntField"; +NSString *StrongDictionarySingleField = @"StrongDictionarySingleField"; +NSString *StrongDictionaryDoubleField = @"StrongDictionaryDoubleField"; +NSString *StrongDictionaryNFloatField = @"StrongDictionaryNFloatField"; +NSString *StrongDictionaryNSObjectField = @"StrongDictionaryNSObjectField"; +NSString *StrongDictionaryBooleanField = @"StrongDictionaryBooleanField"; +NSString *StrongDictionaryNSStringField = @"StrongDictionaryNSStringField"; +NSString *StrongDictionaryNSDateField = @"StrongDictionaryNSDateField"; +NSString *StrongDictionaryNSDictionaryField = @"StrongDictionaryNSDictionaryField"; +NSString *StrongDictionaryStrongDictionaryField = @"StrongDictionaryStrongDictionaryField"; +NSString *StrongDictionaryStrongEnumField = @"StrongDictionaryStrongEnumField"; +// arrays of the above +NSString *StrongDictionaryArrayOfSByteField = @"StrongDictionaryArrayOfSByteField"; +NSString *StrongDictionaryArrayOfInt16Field = @"StrongDictionaryArrayOfInt16Field"; +NSString *StrongDictionaryArrayOfInt32Field = @"StrongDictionaryArrayOfInt32Field"; +NSString *StrongDictionaryArrayOfInt64Field = @"StrongDictionaryArrayOfInt64Field"; +NSString *StrongDictionaryArrayOfByteField = @"StrongDictionaryArrayOfByteField"; +NSString *StrongDictionaryArrayOfUInt16Field = @"StrongDictionaryArrayOfUInt16Field"; +NSString *StrongDictionaryArrayOfUInt32Field = @"StrongDictionaryArrayOfUInt32Field"; +NSString *StrongDictionaryArrayOfUInt64Field = @"StrongDictionaryArrayOfUInt64Field"; +NSString *StrongDictionaryArrayOfNIntField = @"StrongDictionaryArrayOfNIntField"; +NSString *StrongDictionaryArrayOfNUIntField = @"StrongDictionaryArrayOfNUIntField"; +NSString *StrongDictionaryArrayOfSingleField = @"StrongDictionaryArrayOfSingleField"; +NSString *StrongDictionaryArrayOfDoubleField = @"StrongDictionaryArrayOfDoubleField"; +NSString *StrongDictionaryArrayOfNFloatField = @"StrongDictionaryArrayOfNFloatField"; +NSString *StrongDictionaryArrayOfNSObjectField = @"StrongDictionaryArrayOfNSObjectField"; +NSString *StrongDictionaryArrayOfBooleanField = @"StrongDictionaryArrayOfBooleanField"; +NSString *StrongDictionaryArrayOfNSStringField = @"StrongDictionaryArrayOfNSStringField"; +NSString *StrongDictionaryArrayOfNSDateField = @"StrongDictionaryArrayOfNSDateField"; +NSString *StrongDictionaryArrayOfNSDictionaryField = @"StrongDictionaryArrayOfNSDictionaryField"; +NSString *StrongDictionaryArrayOfStrongDictionaryField = @"StrongDictionaryArrayOfStrongDictionaryField"; +NSString *StrongDictionaryArrayOfStrongEnumField = @"StrongDictionaryArrayOfStrongEnumField"; +// other fields +NSString *StrongDictionaryStringField = @"StrongDictionaryStringField"; +NSString *StrongDictionaryDateTimeField = @"StrongDictionaryDateTimeField"; +NSString *StrongDictionaryGenericNSDictionaryField = @"StrongDictionaryGenericNSDictionaryField"; +NSString *StrongDictionaryArrayOfStringField = @"StrongDictionaryArrayOfStringField"; +NSString *StrongDictionaryNSDataField = @"StrongDictionaryNSDataField"; +NSString *StrongDictionaryNSDataAsMatrix3Field = @"StrongDictionaryNSDataAsMatrix3Field"; +NSString *StrongDictionaryCGRectField = @"StrongDictionaryCGRectField"; +NSString *StrongDictionaryCGSizeField = @"StrongDictionaryCGSizeField"; +NSString *StrongDictionaryCGPointField = @"StrongDictionaryCGPointField"; +NSString *StrongDictionaryCMTimeField = @"StrongDictionaryCMTimeField"; +NSString *StrongDictionaryUIEdgeInsetsField = @"StrongDictionaryUIEdgeInsetsField"; + int theUltimateAnswer () { diff --git a/tests/test-libraries/rename.h b/tests/test-libraries/rename.h index 6b35363e9ce9..8bd7e9de3442 100644 --- a/tests/test-libraries/rename.h +++ b/tests/test-libraries/rename.h @@ -75,6 +75,55 @@ #define x_SCNMatrix4Translate object_x_SCNMatrix4Translate #define x_GlobalString object_x_GlobalString #define x_native_field object_x_native_field + #define StrongDictionarySByteField object_StrongDictionarySByteField + #define StrongDictionaryInt16Field object_StrongDictionaryInt16Field + #define StrongDictionaryInt32Field object_StrongDictionaryInt32Field + #define StrongDictionaryInt64Field object_StrongDictionaryInt64Field + #define StrongDictionaryByteField object_StrongDictionaryByteField + #define StrongDictionaryUInt16Field object_StrongDictionaryUInt16Field + #define StrongDictionaryUInt32Field object_StrongDictionaryUInt32Field + #define StrongDictionaryUInt64Field object_StrongDictionaryUInt64Field + #define StrongDictionaryNIntField object_StrongDictionaryNIntField + #define StrongDictionaryNUIntField object_StrongDictionaryNUIntField + #define StrongDictionarySingleField object_StrongDictionarySingleField + #define StrongDictionaryDoubleField object_StrongDictionaryDoubleField + #define StrongDictionaryNFloatField object_StrongDictionaryNFloatField + #define StrongDictionaryNSObjectField object_StrongDictionaryNSObjectField + #define StrongDictionaryBooleanField object_StrongDictionaryBooleanField + #define StrongDictionaryNSStringField object_StrongDictionaryNSStringField + #define StrongDictionaryNSDateField object_StrongDictionaryNSDateField + #define StrongDictionaryNSDictionaryField object_StrongDictionaryNSDictionaryField + #define StrongDictionaryStrongDictionaryField object_StrongDictionaryStrongDictionaryField + #define StrongDictionaryArrayOfSByteField object_StrongDictionaryArrayOfSByteField + #define StrongDictionaryArrayOfInt16Field object_StrongDictionaryArrayOfInt16Field + #define StrongDictionaryArrayOfInt32Field object_StrongDictionaryArrayOfInt32Field + #define StrongDictionaryArrayOfInt64Field object_StrongDictionaryArrayOfInt64Field + #define StrongDictionaryArrayOfByteField object_StrongDictionaryArrayOfByteField + #define StrongDictionaryArrayOfUInt16Field object_StrongDictionaryArrayOfUInt16Field + #define StrongDictionaryArrayOfUInt32Field object_StrongDictionaryArrayOfUInt32Field + #define StrongDictionaryArrayOfUInt64Field object_StrongDictionaryArrayOfUInt64Field + #define StrongDictionaryArrayOfNIntField object_StrongDictionaryArrayOfNIntField + #define StrongDictionaryArrayOfNUIntField object_StrongDictionaryArrayOfNUIntField + #define StrongDictionaryArrayOfSingleField object_StrongDictionaryArrayOfSingleField + #define StrongDictionaryArrayOfDoubleField object_StrongDictionaryArrayOfDoubleField + #define StrongDictionaryArrayOfNFloatField object_StrongDictionaryArrayOfNFloatField + #define StrongDictionaryArrayOfNSObjectField object_StrongDictionaryArrayOfNSObjectField + #define StrongDictionaryArrayOfBooleanField object_StrongDictionaryArrayOfBooleanField + #define StrongDictionaryArrayOfNSStringField object_StrongDictionaryArrayOfNSStringField + #define StrongDictionaryArrayOfNSDateField object_StrongDictionaryArrayOfNSDateField + #define StrongDictionaryArrayOfNSDictionaryField object_StrongDictionaryArrayOfNSDictionaryField + #define StrongDictionaryArrayOfStrongDictionaryField object_StrongDictionaryArrayOfStrongDictionaryField + #define StrongDictionaryStringField object_StrongDictionaryStringField + #define StrongDictionaryDateField object_StrongDictionaryDateField + #define StrongDictionaryGenericNSDictionaryField object_StrongDictionaryGenericNSDictionaryField + #define StrongDictionaryArrayOfStringField object_StrongDictionaryArrayOfStringField + #define StrongDictionaryNSDataField object_StrongDictionaryNSDataField + #define StrongDictionaryNSDataAsMatrix3Field object_StrongDictionaryNSDataAsMatrix3Field + #define StrongDictionaryCGRectField object_StrongDictionaryCGRectField + #define StrongDictionaryCGSizeField object_StrongDictionaryCGSizeField + #define StrongDictionaryCGPointField object_StrongDictionaryCGPointField + #define StrongDictionaryCMTimeField object_StrongDictionaryCMTimeField + #define StrongDictionaryUIEdgeInsetsField object_StrongDictionaryUIEdgeInsetsField #elif PREFIX == 2 #define theUltimateAnswer ar_theUltimateAnswer #define useZLib ar_useZLib @@ -151,6 +200,55 @@ #define x_SCNMatrix4Translate ar_x_SCNMatrix4Translate #define x_GlobalString ar_x_GlobalString #define x_native_field ar_x_native_field + #define StrongDictionarySByteField ar_StrongDictionarySByteField + #define StrongDictionaryInt16Field ar_StrongDictionaryInt16Field + #define StrongDictionaryInt32Field ar_StrongDictionaryInt32Field + #define StrongDictionaryInt64Field ar_StrongDictionaryInt64Field + #define StrongDictionaryByteField ar_StrongDictionaryByteField + #define StrongDictionaryUInt16Field ar_StrongDictionaryUInt16Field + #define StrongDictionaryUInt32Field ar_StrongDictionaryUInt32Field + #define StrongDictionaryUInt64Field ar_StrongDictionaryUInt64Field + #define StrongDictionaryNIntField ar_StrongDictionaryNIntField + #define StrongDictionaryNUIntField ar_StrongDictionaryNUIntField + #define StrongDictionarySingleField ar_StrongDictionarySingleField + #define StrongDictionaryDoubleField ar_StrongDictionaryDoubleField + #define StrongDictionaryNFloatField ar_StrongDictionaryNFloatField + #define StrongDictionaryNSObjectField ar_StrongDictionaryNSObjectField + #define StrongDictionaryBooleanField ar_StrongDictionaryBooleanField + #define StrongDictionaryNSStringField ar_StrongDictionaryNSStringField + #define StrongDictionaryNSDateField ar_StrongDictionaryNSDateField + #define StrongDictionaryNSDictionaryField ar_StrongDictionaryNSDictionaryField + #define StrongDictionaryStrongDictionaryField ar_StrongDictionaryStrongDictionaryField + #define StrongDictionaryArrayOfSByteField ar_StrongDictionaryArrayOfSByteField + #define StrongDictionaryArrayOfInt16Field ar_StrongDictionaryArrayOfInt16Field + #define StrongDictionaryArrayOfInt32Field ar_StrongDictionaryArrayOfInt32Field + #define StrongDictionaryArrayOfInt64Field ar_StrongDictionaryArrayOfInt64Field + #define StrongDictionaryArrayOfByteField ar_StrongDictionaryArrayOfByteField + #define StrongDictionaryArrayOfUInt16Field ar_StrongDictionaryArrayOfUInt16Field + #define StrongDictionaryArrayOfUInt32Field ar_StrongDictionaryArrayOfUInt32Field + #define StrongDictionaryArrayOfUInt64Field ar_StrongDictionaryArrayOfUInt64Field + #define StrongDictionaryArrayOfNIntField ar_StrongDictionaryArrayOfNIntField + #define StrongDictionaryArrayOfNUIntField ar_StrongDictionaryArrayOfNUIntField + #define StrongDictionaryArrayOfSingleField ar_StrongDictionaryArrayOfSingleField + #define StrongDictionaryArrayOfDoubleField ar_StrongDictionaryArrayOfDoubleField + #define StrongDictionaryArrayOfNFloatField ar_StrongDictionaryArrayOfNFloatField + #define StrongDictionaryArrayOfNSObjectField ar_StrongDictionaryArrayOfNSObjectField + #define StrongDictionaryArrayOfBooleanField ar_StrongDictionaryArrayOfBooleanField + #define StrongDictionaryArrayOfNSStringField ar_StrongDictionaryArrayOfNSStringField + #define StrongDictionaryArrayOfNSDateField ar_StrongDictionaryArrayOfNSDateField + #define StrongDictionaryArrayOfNSDictionaryField ar_StrongDictionaryArrayOfNSDictionaryField + #define StrongDictionaryArrayOfStrongDictionaryField ar_StrongDictionaryArrayOfStrongDictionaryField + #define StrongDictionaryStringField ar_StrongDictionaryStringField + #define StrongDictionaryDateField ar_StrongDictionaryDateField + #define StrongDictionaryGenericNSDictionaryField ar_StrongDictionaryGenericNSDictionaryField + #define StrongDictionaryArrayOfStringField ar_StrongDictionaryArrayOfStringField + #define StrongDictionaryNSDataField ar_StrongDictionaryNSDataField + #define StrongDictionaryNSDataAsMatrix3Field ar_StrongDictionaryNSDataAsMatrix3Field + #define StrongDictionaryCGRectField ar_StrongDictionaryCGRectField + #define StrongDictionaryCGSizeField ar_StrongDictionaryCGSizeField + #define StrongDictionaryCGPointField ar_StrongDictionaryCGPointField + #define StrongDictionaryCMTimeField ar_StrongDictionaryCMTimeField + #define StrongDictionaryUIEdgeInsetsField ar_StrongDictionaryUIEdgeInsetsField #else // keep original names #endif diff --git a/tests/xtro-sharpie/api-annotations-dotnet/common-CoreFoundation.ignore b/tests/xtro-sharpie/api-annotations-dotnet/common-CoreFoundation.ignore index 63cf707b6bc0..516a8af5896b 100644 --- a/tests/xtro-sharpie/api-annotations-dotnet/common-CoreFoundation.ignore +++ b/tests/xtro-sharpie/api-annotations-dotnet/common-CoreFoundation.ignore @@ -516,7 +516,6 @@ !missing-pinvoke! CFDictionaryCreateMutableCopy is not bound !missing-pinvoke! CFDictionaryGetCountOfKey is not bound !missing-pinvoke! CFDictionaryGetCountOfValue is not bound -!missing-pinvoke! CFDictionaryGetValueIfPresent is not bound !missing-pinvoke! CFDictionaryRemoveAllValues is not bound !missing-pinvoke! CFDictionaryRemoveValue is not bound !missing-pinvoke! CFDictionaryReplaceValue is not bound diff --git a/tools/devops/automation/templates/tests-stage.yml b/tools/devops/automation/templates/tests-stage.yml index fb26d9dd79e6..1e332637a330 100644 --- a/tools/devops/automation/templates/tests-stage.yml +++ b/tools/devops/automation/templates/tests-stage.yml @@ -64,7 +64,7 @@ parameters: { stageName: 'mac_14_x64', displayName: 'X64 - Mac Sonoma (14)', - macPool: 'VSEng-Xamarin-RedmondMacBuildPool-iOS-Untrusted', + macPool: 'VSEng-VSMac-Xamarin-Shared', useImage: false, statusContext: 'X64 - Mac Sonoma (14)', demands: [