diff --git a/src/Foundation/NSMutableSet_1.cs b/src/Foundation/NSMutableSet_1.cs index e83c185b8f29..253d70014916 100644 --- a/src/Foundation/NSMutableSet_1.cs +++ b/src/Foundation/NSMutableSet_1.cs @@ -27,30 +27,26 @@ using System.Collections; using System.Collections.Generic; -// Disable until we get around to enable + fix any issues. -#nullable disable +#nullable enable namespace Foundation { - [SupportedOSPlatform ("ios")] - [SupportedOSPlatform ("maccatalyst")] - [SupportedOSPlatform ("macos")] - [SupportedOSPlatform ("tvos")] + /// A strongly-typed mutable set that contains objects of type . + /// The type of objects in the set. [Register ("NSMutableSet", SkipRegistration = true)] public sealed partial class NSMutableSet : NSMutableSet, IEnumerable where TKey : class, INativeObject { - /// To be added. - /// To be added. + /// Initializes a new empty mutable set. public NSMutableSet () { } + /// Initializes the object from the data stored in the unarchiver object. /// The unarchiver object. - /// A constructor that initializes the object from the data stored in the unarchiver object. - /// - /// This constructor is provided to allow the class to be initialized from an unarchiver (for example, during NIB deserialization). This is part of the protocol. - /// If developers want to create a subclass of this object and continue to support deserialization from an archive, they should implement a constructor with an identical signature: taking a single parameter of type and decorate it with the [Export("initWithCoder:"] attribute declaration. - /// The state of this object can also be serialized by using the companion method, EncodeTo. - /// + /// + /// This constructor is provided to allow the class to be initialized from an unarchiver (for example, during NIB deserialization). This is part of the protocol. + /// If developers want to create a subclass of this object and continue to support deserialization from an archive, they should implement a constructor with an identical signature: taking a single parameter of type and decorate it with the [Export("initWithCoder:"] attribute declaration. + /// The state of this object can also be serialized by using the companion method, EncodeTo. + /// public NSMutableSet (NSCoder coder) : base (coder) { @@ -61,33 +57,29 @@ internal NSMutableSet (NativeHandle handle) { } - /// To be added. - /// To be added. - /// To be added. + /// Initializes a new mutable set with the specified objects. + /// The objects to add to the set. public NSMutableSet (params TKey [] objs) : base (objs) { } - /// To be added. - /// To be added. - /// To be added. + /// Initializes a new mutable set with the contents of the specified set. + /// The set whose contents will be copied to the new set. public NSMutableSet (NSSet other) : base (other) { } - /// To be added. - /// To be added. - /// To be added. + /// Initializes a new mutable set with the contents of the specified mutable set. + /// The mutable set whose contents will be copied to the new set. public NSMutableSet (NSMutableSet other) : base (other) { } - /// To be added. - /// To be added. - /// To be added. + /// Initializes a new mutable set with the specified initial capacity. + /// The initial capacity of the set. public NSMutableSet (nint capacity) : base (capacity) { @@ -95,33 +87,30 @@ public NSMutableSet (nint capacity) // Strongly typed versions of API from NSSet - /// To be added. - /// To be added. - /// To be added. - /// To be added. - public TKey LookupMember (TKey probe) + /// Returns the object in the set that is equal to the specified object. + /// The object to search for in the set. + /// The object in the set that is equal to , or if no such object exists. + public TKey? LookupMember (TKey probe) { if (probe is null) throw new ArgumentNullException (nameof (probe)); - TKey result = Runtime.GetINativeObject (_LookupMember (probe.Handle), false); + TKey? result = Runtime.GetINativeObject (_LookupMember (probe.Handle), false); GC.KeepAlive (probe); return result; } - /// To be added. - /// To be added. - /// To be added. - public TKey AnyObject { + /// Gets one of the objects in the set, or if the set is empty. + /// An arbitrary object from the set, or if the set contains no objects. + public TKey? AnyObject { get { return Runtime.GetINativeObject (_AnyObject, false); } } - /// To be added. - /// To be added. - /// To be added. - /// To be added. + /// Determines whether the set contains the specified object. + /// The object to locate in the set. + /// if the set contains ; otherwise, . public bool Contains (TKey obj) { if (obj is null) @@ -132,18 +121,23 @@ public bool Contains (TKey obj) return result; } - /// To be added. - /// To be added. - /// To be added. + /// Converts the set to an array. + /// An array containing all the objects in the set. public TKey [] ToArray () { return base.ToArray (); } - public static NSMutableSet operator + (NSMutableSet first, NSMutableSet second) + /// Creates a new mutable set containing all objects from both sets. + /// The first set. + /// The second set. + /// A new containing the union of both sets, or if both sets are . + public static NSMutableSet? operator + (NSMutableSet? first, NSMutableSet? second) { + if (first is null && second is null) + return null; if (first is null || first.Count == 0) - return new NSMutableSet (second); + return second is null ? new NSMutableSet () : new NSMutableSet (second); if (second is null || second.Count == 0) return new NSMutableSet (first); var result = new NSMutableSet (first._SetByAddingObjectsFromSet (second.Handle)); @@ -151,7 +145,11 @@ public TKey [] ToArray () return result; } - public static NSMutableSet operator - (NSMutableSet first, NSMutableSet second) + /// Creates a new mutable set with objects from the first set that are not in the second set. + /// The first set. + /// The second set. + /// A new containing the difference, or if the first set is or empty. + public static NSMutableSet? operator - (NSMutableSet? first, NSMutableSet? second) { if (first is null || first.Count == 0) return null; @@ -163,9 +161,8 @@ public TKey [] ToArray () } // Strongly typed versions of API from NSMutableSet - /// To be added. - /// To be added. - /// To be added. + /// Adds the specified object to the set. + /// The object to add to the set. public void Add (TKey obj) { if (obj is null) @@ -175,9 +172,8 @@ public void Add (TKey obj) GC.KeepAlive (obj); } - /// To be added. - /// To be added. - /// To be added. + /// Removes the specified object from the set. + /// The object to remove from the set. public void Remove (TKey obj) { if (obj is null) @@ -187,9 +183,8 @@ public void Remove (TKey obj) GC.KeepAlive (obj); } - /// To be added. - /// To be added. - /// To be added. + /// Adds multiple objects to the set. + /// The objects to add to the set. public void AddObjects (params TKey [] objects) { if (objects is null) @@ -213,9 +208,8 @@ public void AddObjects (params TKey [] objects) #endregion #region IEnumerable implementation - /// To be added. - /// To be added. - /// To be added. + /// Returns an enumerator that iterates through the set. + /// An enumerator that can be used to iterate through the set. IEnumerator IEnumerable.GetEnumerator () { return new NSFastEnumerator (this); diff --git a/tests/cecil-tests/Documentation.KnownFailures.txt b/tests/cecil-tests/Documentation.KnownFailures.txt index 71f012496e33..b6509eca7635 100644 --- a/tests/cecil-tests/Documentation.KnownFailures.txt +++ b/tests/cecil-tests/Documentation.KnownFailures.txt @@ -11861,8 +11861,6 @@ M:Foundation.NSMutableOrderedSet`1.op_Subtraction(Foundation.NSMutableOrderedSet M:Foundation.NSMutableOrderedSet`1.op_Subtraction(Foundation.NSMutableOrderedSet{`0},Foundation.NSSet{`0}) M:Foundation.NSMutableSet.op_Addition(Foundation.NSMutableSet,Foundation.NSMutableSet) M:Foundation.NSMutableSet.op_Subtraction(Foundation.NSMutableSet,Foundation.NSMutableSet) -M:Foundation.NSMutableSet`1.op_Addition(Foundation.NSMutableSet{`0},Foundation.NSMutableSet{`0}) -M:Foundation.NSMutableSet`1.op_Subtraction(Foundation.NSMutableSet{`0},Foundation.NSMutableSet{`0}) M:Foundation.NSNetService.add_AddressResolved(System.EventHandler) M:Foundation.NSNetService.add_DidAcceptConnection(System.EventHandler{Foundation.NSNetServiceConnectionEventArgs}) M:Foundation.NSNetService.add_Published(System.EventHandler) diff --git a/tests/monotouch-test/Foundation/NSMutableSet1Test.cs b/tests/monotouch-test/Foundation/NSMutableSet1Test.cs index 68ee6f9c6145..c3014749dd10 100644 --- a/tests/monotouch-test/Foundation/NSMutableSet1Test.cs +++ b/tests/monotouch-test/Foundation/NSMutableSet1Test.cs @@ -266,5 +266,335 @@ public void OperatorPlusReferenceTest () Assert.AreNotEqual (IntPtr.Zero, one.Handle, "Handle must be != IntPtr.Zero"); Assert.AreNotEqual (IntPtr.Zero, two.Handle, "Handle must be != IntPtr.Zero"); } + + [Test] + public void OperatorPlus_BothNull () + { + NSMutableSet first = null; + NSMutableSet second = null; + var result = first + second; + Assert.IsNull (result, "Both null should return null"); + } + + [Test] + public void OperatorPlus_FirstNull () + { + NSMutableSet first = null; + using (var second = new NSMutableSet ((NSString) "1", (NSString) "2")) { + using (var result = first + second) { + Assert.IsNotNull (result, "Result should not be null"); + Assert.AreEqual ((nuint) 2, result.Count, "Count"); + Assert.IsTrue (result.Contains ((NSString) "1"), "Contains 1"); + Assert.IsTrue (result.Contains ((NSString) "2"), "Contains 2"); + } + } + } + + [Test] + public void OperatorPlus_SecondNull () + { + using (var first = new NSMutableSet ((NSString) "1", (NSString) "2")) { + NSMutableSet second = null; + using (var result = first + second) { + Assert.IsNotNull (result, "Result should not be null"); + Assert.AreEqual ((nuint) 2, result.Count, "Count"); + Assert.IsTrue (result.Contains ((NSString) "1"), "Contains 1"); + Assert.IsTrue (result.Contains ((NSString) "2"), "Contains 2"); + } + } + } + + [Test] + public void OperatorPlus_BothEmpty () + { + using (var first = new NSMutableSet ()) + using (var second = new NSMutableSet ()) + using (var result = first + second) { + Assert.IsNotNull (result, "Result should not be null"); + Assert.AreEqual ((nuint) 0, result.Count, "Count should be 0"); + } + } + + [Test] + public void OperatorPlus_FirstEmpty () + { + using (var first = new NSMutableSet ()) + using (var second = new NSMutableSet ((NSString) "1", (NSString) "2")) + using (var result = first + second) { + Assert.IsNotNull (result, "Result should not be null"); + Assert.AreEqual ((nuint) 2, result.Count, "Count"); + Assert.IsTrue (result.Contains ((NSString) "1"), "Contains 1"); + Assert.IsTrue (result.Contains ((NSString) "2"), "Contains 2"); + } + } + + [Test] + public void OperatorPlus_SecondEmpty () + { + using (var first = new NSMutableSet ((NSString) "1", (NSString) "2")) + using (var second = new NSMutableSet ()) + using (var result = first + second) { + Assert.IsNotNull (result, "Result should not be null"); + Assert.AreEqual ((nuint) 2, result.Count, "Count"); + Assert.IsTrue (result.Contains ((NSString) "1"), "Contains 1"); + Assert.IsTrue (result.Contains ((NSString) "2"), "Contains 2"); + } + } + + [Test] + public void OperatorPlus_Overlapping () + { + using (var first = new NSMutableSet ((NSString) "1", (NSString) "2")) + using (var second = new NSMutableSet ((NSString) "2", (NSString) "3")) + using (var result = first + second) { + Assert.IsNotNull (result, "Result should not be null"); + Assert.AreEqual ((nuint) 3, result.Count, "Count should be 3 (set union)"); + Assert.IsTrue (result.Contains ((NSString) "1"), "Contains 1"); + Assert.IsTrue (result.Contains ((NSString) "2"), "Contains 2"); + Assert.IsTrue (result.Contains ((NSString) "3"), "Contains 3"); + } + } + + [Test] + public void OperatorMinus_BothNull () + { + NSMutableSet first = null; + NSMutableSet second = null; + var result = first - second; + Assert.IsNull (result, "Both null should return null"); + } + + [Test] + public void OperatorMinus_FirstNull () + { + NSMutableSet first = null; + using (var second = new NSMutableSet ((NSString) "1", (NSString) "2")) { + var result = first - second; + Assert.IsNull (result, "First null should return null"); + } + } + + [Test] + public void OperatorMinus_SecondNull () + { + using (var first = new NSMutableSet ((NSString) "1", (NSString) "2")) { + NSMutableSet second = null; + using (var result = first - second) { + Assert.IsNotNull (result, "Result should not be null"); + Assert.AreEqual ((nuint) 2, result.Count, "Count"); + Assert.IsTrue (result.Contains ((NSString) "1"), "Contains 1"); + Assert.IsTrue (result.Contains ((NSString) "2"), "Contains 2"); + } + } + } + + [Test] + public void OperatorMinus_FirstEmpty () + { + using (var first = new NSMutableSet ()) + using (var second = new NSMutableSet ((NSString) "1", (NSString) "2")) { + var result = first - second; + Assert.IsNull (result, "Empty first should return null"); + } + } + + [Test] + public void OperatorMinus_SecondEmpty () + { + using (var first = new NSMutableSet ((NSString) "1", (NSString) "2")) + using (var second = new NSMutableSet ()) + using (var result = first - second) { + Assert.IsNotNull (result, "Result should not be null"); + Assert.AreEqual ((nuint) 2, result.Count, "Count"); + Assert.IsTrue (result.Contains ((NSString) "1"), "Contains 1"); + Assert.IsTrue (result.Contains ((NSString) "2"), "Contains 2"); + } + } + + [Test] + public void OperatorMinus_BothEmpty () + { + using (var first = new NSMutableSet ()) + using (var second = new NSMutableSet ()) { + var result = first - second; + Assert.IsNull (result, "Both empty should return null"); + } + } + + [Test] + public void OperatorMinus_NoOverlap () + { + using (var first = new NSMutableSet ((NSString) "1", (NSString) "2")) + using (var second = new NSMutableSet ((NSString) "3", (NSString) "4")) + using (var result = first - second) { + Assert.IsNotNull (result, "Result should not be null"); + Assert.AreEqual ((nuint) 2, result.Count, "Count"); + Assert.IsTrue (result.Contains ((NSString) "1"), "Contains 1"); + Assert.IsTrue (result.Contains ((NSString) "2"), "Contains 2"); + } + } + + [Test] + public void OperatorMinus_PartialOverlap () + { + using (var first = new NSMutableSet ((NSString) "1", (NSString) "2", (NSString) "3")) + using (var second = new NSMutableSet ((NSString) "2", (NSString) "4")) + using (var result = first - second) { + Assert.IsNotNull (result, "Result should not be null"); + Assert.AreEqual ((nuint) 2, result.Count, "Count"); + Assert.IsTrue (result.Contains ((NSString) "1"), "Contains 1"); + Assert.IsTrue (result.Contains ((NSString) "3"), "Contains 3"); + Assert.IsFalse (result.Contains ((NSString) "2"), "Should not contain 2"); + } + } + + [Test] + public void OperatorMinus_CompleteOverlap () + { + using (var first = new NSMutableSet ((NSString) "1", (NSString) "2")) + using (var second = new NSMutableSet ((NSString) "1", (NSString) "2")) + using (var result = first - second) { + Assert.IsNotNull (result, "Result should not be null"); + Assert.AreEqual ((nuint) 0, result.Count, "Count should be 0"); + } + } + + [Test] + public void Ctor_Capacity () + { + using (var set = new NSMutableSet (10)) { + Assert.AreEqual ((nuint) 0, set.Count, "Empty with capacity"); + } + } + + [Test] + public void ToArray_Empty () + { + using (var set = new NSMutableSet ()) { + var arr = set.ToArray (); + Assert.IsNotNull (arr, "Array should not be null"); + Assert.AreEqual (0, arr.Length, "Length should be 0"); + } + } + + [Test] + public void ToArray_Multiple () + { + var v1 = (NSString) "1"; + var v2 = (NSString) "2"; + var v3 = (NSString) "3"; + + using (var set = new NSMutableSet (v1, v2, v3)) { + var arr = set.ToArray (); + Assert.AreEqual (3, arr.Length, "Length"); + Assert.Contains (v1, arr, "Contains v1"); + Assert.Contains (v2, arr, "Contains v2"); + Assert.Contains (v3, arr, "Contains v3"); + } + } + + [Test] + public void Add_Duplicate () + { + var v1 = (NSString) "1"; + + using (var set = new NSMutableSet ()) { + set.Add (v1); + Assert.AreEqual ((nuint) 1, set.Count, "Count after first add"); + + set.Add (v1); + Assert.AreEqual ((nuint) 1, set.Count, "Count after duplicate add"); + } + } + + [Test] + public void Remove_NonExistent () + { + var v1 = (NSString) "1"; + var v2 = (NSString) "2"; + + using (var set = new NSMutableSet (v1)) { + set.Remove (v2); + Assert.AreEqual ((nuint) 1, set.Count, "Count should remain 1"); + Assert.IsTrue (set.Contains (v1), "Should still contain v1"); + } + } + + [Test] + public void AddObjects_Empty () + { + using (var set = new NSMutableSet ()) { + set.AddObjects (); + Assert.AreEqual ((nuint) 0, set.Count, "Count should be 0"); + } + } + + [Test] + public void AddObjects_WithNullElement () + { + var v1 = (NSString) "1"; + + using (var set = new NSMutableSet ()) { + Assert.Throws (() => set.AddObjects (v1, null), "Should throw on null element"); + } + } + + [Test] + public void LookupMember_Empty () + { + var v1 = (NSString) "1"; + + using (var set = new NSMutableSet ()) { + var result = set.LookupMember (v1); + Assert.IsNull (result, "Should return null for empty set"); + } + } + + [Test] + public void Contains_Empty () + { + var v1 = (NSString) "1"; + + using (var set = new NSMutableSet ()) { + Assert.IsFalse (set.Contains (v1), "Empty set should not contain any element"); + } + } + + [Test] + public void Enumeration_Empty () + { + using (var set = new NSMutableSet ()) { + var count = 0; + foreach (var item in set) { + count++; + } + Assert.AreEqual (0, count, "Should not enumerate any items"); + } + } + + [Test] + public void Enumeration_Single () + { + var v1 = (NSString) "1"; + + using (var set = new NSMutableSet (v1)) { + var count = 0; + NSString found = null; + foreach (var item in set) { + count++; + found = item; + } + Assert.AreEqual (1, count, "Should enumerate one item"); + Assert.AreSame (v1, found, "Should find v1"); + } + } + + [Test] + public void Ctor_Params_Empty () + { + using (var set = new NSMutableSet ()) { + Assert.AreEqual ((nuint) 0, set.Count, "Empty params"); + } + } } }