From cb287dc948f7aeb64a40300aa2d78364bee2e12a Mon Sep 17 00:00:00 2001 From: Daniel Lerch <36048059+daniel-lerch@users.noreply.github.com> Date: Sat, 24 Aug 2024 18:24:48 +0200 Subject: [PATCH 1/3] Enable nullable reference types for some header related classes --- MimeKit/Header.cs | 77 ++++++++++++++++++++++----- MimeKit/HeaderId.cs | 2 + MimeKit/HeaderList.cs | 33 ++++++++---- MimeKit/HeaderListChangedEventArgs.cs | 6 ++- MimeKit/HeaderListCollection.cs | 6 ++- 5 files changed, 98 insertions(+), 26 deletions(-) diff --git a/MimeKit/Header.cs b/MimeKit/Header.cs index 6a23a9b184..9d61cd6503 100644 --- a/MimeKit/Header.cs +++ b/MimeKit/Header.cs @@ -24,9 +24,20 @@ // THE SOFTWARE. // +#nullable enable + +#if !NET5_0_OR_GREATER +// MemberNotNull attribute is not available below net5.0 +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable. +#endif + + using System; using System.Text; using System.Collections.Generic; +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER +using System.Diagnostics.CodeAnalysis; +#endif using System.Runtime.CompilerServices; using MimeKit.Utils; @@ -53,7 +64,7 @@ public class Header readonly byte[] rawField; bool explicitRawValue; - string textValue; + string? textValue; byte[] rawValue; /// @@ -678,7 +689,7 @@ static byte[] EncodeReceivedHeader (ParserOptions options, FormatOptions format, int count = 0; while (index < rawValue.Length) { - ReceivedTokenValue token = null; + ReceivedTokenValue? token = null; int startIndex = index; if (!ParseUtils.SkipCommentsAndWhiteSpace (rawValue, ref index, rawValue.Length, false) || index >= rawValue.Length) { @@ -1443,6 +1454,9 @@ internal byte[] GetRawValue (FormatOptions format) /// -or- /// is . /// +#if NET5_0_OR_GREATER + [MemberNotNull(nameof(rawValue))] +#endif public void SetValue (FormatOptions format, Encoding encoding, string value) { if (format is null) @@ -1483,6 +1497,9 @@ public void SetValue (FormatOptions format, Encoding encoding, string value) /// -or- /// is . /// +#if NET5_0_OR_GREATER + [MemberNotNull (nameof (rawValue))] +#endif public void SetValue (Encoding encoding, string value) { SetValue (FormatOptions.Default, encoding, value); @@ -1575,7 +1592,7 @@ public void SetRawValue (byte[] value) OnChanged (); } - internal event EventHandler Changed; + internal event EventHandler? Changed; void OnChanged () { @@ -1655,7 +1672,11 @@ static bool IsBlank (byte c) return c.IsBlank (); } - internal static unsafe bool TryParse (ParserOptions options, byte* input, int length, bool strict, out Header header) +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER + internal static unsafe bool TryParse (ParserOptions options, byte* input, int length, bool strict, [NotNullWhen(true)] out Header? header) +#else + internal static unsafe bool TryParse (ParserOptions options, byte* input, int length, bool strict, out Header? header) +#endif { byte* inend = input + length; byte* start = input; @@ -1749,7 +1770,11 @@ internal static unsafe bool TryParse (ParserOptions options, byte* input, int le /// and do not specify /// a valid range in the byte array. /// - public static bool TryParse (ParserOptions options, byte[] buffer, int startIndex, int length, out Header header) +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER + public static bool TryParse (ParserOptions options, byte[] buffer, int startIndex, int length, [NotNullWhen (true)] out Header? header) +#else + public static bool TryParse (ParserOptions options, byte[] buffer, int startIndex, int length, out Header? header) +#endif { ParseUtils.ValidateArguments (options, buffer, startIndex, length); @@ -1779,7 +1804,11 @@ public static bool TryParse (ParserOptions options, byte[] buffer, int startInde /// and do not specify /// a valid range in the byte array. /// - public static bool TryParse (byte[] buffer, int startIndex, int length, out Header header) +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER + public static bool TryParse (byte[] buffer, int startIndex, int length, [NotNullWhen (true)] out Header? header) +#else + public static bool TryParse (byte[] buffer, int startIndex, int length, out Header? header) +#endif { return TryParse (ParserOptions.Default, buffer, startIndex, length, out header); } @@ -1803,7 +1832,11 @@ public static bool TryParse (byte[] buffer, int startIndex, int length, out Head /// /// is out of range. /// - public static bool TryParse (ParserOptions options, byte[] buffer, int startIndex, out Header header) +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER + public static bool TryParse (ParserOptions options, byte[] buffer, int startIndex, [NotNullWhen (true)] out Header? header) +#else + public static bool TryParse (ParserOptions options, byte[] buffer, int startIndex, out Header? header) +#endif { ParseUtils.ValidateArguments (options, buffer, startIndex); @@ -1832,7 +1865,11 @@ public static bool TryParse (ParserOptions options, byte[] buffer, int startInde /// /// is out of range. /// - public static bool TryParse (byte[] buffer, int startIndex, out Header header) +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER + public static bool TryParse (byte[] buffer, int startIndex, [NotNullWhen (true)] out Header? header) +#else + public static bool TryParse (byte[] buffer, int startIndex, out Header? header) +#endif { return TryParse (ParserOptions.Default, buffer, startIndex, out header); } @@ -1852,7 +1889,11 @@ public static bool TryParse (byte[] buffer, int startIndex, out Header header) /// -or- /// is . /// - public static bool TryParse (ParserOptions options, byte[] buffer, out Header header) +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER + public static bool TryParse (ParserOptions options, byte[] buffer, [NotNullWhen (true)] out Header? header) +#else + public static bool TryParse (ParserOptions options, byte[] buffer, out Header? header) +#endif { return TryParse (options, buffer, 0, out header); } @@ -1869,7 +1910,11 @@ public static bool TryParse (ParserOptions options, byte[] buffer, out Header he /// /// is . /// - public static bool TryParse (byte[] buffer, out Header header) +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER + public static bool TryParse (byte[] buffer, [NotNullWhen (true)] out Header? header) +#else + public static bool TryParse (byte[] buffer, out Header? header) +#endif { return TryParse (ParserOptions.Default, buffer, out header); } @@ -1889,7 +1934,11 @@ public static bool TryParse (byte[] buffer, out Header header) /// -or- /// is . /// - public static bool TryParse (ParserOptions options, string text, out Header header) +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER + public static bool TryParse (ParserOptions options, string text, [NotNullWhen(true)] out Header? header) +#else + public static bool TryParse (ParserOptions options, string text, out Header? header) +#endif { ParseUtils.ValidateArguments (options, text); @@ -1914,7 +1963,11 @@ public static bool TryParse (ParserOptions options, string text, out Header head /// /// is . /// - public static bool TryParse (string text, out Header header) +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER + public static bool TryParse (string text, [NotNullWhen(true)] out Header? header) +#else + public static bool TryParse (string text, out Header? header) +#endif { return TryParse (ParserOptions.Default, text, out header); } diff --git a/MimeKit/HeaderId.cs b/MimeKit/HeaderId.cs index 6fc40f74ff..33059dc97c 100644 --- a/MimeKit/HeaderId.cs +++ b/MimeKit/HeaderId.cs @@ -24,6 +24,8 @@ // THE SOFTWARE. // +#nullable enable + using System; using System.Collections.Generic; diff --git a/MimeKit/HeaderList.cs b/MimeKit/HeaderList.cs index 0a831e062a..bcf9f30895 100644 --- a/MimeKit/HeaderList.cs +++ b/MimeKit/HeaderList.cs @@ -24,13 +24,18 @@ // THE SOFTWARE. // +#nullable enable + using System; +using System.Collections; +using System.Collections.Generic; +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER +using System.Diagnostics.CodeAnalysis; +#endif using System.IO; using System.Text; using System.Threading; -using System.Collections; using System.Threading.Tasks; -using System.Collections.Generic; using MimeKit.IO; using MimeKit.Utils; @@ -594,7 +599,7 @@ public void Replace (string field, string value) /// /// is . /// - public string this [HeaderId id] { + public string? this [HeaderId id] { get { if (id == HeaderId.Unknown) throw new ArgumentOutOfRangeException (nameof (id)); @@ -634,7 +639,7 @@ public string this [HeaderId id] { /// -or- /// is . /// - public string this [string field] { + public string? this [string field] { get { if (field is null) throw new ArgumentNullException (nameof (field)); @@ -1205,24 +1210,32 @@ IEnumerator IEnumerable.GetEnumerator () #endregion - internal event EventHandler Changed; + internal event EventHandler? Changed; - void HeaderChanged (object sender, EventArgs args) + void HeaderChanged (object? sender, EventArgs args) { - OnChanged ((Header) sender, HeaderListChangedAction.Changed); + OnChanged (sender as Header, HeaderListChangedAction.Changed); } - void OnChanged (Header header, HeaderListChangedAction action) + void OnChanged (Header? header, HeaderListChangedAction action) { Changed?.Invoke (this, new HeaderListChangedEventArgs (header, action)); } - internal bool TryGetHeader (HeaderId id, out Header header) +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER + internal bool TryGetHeader (HeaderId id, [NotNullWhen(true)] out Header? header) +#else + internal bool TryGetHeader (HeaderId id, out Header? header) +#endif { return table.TryGetValue (id.ToHeaderName (), out header); } - internal bool TryGetHeader (string field, out Header header) +#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER + internal bool TryGetHeader (string field, [NotNullWhen (true)] out Header? header) +#else + internal bool TryGetHeader (string field, out Header? header) +#endif { return table.TryGetValue (field, out header); } diff --git a/MimeKit/HeaderListChangedEventArgs.cs b/MimeKit/HeaderListChangedEventArgs.cs index a2781afa09..159cc62b76 100644 --- a/MimeKit/HeaderListChangedEventArgs.cs +++ b/MimeKit/HeaderListChangedEventArgs.cs @@ -24,6 +24,8 @@ // THE SOFTWARE. // +#nullable enable + using System; namespace MimeKit { @@ -57,7 +59,7 @@ public enum HeaderListChangedAction { class HeaderListChangedEventArgs : EventArgs { - internal HeaderListChangedEventArgs (Header header, HeaderListChangedAction action) + internal HeaderListChangedEventArgs (Header? header, HeaderListChangedAction action) { Header = header; Action = action; @@ -67,7 +69,7 @@ public HeaderListChangedAction Action { get; private set; } - public Header Header { + public Header? Header { get; private set; } } diff --git a/MimeKit/HeaderListCollection.cs b/MimeKit/HeaderListCollection.cs index 420cb4d112..ee48b72cdc 100644 --- a/MimeKit/HeaderListCollection.cs +++ b/MimeKit/HeaderListCollection.cs @@ -24,6 +24,8 @@ // THE SOFTWARE. // +#nullable enable + using System; using System.Collections; using System.Collections.Generic; @@ -236,14 +238,14 @@ IEnumerator IEnumerable.GetEnumerator () return GetEnumerator (); } - internal event EventHandler Changed; + internal event EventHandler? Changed; void OnChanged () { Changed?.Invoke (this, EventArgs.Empty); } - void OnGroupChanged (object sender, HeaderListChangedEventArgs e) + void OnGroupChanged (object? sender, HeaderListChangedEventArgs e) { OnChanged (); } From e4d1b7025714e8fedb02ae25d37be1769613452d Mon Sep 17 00:00:00 2001 From: Jeffrey Stedfast Date: Tue, 27 Aug 2024 11:13:16 -0400 Subject: [PATCH 2/3] Remove unnecessary #if/#else/#endif --- MimeKit/Header.cs | 56 ++++------------------------------------------- 1 file changed, 4 insertions(+), 52 deletions(-) diff --git a/MimeKit/Header.cs b/MimeKit/Header.cs index 9d61cd6503..8d28196268 100644 --- a/MimeKit/Header.cs +++ b/MimeKit/Header.cs @@ -26,18 +26,10 @@ #nullable enable -#if !NET5_0_OR_GREATER -// MemberNotNull attribute is not available below net5.0 -#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable. -#endif - - using System; using System.Text; using System.Collections.Generic; -#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER using System.Diagnostics.CodeAnalysis; -#endif using System.Runtime.CompilerServices; using MimeKit.Utils; @@ -1454,9 +1446,7 @@ internal byte[] GetRawValue (FormatOptions format) /// -or- /// is . /// -#if NET5_0_OR_GREATER - [MemberNotNull(nameof(rawValue))] -#endif + [MemberNotNull (nameof (rawValue))] public void SetValue (FormatOptions format, Encoding encoding, string value) { if (format is null) @@ -1497,9 +1487,7 @@ public void SetValue (FormatOptions format, Encoding encoding, string value) /// -or- /// is . /// -#if NET5_0_OR_GREATER [MemberNotNull (nameof (rawValue))] -#endif public void SetValue (Encoding encoding, string value) { SetValue (FormatOptions.Default, encoding, value); @@ -1672,11 +1660,7 @@ static bool IsBlank (byte c) return c.IsBlank (); } -#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER - internal static unsafe bool TryParse (ParserOptions options, byte* input, int length, bool strict, [NotNullWhen(true)] out Header? header) -#else - internal static unsafe bool TryParse (ParserOptions options, byte* input, int length, bool strict, out Header? header) -#endif + internal static unsafe bool TryParse (ParserOptions options, byte* input, int length, bool strict, [NotNullWhen (true)] out Header? header) { byte* inend = input + length; byte* start = input; @@ -1770,11 +1754,7 @@ internal static unsafe bool TryParse (ParserOptions options, byte* input, int le /// and do not specify /// a valid range in the byte array. /// -#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER public static bool TryParse (ParserOptions options, byte[] buffer, int startIndex, int length, [NotNullWhen (true)] out Header? header) -#else - public static bool TryParse (ParserOptions options, byte[] buffer, int startIndex, int length, out Header? header) -#endif { ParseUtils.ValidateArguments (options, buffer, startIndex, length); @@ -1804,11 +1784,7 @@ public static bool TryParse (ParserOptions options, byte[] buffer, int startInde /// and do not specify /// a valid range in the byte array. /// -#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER public static bool TryParse (byte[] buffer, int startIndex, int length, [NotNullWhen (true)] out Header? header) -#else - public static bool TryParse (byte[] buffer, int startIndex, int length, out Header? header) -#endif { return TryParse (ParserOptions.Default, buffer, startIndex, length, out header); } @@ -1832,11 +1808,7 @@ public static bool TryParse (byte[] buffer, int startIndex, int length, out Head /// /// is out of range. /// -#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER public static bool TryParse (ParserOptions options, byte[] buffer, int startIndex, [NotNullWhen (true)] out Header? header) -#else - public static bool TryParse (ParserOptions options, byte[] buffer, int startIndex, out Header? header) -#endif { ParseUtils.ValidateArguments (options, buffer, startIndex); @@ -1865,11 +1837,7 @@ public static bool TryParse (ParserOptions options, byte[] buffer, int startInde /// /// is out of range. /// -#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER public static bool TryParse (byte[] buffer, int startIndex, [NotNullWhen (true)] out Header? header) -#else - public static bool TryParse (byte[] buffer, int startIndex, out Header? header) -#endif { return TryParse (ParserOptions.Default, buffer, startIndex, out header); } @@ -1889,11 +1857,7 @@ public static bool TryParse (byte[] buffer, int startIndex, out Header? header) /// -or- /// is . /// -#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER public static bool TryParse (ParserOptions options, byte[] buffer, [NotNullWhen (true)] out Header? header) -#else - public static bool TryParse (ParserOptions options, byte[] buffer, out Header? header) -#endif { return TryParse (options, buffer, 0, out header); } @@ -1910,11 +1874,7 @@ public static bool TryParse (ParserOptions options, byte[] buffer, out Header? h /// /// is . /// -#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER public static bool TryParse (byte[] buffer, [NotNullWhen (true)] out Header? header) -#else - public static bool TryParse (byte[] buffer, out Header? header) -#endif { return TryParse (ParserOptions.Default, buffer, out header); } @@ -1934,11 +1894,7 @@ public static bool TryParse (byte[] buffer, out Header? header) /// -or- /// is . /// -#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER - public static bool TryParse (ParserOptions options, string text, [NotNullWhen(true)] out Header? header) -#else - public static bool TryParse (ParserOptions options, string text, out Header? header) -#endif + public static bool TryParse (ParserOptions options, string text, [NotNullWhen (true)] out Header? header) { ParseUtils.ValidateArguments (options, text); @@ -1963,11 +1919,7 @@ public static bool TryParse (ParserOptions options, string text, out Header? hea /// /// is . /// -#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER - public static bool TryParse (string text, [NotNullWhen(true)] out Header? header) -#else - public static bool TryParse (string text, out Header? header) -#endif + public static bool TryParse (string text, [NotNullWhen (true)] out Header? header) { return TryParse (ParserOptions.Default, text, out header); } From 92314e0000be4e98b45f54beb3075c587e405b8b Mon Sep 17 00:00:00 2001 From: Jeffrey Stedfast Date: Tue, 27 Aug 2024 11:15:44 -0400 Subject: [PATCH 3/3] Update HeaderList.cs --- MimeKit/HeaderList.cs | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/MimeKit/HeaderList.cs b/MimeKit/HeaderList.cs index bcf9f30895..30a27b519d 100644 --- a/MimeKit/HeaderList.cs +++ b/MimeKit/HeaderList.cs @@ -27,15 +27,13 @@ #nullable enable using System; -using System.Collections; -using System.Collections.Generic; -#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER -using System.Diagnostics.CodeAnalysis; -#endif using System.IO; using System.Text; using System.Threading; +using System.Collections; using System.Threading.Tasks; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using MimeKit.IO; using MimeKit.Utils; @@ -1222,20 +1220,12 @@ void OnChanged (Header? header, HeaderListChangedAction action) Changed?.Invoke (this, new HeaderListChangedEventArgs (header, action)); } -#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER - internal bool TryGetHeader (HeaderId id, [NotNullWhen(true)] out Header? header) -#else - internal bool TryGetHeader (HeaderId id, out Header? header) -#endif + internal bool TryGetHeader (HeaderId id, [NotNullWhen (true)] out Header? header) { return table.TryGetValue (id.ToHeaderName (), out header); } -#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_0_OR_GREATER internal bool TryGetHeader (string field, [NotNullWhen (true)] out Header? header) -#else - internal bool TryGetHeader (string field, out Header? header) -#endif { return table.TryGetValue (field, out header); }