Skip to content

Commit

Permalink
J2N.Collections: Enabled nullable on most types
Browse files Browse the repository at this point in the history
  • Loading branch information
NightOwl888 committed Jul 11, 2020
1 parent 4b534d0 commit 139ec58
Show file tree
Hide file tree
Showing 16 changed files with 206 additions and 152 deletions.
17 changes: 8 additions & 9 deletions src/J2N/Collections/Arrays.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
using J2N.Text;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
#nullable enable

namespace J2N.Collections
{
Expand Down Expand Up @@ -35,7 +34,7 @@ internal static class Arrays
/// same length and the elements at each index in the two arrays are
/// equal according to <see cref="IEqualityComparer{T}.Equals(T, T)"/> of
/// <see cref="EqualityComparer{T}.Default"/>; otherwise, <c>false</c>.</returns>
public static bool DeepEquals<T>(T[] arrayA, T[] arrayB)
public static bool DeepEquals<T>(T[]? arrayA, T[]? arrayB)
{
return StructuralEqualityComparer.Default.Equals(arrayA, arrayB);
}
Expand All @@ -59,9 +58,9 @@ public static bool DeepEquals<T>(T[] arrayA, T[] arrayB)
/// <see cref="IList{T}"/>, or <see cref="ISet{T}"/>, its values and any nested collection values
/// will be compared for equality as well.
/// </returns>
public static bool Equals<T>(T[] arrayA, T[] arrayB)
public static bool Equals<T>(T[]? arrayA, T[]? arrayB)
{
return ArrayEqualityComparer<T>.OneDimensional.Equals(arrayA, arrayB);
return ArrayEqualityComparer<T>.OneDimensional.Equals(arrayA!, arrayB!);
}

/// <summary>
Expand Down Expand Up @@ -90,7 +89,7 @@ public static bool Equals<T>(T[] arrayA, T[] arrayB)
/// <typeparam name="T">The type of array.</typeparam>
/// <param name="array">The array whose hash code to compute.</param>
/// <returns>The deep hash code for <paramref name="array"/>.</returns>
public static int GetDeepHashCode<T>(T[] array)
public static int GetDeepHashCode<T>(T[]? array)
{
return StructuralEqualityComparer.Default.GetHashCode(array);
}
Expand All @@ -104,9 +103,9 @@ public static int GetDeepHashCode<T>(T[] array)
/// <typeparam name="T">The array element type.</typeparam>
/// <param name="array">The array whose hash code to compute.</param>
/// <returns>The hash code for <paramref name="array"/>.</returns>
public static int GetHashCode<T>(T[] array)
public static int GetHashCode<T>(T[]? array)
{
return ArrayEqualityComparer<T>.OneDimensional.GetHashCode(array);
return ArrayEqualityComparer<T>.OneDimensional.GetHashCode(array!); // J2N TODO: array can be null here, but need to override the constraint
}

// J2N TODO: DeepToString()
Expand All @@ -120,7 +119,7 @@ public static int GetHashCode<T>(T[] array)
/// </summary>
/// <typeparam name="T">The type of array element.</typeparam>
/// <param name="array"></param>
public static string ToString<T>(T[] array)
public static string ToString<T>(T[]? array)
{
if (array == null)
return "null"; //$NON-NLS-1$
Expand Down
11 changes: 6 additions & 5 deletions src/J2N/Collections/BitSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System;
using System.ComponentModel;
using System.Text;
#nullable enable

namespace J2N.Collections
{
Expand Down Expand Up @@ -141,17 +142,17 @@ public virtual object Clone()
/// <returns>A <see cref="bool"/> indicating whether or not this <see cref="BitSet"/> and
/// <paramref name="obj"/> are equal.</returns>
/// <seealso cref="GetHashCode()"/>
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
if (this == obj)
{
return true;
}
if (obj is BitSet)
if (obj is BitSet other)
{
long[] bsBits = ((BitSet)obj).bits;
int length1 = this.actualArrayLength, length2 = ((BitSet)obj).actualArrayLength;
if (this.isLengthActual && ((BitSet)obj).isLengthActual
long[] bsBits = other.bits;
int length1 = this.actualArrayLength, length2 = other.actualArrayLength;
if (this.isLengthActual && other.isLengthActual
&& length1 != length2)
{
return false;
Expand Down
85 changes: 46 additions & 39 deletions src/J2N/Collections/CollectionUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@
using System.Collections.Generic;
using System.Reflection;
using System.Text;
#nullable enable

namespace J2N.Collections
{
#pragma warning disable CS8714 // The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match 'notnull' constraint.

/// <summary>
/// Static methods for assisting with making .NET collections check for equality and print
/// strings the same way they are done in Java.
Expand All @@ -27,7 +30,7 @@ internal static class CollectionUtil
/// Note this operation currently only supports <see cref="IList{T}"/>, <see cref="ISet{T}"/>,
/// and <see cref="IDictionary{TKey, TValue}"/>.
/// </summary>
public static bool Equals<T>(IList<T> listA, IList<T> listB)
public static bool Equals<T>(IList<T>? listA, IList<T>? listB)
{
return ListEqualityComparer<T>.Aggressive.Equals(listA, listB);
}
Expand All @@ -43,7 +46,7 @@ public static bool Equals<T>(IList<T> listA, IList<T> listB)
/// Note this operation currently only supports <see cref="IList{T}"/>, <see cref="ISet{T}"/>,
/// and <see cref="IDictionary{TKey, TValue}"/>.
/// </summary>
public static bool Equals<T>(ISet<T> setA, ISet<T> setB)
public static bool Equals<T>(ISet<T>? setA, ISet<T>? setB)
{
return SetEqualityComparer<T>.Aggressive.Equals(setA, setB);
}
Expand All @@ -59,7 +62,7 @@ public static bool Equals<T>(ISet<T> setA, ISet<T> setB)
/// Note this operation currently only supports <see cref="IList{T}"/>, <see cref="ISet{T}"/>,
/// and <see cref="IDictionary{TKey, TValue}"/>.
/// </summary>
public static bool Equals<TKey, TValue>(IDictionary<TKey, TValue> dictionaryA, IDictionary<TKey, TValue> dictionaryB)
public static bool Equals<TKey, TValue>(IDictionary<TKey, TValue>? dictionaryA, IDictionary<TKey, TValue>? dictionaryB)
{
return DictionaryEqualityComparer<TKey, TValue>.Aggressive.Equals(dictionaryA, dictionaryB);
}
Expand All @@ -71,7 +74,7 @@ public static bool Equals<T>(ISet<T> setA, ISet<T> setB)
/// Note this operation currently only supports <see cref="IList{T}"/>, <see cref="ISet{T}"/>,
/// and <see cref="IDictionary{TKey, TValue}"/>.
/// </summary>
new public static bool Equals(object objA, object objB)
new public static bool Equals(object? objA, object? objB)
{
if (objA is null)
return objB is null;
Expand All @@ -82,15 +85,15 @@ public static bool Equals<T>(ISet<T> setA, ISet<T> setB)
Type tB = objB.GetType();
if (objA is Array arrayA && arrayA.Rank == 1 && objB is Array arrayB && arrayB.Rank == 1)
{
Type elementType = tA.GetElementType();
if (
Type? elementType = tA.GetElementType();
bool isPrimitive = elementType != null &&
#if FEATURE_TYPEEXTENSIONS_GETTYPEINFO
elementType.GetTypeInfo().IsPrimitive
elementType.GetTypeInfo().IsPrimitive;
#else
elementType.IsPrimitive
elementType.IsPrimitive;
#endif
)
return ArrayEqualityComparer<object>.GetPrimitiveOneDimensionalArrayEqualityComparer(elementType).Equals(objA, objB);
if (isPrimitive)
return ArrayEqualityComparer<object>.GetPrimitiveOneDimensionalArrayEqualityComparer(elementType!).Equals(objA, objB);

var eA = arrayA.GetEnumerator();
var eB = arrayB.GetEnumerator();
Expand All @@ -105,13 +108,14 @@ public static bool Equals<T>(ISet<T> setA, ISet<T> setB)
}
else if (objA is IStructuralEquatable seObj)
return seObj.Equals(objB, StructuralEqualityComparer.Aggressive);
if (

bool isGenericType =
#if FEATURE_TYPEEXTENSIONS_GETTYPEINFO
tA.GetTypeInfo().IsGenericType
tA.GetTypeInfo().IsGenericType;
#else
tA.IsGenericType
tA.IsGenericType;
#endif
)
if (isGenericType)
{
bool shouldReturn = false;

Expand Down Expand Up @@ -159,7 +163,7 @@ public static bool Equals<T>(ISet<T> setA, ISet<T> setB)
/// Note this operation currently only supports <see cref="IList{T}"/>, <see cref="ISet{T}"/>,
/// and <see cref="IDictionary{TKey, TValue}"/>.
/// </summary>
public static int GetHashCode<T>(IList<T> list)
public static int GetHashCode<T>(IList<T>? list)
{
return ListEqualityComparer<T>.Aggressive.GetHashCode(list);
}
Expand All @@ -175,7 +179,7 @@ public static int GetHashCode<T>(IList<T> list)
/// Note this operation currently only supports <see cref="IList{T}"/>, <see cref="ISet{T}"/>,
/// and <see cref="IDictionary{TKey, TValue}"/>.
/// </summary>
public static int GetHashCode<T>(ISet<T> set)
public static int GetHashCode<T>(ISet<T>? set)
{
return SetEqualityComparer<T>.Aggressive.GetHashCode(set);
}
Expand All @@ -191,7 +195,7 @@ public static int GetHashCode<T>(ISet<T> set)
/// Note this operation currently only supports <see cref="IList{T}"/>, <see cref="ISet{T}"/>,
/// and <see cref="IDictionary{TKey, TValue}"/>.
/// </summary>
public static int GetHashCode<TKey, TValue>(IDictionary<TKey, TValue> dictionary)
public static int GetHashCode<TKey, TValue>(IDictionary<TKey, TValue>? dictionary)
{
return DictionaryEqualityComparer<TKey, TValue>.Aggressive.GetHashCode(dictionary);
}
Expand All @@ -209,27 +213,23 @@ public static int GetHashCode<T>(ISet<T> set)
/// nested collection values in the object, provided the main object itself is
/// a collection, otherwise calls <see cref="object.GetHashCode()"/> on the
/// object that is passed.</returns>
public static int GetHashCode(object obj)
public static int GetHashCode(object? obj)
{
if (obj == null)
return 0; // 0 for null

#if FEATURE_TYPEEXTENSIONS_GETTYPEINFO
TypeInfo t = obj.GetType().GetTypeInfo();
#else
Type t = obj.GetType();
#endif
if (obj is Array array && array.Rank == 1)
{
Type elementType = t.GetElementType();
if (
Type? elementType = t.GetElementType();
bool isPrimitive = elementType != null &&
#if FEATURE_TYPEEXTENSIONS_GETTYPEINFO
elementType.GetTypeInfo().IsPrimitive
elementType.GetTypeInfo().IsPrimitive;
#else
elementType.IsPrimitive
elementType.IsPrimitive;
#endif
)
return ArrayEqualityComparer<object>.GetPrimitiveOneDimensionalArrayEqualityComparer(elementType).GetHashCode(obj);
if (isPrimitive)
return ArrayEqualityComparer<object>.GetPrimitiveOneDimensionalArrayEqualityComparer(elementType!).GetHashCode(obj);

int hashCode = 1, elementHashCode;
foreach (var element in array)
Expand All @@ -250,7 +250,12 @@ public static int GetHashCode(object obj)
}
else if (obj is IStructuralEquatable seObj)
return seObj.GetHashCode(StructuralEqualityComparer.Aggressive);
else if (t.IsGenericType
else if (
#if FEATURE_TYPEEXTENSIONS_GETTYPEINFO
t.GetTypeInfo().IsGenericType
#else
t.IsGenericType
#endif
&& (t.ImplementsGenericInterface(typeof(IList<>))
|| t.ImplementsGenericInterface(typeof(ISet<>))
|| t.ImplementsGenericInterface(typeof(IDictionary<,>))))
Expand Down Expand Up @@ -278,7 +283,7 @@ public static int GetHashCode(object obj)
/// This overload is intended to be called from within collections to bypass the
/// reflection/dynamic conversion of working out whether we are a collection type.
/// </summary>
public static string ToString<T>(IFormatProvider provider, string format, ICollection<T> collection)
public static string ToString<T>(IFormatProvider? provider, string? format, ICollection<T>? collection)
{
return string.Format(provider, format ?? SingleFormatArgument, ToString(collection, provider));
}
Expand All @@ -290,7 +295,7 @@ public static string ToString<T>(IFormatProvider provider, string format, IColle
/// to specify culture for formatting of nested numbers and dates. Note that
/// this overload will change the culture of the current thread.
/// </summary>
public static string ToString<T>(ICollection<T> collection, IFormatProvider provider)
public static string ToString<T>(ICollection<T>? collection, IFormatProvider? provider)
{
if (collection == null) return "null";
if (collection.Count == 0)
Expand Down Expand Up @@ -336,7 +341,7 @@ public static string ToString<T>(ICollection<T> collection, IFormatProvider prov
/// This overload is intended to be called from within dictionaries to bypass the
/// reflection/dynamic conversion of working out whether we are a dictionary type.
/// </summary>
public static string ToString<TKey, TValue>(IFormatProvider provider, string format, IDictionary<TKey, TValue> dictionary)
public static string ToString<TKey, TValue>(IFormatProvider? provider, string? format, IDictionary<TKey, TValue>? dictionary)
{
return string.Format(provider, format ?? SingleFormatArgument, ToString(dictionary, provider));
}
Expand All @@ -347,7 +352,7 @@ public static string ToString<T>(ICollection<T> collection, IFormatProvider prov
/// to specify culture for formatting of nested numbers and dates. Note that
/// this overload will change the culture of the current thread.
/// </summary>
public static string ToString<TKey, TValue>(IDictionary<TKey, TValue> dictionary, IFormatProvider provider)
public static string ToString<TKey, TValue>(IDictionary<TKey, TValue>? dictionary, IFormatProvider? provider)
{
if (dictionary == null) return "null";
if (dictionary.Count == 0)
Expand Down Expand Up @@ -389,7 +394,7 @@ public static string ToString<T>(ICollection<T> collection, IFormatProvider prov
/// This is a helper method that assists with recursively building
/// a string of the current collection and all nested collections.
/// </summary>
public static string ToString(object obj)
public static string ToString(object? obj)
{
return ToString(obj, StringFormatter.CurrentCulture);
}
Expand All @@ -400,9 +405,9 @@ public static string ToString(object obj)
/// to specify culture for formatting of nested numbers and dates. Note that
/// this overload will change the culture of the current thread.
/// </summary>
public static string ToString(object obj, IFormatProvider provider)
public static string ToString(object? obj, IFormatProvider? provider)
{
if (obj == null) return "null";
if (obj is null) return "null";
Type t = obj.GetType();
if (
#if FEATURE_TYPEEXTENSIONS_GETTYPEINFO
Expand All @@ -416,13 +421,15 @@ public static string ToString(object obj, IFormatProvider provider)
return ToStringImpl(obj, t, provider);
}

return obj.ToString();
return obj.ToString()!;
}

public static string ToStringImpl(object obj, Type type, IFormatProvider provider)
public static string ToStringImpl(object? obj, Type type, IFormatProvider? provider)
{
dynamic genericType = Convert.ChangeType(obj, type);
dynamic? genericType = Convert.ChangeType(obj, type);
return ToString(genericType, provider);
}
}

#pragma warning restore CS8714 // The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match 'notnull' constraint.
}
1 change: 1 addition & 0 deletions src/J2N/Collections/Generic/BitHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// Dependency of SortedSet, SortedDictionary

using System;
#nullable enable

namespace J2N.Collections.Generic
{
Expand Down
1 change: 1 addition & 0 deletions src/J2N/Collections/Generic/Comparer.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
#nullable enable

namespace J2N.Collections.Generic
{
Expand Down

0 comments on commit 139ec58

Please sign in to comment.