diff --git a/Ical.Net.Tests/EncodingProviderTests.cs b/Ical.Net.Tests/EncodingProviderTests.cs index f25312c98..b32cc36cf 100644 --- a/Ical.Net.Tests/EncodingProviderTests.cs +++ b/Ical.Net.Tests/EncodingProviderTests.cs @@ -5,6 +5,7 @@ #nullable enable using System; +using System.Runtime.Serialization; using Ical.Net.Serialization; using NUnit.Framework; using EncodingProvider = Ical.Net.Serialization.EncodingProvider; @@ -33,7 +34,7 @@ public void Encode_ShouldBeNull_WhenInvalidEncodingIsProvided() const string encoding = "Invalid-Encoding"; var data = "Hello"u8.ToArray(); - Assert.That(GetEncodingProvider().Encode(encoding, data), Is.Null); + Assert.That(() => GetEncodingProvider().Encode(encoding, data), Throws.TypeOf()); } [Test] @@ -53,7 +54,7 @@ public void Decode_ShouldBeNull_WhenInvalidEncodingIsProvided() const string encoding = "Invalid-Encoding"; const string data = "Hello"; - Assert.That(GetEncodingProvider().DecodeString(encoding, data), Is.Null); + Assert.That(() => GetEncodingProvider().DecodeString(encoding, data), Throws.TypeOf()); } [Test] diff --git a/Ical.Net.Tests/PeriodListWrapperTests.cs b/Ical.Net.Tests/PeriodListWrapperTests.cs index d6f5c8a0f..995d392f1 100644 --- a/Ical.Net.Tests/PeriodListWrapperTests.cs +++ b/Ical.Net.Tests/PeriodListWrapperTests.cs @@ -185,7 +185,7 @@ public void AddRPeriod_ShouldCreate_DedicatePeriodList() ]); var serializer = new CalendarSerializer(cal); - var serialized = serializer.SerializeToString(); + var serialized = serializer.SerializeToString()!; // Assign the deserialized event cal = Calendar.Load(serialized)!; evt = cal.Events[0]; diff --git a/Ical.Net.Tests/RecurrenceTests.cs b/Ical.Net.Tests/RecurrenceTests.cs index b573aae01..fe535597c 100644 --- a/Ical.Net.Tests/RecurrenceTests.cs +++ b/Ical.Net.Tests/RecurrenceTests.cs @@ -3940,7 +3940,7 @@ public void TestDtStartTimezone(string? tzId) [TestCase(1, TestMaxIncrementCountWithoutGaps, false)] public void TestMaxIncrementCount(int? limit, string ical, bool expectException) { - var cal = Calendar.Load(ical); + var cal = Calendar.Load(ical)!; var options = new EvaluationOptions { diff --git a/Ical.Net.Tests/RecurrenceWithExDateTests.cs b/Ical.Net.Tests/RecurrenceWithExDateTests.cs index 160bfce06..706ab55f3 100644 --- a/Ical.Net.Tests/RecurrenceWithExDateTests.cs +++ b/Ical.Net.Tests/RecurrenceWithExDateTests.cs @@ -55,7 +55,7 @@ public void ShouldNotOccurOnLocalExceptionDate(bool useExDateWithTime) // Act var serializer = new CalendarSerializer(); - var ics = serializer.SerializeToString(calendar); + var ics = serializer.SerializeToString(calendar)!; var deserializedCalendar = Calendar.Load(ics)!; var occurrences = deserializedCalendar.GetOccurrences().ToList(); @@ -102,7 +102,7 @@ public void ShouldNotOccurOnUtcExceptionDate() var serializer = new CalendarSerializer(); ics = serializer.SerializeToString(cal); // serialize and deserialize to ensure the exclusion dates de/serialized - cal = Calendar.Load(new CalendarSerializer(cal).SerializeToString())!; + cal = Calendar.Load(new CalendarSerializer(cal).SerializeToString()!)!; // Start date: 2024-10-19 at 18:00 (GMT Standard Time) // Recurrence: Every hour, 4 occurrences @@ -150,7 +150,7 @@ public void MultipleExclusionDatesSameTimeZoneShouldBeExcluded() var serializer = new CalendarSerializer(); ics = serializer.SerializeToString(cal); // serialize and deserialize to ensure the exclusion dates de/serialized - cal = Calendar.Load(new CalendarSerializer(cal).SerializeToString())!; + cal = Calendar.Load(new CalendarSerializer(cal).SerializeToString()!)!; // Occurrences: // 2023-10-25 09:00 (UTC Offset: +0200) @@ -206,7 +206,7 @@ public void MultipleExclusionDatesDifferentZoneShouldBeExcluded() var cal = Calendar.Load(ics)!; // serialize and deserialize to ensure the exclusion dates de/serialized - cal = Calendar.Load(new CalendarSerializer(cal).SerializeToString())!; + cal = Calendar.Load(new CalendarSerializer(cal).SerializeToString()!)!; var occurrences = cal.GetOccurrences().ToList(); // Occurrences: diff --git a/Ical.Net/Calendar.cs b/Ical.Net/Calendar.cs index 7f9be70bd..446250751 100644 --- a/Ical.Net/Calendar.cs +++ b/Ical.Net/Calendar.cs @@ -121,7 +121,7 @@ public override int GetHashCode() { unchecked { - var hashCode = Name?.GetHashCode() ?? 0; + var hashCode = Name.GetHashCode(); hashCode = (hashCode * 397) ^ CollectionHelpers.GetHashCode(UniqueComponents); hashCode = (hashCode * 397) ^ CollectionHelpers.GetHashCode(Events); hashCode = (hashCode * 397) ^ CollectionHelpers.GetHashCode(Todos); @@ -227,7 +227,7 @@ public virtual IEnumerable GetOccurrences(CalDateTime? startTime // These are the UID/RECURRENCE-ID combinations that replace other occurrences. var recurrenceIdsAndUids = this.Children.OfType() .Where(r => r.RecurrenceId != null) - .Select(r => new { (r as IUniqueComponent).Uid, Dt = r.RecurrenceId!.Value }) + .Select(r => new { (r as IUniqueComponent)?.Uid, Dt = r.RecurrenceId!.Value }) .Where(r => r.Uid != null) .ToDictionary(x => x); @@ -290,14 +290,12 @@ public virtual void MergeWith(IMergeable obj) return; } - Name ??= c.Name; - Method = c.Method; Version = c.Version; ProductId = c.ProductId; Scale = c.Scale; - foreach (var p in c.Properties.Where(p => p.Name != null && !Properties.ContainsKey(p.Name))) + foreach (var p in c.Properties.Where(p => !Properties.ContainsKey(p.Name))) { Properties.Add(p); } diff --git a/Ical.Net/CalendarCollection.cs b/Ical.Net/CalendarCollection.cs index 5d14c1811..c61672a51 100644 --- a/Ical.Net/CalendarCollection.cs +++ b/Ical.Net/CalendarCollection.cs @@ -74,7 +74,7 @@ private FreeBusy CombineFreeBusy(FreeBusy? main, FreeBusy current) return this.Aggregate(null, (current, iCal) => { var freeBusy = iCal.GetFreeBusy(freeBusyRequest); - return current is null ? freeBusy : CombineFreeBusy(current, freeBusy); + return current is null || freeBusy is null ? freeBusy : CombineFreeBusy(current, freeBusy); }); } @@ -83,7 +83,7 @@ private FreeBusy CombineFreeBusy(FreeBusy? main, FreeBusy current) return this.Aggregate(null, (current, iCal) => { var freeBusy = iCal.GetFreeBusy(organizer, contacts, fromInclusive, toExclusive); - return current is null ? freeBusy : CombineFreeBusy(current, freeBusy); + return current is null || freeBusy is null ? freeBusy : CombineFreeBusy(current, freeBusy); }); } diff --git a/Ical.Net/CalendarComponents/Alarm.cs b/Ical.Net/CalendarComponents/Alarm.cs index 56bfc47cd..698371470 100644 --- a/Ical.Net/CalendarComponents/Alarm.cs +++ b/Ical.Net/CalendarComponents/Alarm.cs @@ -172,7 +172,7 @@ private void AddRepeatedItems(List occurrences) for (var i = 0; i < len; i++) { var ao = occurrences[i]; - if (ao?.DateTime == null || ao.Component == null) + if (ao.DateTime == null || ao.Component == null) { continue; } diff --git a/Ical.Net/CalendarComponents/Todo.cs b/Ical.Net/CalendarComponents/Todo.cs index 03d66a819..71d26f199 100644 --- a/Ical.Net/CalendarComponents/Todo.cs +++ b/Ical.Net/CalendarComponents/Todo.cs @@ -85,7 +85,7 @@ public virtual int PercentComplete public virtual IList Resources { get => Properties.GetMany("RESOURCES"); - set => Properties.Set("RESOURCES", value ?? new List()); + set => Properties.Set("RESOURCES", value); } /// diff --git a/Ical.Net/CalendarComponents/VTimeZone.cs b/Ical.Net/CalendarComponents/VTimeZone.cs index df55547d0..5c502feb4 100644 --- a/Ical.Net/CalendarComponents/VTimeZone.cs +++ b/Ical.Net/CalendarComponents/VTimeZone.cs @@ -383,7 +383,7 @@ public override int GetHashCode() { unchecked { - var hashCode = Name?.GetHashCode() ?? 0; + var hashCode = Name.GetHashCode(); hashCode = (hashCode * 397) ^ (TzId?.GetHashCode() ?? 0); hashCode = (hashCode * 397) ^ (Url?.GetHashCode() ?? 0); return hashCode; diff --git a/Ical.Net/Collections/Proxies/GroupedValueListProxy.cs b/Ical.Net/Collections/Proxies/GroupedValueListProxy.cs index ab5181450..7b0476428 100644 --- a/Ical.Net/Collections/Proxies/GroupedValueListProxy.cs +++ b/Ical.Net/Collections/Proxies/GroupedValueListProxy.cs @@ -64,7 +64,7 @@ private void IterateValues(Func, int, int, bool> ac foreach (var obj in _realObject) { // Get the number of items of the target value i this object - var count = obj.Values?.OfType().Count() ?? 0; + var count = obj.Values.OfType().Count(); // Perform some action on this item if (!action(obj, i, count)) diff --git a/Ical.Net/DataTypes/Attachment.cs b/Ical.Net/DataTypes/Attachment.cs index 6cb6ba933..f7e212545 100644 --- a/Ical.Net/DataTypes/Attachment.cs +++ b/Ical.Net/DataTypes/Attachment.cs @@ -113,8 +113,8 @@ public override int GetHashCode() unchecked { var hashCode = Uri?.GetHashCode() ?? 0; - hashCode = (hashCode * 397) ^ (CollectionHelpers.GetHashCode(Data)); - hashCode = (hashCode * 397) ^ (ValueEncoding?.GetHashCode() ?? 0); + hashCode = (hashCode * 397) ^ (Data != null ? CollectionHelpers.GetHashCode(Data) : 0); + hashCode = (hashCode * 397) ^ (ValueEncoding.GetHashCode()); return hashCode; } } diff --git a/Ical.Net/DataTypes/Occurrence.cs b/Ical.Net/DataTypes/Occurrence.cs index e3f3b2ff0..d8c8ddc6a 100644 --- a/Ical.Net/DataTypes/Occurrence.cs +++ b/Ical.Net/DataTypes/Occurrence.cs @@ -41,7 +41,7 @@ public override int GetHashCode() { unchecked { - return ((Period?.GetHashCode() ?? 0) * 397) ^ (Source?.GetHashCode() ?? 0); + return ((Period.GetHashCode()) * 397) ^ (Source.GetHashCode()); } } diff --git a/Ical.Net/DataTypes/PeriodList.cs b/Ical.Net/DataTypes/PeriodList.cs index b90bacc11..9d0ddbb79 100644 --- a/Ical.Net/DataTypes/PeriodList.cs +++ b/Ical.Net/DataTypes/PeriodList.cs @@ -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/DataTypes/Trigger.cs b/Ical.Net/DataTypes/Trigger.cs index becbe6aa1..1fc0248e5 100644 --- a/Ical.Net/DataTypes/Trigger.cs +++ b/Ical.Net/DataTypes/Trigger.cs @@ -119,7 +119,7 @@ public override int GetHashCode() { var hashCode = _mDateTime?.GetHashCode() ?? 0; hashCode = (hashCode * 397) ^ _mDuration.GetHashCode(); - hashCode = (hashCode * 397) ^ _mRelated?.GetHashCode() ?? 0; + hashCode = (hashCode * 397) ^ _mRelated.GetHashCode(); return hashCode; } } diff --git a/Ical.Net/Evaluation/RecurrencePatternEvaluator.cs b/Ical.Net/Evaluation/RecurrencePatternEvaluator.cs index 8b07df17f..a07ca11a8 100644 --- a/Ical.Net/Evaluation/RecurrencePatternEvaluator.cs +++ b/Ical.Net/Evaluation/RecurrencePatternEvaluator.cs @@ -100,10 +100,10 @@ private RecurrencePattern ProcessRecurrencePattern(CalDateTime referenceDate) // Pre-order those BY values that don't allow for negative values. Those with negative values can only // be ordered once the individual position is known. - if (r.BySecond?.Count > 0) r.BySecond = r.BySecond.OrderBy(x => x).ToList(); - if (r.ByMinute?.Count > 0) r.ByMinute = r.ByMinute.OrderBy(x => x).ToList(); - if (r.ByHour?.Count > 0) r.ByHour = r.ByHour.OrderBy(x => x).ToList(); - if (r.ByMonth?.Count > 0) r.ByMonth = r.ByMonth.OrderBy(x => x).ToList(); + if (r.BySecond.Count > 0) r.BySecond = r.BySecond.OrderBy(x => x).ToList(); + if (r.ByMinute.Count > 0) r.ByMinute = r.ByMinute.OrderBy(x => x).ToList(); + if (r.ByHour.Count > 0) r.ByHour = r.ByHour.OrderBy(x => x).ToList(); + if (r.ByMonth.Count > 0) r.ByMonth = r.ByMonth.OrderBy(x => x).ToList(); return r; } diff --git a/Ical.Net/Serialization/ComponentSerializer.cs b/Ical.Net/Serialization/ComponentSerializer.cs index d101c70ec..d606e8658 100644 --- a/Ical.Net/Serialization/ComponentSerializer.cs +++ b/Ical.Net/Serialization/ComponentSerializer.cs @@ -45,7 +45,7 @@ public ComponentSerializer(SerializationContext ctx) : base(ctx) { } foreach (var p in properties) { // Get a serializer for each property. - var serializer = sf?.Build(p.GetType(), SerializationContext) as IStringSerializer; + var serializer = sf.Build(p.GetType(), SerializationContext) as IStringSerializer; var val = serializer?.SerializeToString(p); if (val != null) sb.Append(val); } diff --git a/Ical.Net/Serialization/DataTypes/DataTypeSerializer.cs b/Ical.Net/Serialization/DataTypes/DataTypeSerializer.cs index 35830a1ed..85ef5cc09 100644 --- a/Ical.Net/Serialization/DataTypes/DataTypeSerializer.cs +++ b/Ical.Net/Serialization/DataTypes/DataTypeSerializer.cs @@ -23,7 +23,7 @@ protected DataTypeSerializer(SerializationContext ctx) : base(ctx) { } return null; } - if (SerializationContext?.Peek() is ICalendarObject associatedObject) + if (SerializationContext.Peek() is ICalendarObject associatedObject) { dt.AssociatedObject = associatedObject; } diff --git a/Ical.Net/Serialization/DataTypes/DateTimeSerializer.cs b/Ical.Net/Serialization/DataTypes/DateTimeSerializer.cs index dd82b6555..68b010bfa 100644 --- a/Ical.Net/Serialization/DataTypes/DateTimeSerializer.cs +++ b/Ical.Net/Serialization/DataTypes/DateTimeSerializer.cs @@ -68,7 +68,7 @@ public DateTimeSerializer(SerializationContext ctx) : base(ctx) { } var value = tr.ReadToEnd(); // CalDateTime is defined as the Target type - var parent = SerializationContext?.Peek(); + var parent = SerializationContext.Peek(); // The associated object is an ICalendarObject of type CalendarProperty // that contains any timezone ("TZID" property) deserialized in a prior step diff --git a/Ical.Net/Serialization/DataTypes/EncodableDataTypeSerializer.cs b/Ical.Net/Serialization/DataTypes/EncodableDataTypeSerializer.cs index 5915e97a4..972b06497 100644 --- a/Ical.Net/Serialization/DataTypes/EncodableDataTypeSerializer.cs +++ b/Ical.Net/Serialization/DataTypes/EncodableDataTypeSerializer.cs @@ -28,9 +28,8 @@ protected EncodableDataTypeSerializer(SerializationContext ctx) : base(ctx) { } // Return the value in the current encoding var encodingStack = GetService(); - return encodingStack?.Current == null - ? value - : Encode(dt, encodingStack.Current.GetBytes(value)); + + return Encode(dt, encodingStack.Current.GetBytes(value)); } protected string? Encode(IEncodableDataType dt, byte[]? data) @@ -44,11 +43,11 @@ protected EncodableDataTypeSerializer(SerializationContext ctx) : base(ctx) { } { // Default to the current encoding var encodingStack = GetService(); - return encodingStack?.Current.GetString(data); + return encodingStack.Current.GetString(data); } var encodingProvider = GetService(); - return encodingProvider?.Encode(dt.Encoding, data); + return encodingProvider.Encode(dt.Encoding, data); } protected string? Decode(IEncodableDataType dt, string value) @@ -66,7 +65,7 @@ protected EncodableDataTypeSerializer(SerializationContext ctx) : base(ctx) { } // Default to the current encoding var encodingStack = GetService(); - return encodingStack?.Current.GetString(data); + return encodingStack.Current.GetString(data); } protected byte[]? DecodeData(IEncodableDataType dt, string? value) @@ -80,10 +79,10 @@ protected EncodableDataTypeSerializer(SerializationContext ctx) : base(ctx) { } { // Default to the current encoding var encodingStack = GetService(); - return encodingStack?.Current.GetBytes(value); + return encodingStack.Current.GetBytes(value); } var encodingProvider = GetService(); - return encodingProvider?.DecodeData(dt.Encoding, value); + return encodingProvider.DecodeData(dt.Encoding, value); } } diff --git a/Ical.Net/Serialization/DataTypes/EnumSerializer.cs b/Ical.Net/Serialization/DataTypes/EnumSerializer.cs index 5507adf6c..10d8b9183 100644 --- a/Ical.Net/Serialization/DataTypes/EnumSerializer.cs +++ b/Ical.Net/Serialization/DataTypes/EnumSerializer.cs @@ -30,7 +30,7 @@ public EnumSerializer(Type enumType, SerializationContext ctx) : base(ctx) { try { - if (SerializationContext?.Peek() is ICalendarObject calObject) + if (SerializationContext.Peek() is ICalendarObject calObject) { // Encode the value as needed. var dt = new EncodableDataType @@ -53,7 +53,7 @@ public EnumSerializer(Type enumType, SerializationContext ctx) : base(ctx) try { - if (SerializationContext?.Peek() is ICalendarObject obj) + if (SerializationContext.Peek() is ICalendarObject obj) { // Decode the value, if necessary! var dt = new EncodableDataType diff --git a/Ical.Net/Serialization/DataTypes/IntegerSerializer.cs b/Ical.Net/Serialization/DataTypes/IntegerSerializer.cs index 0bf785757..84814a603 100644 --- a/Ical.Net/Serialization/DataTypes/IntegerSerializer.cs +++ b/Ical.Net/Serialization/DataTypes/IntegerSerializer.cs @@ -24,7 +24,7 @@ public IntegerSerializer(SerializationContext ctx) : base(ctx) { } { var i = Convert.ToInt32(obj); - if (SerializationContext?.Peek() is ICalendarObject calObject) + if (SerializationContext.Peek() is ICalendarObject calObject) { // Encode the value as needed. var dt = new EncodableDataType @@ -47,7 +47,7 @@ public IntegerSerializer(SerializationContext ctx) : base(ctx) { } try { - if (SerializationContext?.Peek() is ICalendarObject obj) + if (SerializationContext.Peek() is ICalendarObject obj) { // Decode the value, if necessary! var dt = new EncodableDataType diff --git a/Ical.Net/Serialization/DataTypes/PeriodSerializer.cs b/Ical.Net/Serialization/DataTypes/PeriodSerializer.cs index b2f19dce4..351c99379 100644 --- a/Ical.Net/Serialization/DataTypes/PeriodSerializer.cs +++ b/Ical.Net/Serialization/DataTypes/PeriodSerializer.cs @@ -29,7 +29,7 @@ public PeriodSerializer(SerializationContext ctx) : base(ctx) { } } // Push the period onto the serialization context stack - SerializationContext?.Push(p); + SerializationContext.Push(p); try { @@ -71,7 +71,7 @@ public PeriodSerializer(SerializationContext ctx) : base(ctx) { } finally { // Pop the period off the serialization context stack - SerializationContext?.Pop(); + SerializationContext.Pop(); } } diff --git a/Ical.Net/Serialization/DataTypes/RequestStatusSerializer.cs b/Ical.Net/Serialization/DataTypes/RequestStatusSerializer.cs index 067deca13..c40a31563 100644 --- a/Ical.Net/Serialization/DataTypes/RequestStatusSerializer.cs +++ b/Ical.Net/Serialization/DataTypes/RequestStatusSerializer.cs @@ -40,7 +40,7 @@ public RequestStatusSerializer(SerializationContext ctx) : base(ctx) { } try { var factory = GetService(); - var serializer = factory?.Build(typeof(StatusCode), SerializationContext) as IStringSerializer; + var serializer = factory.Build(typeof(StatusCode), SerializationContext) as IStringSerializer; if (serializer == null) { return null; @@ -60,7 +60,7 @@ public RequestStatusSerializer(SerializationContext ctx) : base(ctx) { } finally { // Pop the object off the serialization stack - SerializationContext?.Pop(); + SerializationContext.Pop(); } } catch @@ -128,7 +128,7 @@ public RequestStatusSerializer(SerializationContext ctx) : base(ctx) { } finally { // Pop the object off the serialization stack - SerializationContext?.Pop(); + SerializationContext.Pop(); } return null; } diff --git a/Ical.Net/Serialization/DataTypes/StringSerializer.cs b/Ical.Net/Serialization/DataTypes/StringSerializer.cs index d74b322d2..736d24112 100644 --- a/Ical.Net/Serialization/DataTypes/StringSerializer.cs +++ b/Ical.Net/Serialization/DataTypes/StringSerializer.cs @@ -81,7 +81,7 @@ public StringSerializer(SerializationContext ctx) : base(ctx) { } values.AddRange(from object child in enumerable select child.ToString()); } - if (SerializationContext?.Peek() is ICalendarObject co) + if (SerializationContext.Peek() is ICalendarObject co) { // Encode the string as needed. var dt = new EncodableDataType @@ -125,18 +125,15 @@ public StringSerializer(SerializationContext ctx) : base(ctx) { } // Ensure SerializationContext is not null before accessing Peek() var context = SerializationContext; - if (context?.Peek() is ICalendarProperty cp) + if (context.Peek() is ICalendarProperty cp) { var dataTypeMapper = GetService(); - if (dataTypeMapper != null) - { - serializeAsList = dataTypeMapper.GetPropertyAllowsMultipleValues(cp); - } + serializeAsList = dataTypeMapper.GetPropertyAllowsMultipleValues(cp); } var dt = new EncodableDataType { - AssociatedObject = context?.Peek() as ICalendarObject + AssociatedObject = context.Peek() as ICalendarObject }; var encodedValues = serializeAsList ? UnescapedCommas.Split(value) : new[] { value }; diff --git a/Ical.Net/Serialization/DataTypes/TriggerSerializer.cs b/Ical.Net/Serialization/DataTypes/TriggerSerializer.cs index 39c292694..e536d23ee 100644 --- a/Ical.Net/Serialization/DataTypes/TriggerSerializer.cs +++ b/Ical.Net/Serialization/DataTypes/TriggerSerializer.cs @@ -28,7 +28,7 @@ public TriggerSerializer(SerializationContext ctx) : base(ctx) { } } // Push the trigger onto the serialization stack - SerializationContext?.Push(t); + SerializationContext.Push(t); try { var factory = GetService(); @@ -52,7 +52,7 @@ public TriggerSerializer(SerializationContext ctx) : base(ctx) { } finally { // Pop the trigger off the serialization stack - SerializationContext?.Pop(); + SerializationContext.Pop(); } } catch @@ -73,7 +73,7 @@ public TriggerSerializer(SerializationContext ctx) : base(ctx) { } } // Push the trigger onto the serialization stack - SerializationContext?.Push(t); + SerializationContext.Push(t); try { // Decode the value as needed @@ -82,7 +82,8 @@ public TriggerSerializer(SerializationContext ctx) : base(ctx) { } if (value == null) return null; // Set the trigger relation - if (t.Parameters.ContainsKey("RELATED") && t.Parameters.Get("RELATED").Equals("END")) + var relatedParameter = t.Parameters.Get("RELATED"); + if (relatedParameter is not null && relatedParameter.Equals("END")) { t.Related = TriggerRelation.End; } @@ -113,7 +114,7 @@ public TriggerSerializer(SerializationContext ctx) : base(ctx) { } finally { // Pop the trigger off the serialization stack - SerializationContext?.Pop(); + SerializationContext.Pop(); } } } diff --git a/Ical.Net/Serialization/DataTypes/UriSerializer.cs b/Ical.Net/Serialization/DataTypes/UriSerializer.cs index 104b3fdcc..34dca5cf0 100644 --- a/Ical.Net/Serialization/DataTypes/UriSerializer.cs +++ b/Ical.Net/Serialization/DataTypes/UriSerializer.cs @@ -25,7 +25,7 @@ public UriSerializer(SerializationContext ctx) : base(ctx) { } return null; } - if (SerializationContext?.Peek() is ICalendarObject co) + if (SerializationContext.Peek() is ICalendarObject co) { var dt = new EncodableDataType { @@ -45,7 +45,7 @@ public UriSerializer(SerializationContext ctx) : base(ctx) { } var value = tr.ReadToEnd(); - if (SerializationContext?.Peek() is ICalendarObject co) + if (SerializationContext.Peek() is ICalendarObject co) { var dt = new EncodableDataType { diff --git a/Ical.Net/Serialization/EncodingProvider.cs b/Ical.Net/Serialization/EncodingProvider.cs index 67ab601a7..fb55c35c9 100644 --- a/Ical.Net/Serialization/EncodingProvider.cs +++ b/Ical.Net/Serialization/EncodingProvider.cs @@ -5,6 +5,7 @@ #nullable enable using System; +using System.Runtime.Serialization; using System.Text; namespace Ical.Net.Serialization; @@ -19,7 +20,7 @@ internal class EncodingProvider : IEncodingProvider /// /// Represents a method that encodes a byte array into a string. /// - public delegate string? EncoderDelegate(byte[] data); + public delegate string EncoderDelegate(byte[] data); /// /// Represents a method that decodes a string into a byte array. @@ -60,14 +61,14 @@ protected byte[] DecodeBase64(string value) /// Gets a decoder for the specified encoding. /// /// - /// - protected virtual DecoderDelegate? GetDecoderFor(string encoding) + /// Decoder not supported. + protected virtual DecoderDelegate GetDecoderFor(string encoding) { return encoding.ToUpper() switch { "8BIT" => Decode8Bit, "BASE64" => DecodeBase64, - _ => null, + _ => throw new SerializationException($"Encoding '{encoding}' is not supported.") }; } @@ -96,14 +97,14 @@ protected string EncodeBase64(byte[] data) /// Gets an encoder for the specified encoding. ///
/// - /// - protected virtual EncoderDelegate? GetEncoderFor(string encoding) + /// Encoder not supported. + protected virtual EncoderDelegate GetEncoderFor(string encoding) { return encoding.ToUpper() switch { "8BIT" => Encode8Bit, "BASE64" => EncodeBase64, - _ => null + _ => throw new SerializationException($"Encoding '{encoding}' is not supported.") }; } @@ -113,10 +114,10 @@ protected string EncodeBase64(byte[] data) /// /// /// A string representation of using the specified , or if encoding fails. - public string? Encode(string encoding, byte[] data) + public string Encode(string encoding, byte[] data) { var encoder = GetEncoderFor(encoding); - return encoder?.Invoke(data); + return encoder.Invoke(data); } /// @@ -126,13 +127,13 @@ protected string EncodeBase64(byte[] data) /// /// A string representation of using the specified . /// Base64 string is invalid. - public string? DecodeString(string encoding, string value) + public string DecodeString(string encoding, string value) { var data = DecodeData(encoding, value); // Decode the string into the current encoding - var encodingStack = _mSerializationContext.GetService(typeof(EncodingStack)) as EncodingStack; - return data != null ? encodingStack?.Current.GetString(data) : null; + var encodingStack = (EncodingStack) _mSerializationContext.GetService(typeof(EncodingStack)); + return encodingStack.Current.GetString(data); } /// @@ -141,9 +142,9 @@ protected string EncodeBase64(byte[] data) /// /// /// A string representation of using the specified , or when decoding fails. - public byte[]? DecodeData(string encoding, string value) + public byte[] DecodeData(string encoding, string value) { var decoder = GetDecoderFor(encoding); - return decoder?.Invoke(value); + return decoder.Invoke(value); } } diff --git a/Ical.Net/Serialization/GenericListSerializer.cs b/Ical.Net/Serialization/GenericListSerializer.cs index ae9899f82..1775294f8 100644 --- a/Ical.Net/Serialization/GenericListSerializer.cs +++ b/Ical.Net/Serialization/GenericListSerializer.cs @@ -32,7 +32,7 @@ public GenericListSerializer(Type objectType) private MethodInfo? _addMethodInfo; public override object? Deserialize(TextReader tr) { - var p = SerializationContext?.Peek() as ICalendarProperty; + var p = SerializationContext.Peek() as ICalendarProperty; if (p == null) { return null; @@ -47,7 +47,7 @@ public GenericListSerializer(Type objectType) // Get a serializer for the inner type var sf = GetService(); - var stringSerializer = sf?.Build(_innerType, SerializationContext) as IStringSerializer; + var stringSerializer = sf.Build(_innerType, SerializationContext) as IStringSerializer; if (stringSerializer == null) { return null; diff --git a/Ical.Net/Serialization/IEncodingProvider.cs b/Ical.Net/Serialization/IEncodingProvider.cs index 2e353d080..6d48e950f 100644 --- a/Ical.Net/Serialization/IEncodingProvider.cs +++ b/Ical.Net/Serialization/IEncodingProvider.cs @@ -8,7 +8,7 @@ namespace Ical.Net.Serialization; internal interface IEncodingProvider { - string Encode(string encoding, byte[] data); - string DecodeString(string encoding, string value); - byte[] DecodeData(string encoding, string value); + string? Encode(string encoding, byte[] data); + string? DecodeString(string encoding, string value); + byte[]? DecodeData(string encoding, string value); } diff --git a/Ical.Net/Serialization/ISerializer.cs b/Ical.Net/Serialization/ISerializer.cs index f72c4e7bd..47a2d38f8 100644 --- a/Ical.Net/Serialization/ISerializer.cs +++ b/Ical.Net/Serialization/ISerializer.cs @@ -12,7 +12,7 @@ namespace Ical.Net.Serialization; public interface ISerializer : IServiceProvider { - SerializationContext? SerializationContext { get; set; } + SerializationContext SerializationContext { get; set; } Type TargetType { get; } void Serialize(object obj, Stream stream, Encoding encoding); diff --git a/Ical.Net/Serialization/PropertySerializer.cs b/Ical.Net/Serialization/PropertySerializer.cs index 4edf76b3e..de4e5fada 100644 --- a/Ical.Net/Serialization/PropertySerializer.cs +++ b/Ical.Net/Serialization/PropertySerializer.cs @@ -31,12 +31,11 @@ public PropertySerializer(SerializationContext ctx) : base(ctx) { } } // Push this object on the serialization context. - SerializationContext?.Push(prop); + SerializationContext.Push(prop); // Get a serializer factory that we can use to serialize // the property and parameter values var sf = GetService(); - if (sf == null) return null; var result = new StringBuilder(); foreach (var v in prop.Values.Where(value => value != null)) @@ -45,7 +44,7 @@ public PropertySerializer(SerializationContext ctx) : base(ctx) { } } // Pop the object off the serialization context. - SerializationContext?.Pop(); + SerializationContext.Pop(); return result.ToString(); } diff --git a/Ical.Net/Serialization/SerializerBase.cs b/Ical.Net/Serialization/SerializerBase.cs index d238b7bea..dd94c25a6 100644 --- a/Ical.Net/Serialization/SerializerBase.cs +++ b/Ical.Net/Serialization/SerializerBase.cs @@ -12,7 +12,7 @@ namespace Ical.Net.Serialization; public abstract class SerializerBase : IStringSerializer { - private SerializationContext? _mSerializationContext; + private SerializationContext _mSerializationContext; protected SerializerBase() { @@ -24,7 +24,7 @@ protected SerializerBase(SerializationContext ctx) _mSerializationContext = ctx; } - public virtual SerializationContext? SerializationContext // NOSONAR: auto-property + public virtual SerializationContext SerializationContext // NOSONAR: auto-property { get => _mSerializationContext; set => _mSerializationContext = value; @@ -38,9 +38,9 @@ protected SerializerBase(SerializationContext ctx) { using var sr = new StreamReader(stream, encoding); var encodingStack = GetService(); - encodingStack?.Push(encoding); + encodingStack.Push(encoding); var obj = Deserialize(sr); - encodingStack?.Pop(); + encodingStack.Pop(); return obj; } @@ -54,40 +54,40 @@ public void Serialize(object obj, Stream stream, Encoding encoding) using var sw = new StreamWriter(stream, encoding, defaultBuffer, leaveOpen: true); // Push the current object onto the serialization stack - SerializationContext?.Push(obj); + SerializationContext.Push(obj); // Push the current encoding on the stack var encodingStack = GetService(); - encodingStack?.Push(encoding); + encodingStack.Push(encoding); sw.Write(SerializeToString(obj)); // Pop the current encoding off the serialization stack - encodingStack?.Pop(); + encodingStack.Pop(); // Pop the current object off the serialization stack - SerializationContext?.Pop(); + SerializationContext.Pop(); } - public virtual object? GetService(Type serviceType) => SerializationContext?.GetService(serviceType); + public virtual object GetService(Type serviceType) => SerializationContext.GetService(serviceType); - public virtual object? GetService(string name) => SerializationContext?.GetService(name); + public virtual object GetService(string name) => SerializationContext.GetService(name); - public virtual T? GetService() - => SerializationContext != null ? SerializationContext.GetService() : default; + public virtual T GetService() + => SerializationContext.GetService(); - public virtual T? GetService(string name) => - SerializationContext != null ? SerializationContext.GetService(name) : default; + public virtual T GetService(string name) => + SerializationContext.GetService(name); public void SetService(string name, object obj) - => SerializationContext?.SetService(name, obj); + => SerializationContext.SetService(name, obj); public void SetService(object obj) - => SerializationContext?.SetService(obj); + => SerializationContext.SetService(obj); public void RemoveService(Type type) - => SerializationContext?.RemoveService(type); + => SerializationContext.RemoveService(type); public void RemoveService(string name) - => SerializationContext?.RemoveService(name); + => SerializationContext.RemoveService(name); } diff --git a/Ical.Net/Serialization/SimpleDeserializer.cs b/Ical.Net/Serialization/SimpleDeserializer.cs index 17e4683ff..5b36147ae 100644 --- a/Ical.Net/Serialization/SimpleDeserializer.cs +++ b/Ical.Net/Serialization/SimpleDeserializer.cs @@ -77,15 +77,19 @@ private static string BuildContentLineRegex() public IEnumerable Deserialize(TextReader reader) { var context = new SerializationContext(); - var stack = new Stack(); + var stack = new Stack(); var current = default(ICalendarComponent); foreach (var contentLineString in GetContentLines(reader)) { var contentLine = ParseContentLine(context, contentLineString); if (string.Equals(contentLine.Name, "BEGIN", StringComparison.OrdinalIgnoreCase)) { - stack.Push(current!); // Must push to stack! - current = _componentFactory.Build((string) contentLine.Value); + stack.Push(current); // Must push to stack! + if (contentLine.Value is not string value) + { + throw new SerializationException("Content line value is null or not a string."); + } + current = _componentFactory.Build(value); SerializationUtil.OnDeserializing(current); } else @@ -96,10 +100,15 @@ public IEnumerable Deserialize(TextReader reader) } if (string.Equals(contentLine.Name, "END", StringComparison.OrdinalIgnoreCase)) { - if (!string.Equals((string) contentLine.Value, current.Name, StringComparison.OrdinalIgnoreCase)) + if (contentLine.Value is not string value) { - throw new SerializationException($"Expected 'END:{current.Name}', found 'END:{contentLine.Value}'"); + throw new SerializationException("Content line value is null or not a string."); } + if (!string.Equals(value, current.Name, StringComparison.OrdinalIgnoreCase)) + { + throw new SerializationException($"Expected 'END:{current.Name}', found 'END:{value}'"); + } + SerializationUtil.OnDeserialized(current); var finished = current; current = stack.Pop(); @@ -165,7 +174,7 @@ private static void SetPropertyParameters(CalendarProperty property, CaptureColl private void SetPropertyValue(SerializationContext context, CalendarProperty property, string value) { var type = _dataTypeMapper.GetPropertyMapping(property) ?? typeof(string); - var serializer = (SerializerBase?) _serializerFactory.Build(type, context); + var serializer = _serializerFactory.Build(type, context) as SerializerBase; using var valueReader = new StringReader(value); var propertyValue = serializer?.Deserialize(valueReader); diff --git a/Ical.Net/ServiceProvider.cs b/Ical.Net/ServiceProvider.cs index 7a7542ecf..1cd35eee2 100644 --- a/Ical.Net/ServiceProvider.cs +++ b/Ical.Net/ServiceProvider.cs @@ -15,37 +15,25 @@ public class ServiceProvider private readonly IDictionary _mTypedServices = new Dictionary(); private readonly IDictionary _mNamedServices = new Dictionary(); - public virtual object? GetService(Type serviceType) + public virtual object GetService(Type serviceType) { - _mTypedServices.TryGetValue(serviceType, out var service); + if (!_mTypedServices.TryGetValue(serviceType, out var service)) + throw new ArgumentException($"Service of type {serviceType.FullName} not found.", nameof(serviceType)); + return service; } - public virtual object? GetService(string name) + public virtual object GetService(string name) { - _mNamedServices.TryGetValue(name, out var service); + if (!_mNamedServices.TryGetValue(name, out var service)) + throw new ArgumentException($"Service with name {name} not found.", nameof(name)); + return service; } - public virtual T? GetService() - { - var service = GetService(typeof(T)); - if (service is T svc) - { - return svc; - } - return default(T); - } + public virtual T GetService() => (T) GetService(typeof(T)); - public virtual T? GetService(string name) - { - var service = GetService(name); - if (service is T svc) - { - return svc; - } - return default(T); - } + public virtual T GetService(string name) => (T) GetService(name); public virtual void SetService(string name, object obj) {