diff --git a/Ical.Net.Tests/RecurrenceTests.cs b/Ical.Net.Tests/RecurrenceTests.cs index 62a341960..10fc184cf 100644 --- a/Ical.Net.Tests/RecurrenceTests.cs +++ b/Ical.Net.Tests/RecurrenceTests.cs @@ -3904,7 +3904,7 @@ public void TestDtStartTimezone(string? tzId) var cal = Calendar.Load(icalText); var evt = cal.Events.First(); var ev = new EventEvaluator(evt); - var occurrences = ev.Evaluate(evt.DtStart, evt.DtStart.ToTimeZone(tzId), evt.DtStart.AddMinutes(61).ToTimeZone(tzId), default); + var occurrences = ev.Evaluate(evt.DtStart, evt.DtStart.ToTimeZone(tzId), evt.DtStart.AddMinutes(61).ToTimeZone(tzId), null); var occurrencesStartTimes = occurrences.Select(x => x.StartTime).Take(2).ToList(); var expectedStartTimes = new[] diff --git a/Ical.Net/CalendarComponents/Alarm.cs b/Ical.Net/CalendarComponents/Alarm.cs index ad9bf7a95..68f7eeb53 100644 --- a/Ical.Net/CalendarComponents/Alarm.cs +++ b/Ical.Net/CalendarComponents/Alarm.cs @@ -141,7 +141,7 @@ public virtual IList GetOccurrences(IRecurringComponent rc, Cal /// since the provided date/time. If /// is null, all triggered alarms will be returned. /// - /// The earliest date/time to poll trigered alarms for. + /// The earliest date/time to poll triggered alarms for. /// /// /// A list of objects, each containing a triggered alarm. @@ -171,12 +171,20 @@ private void AddRepeatedItems(List occurrences) for (var i = 0; i < len; i++) { var ao = occurrences[i]; + if (ao?.DateTime == null || ao.Component == null) + { + continue; + } + var alarmTime = ao.DateTime.Copy(); for (var j = 0; j < Repeat; j++) { - alarmTime = alarmTime.Add(Duration); - occurrences.Add(new AlarmOccurrence(this, alarmTime.Copy(), ao.Component)); + alarmTime = alarmTime?.Add(Duration); + if (alarmTime != null) + { + occurrences.Add(new AlarmOccurrence(this, alarmTime.Copy(), ao.Component)); + } } } } diff --git a/Ical.Net/DataTypes/AlarmOccurrence.cs b/Ical.Net/DataTypes/AlarmOccurrence.cs index ea1d5640c..f11a78e24 100644 --- a/Ical.Net/DataTypes/AlarmOccurrence.cs +++ b/Ical.Net/DataTypes/AlarmOccurrence.cs @@ -3,6 +3,7 @@ // Licensed under the MIT license. // +#nullable enable using System; using Ical.Net.CalendarComponents; @@ -18,16 +19,16 @@ namespace Ical.Net.DataTypes; /// public class AlarmOccurrence : IComparable { - public Period Period { get; set; } + public Period? Period { get; set; } - public IRecurringComponent Component { get; set; } + public IRecurringComponent? Component { get; set; } - public Alarm Alarm { get; set; } + public Alarm? Alarm { get; set; } - public CalDateTime DateTime + public CalDateTime? DateTime { - get => Period.StartTime; - set => Period = new Period(value); + get => Period?.StartTime; + set => Period = value != null ? new Period(value) : null; } public AlarmOccurrence(AlarmOccurrence ao) @@ -44,14 +45,19 @@ public AlarmOccurrence(Alarm a, CalDateTime dt, IRecurringComponent rc) Component = rc; } - public int CompareTo(AlarmOccurrence other) => Period.CompareTo(other.Period); + public int CompareTo(AlarmOccurrence? other) + { + if (other == null) return 1; + if (Period == null) return other.Period == null ? 0 : -1; + return Period.CompareTo(other.Period); + } protected bool Equals(AlarmOccurrence other) => Equals(Period, other.Period) && Equals(Component, other.Component) && Equals(Alarm, other.Alarm); - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; diff --git a/Ical.Net/DataTypes/Attachment.cs b/Ical.Net/DataTypes/Attachment.cs index 7e277488f..22c567349 100644 --- a/Ical.Net/DataTypes/Attachment.cs +++ b/Ical.Net/DataTypes/Attachment.cs @@ -3,6 +3,7 @@ // Licensed under the MIT license. // +#nullable enable using System; using System.Linq; using System.Text; @@ -18,8 +19,8 @@ namespace Ical.Net.DataTypes; /// public class Attachment : EncodableDataType { - public virtual Uri Uri { get; set; } - public virtual byte[] Data { get; private set; } // private set for CopyFrom + public virtual Uri? Uri { get; set; } + public virtual byte[]? Data { get; private set; } // private set for CopyFrom private Encoding _valueEncoding = System.Text.Encoding.UTF8; public virtual Encoding ValueEncoding @@ -43,7 +44,7 @@ public virtual string FormatType public Attachment() { } - public Attachment(byte[] value) : this() + public Attachment(byte[]? value) : this() { if (value != null) { @@ -93,15 +94,21 @@ public override void CopyFrom(ICopyable obj) FormatType = att.FormatType; } - protected bool Equals(Attachment other) + protected bool Equals(Attachment? other) { - var firstPart = Equals(Uri, other.Uri) && ValueEncoding.Equals(other.ValueEncoding); - return Data == null - ? firstPart - : firstPart && Data.SequenceEqual(other.Data); + var firstPart = Equals(Uri, other?.Uri) && ValueEncoding.Equals(other?.ValueEncoding); + if (Data == null && other?.Data == null) + { + return firstPart; + } + if (Data == null || other?.Data == null) + { + return false; + } + return firstPart && Data.SequenceEqual(other.Data); } - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; @@ -118,4 +125,4 @@ public override int GetHashCode() return hashCode; } } -} \ No newline at end of file +} diff --git a/Ical.Net/DataTypes/Attendee.cs b/Ical.Net/DataTypes/Attendee.cs index 37395ca4d..f4a1b4a9f 100644 --- a/Ical.Net/DataTypes/Attendee.cs +++ b/Ical.Net/DataTypes/Attendee.cs @@ -3,6 +3,7 @@ // Licensed under the MIT license. // +#nullable enable using System; using System.Collections.Generic; using System.Linq; @@ -12,9 +13,9 @@ namespace Ical.Net.DataTypes; public class Attendee : EncodableDataType { - private Uri _sentBy; + private Uri? _sentBy; /// SENT-BY, to indicate who is acting on behalf of the ATTENDEE - public virtual Uri SentBy + public virtual Uri? SentBy { get { @@ -38,7 +39,7 @@ public virtual Uri SentBy } } - private string _commonName; + private string? _commonName; /// CN: to show the common or displayable name associated with the calendar address public virtual string CommonName { @@ -61,9 +62,9 @@ public virtual string CommonName } } - private Uri _directoryEntry; + private Uri? _directoryEntry; /// DIR, to indicate the URI that points to the directory information corresponding to the attendee - public virtual Uri DirectoryEntry + public virtual Uri? DirectoryEntry { get { @@ -87,7 +88,7 @@ public virtual Uri DirectoryEntry } } - private string _type; + private string? _type; /// CUTYPE: the type of calendar user public virtual string Type { @@ -111,7 +112,7 @@ public virtual string Type } } - private List _members; + private List? _members; /// MEMBER: the groups the user belongs to public virtual IList Members { @@ -123,7 +124,7 @@ public virtual IList Members } } - private string _role; + private string? _role; /// ROLE: the intended role the attendee will have public virtual string Role { @@ -146,7 +147,7 @@ public virtual string Role } } - private string _participationStatus; + private string? _participationStatus; public virtual string ParticipationStatus { get @@ -179,9 +180,8 @@ public virtual bool Rsvp return _rsvp.Value; } - bool val; var rsvp = Parameters.Get("RSVP"); - if (rsvp != null && bool.TryParse(rsvp, out val)) + if (rsvp != null && bool.TryParse(rsvp, out var val)) { _rsvp = val; return _rsvp.Value; @@ -196,40 +196,32 @@ public virtual bool Rsvp } } - private List _delegatedTo; + private List? _delegatedTo; /// DELEGATED-TO, to indicate the calendar users that the original request was delegated to public virtual IList DelegatedTo { get => _delegatedTo ?? (_delegatedTo = new List(Parameters.GetMany("DELEGATED-TO"))); set { - if (value == null) - { - return; - } _delegatedTo = new List(value); Parameters.Set("DELEGATED-TO", value); } } - private List _delegatedFrom; + private List? _delegatedFrom; /// DELEGATED-FROM, to indicate whom the request was delegated from public virtual IList DelegatedFrom { get => _delegatedFrom ?? (_delegatedFrom = new List(Parameters.GetMany("DELEGATED-FROM"))); set { - if (value == null) - { - return; - } _delegatedFrom = new List(value); Parameters.Set("DELEGATED-FROM", value); } } /// Uri associated with the attendee, typically an email address - public virtual Uri Value { get; set; } + public virtual Uri? Value { get; set; } public Attendee() { } @@ -278,8 +270,7 @@ protected bool Equals(Attendee other) => Equals(SentBy, other.SentBy) && Members.SequenceEqual(other.Members) && DelegatedTo.SequenceEqual(other.DelegatedTo) && DelegatedFrom.SequenceEqual(other.DelegatedFrom); - - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; @@ -305,4 +296,4 @@ public override int GetHashCode() return hashCode; } } -} \ No newline at end of file +} diff --git a/Ical.Net/DataTypes/CalendarDataType.cs b/Ical.Net/DataTypes/CalendarDataType.cs index 48381c8b4..f41fc4c25 100644 --- a/Ical.Net/DataTypes/CalendarDataType.cs +++ b/Ical.Net/DataTypes/CalendarDataType.cs @@ -3,6 +3,7 @@ // Licensed under the MIT license. // +#nullable enable using System; using System.Runtime.Serialization; using Ical.Net.Proxies; @@ -14,10 +15,11 @@ namespace Ical.Net.DataTypes; /// public abstract class CalendarDataType : ICalendarDataType { - private IParameterCollection _parameters; - private ParameterCollectionProxy _proxy; + // Well be set with Initialize() + private IParameterCollection _parameters = null!; + private ParameterCollectionProxy _proxy = null!; - private ICalendarObject _associatedObject; + private ICalendarObject? _associatedObject; protected CalendarDataType() { @@ -49,10 +51,10 @@ protected virtual void OnDeserializing(StreamingContext context) protected virtual void OnDeserialized(StreamingContext context) { } - public virtual Type GetValueType() + public virtual Type? GetValueType() { // See RFC 5545 Section 3.2.20. - if (_proxy != null && _proxy.ContainsKey("VALUE")) + if (_proxy.ContainsKey("VALUE")) { switch (_proxy.Get("VALUE")) { @@ -92,12 +94,12 @@ public virtual Type GetValueType() return null; } - public virtual void SetValueType(string type) + public virtual void SetValueType(string? type) { - _proxy?.Set("VALUE", type?.ToUpper()); + _proxy.Set("VALUE", type?.ToUpper()); } - public virtual ICalendarObject AssociatedObject + public virtual ICalendarObject? AssociatedObject { get => _associatedObject; set @@ -124,9 +126,9 @@ public virtual ICalendarObject AssociatedObject } } - public virtual Calendar Calendar => _associatedObject?.Calendar; + public virtual Calendar? Calendar => _associatedObject?.Calendar; - public virtual string Language + public virtual string? Language { get => Parameters.Get("LANGUAGE"); set => Parameters.Set("LANGUAGE", value); @@ -149,7 +151,7 @@ public virtual void CopyFrom(ICopyable obj) /// Creates a deep copy of the object. /// /// The copy of the object. - public virtual T Copy() + public virtual T? Copy() { var type = GetType(); var obj = Activator.CreateInstance(type, true) as ICopyable; diff --git a/Ical.Net/DataTypes/Duration.cs b/Ical.Net/DataTypes/Duration.cs index d0313c4c3..4c751ac64 100644 --- a/Ical.Net/DataTypes/Duration.cs +++ b/Ical.Net/DataTypes/Duration.cs @@ -3,6 +3,7 @@ // Licensed under the MIT license. // +#nullable enable using System; using System.IO; using Ical.Net.Serialization.DataTypes; @@ -118,7 +119,8 @@ public static Duration FromSeconds(int seconds) => /// Parses the specified value according to RFC 5545. /// /// Thrown if the value is not a valid duration. - public static Duration Parse(string value) => (Duration)new DurationSerializer().Deserialize(new StringReader(value)); + public static Duration Parse(string value) => + (Duration) new DurationSerializer().Deserialize(new StringReader(value))!; // throws if null /// /// Creates an instance that represents the given time span as exact value, that is, time-only. @@ -143,32 +145,12 @@ internal static Duration FromTimeSpan(TimeSpan t) /// /// Gets a value representing the time parts of the given instance. /// - internal TimeSpan TimeAsTimeSpan - { - get - { - return new TimeSpan( - 0, - Hours ?? 0, - Minutes ?? 0, - Seconds ?? 0); - } - } + internal TimeSpan TimeAsTimeSpan => new(0, Hours ?? 0, Minutes ?? 0, Seconds ?? 0); /// /// Gets a value representing the date parts (days and weeks) of the given instance. /// - internal TimeSpan DateAsTimeSpan - { - get - { - return new TimeSpan( - (Weeks ?? 0) * 7 + (Days ?? 0), - 0, - 0, - 0); - } - } + internal TimeSpan DateAsTimeSpan => new((Weeks ?? 0) * 7 + (Days ?? 0), 0, 0, 0); /// /// Convert the instance to a , ignoring potential @@ -181,11 +163,7 @@ internal TimeSpan DateAsTimeSpan /// nominal durations, use . /// public TimeSpan ToTimeSpanUnspecified() - => new TimeSpan( - (Weeks ?? 0) * 7 + (Days ?? 0), - Hours ?? 0, - Minutes ?? 0, - Seconds ?? 0); + => new TimeSpan((Weeks ?? 0) * 7 + (Days ?? 0), Hours ?? 0, Minutes ?? 0, Seconds ?? 0); /// /// Convert the instance to a , treating the days as nominal duration and @@ -226,7 +204,7 @@ internal bool IsEmpty new Duration(-d.Weeks, -d.Days, -d.Hours, -d.Minutes, -d.Seconds); /// - public override string ToString() + public override string? ToString() => new DurationSerializer().SerializeToString(this); private static int? GetSign(int? v) => diff --git a/Ical.Net/DataTypes/ICalendarDataType.cs b/Ical.Net/DataTypes/ICalendarDataType.cs index ac3ceeda5..eaf4b65ba 100644 --- a/Ical.Net/DataTypes/ICalendarDataType.cs +++ b/Ical.Net/DataTypes/ICalendarDataType.cs @@ -3,16 +3,16 @@ // Licensed under the MIT license. // +#nullable enable using System; namespace Ical.Net.DataTypes; public interface ICalendarDataType : ICalendarParameterCollectionContainer, ICopyable { - Type GetValueType(); + Type? GetValueType(); void SetValueType(string type); - ICalendarObject AssociatedObject { get; set; } - Calendar Calendar { get; } - - string Language { get; set; } + ICalendarObject? AssociatedObject { get; set; } + Calendar? Calendar { get; } + string? Language { get; set; } } diff --git a/Ical.Net/DataTypes/ICalendarParameterCollectionContainer.cs b/Ical.Net/DataTypes/ICalendarParameterCollectionContainer.cs index 36ca6a57b..18874174c 100644 --- a/Ical.Net/DataTypes/ICalendarParameterCollectionContainer.cs +++ b/Ical.Net/DataTypes/ICalendarParameterCollectionContainer.cs @@ -3,9 +3,10 @@ // Licensed under the MIT license. // +#nullable enable namespace Ical.Net.DataTypes; public interface ICalendarParameterCollectionContainer { IParameterCollection Parameters { get; } -} \ No newline at end of file +} diff --git a/Ical.Net/DataTypes/IEncodableDataType.cs b/Ical.Net/DataTypes/IEncodableDataType.cs index 82cd0283f..83590f870 100644 --- a/Ical.Net/DataTypes/IEncodableDataType.cs +++ b/Ical.Net/DataTypes/IEncodableDataType.cs @@ -3,9 +3,10 @@ // Licensed under the MIT license. // +#nullable enable namespace Ical.Net.DataTypes; public interface IEncodableDataType { - string Encoding { get; set; } -} \ No newline at end of file + string? Encoding { get; set; } +} diff --git a/Ical.Net/DataTypes/Organizer.cs b/Ical.Net/DataTypes/Organizer.cs index 1401eccd7..4273eb654 100644 --- a/Ical.Net/DataTypes/Organizer.cs +++ b/Ical.Net/DataTypes/Organizer.cs @@ -21,7 +21,7 @@ public virtual Uri? SentBy { get { - string sentBy = Parameters.Get("SENT-BY"); + var sentBy = Parameters.Get("SENT-BY"); if (!string.IsNullOrWhiteSpace(sentBy)) { return new Uri(sentBy); diff --git a/Ical.Net/DataTypes/PeriodList.cs b/Ical.Net/DataTypes/PeriodList.cs index f43729691..b90bacc11 100644 --- a/Ical.Net/DataTypes/PeriodList.cs +++ b/Ical.Net/DataTypes/PeriodList.cs @@ -69,7 +69,7 @@ public override void CopyFrom(ICopyable obj) foreach (var p in list) { - Add(p.Copy()); + Add(p.Copy()!); } } @@ -125,7 +125,7 @@ public void Insert(int index, Period item) } /// - public void RemoveAt(int index) => Periods.RemoveAt(index); + public void RemoveAt(int index) => Periods?.RemoveAt(index); /// /// Adds a to the list if it does not already exist.
@@ -159,7 +159,7 @@ public void Add(CalDateTime dt) public bool Contains(Period item) => Periods.Contains(item); /// - public void CopyTo(Period[] array, int arrayIndex) => Periods.CopyTo(array, arrayIndex); + public void CopyTo(Period[] array, int arrayIndex) => Periods?.CopyTo(array, arrayIndex); /// public IEnumerator GetEnumerator() => Periods.GetEnumerator(); diff --git a/Ical.Net/Evaluation/TodoEvaluator.cs b/Ical.Net/Evaluation/TodoEvaluator.cs index 5dafb061a..ba97d0cb8 100644 --- a/Ical.Net/Evaluation/TodoEvaluator.cs +++ b/Ical.Net/Evaluation/TodoEvaluator.cs @@ -79,7 +79,7 @@ private void DetermineStartingRecurrence(RecurrencePattern recur, ref CalDateTim public override IEnumerable Evaluate(CalDateTime referenceDate, CalDateTime? periodStart, CalDateTime? periodEnd, EvaluationOptions? options) { - // TODO items can only recur if a start date is specified + // Items can only recur if a start date is specified if (Todo.Start == null) return [];