-
Notifications
You must be signed in to change notification settings - Fork 234
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enable NRT for classes in namespace Ical.Net.Utility #706
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ | |
// Licensed under the MIT license. | ||
// | ||
|
||
#nullable enable | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
|
@@ -12,7 +13,7 @@ | |
internal static class CollectionHelpers | ||
{ | ||
/// <summary> Commutative, stable, order-independent hashing for collections of collections. </summary> | ||
public static int GetHashCode<T>(IEnumerable<T> collection) | ||
public static int GetHashCode<T>(IEnumerable<T>? collection) | ||
{ | ||
unchecked | ||
{ | ||
|
@@ -23,12 +24,12 @@ | |
|
||
return collection | ||
.Where(e => e != null) | ||
.Aggregate(0, (current, element) => current + element.GetHashCode()); | ||
.Aggregate(0, (current, element) => current + element?.GetHashCode() ?? 0); | ||
} | ||
} | ||
|
||
/// <summary> Commutative, stable, order-independent hashing for collections of collections. </summary> | ||
public static int GetHashCodeForNestedCollection<T>(IEnumerable<IEnumerable<T>> nestedCollection) | ||
public static int GetHashCodeForNestedCollection<T>(IEnumerable<IEnumerable<T>>? nestedCollection) | ||
{ | ||
unchecked | ||
{ | ||
|
@@ -40,23 +41,18 @@ | |
return nestedCollection | ||
.SelectMany(c => c) | ||
.Where(e => e != null) | ||
.Aggregate(0, (current, element) => current + element.GetHashCode()); | ||
.Aggregate(0, (current, element) => current + element?.GetHashCode() ?? 0); | ||
} | ||
} | ||
|
||
public static bool Equals<T>(IEnumerable<T> left, IEnumerable<T> right, bool orderSignificant = false) | ||
public static bool Equals<T>(IEnumerable<T>? left, IEnumerable<T>? right, bool orderSignificant = false) | ||
{ | ||
if (ReferenceEquals(left, right)) | ||
{ | ||
return true; | ||
} | ||
|
||
if (left == null && right != null) | ||
{ | ||
return false; | ||
} | ||
|
||
if (left != null && right == null) | ||
if (left == null || right == null) | ||
{ | ||
return false; | ||
} | ||
|
@@ -66,18 +62,21 @@ | |
return left.SequenceEqual(right); | ||
} | ||
|
||
// No multiple enumerations | ||
var rightArray = right as T[] ?? right.ToArray(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Eager iteration would only help if right/left would be generators, which doesn't seem to be the case in any of today's uses, otherwise it would rather add overhead. |
||
var leftArray = left as T[] ?? left.ToArray(); | ||
try | ||
{ | ||
//Many things have natural IComparers defined, but some don't, because no natural comparer exists | ||
return left.OrderBy(l => l).SequenceEqual(right.OrderBy(r => r)); | ||
return leftArray.OrderBy(l => l).SequenceEqual(rightArray.OrderBy(r => r)); | ||
} | ||
catch (Exception) | ||
{ | ||
//It's not possible to sort some collections of things (like Calendars) in any meaningful way. Properties can be null, and there's no natural | ||
//ordering for the contents therein. In cases like that, the best we can do is treat them like sets, and compare them. We don't maintain | ||
//fidelity with respect to duplicates, but it seems better than doing nothing | ||
var leftSet = new HashSet<T>(left); | ||
var rightSet = new HashSet<T>(right); | ||
var leftSet = new HashSet<T>(leftArray); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this whole way of comparing isn't too helpful. We discussed this in another ticket, that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I wanted to stick to NRT |
||
var rightSet = new HashSet<T>(rightArray); | ||
return leftSet.SetEquals(rightSet); | ||
} | ||
} | ||
|
@@ -262,7 +261,7 @@ | |
|
||
foreach (var item in items) | ||
{ | ||
if (first || !comparer.Equals(prev, item)) | ||
Check warning on line 264 in Ical.Net/Utility/CollectionHelpers.cs
|
||
yield return item; | ||
|
||
prev = item; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ | |
// Licensed under the MIT license. | ||
// | ||
|
||
#nullable enable | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
|
@@ -23,8 +24,6 @@ public static CalDateTime AsCalDateTime(this DateTime t) | |
|
||
public static DateTime AddWeeks(DateTime dt, int interval, DayOfWeek firstDayOfWeek) | ||
{ | ||
// NOTE: fixes WeeklyUntilWkst2() eval. | ||
// NOTE: simplified the execution of this - fixes bug #3119920 - missing weekly occurences also | ||
dt = dt.AddDays(interval * 7); | ||
while (dt.DayOfWeek != firstDayOfWeek) | ||
{ | ||
|
@@ -63,8 +62,11 @@ private static Dictionary<string, string> InitializeWindowsMappings() | |
/// <param name="tzId">A BCL, IANA, or serialization time zone identifier</param> | ||
/// <param name="useLocalIfNotFound">If true, this method will return the system local time zone if tzId doesn't match a known time zone identifier. | ||
/// Otherwise, it will throw an exception.</param> | ||
/// <exception cref="ArgumentException">Unrecognized time zone id</exception> | ||
public static DateTimeZone GetZone(string tzId, bool useLocalIfNotFound = true) | ||
{ | ||
var exMsg = $"Unrecognized time zone id {tzId}"; | ||
|
||
if (string.IsNullOrWhiteSpace(tzId)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We removed the implicit usage of the local time zone in other parts, didn't we? Hope, this is the only one left. |
||
{ | ||
return LocalDateTimeZone; | ||
|
@@ -83,7 +85,7 @@ public static DateTimeZone GetZone(string tzId, bool useLocalIfNotFound = true) | |
|
||
if (_windowsMapping.Value.TryGetValue(tzId, out var ianaZone)) | ||
{ | ||
return DateTimeZoneProviders.Tzdb.GetZoneOrNull(ianaZone); | ||
return DateTimeZoneProviders.Tzdb.GetZoneOrNull(ianaZone) ?? throw new ArgumentException(exMsg); | ||
} | ||
|
||
zone = NodaTime.Xml.XmlSerializationSettings.DateTimeZoneProvider.GetZoneOrNull(tzId); | ||
|
@@ -103,29 +105,29 @@ public static DateTimeZone GetZone(string tzId, bool useLocalIfNotFound = true) | |
var providerId = DateTimeZoneProviders.Tzdb.Ids.FirstOrDefault(tzId.Contains); | ||
if (providerId != null) | ||
{ | ||
return DateTimeZoneProviders.Tzdb.GetZoneOrNull(providerId); | ||
return DateTimeZoneProviders.Tzdb.GetZoneOrNull(providerId) ?? throw new ArgumentException(exMsg); | ||
} | ||
|
||
if (_windowsMapping.Value.Keys | ||
.Where(tzId.Contains) | ||
.Any(pId => _windowsMapping.Value.TryGetValue(pId, out ianaZone)) | ||
) | ||
{ | ||
return DateTimeZoneProviders.Tzdb.GetZoneOrNull(ianaZone); | ||
return DateTimeZoneProviders.Tzdb.GetZoneOrNull(ianaZone!) ?? throw new ArgumentException(exMsg); | ||
} | ||
|
||
providerId = NodaTime.Xml.XmlSerializationSettings.DateTimeZoneProvider.Ids.FirstOrDefault(tzId.Contains); | ||
if (providerId != null) | ||
{ | ||
return NodaTime.Xml.XmlSerializationSettings.DateTimeZoneProvider.GetZoneOrNull(providerId); | ||
return NodaTime.Xml.XmlSerializationSettings.DateTimeZoneProvider.GetZoneOrNull(providerId) ?? throw new ArgumentException(exMsg); | ||
} | ||
|
||
if (useLocalIfNotFound) | ||
{ | ||
return LocalDateTimeZone; | ||
} | ||
|
||
throw new ArgumentException($"Unrecognized time zone id {tzId}"); | ||
throw new ArgumentException(exMsg); | ||
} | ||
|
||
public static ZonedDateTime AddYears(ZonedDateTime zonedDateTime, int years) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we handle floating separately? Not sure how the method behaves if we pass an empty string.