From 6b9e4bdcd251812f743ef83c5d5e0a309bbd142b Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Fri, 18 Oct 2024 17:28:24 +0200 Subject: [PATCH 01/97] fix: add NotNull attribute to MustNotBeNull Signed-off-by: Kenny Pflug --- .../Issues/Issue72.cs | 29 +++++++++++++++++++ Code/Light.GuardClauses.sln.DotSettings | 1 + .../Check.CommonAssertions.cs | 5 ++-- 3 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 Code/Light.GuardClauses.Tests/Issues/Issue72.cs diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72.cs new file mode 100644 index 00000000..0cda17c6 --- /dev/null +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72.cs @@ -0,0 +1,29 @@ +using System; +using Xunit; + +#nullable enable + +namespace Light.GuardClauses.Tests.Issues; + +public static class Issue72 +{ + [Fact] + public static void MustNotBeNullDoesNotPropagate() + { + _ = TestMustNotBeNull("foo"); + _ = TestMustNotBeNullWithDelegate("foo"); + return; + + static int TestMustNotBeNull(string? input) + { + Check.MustNotBeNull(input); + return input.Length; + } + + static int TestMustNotBeNullWithDelegate(string? input) + { + input.MustNotBeNull(() => new Exception()); + return input.Length; + } + } +} \ No newline at end of file diff --git a/Code/Light.GuardClauses.sln.DotSettings b/Code/Light.GuardClauses.sln.DotSettings index 14c11e83..47d8c240 100644 --- a/Code/Light.GuardClauses.sln.DotSettings +++ b/Code/Light.GuardClauses.sln.DotSettings @@ -249,6 +249,7 @@ True True True + True True True True diff --git a/Code/Light.GuardClauses/Check.CommonAssertions.cs b/Code/Light.GuardClauses/Check.CommonAssertions.cs index 73a6379a..e54a1973 100644 --- a/Code/Light.GuardClauses/Check.CommonAssertions.cs +++ b/Code/Light.GuardClauses/Check.CommonAssertions.cs @@ -3,6 +3,7 @@ using System.Runtime.CompilerServices; using JetBrains.Annotations; using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; namespace Light.GuardClauses; @@ -20,7 +21,7 @@ public static partial class Check /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static T MustNotBeNull([ValidatedNotNull, NoEnumeration] this T? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : class + public static T MustNotBeNull([NotNull, ValidatedNotNull, NoEnumeration] this T? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : class { if (parameter is null) Throw.ArgumentNull(parameterName, message); @@ -35,7 +36,7 @@ public static T MustNotBeNull([ValidatedNotNull, NoEnumeration] this T? param /// Your custom exception thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] - public static T MustNotBeNull([ValidatedNotNull, NoEnumeration] this T? parameter, Func exceptionFactory) where T : class + public static T MustNotBeNull([NotNull, ValidatedNotNull, NoEnumeration] this T? parameter, Func exceptionFactory) where T : class { if (parameter is null) Throw.CustomException(exceptionFactory); From d8e6d44404ac2c8b584fc7db9f521956ddf4a9a1 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Fri, 18 Oct 2024 17:49:58 +0200 Subject: [PATCH 02/97] fix: add NotNull attribute to MustNotBeDefault Signed-off-by: Kenny Pflug --- .../Issues/Issue72.cs | 29 ----------- .../Issues/Issue72NotNullAttributeTests.cs | 49 +++++++++++++++++++ .../Check.CommonAssertions.cs | 12 ++++- 3 files changed, 59 insertions(+), 31 deletions(-) delete mode 100644 Code/Light.GuardClauses.Tests/Issues/Issue72.cs create mode 100644 Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72.cs deleted file mode 100644 index 0cda17c6..00000000 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using Xunit; - -#nullable enable - -namespace Light.GuardClauses.Tests.Issues; - -public static class Issue72 -{ - [Fact] - public static void MustNotBeNullDoesNotPropagate() - { - _ = TestMustNotBeNull("foo"); - _ = TestMustNotBeNullWithDelegate("foo"); - return; - - static int TestMustNotBeNull(string? input) - { - Check.MustNotBeNull(input); - return input.Length; - } - - static int TestMustNotBeNullWithDelegate(string? input) - { - input.MustNotBeNull(() => new Exception()); - return input.Length; - } - } -} \ No newline at end of file diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs new file mode 100644 index 00000000..410e2bbc --- /dev/null +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -0,0 +1,49 @@ +using System; +using Xunit; + +#nullable enable + +namespace Light.GuardClauses.Tests.Issues; + +public static class Issue72NotNullAttributeTests +{ + [Fact] + public static void MustNotBeNull() + { + _ = TestMustNotBeNull("foo"); + _ = TestMustNotBeNullWithDelegate("foo"); + return; + + static int TestMustNotBeNull(string? input) + { + Check.MustNotBeNull(input); + return input.Length; + } + + static int TestMustNotBeNullWithDelegate(string? input) + { + input.MustNotBeNull(() => new Exception()); + return input.Length; + } + } + + [Fact] + public static void MustNotBeDefault() + { + _ = TestMustNotBeDefault("foo"); + _ = TestMustNotBeDefaultWithDelegate("foo"); + return; + + static int TestMustNotBeDefault(string? input) + { + input.MustNotBeDefault(); + return input.Length; + } + + static int TestMustNotBeDefaultWithDelegate(string? input) + { + input.MustNotBeDefault(() => new Exception()); + return input.Length; + } + } +} \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.CommonAssertions.cs b/Code/Light.GuardClauses/Check.CommonAssertions.cs index e54a1973..80d4e703 100644 --- a/Code/Light.GuardClauses/Check.CommonAssertions.cs +++ b/Code/Light.GuardClauses/Check.CommonAssertions.cs @@ -54,7 +54,7 @@ public static T MustNotBeNull([NotNull, ValidatedNotNull, NoEnumeration] this /// Thrown when is a value type and the default value. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static T MustNotBeDefault([ValidatedNotNull] this T parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) + public static T MustNotBeDefault([NotNull, ValidatedNotNull] this T parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (default(T) is null) { @@ -65,7 +65,11 @@ public static T MustNotBeDefault([ValidatedNotNull] this T parameter, [Caller if (EqualityComparer.Default.Equals(parameter, default!)) Throw.ArgumentDefault(parameterName, message); + + // If we end up here, we have a value type which cannot be null +#pragma warning disable CS8777 // Parameter must have a non-null value when exiting. return parameter; +#pragma warning restore CS8777 } /// @@ -76,7 +80,7 @@ public static T MustNotBeDefault([ValidatedNotNull] this T parameter, [Caller /// Your custom exception thrown when is the default value. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] - public static T MustNotBeDefault([ValidatedNotNull] this T parameter, Func exceptionFactory) + public static T MustNotBeDefault([NotNull, ValidatedNotNull] this T parameter, Func exceptionFactory) { if (default(T) is null) { @@ -87,7 +91,11 @@ public static T MustNotBeDefault([ValidatedNotNull] this T parameter, Func.Default.Equals(parameter, default!)) Throw.CustomException(exceptionFactory); + + // If we end up here, we have a value type which cannot be null +#pragma warning disable CS8777 // Parameter must have a non-null value when exiting. return parameter; +#pragma warning restore CS8777 } From a8aec784ac12807f6feb0d029b36418de3fc535c Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Fri, 18 Oct 2024 17:53:23 +0200 Subject: [PATCH 03/97] refactor: rename test methods for Issue 72 Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 410e2bbc..da07eccf 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -8,7 +8,7 @@ namespace Light.GuardClauses.Tests.Issues; public static class Issue72NotNullAttributeTests { [Fact] - public static void MustNotBeNull() + public static void CheckMustNotBeNull() { _ = TestMustNotBeNull("foo"); _ = TestMustNotBeNullWithDelegate("foo"); @@ -28,7 +28,7 @@ static int TestMustNotBeNullWithDelegate(string? input) } [Fact] - public static void MustNotBeDefault() + public static void CheckMustNotBeDefault() { _ = TestMustNotBeDefault("foo"); _ = TestMustNotBeDefaultWithDelegate("foo"); From 4167eebf0899ee7654bc3e898fce3d4280847293 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Fri, 18 Oct 2024 18:00:27 +0200 Subject: [PATCH 04/97] fix: add NotNull attribute to MustNotBeNullReference Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 20 +++++++++++++++++++ .../Check.CommonAssertions.cs | 14 +++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index da07eccf..a651528b 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -46,4 +46,24 @@ static int TestMustNotBeDefaultWithDelegate(string? input) return input.Length; } } + + [Fact] + public static void CheckMustNotBeNullReference() + { + _ = TestMustNotBeNullReference("foo"); + _ = TestMustNotBeNullReferenceWithDelegate("foo"); + return; + + static int TestMustNotBeNullReference(string? input) + { + input.MustNotBeNullReference(); + return input.Length; + } + + static int TestMustNotBeNullReferenceWithDelegate(string? input) + { + input.MustNotBeNullReference(() => new Exception()); + return input.Length; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.CommonAssertions.cs b/Code/Light.GuardClauses/Check.CommonAssertions.cs index 80d4e703..39224851 100644 --- a/Code/Light.GuardClauses/Check.CommonAssertions.cs +++ b/Code/Light.GuardClauses/Check.CommonAssertions.cs @@ -110,10 +110,15 @@ public static T MustNotBeDefault([NotNull, ValidatedNotNull] this T parameter /// Thrown when is a reference type and is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static T MustNotBeNullReference([ValidatedNotNull, NoEnumeration] this T parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) + public static T MustNotBeNullReference([NotNull, ValidatedNotNull, NoEnumeration] this T parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (default(T) != null) + { + // If we end up here, parameter cannot be null +#pragma warning disable CS8777 // Parameter must have a non-null value when exiting. return parameter; +#pragma warning restore CS8777 // Parameter must have a non-null value when exiting. + } if (parameter is null) Throw.ArgumentNull(parameterName, message); @@ -130,10 +135,15 @@ public static T MustNotBeNullReference([ValidatedNotNull, NoEnumeration] this /// Your custom exception thrown when is a reference type and is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] - public static T MustNotBeNullReference([ValidatedNotNull, NoEnumeration] this T parameter, Func exceptionFactory) + public static T MustNotBeNullReference([NotNull, ValidatedNotNull, NoEnumeration] this T parameter, Func exceptionFactory) { if (default(T) != null) + { + // If we end up here, parameter cannot be null +#pragma warning disable CS8777 // Parameter must have a non-null value when exiting. return parameter; +#pragma warning restore CS8777 // Parameter must have a non-null value when exiting. + } if (parameter is null) Throw.CustomException(exceptionFactory); From d79b700be3c29593cda698a12c9074aabcca167b Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Fri, 18 Oct 2024 18:02:46 +0200 Subject: [PATCH 05/97] build: enabled TreatWarningsAsErrors for main test project Signed-off-by: Kenny Pflug --- Code/Light.GuardClauses.Tests/Light.GuardClauses.Tests.csproj | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Code/Light.GuardClauses.Tests/Light.GuardClauses.Tests.csproj b/Code/Light.GuardClauses.Tests/Light.GuardClauses.Tests.csproj index 2633bd00..f6ad39a7 100644 --- a/Code/Light.GuardClauses.Tests/Light.GuardClauses.Tests.csproj +++ b/Code/Light.GuardClauses.Tests/Light.GuardClauses.Tests.csproj @@ -3,9 +3,10 @@ - net8.0 + net8.0 false 12 + true From 5ce4e56ee4951b471a8f093169caf1f6f3c03ae1 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Fri, 18 Oct 2024 18:06:03 +0200 Subject: [PATCH 06/97] fix: add NotNull attribute to MustBeOfType Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 34 +++++++++++++++---- .../Check.CommonAssertions.cs | 4 +-- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index a651528b..90d5d38c 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -1,8 +1,8 @@ +#nullable enable + using System; using Xunit; -#nullable enable - namespace Light.GuardClauses.Tests.Issues; public static class Issue72NotNullAttributeTests @@ -33,37 +33,57 @@ public static void CheckMustNotBeDefault() _ = TestMustNotBeDefault("foo"); _ = TestMustNotBeDefaultWithDelegate("foo"); return; - + static int TestMustNotBeDefault(string? input) { input.MustNotBeDefault(); return input.Length; } - + static int TestMustNotBeDefaultWithDelegate(string? input) { input.MustNotBeDefault(() => new Exception()); return input.Length; } } - + [Fact] public static void CheckMustNotBeNullReference() { _ = TestMustNotBeNullReference("foo"); _ = TestMustNotBeNullReferenceWithDelegate("foo"); return; - + static int TestMustNotBeNullReference(string? input) { input.MustNotBeNullReference(); return input.Length; } - + static int TestMustNotBeNullReferenceWithDelegate(string? input) { input.MustNotBeNullReference(() => new Exception()); return input.Length; } } + + [Fact] + public static void CheckMustBeOfType() + { + _ = TestMustBeOfType("foo"); + _ = TestMustBeOfTypeWithDelegate("foo"); + return; + + static int TestMustBeOfType(object? input) + { + input.MustBeOfType(); + return ((string) input).Length; + } + + static int TestMustBeOfTypeWithDelegate(object? input) + { + input.MustBeOfType(_ => new Exception()); + return ((string) input).Length; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.CommonAssertions.cs b/Code/Light.GuardClauses/Check.CommonAssertions.cs index 39224851..ffdc9526 100644 --- a/Code/Light.GuardClauses/Check.CommonAssertions.cs +++ b/Code/Light.GuardClauses/Check.CommonAssertions.cs @@ -160,7 +160,7 @@ public static T MustNotBeNullReference([NotNull, ValidatedNotNull, NoEnumerat /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static T MustBeOfType([ValidatedNotNull, NoEnumeration] this object? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) + public static T MustBeOfType([NotNull, ValidatedNotNull, NoEnumeration] this object? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (parameter.MustNotBeNull(parameterName, message) is T castValue) return castValue; @@ -177,7 +177,7 @@ public static T MustBeOfType([ValidatedNotNull, NoEnumeration] this object? p /// Your custom exception thrown when cannot be cast to . [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] - public static T MustBeOfType([ValidatedNotNull, NoEnumeration] this object? parameter, Func exceptionFactory) + public static T MustBeOfType([NotNull, ValidatedNotNull, NoEnumeration] this object? parameter, Func exceptionFactory) { if (parameter is T castValue) return castValue; From ec675b5f2aae14d3956a1a3e84083a4b116f0601 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Fri, 18 Oct 2024 18:13:57 +0200 Subject: [PATCH 07/97] fix: add NotNull attribute to MustHaveValue Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 37 +++++++++++++++---- .../Check.CommonAssertions.cs | 4 +- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 90d5d38c..e63f1493 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -1,6 +1,7 @@ #nullable enable using System; +using FluentAssertions; using Xunit; namespace Light.GuardClauses.Tests.Issues; @@ -10,8 +11,8 @@ public static class Issue72NotNullAttributeTests [Fact] public static void CheckMustNotBeNull() { - _ = TestMustNotBeNull("foo"); - _ = TestMustNotBeNullWithDelegate("foo"); + TestMustNotBeNull("foo").Should().Be(3); + _ = TestMustNotBeNullWithDelegate("foo").Should().Be(3); return; static int TestMustNotBeNull(string? input) @@ -30,8 +31,8 @@ static int TestMustNotBeNullWithDelegate(string? input) [Fact] public static void CheckMustNotBeDefault() { - _ = TestMustNotBeDefault("foo"); - _ = TestMustNotBeDefaultWithDelegate("foo"); + TestMustNotBeDefault("foo").Should().Be(3); + TestMustNotBeDefaultWithDelegate("foo").Should().Be(3); return; static int TestMustNotBeDefault(string? input) @@ -50,8 +51,8 @@ static int TestMustNotBeDefaultWithDelegate(string? input) [Fact] public static void CheckMustNotBeNullReference() { - _ = TestMustNotBeNullReference("foo"); - _ = TestMustNotBeNullReferenceWithDelegate("foo"); + TestMustNotBeNullReference("foo").Should().Be(3); + TestMustNotBeNullReferenceWithDelegate("foo").Should().Be(3); return; static int TestMustNotBeNullReference(string? input) @@ -70,8 +71,8 @@ static int TestMustNotBeNullReferenceWithDelegate(string? input) [Fact] public static void CheckMustBeOfType() { - _ = TestMustBeOfType("foo"); - _ = TestMustBeOfTypeWithDelegate("foo"); + TestMustBeOfType("foo").Should().Be(3); + TestMustBeOfTypeWithDelegate("foo").Should().Be(3); return; static int TestMustBeOfType(object? input) @@ -86,4 +87,24 @@ static int TestMustBeOfTypeWithDelegate(object? input) return ((string) input).Length; } } + + [Fact] + public static void CheckMustHaveValue() + { + TestMustHaveValue(42).Should().Be(42); + TestMustHaveValueWithDelegate(42).Should().Be(42); + return; + + static int TestMustHaveValue(int? input) + { + input.MustHaveValue(); + return input.Value; + } + + static int TestMustHaveValueWithDelegate(int? input) + { + input.MustHaveValue(() => new Exception()); + return input.Value; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.CommonAssertions.cs b/Code/Light.GuardClauses/Check.CommonAssertions.cs index ffdc9526..0104f58a 100644 --- a/Code/Light.GuardClauses/Check.CommonAssertions.cs +++ b/Code/Light.GuardClauses/Check.CommonAssertions.cs @@ -347,7 +347,7 @@ public static void InvalidArgument(bool condition, T parameter, FuncThe message that will be passed to the resulting exception (optional). /// Thrown when has no value. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T MustHaveValue([NoEnumeration] this T? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : struct + public static T MustHaveValue([NotNull, NoEnumeration] this T? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : struct { if (!parameter.HasValue) Throw.NullableHasNoValue(parameterName, message); @@ -363,7 +363,7 @@ public static T MustHaveValue([NoEnumeration] this T? parameter, [CallerArgum /// Thrown when has no value. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("exceptionFactory:null => halt")] - public static T MustHaveValue([NoEnumeration] this T? parameter, Func exceptionFactory) where T : struct + public static T MustHaveValue([NotNull, NoEnumeration] this T? parameter, Func exceptionFactory) where T : struct { if (!parameter.HasValue) Throw.CustomException(exceptionFactory); From 43c3f26f46d7c89c48a406541c87eb0936930614 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Fri, 18 Oct 2024 18:21:22 +0200 Subject: [PATCH 08/97] fix: add NotNull attribute to MustNotBeLessThan Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 25 ++++++++++++++++++- .../Check.ComparableAssertions.cs | 7 +++--- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index e63f1493..154ac3d1 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -87,7 +87,7 @@ static int TestMustBeOfTypeWithDelegate(object? input) return ((string) input).Length; } } - + [Fact] public static void CheckMustHaveValue() { @@ -107,4 +107,27 @@ static int TestMustHaveValueWithDelegate(int? input) return input.Value; } } + + [Fact] + public static void CheckMustNotBeLessThan() + { + TestMustNotBeLessThan("foo").Should().Be("foo"); + TestMustNotBeLessThanWithDelegate("foo").Should().Be("foo"); + return; + + // I need to provoke a compiler warning +#pragma warning disable CS8631 // The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match constraint type. + static string TestMustNotBeLessThan(string? input) + { + input.MustNotBeLessThan("bar"); + return input; + } + + static string TestMustNotBeLessThanWithDelegate(string? input) + { + input.MustNotBeLessThan("bar", (_, _) => new Exception()); + return input; + } +#pragma warning restore CS8631 + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.ComparableAssertions.cs b/Code/Light.GuardClauses/Check.ComparableAssertions.cs index d8251980..2ffc4d24 100644 --- a/Code/Light.GuardClauses/Check.ComparableAssertions.cs +++ b/Code/Light.GuardClauses/Check.ComparableAssertions.cs @@ -2,6 +2,7 @@ using JetBrains.Annotations; using System.Runtime.CompilerServices; using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; namespace Light.GuardClauses; @@ -24,7 +25,7 @@ public static partial class Check /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static T MustNotBeLessThan([ValidatedNotNull] this T parameter, T other, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : IComparable + public static T MustNotBeLessThan([NotNull, ValidatedNotNull] this T parameter, T other, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : IComparable { if (parameter.MustNotBeNullReference(parameterName, message).CompareTo(other) < 0) Throw.MustNotBeLessThan(parameter, other, parameterName, message); @@ -40,9 +41,9 @@ public static T MustNotBeLessThan([ValidatedNotNull] this T parameter, T othe /// Your custom exception thrown when the specified is less than , or when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] - public static T MustNotBeLessThan([ValidatedNotNull] this T parameter, T other, Func exceptionFactory) where T : IComparable + public static T MustNotBeLessThan([NotNull, ValidatedNotNull] this T parameter, T other, Func exceptionFactory) where T : IComparable { - // ReSharper disable once ConditionIsAlwaysTrueOrFalse - caller might have NRTs turned off + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract -- caller might have NRTs off if (parameter is null || parameter.CompareTo(other) < 0) Throw.CustomException(exceptionFactory, parameter!, other); return parameter; From 45832166cecffb95cef793dfac1d196922757c4d Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Fri, 18 Oct 2024 18:26:17 +0200 Subject: [PATCH 09/97] fix: add NotNull attribute to MustBeGreaterThanOrEqualTo Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 22 +++++++++++++++++++ .../Check.ComparableAssertions.cs | 6 ++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 154ac3d1..14335a96 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -128,6 +128,28 @@ static string TestMustNotBeLessThanWithDelegate(string? input) input.MustNotBeLessThan("bar", (_, _) => new Exception()); return input; } +#pragma warning restore CS8631 + } + + [Fact] + public static void CheckMustBeGreaterThanOrEqualTo() + { + TestMustBeGreaterThanOrEqualTo("foo").Should().Be("foo"); + TestMustBeGreaterThanOrEqualToWithDelegate("foo").Should().Be("foo"); + return; + +#pragma warning disable CS8631 // The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match constraint type. + static string TestMustBeGreaterThanOrEqualTo(string? input) + { + input.MustBeGreaterThanOrEqualTo("bar"); + return input; + } + + static string TestMustBeGreaterThanOrEqualToWithDelegate(string? input) + { + input.MustBeGreaterThanOrEqualTo("bar", (_, _) => new Exception()); + return input; + } #pragma warning restore CS8631 } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.ComparableAssertions.cs b/Code/Light.GuardClauses/Check.ComparableAssertions.cs index 2ffc4d24..05dc81cd 100644 --- a/Code/Light.GuardClauses/Check.ComparableAssertions.cs +++ b/Code/Light.GuardClauses/Check.ComparableAssertions.cs @@ -60,7 +60,7 @@ public static T MustNotBeLessThan([NotNull, ValidatedNotNull] this T paramete /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static T MustBeGreaterThanOrEqualTo([ValidatedNotNull] this T parameter, T other, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : IComparable + public static T MustBeGreaterThanOrEqualTo([NotNull, ValidatedNotNull] this T parameter, T other, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : IComparable { if (parameter.MustNotBeNullReference(parameterName, message).CompareTo(other) < 0) Throw.MustBeGreaterThanOrEqualTo(parameter, other, parameterName, message); @@ -76,9 +76,9 @@ public static T MustBeGreaterThanOrEqualTo([ValidatedNotNull] this T paramete /// Your custom exception thrown when the specified is less than , or when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] - public static T MustBeGreaterThanOrEqualTo([ValidatedNotNull] this T parameter, T other, Func exceptionFactory) where T : IComparable + public static T MustBeGreaterThanOrEqualTo([NotNull, ValidatedNotNull] this T parameter, T other, Func exceptionFactory) where T : IComparable { - // ReSharper disable once ConditionIsAlwaysTrueOrFalse - caller might have NRTs turned off + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off if (parameter is null || parameter.CompareTo(other) < 0) Throw.CustomException(exceptionFactory, parameter!, other); return parameter; From 418f1dba0d02c87923c454403d8ba4e2e94232c7 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Fri, 18 Oct 2024 18:31:42 +0200 Subject: [PATCH 10/97] fix: add NotNull attribute to MustBeLessThan Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 22 +++++++++++++++++++ .../Check.ComparableAssertions.cs | 6 ++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 14335a96..7f5bc774 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -150,6 +150,28 @@ static string TestMustBeGreaterThanOrEqualToWithDelegate(string? input) input.MustBeGreaterThanOrEqualTo("bar", (_, _) => new Exception()); return input; } +#pragma warning restore CS8631 + } + + [Fact] + public static void CheckMustBeLessThan() + { + TestMustBeLessThan("bar").Should().Be("bar"); + TestMustBeLessThanWithDelegate("bar").Should().Be("bar"); + return; + +#pragma warning disable CS8631 // The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match constraint type. + static string TestMustBeLessThan(string? input) + { + input.MustBeLessThan("foo"); + return input; + } + + static string TestMustBeLessThanWithDelegate(string? input) + { + input.MustBeLessThan("foo", (_, _) => new Exception()); + return input; + } #pragma warning restore CS8631 } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.ComparableAssertions.cs b/Code/Light.GuardClauses/Check.ComparableAssertions.cs index 05dc81cd..83c87cbf 100644 --- a/Code/Light.GuardClauses/Check.ComparableAssertions.cs +++ b/Code/Light.GuardClauses/Check.ComparableAssertions.cs @@ -101,7 +101,7 @@ public static T MustBeGreaterThanOrEqualTo([NotNull, ValidatedNotNull] this T /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static T MustBeLessThan([ValidatedNotNull] this T parameter, T other, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : IComparable + public static T MustBeLessThan([NotNull, ValidatedNotNull] this T parameter, T other, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : IComparable { if (parameter.MustNotBeNullReference(parameterName, message).CompareTo(other) >= 0) Throw.MustBeLessThan(parameter, other, parameterName, message); @@ -117,9 +117,9 @@ public static T MustBeLessThan([ValidatedNotNull] this T parameter, T other, /// Your custom exception thrown when the specified is not less than , or when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] - public static T MustBeLessThan([ValidatedNotNull] this T parameter, T other, Func exceptionFactory) where T : IComparable + public static T MustBeLessThan([NotNull, ValidatedNotNull] this T parameter, T other, Func exceptionFactory) where T : IComparable { - // ReSharper disable once ConditionIsAlwaysTrueOrFalse - caller might have NRTs turned off + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off if (parameter is null || parameter.CompareTo(other) >= 0) Throw.CustomException(exceptionFactory, parameter!, other); return parameter; From dc545d3b482497c4bd38d79cb95b15dd2906312d Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Fri, 18 Oct 2024 18:36:06 +0200 Subject: [PATCH 11/97] fix: add NotNull attribute to MustNotBeGreaterThanOrEqualTo Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 22 +++++++++++++++++++ .../Check.ComparableAssertions.cs | 6 ++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 7f5bc774..7d6a197e 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -172,6 +172,28 @@ static string TestMustBeLessThanWithDelegate(string? input) input.MustBeLessThan("foo", (_, _) => new Exception()); return input; } +#pragma warning restore CS8631 + } + + [Fact] + public static void CheckMustNotBeGreaterThanOrEqualTo() + { + TestMustNotBeGreaterThanOrEqualTo("bar").Should().Be("bar"); + TestMustNotBeGreaterThanOrEqualToWithDelegate("bar").Should().Be("bar"); + return; + +#pragma warning disable CS8631 // The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match constraint type. + static string TestMustNotBeGreaterThanOrEqualTo(string? input) + { + input.MustNotBeGreaterThanOrEqualTo("foo"); + return input; + } + + static string TestMustNotBeGreaterThanOrEqualToWithDelegate(string? input) + { + input.MustNotBeGreaterThanOrEqualTo("foo", (_, _) => new Exception()); + return input; + } #pragma warning restore CS8631 } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.ComparableAssertions.cs b/Code/Light.GuardClauses/Check.ComparableAssertions.cs index 83c87cbf..60e7c4c8 100644 --- a/Code/Light.GuardClauses/Check.ComparableAssertions.cs +++ b/Code/Light.GuardClauses/Check.ComparableAssertions.cs @@ -136,7 +136,7 @@ public static T MustBeLessThan([NotNull, ValidatedNotNull] this T parameter, /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static T MustNotBeGreaterThanOrEqualTo([ValidatedNotNull] this T parameter, T other, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : IComparable + public static T MustNotBeGreaterThanOrEqualTo([NotNull, ValidatedNotNull] this T parameter, T other, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : IComparable { if (parameter.MustNotBeNullReference(parameterName, message).CompareTo(other) >= 0) Throw.MustNotBeGreaterThanOrEqualTo(parameter, other, parameterName, message); @@ -152,9 +152,9 @@ public static T MustNotBeGreaterThanOrEqualTo([ValidatedNotNull] this T param /// Your custom exception thrown when the specified is not less than , or when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] - public static T MustNotBeGreaterThanOrEqualTo([ValidatedNotNull] this T parameter, T other, Func exceptionFactory) where T : IComparable + public static T MustNotBeGreaterThanOrEqualTo([NotNull, ValidatedNotNull] this T parameter, T other, Func exceptionFactory) where T : IComparable { - // ReSharper disable once ConditionIsAlwaysTrueOrFalse - caller might have NRTs turned off + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off if (parameter is null || parameter.CompareTo(other) >= 0) Throw.CustomException(exceptionFactory, parameter!, other); return parameter; From efd38fcbbbf4a95598ca8a1cbecaf95fc11fd275 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Fri, 18 Oct 2024 18:39:26 +0200 Subject: [PATCH 12/97] fix: add NotNull attribute to MustBeGreaterThan Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 22 +++++++++++++++++++ .../Check.ComparableAssertions.cs | 6 ++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 7d6a197e..7a22cde5 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -194,6 +194,28 @@ static string TestMustNotBeGreaterThanOrEqualToWithDelegate(string? input) input.MustNotBeGreaterThanOrEqualTo("foo", (_, _) => new Exception()); return input; } +#pragma warning restore CS8631 + } + + [Fact] + public static void CheckMustBeGreaterThan() + { + TestMustBeGreaterThan("foo").Should().Be("foo"); + TestMustBeGreaterThanWithDelegate("foo").Should().Be("foo"); + return; + +#pragma warning disable CS8631 // The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match constraint type. + static string TestMustBeGreaterThan(string? input) + { + input.MustBeGreaterThan("bar"); + return input; + } + + static string TestMustBeGreaterThanWithDelegate(string? input) + { + input.MustBeGreaterThan("bar", (_, _) => new Exception()); + return input; + } #pragma warning restore CS8631 } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.ComparableAssertions.cs b/Code/Light.GuardClauses/Check.ComparableAssertions.cs index 60e7c4c8..161d3190 100644 --- a/Code/Light.GuardClauses/Check.ComparableAssertions.cs +++ b/Code/Light.GuardClauses/Check.ComparableAssertions.cs @@ -177,7 +177,7 @@ public static T MustNotBeGreaterThanOrEqualTo([NotNull, ValidatedNotNull] thi /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static T MustBeGreaterThan([ValidatedNotNull] this T parameter, T other, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : IComparable + public static T MustBeGreaterThan([NotNull, ValidatedNotNull] this T parameter, T other, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : IComparable { if (parameter.MustNotBeNullReference(parameterName, message).CompareTo(other) <= 0) Throw.MustBeGreaterThan(parameter, other, parameterName, message); @@ -193,9 +193,9 @@ public static T MustBeGreaterThan([ValidatedNotNull] this T parameter, T othe /// Your custom exception thrown when the specified is less than or equal to , or when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] - public static T MustBeGreaterThan([ValidatedNotNull] this T parameter, T other, Func exceptionFactory) where T : IComparable + public static T MustBeGreaterThan([NotNull, ValidatedNotNull] this T parameter, T other, Func exceptionFactory) where T : IComparable { - // ReSharper disable once ConditionIsAlwaysTrueOrFalse - caller might have NRTs turned off + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off if (parameter is null || parameter.CompareTo(other) <= 0) Throw.CustomException(exceptionFactory, parameter!, other); return parameter; From 3bc9b4b1df800c83d1994ca20f17f957f16ca782 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Fri, 18 Oct 2024 18:42:15 +0200 Subject: [PATCH 13/97] fix: add NotNull attribute to MustNotBeLessThanOrEqualTo Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 22 +++++++++++++++++++ .../Check.ComparableAssertions.cs | 6 ++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 7a22cde5..c5fc8161 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -216,6 +216,28 @@ static string TestMustBeGreaterThanWithDelegate(string? input) input.MustBeGreaterThan("bar", (_, _) => new Exception()); return input; } +#pragma warning restore CS8631 + } + + [Fact] + public static void CheckMustNotBeLessThanOrEqualTo() + { + TestMustNotBeLessThanOrEqualTo("foo").Should().Be("foo"); + TestMustNotBeLessThanOrEqualToWithDelegate("foo").Should().Be("foo"); + return; + +#pragma warning disable CS8631 // The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match constraint type. + static string TestMustNotBeLessThanOrEqualTo(string? input) + { + input.MustNotBeLessThanOrEqualTo("bar"); + return input; + } + + static string TestMustNotBeLessThanOrEqualToWithDelegate(string? input) + { + input.MustNotBeLessThanOrEqualTo("bar", (_, _) => new Exception()); + return input; + } #pragma warning restore CS8631 } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.ComparableAssertions.cs b/Code/Light.GuardClauses/Check.ComparableAssertions.cs index 161d3190..082c8bc1 100644 --- a/Code/Light.GuardClauses/Check.ComparableAssertions.cs +++ b/Code/Light.GuardClauses/Check.ComparableAssertions.cs @@ -212,7 +212,7 @@ public static T MustBeGreaterThan([NotNull, ValidatedNotNull] this T paramete /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static T MustNotBeLessThanOrEqualTo([ValidatedNotNull] this T parameter, T other, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : IComparable + public static T MustNotBeLessThanOrEqualTo([NotNull, ValidatedNotNull] this T parameter, T other, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : IComparable { if (parameter.MustNotBeNullReference(parameterName, message).CompareTo(other) <= 0) Throw.MustNotBeLessThanOrEqualTo(parameter, other, parameterName, message); @@ -228,9 +228,9 @@ public static T MustNotBeLessThanOrEqualTo([ValidatedNotNull] this T paramete /// Your custom exception thrown when the specified is less than or equal to , or when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] - public static T MustNotBeLessThanOrEqualTo([ValidatedNotNull] this T parameter, T other, Func exceptionFactory) where T : IComparable + public static T MustNotBeLessThanOrEqualTo([NotNull, ValidatedNotNull] this T parameter, T other, Func exceptionFactory) where T : IComparable { - // ReSharper disable once ConditionIsAlwaysTrueOrFalse - caller might have NRTs turned off + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off if (parameter is null || parameter.CompareTo(other) <= 0) Throw.CustomException(exceptionFactory, parameter!, other); return parameter; From d04d57dad7abe010d50c5467a08def0dd97df271 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Fri, 18 Oct 2024 18:44:36 +0200 Subject: [PATCH 14/97] fix: add NotNull attribute to MustNotBeGreaterThan Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 22 +++++++++++++++++++ .../Check.ComparableAssertions.cs | 6 ++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index c5fc8161..c8dce7b5 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -238,6 +238,28 @@ static string TestMustNotBeLessThanOrEqualToWithDelegate(string? input) input.MustNotBeLessThanOrEqualTo("bar", (_, _) => new Exception()); return input; } +#pragma warning restore CS8631 + } + + [Fact] + public static void CheckMustNotBeGreaterThan() + { + TestMustNotBeGreaterThan("bar").Should().Be("bar"); + TestMustNotBeGreaterThanWithDelegate("bar").Should().Be("bar"); + return; + +#pragma warning disable CS8631 // The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match constraint type. + static string TestMustNotBeGreaterThan(string? input) + { + input.MustNotBeGreaterThan("foo"); + return input; + } + + static string TestMustNotBeGreaterThanWithDelegate(string? input) + { + input.MustNotBeGreaterThan("foo", (_, _) => new Exception()); + return input; + } #pragma warning restore CS8631 } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.ComparableAssertions.cs b/Code/Light.GuardClauses/Check.ComparableAssertions.cs index 082c8bc1..d3fb55d0 100644 --- a/Code/Light.GuardClauses/Check.ComparableAssertions.cs +++ b/Code/Light.GuardClauses/Check.ComparableAssertions.cs @@ -253,7 +253,7 @@ public static T MustNotBeLessThanOrEqualTo([NotNull, ValidatedNotNull] this T /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static T MustNotBeGreaterThan([ValidatedNotNull] this T parameter, T other, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : IComparable + public static T MustNotBeGreaterThan([NotNull, ValidatedNotNull] this T parameter, T other, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : IComparable { if (parameter.MustNotBeNullReference(parameterName, message).CompareTo(other) > 0) Throw.MustNotBeGreaterThan(parameter, other, parameterName, message); @@ -269,9 +269,9 @@ public static T MustNotBeGreaterThan([ValidatedNotNull] this T parameter, T o /// Your custom exception thrown when the specified is greater than , or when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] - public static T MustNotBeGreaterThan([ValidatedNotNull] this T parameter, T other, Func exceptionFactory) where T : IComparable + public static T MustNotBeGreaterThan([NotNull, ValidatedNotNull] this T parameter, T other, Func exceptionFactory) where T : IComparable { - // ReSharper disable once ConditionIsAlwaysTrueOrFalse - caller might have NRTs turned off + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off if (parameter is null || parameter.CompareTo(other) > 0) Throw.CustomException(exceptionFactory, parameter!, other); return parameter; From ae9b3a98a5bfa503ce6508029558cc553deab871 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Fri, 18 Oct 2024 18:47:30 +0200 Subject: [PATCH 15/97] fix: add NotNull attribute to MustBeLessThanOrEqualTo Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 22 +++++++++++++++++++ .../Check.ComparableAssertions.cs | 6 ++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index c8dce7b5..e16b6cdd 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -260,6 +260,28 @@ static string TestMustNotBeGreaterThanWithDelegate(string? input) input.MustNotBeGreaterThan("foo", (_, _) => new Exception()); return input; } +#pragma warning restore CS8631 + } + + [Fact] + public static void CheckMustBeLessThanOrEqualTo() + { + TestMustBeLessThanOrEqualTo("bar").Should().Be("bar"); + TestMustBeLessThanOrEqualToWithDelegate("bar").Should().Be("bar"); + return; + +#pragma warning disable CS8631 // The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match constraint type. + static string TestMustBeLessThanOrEqualTo(string? input) + { + input.MustBeLessThanOrEqualTo("foo"); + return input; + } + + static string TestMustBeLessThanOrEqualToWithDelegate(string? input) + { + input.MustBeLessThanOrEqualTo("foo", (_, _) => new Exception()); + return input; + } #pragma warning restore CS8631 } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.ComparableAssertions.cs b/Code/Light.GuardClauses/Check.ComparableAssertions.cs index d3fb55d0..6a8d703c 100644 --- a/Code/Light.GuardClauses/Check.ComparableAssertions.cs +++ b/Code/Light.GuardClauses/Check.ComparableAssertions.cs @@ -288,7 +288,7 @@ public static T MustNotBeGreaterThan([NotNull, ValidatedNotNull] this T param /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static T MustBeLessThanOrEqualTo([ValidatedNotNull] this T parameter, T other, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : IComparable + public static T MustBeLessThanOrEqualTo([NotNull, ValidatedNotNull] this T parameter, T other, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : IComparable { if (parameter.MustNotBeNullReference(parameterName, message).CompareTo(other) > 0) Throw.MustBeLessThanOrEqualTo(parameter, other, parameterName, message); @@ -304,9 +304,9 @@ public static T MustBeLessThanOrEqualTo([ValidatedNotNull] this T parameter, /// Your custom exception thrown when the specified is greater than , or when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] - public static T MustBeLessThanOrEqualTo([ValidatedNotNull] this T parameter, T other, Func exceptionFactory) where T : IComparable + public static T MustBeLessThanOrEqualTo([NotNull, ValidatedNotNull] this T parameter, T other, Func exceptionFactory) where T : IComparable { - // ReSharper disable once ConditionIsAlwaysTrueOrFalse - caller might have NRTs turned off + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off if (parameter is null || parameter.CompareTo(other) > 0) Throw.CustomException(exceptionFactory, parameter!, other); return parameter; From dee2c556c697dbf33de0145041c3db32fc290a23 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Fri, 18 Oct 2024 18:52:57 +0200 Subject: [PATCH 16/97] fix: add NotNull attribute to MustBeIn Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 21 +++++++++++++++++++ .../Check.ComparableAssertions.cs | 6 +++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index e16b6cdd..4b8bc083 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -282,6 +282,27 @@ static string TestMustBeLessThanOrEqualToWithDelegate(string? input) input.MustBeLessThanOrEqualTo("foo", (_, _) => new Exception()); return input; } +#pragma warning restore CS8631 + } + + [Fact] + public static void CheckMustBeIn() + { + TestMustBeIn("b").Should().Be(1); + TestMustBeInWithDelegate("b").Should().Be(1); + +#pragma warning disable CS8631 // The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match constraint type. + static int TestMustBeIn(string? input) + { + input.MustBeIn(Range.FromInclusive("a").ToInclusive("c")!); + return input.Length; + } + + static int TestMustBeInWithDelegate(string? input) + { + input.MustBeIn(Range.FromInclusive("a").ToInclusive("c")!, (_, _) => new Exception()); + return input.Length; + } #pragma warning restore CS8631 } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.ComparableAssertions.cs b/Code/Light.GuardClauses/Check.ComparableAssertions.cs index 6a8d703c..dba964dc 100644 --- a/Code/Light.GuardClauses/Check.ComparableAssertions.cs +++ b/Code/Light.GuardClauses/Check.ComparableAssertions.cs @@ -349,7 +349,7 @@ public static T MustBeLessThanOrEqualTo([NotNull, ValidatedNotNull] this T pa /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static T MustBeIn([ValidatedNotNull] this T parameter, Range range, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : IComparable + public static T MustBeIn([NotNull, ValidatedNotNull] this T parameter, Range range, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : IComparable { if (!range.IsValueWithinRange(parameter.MustNotBeNullReference(parameterName, message))) Throw.MustBeInRange(parameter, range, parameterName, message); @@ -365,9 +365,9 @@ public static T MustBeIn([ValidatedNotNull] this T parameter, Range range, /// Your custom exception thrown when is not within , or when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] - public static T MustBeIn([ValidatedNotNull] this T parameter, Range range, Func, Exception> exceptionFactory) where T : IComparable + public static T MustBeIn([NotNull, ValidatedNotNull] this T parameter, Range range, Func, Exception> exceptionFactory) where T : IComparable { - // ReSharper disable once ConditionIsAlwaysTrueOrFalse - caller might have NRTs turned off + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off if (parameter is null || !range.IsValueWithinRange(parameter)) Throw.CustomException(exceptionFactory, parameter!, range); return parameter; From 3bec4c1910b500bed19fd3faba27e08b29137e8b Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Fri, 18 Oct 2024 18:58:40 +0200 Subject: [PATCH 17/97] fix: add NotNull attribute to MustNotBeIn Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 21 +++++++++++++++++++ .../Check.ComparableAssertions.cs | 6 +++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 4b8bc083..5b1546a9 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -303,6 +303,27 @@ static int TestMustBeInWithDelegate(string? input) input.MustBeIn(Range.FromInclusive("a").ToInclusive("c")!, (_, _) => new Exception()); return input.Length; } +#pragma warning restore CS8631 + } + + [Fact] + public static void CheckMustNotBeIn() + { + TestMustNotBeIn("d").Should().Be(1); + TestMustNotBeInWithDelegate("d").Should().Be(1); + +#pragma warning disable CS8631 // The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match constraint type. + static int TestMustNotBeIn(string? input) + { + input.MustNotBeIn(Range.FromInclusive("a").ToInclusive("c")!); + return input.Length; + } + + static int TestMustNotBeInWithDelegate(string? input) + { + input.MustNotBeIn(Range.FromInclusive("a").ToInclusive("c")!, (_, _) => new Exception()); + return input.Length; + } #pragma warning restore CS8631 } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.ComparableAssertions.cs b/Code/Light.GuardClauses/Check.ComparableAssertions.cs index dba964dc..71ae9337 100644 --- a/Code/Light.GuardClauses/Check.ComparableAssertions.cs +++ b/Code/Light.GuardClauses/Check.ComparableAssertions.cs @@ -385,7 +385,7 @@ public static T MustBeIn([NotNull, ValidatedNotNull] this T parameter, Range< /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static T MustNotBeIn([ValidatedNotNull] this T parameter, Range range, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : IComparable + public static T MustNotBeIn([NotNull, ValidatedNotNull] this T parameter, Range range, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : IComparable { if (range.IsValueWithinRange(parameter.MustNotBeNullReference(parameterName, message))) Throw.MustNotBeInRange(parameter, range, parameterName, message); @@ -401,9 +401,9 @@ public static T MustNotBeIn([ValidatedNotNull] this T parameter, Range ran /// Your custom exception thrown when is within , or when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] - public static T MustNotBeIn([ValidatedNotNull] this T parameter, Range range, Func, Exception> exceptionFactory) where T : IComparable + public static T MustNotBeIn([NotNull, ValidatedNotNull] this T parameter, Range range, Func, Exception> exceptionFactory) where T : IComparable { - // ReSharper disable once ConditionIsAlwaysTrueOrFalse - caller might have NRTs turned off + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off if (parameter is null || range.IsValueWithinRange(parameter)) Throw.CustomException(exceptionFactory, parameter!, range); return parameter; From 4b41b4818f0335fe9788158e165f97487813b0ba Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Fri, 18 Oct 2024 23:40:37 +0200 Subject: [PATCH 18/97] fix: add NotNull attribute to MustHaveCount Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 20 +++++++++++++++++++ .../Check.EnumerableAssertions.cs | 5 +++-- .../EnumerableExtensions.cs | 5 +++-- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 5b1546a9..51e4e8b0 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -326,4 +326,24 @@ static int TestMustNotBeInWithDelegate(string? input) } #pragma warning restore CS8631 } + + [Fact] + public static void CheckMustHaveCount() + { + TestMustHaveCount([]).Should().Be(0); + TestMustHaveCountWithDelegate([]).Should().Be(0); + return; + + static int TestMustHaveCount(string[]? input) + { + input.MustHaveCount(0); + return input.Length; + } + + static int TestMustHaveCountWithDelegate(string[]? input) + { + input.MustHaveCount(0, (_, _) => new Exception()); + return input.Length; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.EnumerableAssertions.cs b/Code/Light.GuardClauses/Check.EnumerableAssertions.cs index 3392408f..9d36eb43 100644 --- a/Code/Light.GuardClauses/Check.EnumerableAssertions.cs +++ b/Code/Light.GuardClauses/Check.EnumerableAssertions.cs @@ -7,6 +7,7 @@ using JetBrains.Annotations; using Light.GuardClauses.Exceptions; using Light.GuardClauses.FrameworkExtensions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; namespace Light.GuardClauses; @@ -23,7 +24,7 @@ public static partial class Check /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static TCollection MustHaveCount([ValidatedNotNull] this TCollection? parameter, int count, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where TCollection : class, IEnumerable + public static TCollection MustHaveCount([NotNull, ValidatedNotNull] this TCollection? parameter, int count, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where TCollection : class, IEnumerable { if (parameter!.Count(parameterName, message) != count) Throw.InvalidCollectionCount(parameter!, count, parameterName, message); @@ -39,7 +40,7 @@ public static TCollection MustHaveCount([ValidatedNotNull] this TCo /// Your custom exception thrown when does not have the specified number of items, or when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static TCollection MustHaveCount([ValidatedNotNull] this TCollection? parameter, int count, Func exceptionFactory) where TCollection : class, IEnumerable + public static TCollection MustHaveCount([NotNull, ValidatedNotNull] this TCollection? parameter, int count, Func exceptionFactory) where TCollection : class, IEnumerable { if (parameter is null || parameter.Count() != count) Throw.CustomException(exceptionFactory, parameter, count); diff --git a/Code/Light.GuardClauses/FrameworkExtensions/EnumerableExtensions.cs b/Code/Light.GuardClauses/FrameworkExtensions/EnumerableExtensions.cs index a6f66e2e..44001dc9 100644 --- a/Code/Light.GuardClauses/FrameworkExtensions/EnumerableExtensions.cs +++ b/Code/Light.GuardClauses/FrameworkExtensions/EnumerableExtensions.cs @@ -5,6 +5,7 @@ using JetBrains.Annotations; using System.Runtime.CompilerServices; using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; namespace Light.GuardClauses.FrameworkExtensions; @@ -154,7 +155,7 @@ public static int Count([ValidatedNotNull] this IEnumerable enumerable) /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("enumerable:null => halt")] - public static int Count([ValidatedNotNull] this IEnumerable? enumerable, string? parameterName, string? message) + public static int Count([NotNull, ValidatedNotNull] this IEnumerable? enumerable, string? parameterName, string? message) { if (enumerable is ICollection collection) return collection.Count; @@ -230,7 +231,7 @@ private static int DetermineCountViaEnumerating(IEnumerable? enumerable) return count; } - private static int DetermineCountViaEnumerating(IEnumerable? enumerable, string? parameterName, string? message) + private static int DetermineCountViaEnumerating([NotNull] IEnumerable? enumerable, string? parameterName, string? message) { var count = 0; var enumerator = enumerable.MustNotBeNull(parameterName, message).GetEnumerator(); From 374240e3aa297bda46757845cf0d304d6b7ed71a Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Fri, 18 Oct 2024 23:48:23 +0200 Subject: [PATCH 19/97] fix: TargetFramework in main test project Signed-off-by: Kenny Pflug --- .../Light.GuardClauses.Tests.csproj | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Light.GuardClauses.Tests.csproj b/Code/Light.GuardClauses.Tests/Light.GuardClauses.Tests.csproj index f6ad39a7..f062d75c 100644 --- a/Code/Light.GuardClauses.Tests/Light.GuardClauses.Tests.csproj +++ b/Code/Light.GuardClauses.Tests/Light.GuardClauses.Tests.csproj @@ -1,20 +1,20 @@ - - - - - - net8.0 - false - 12 - true - - - - - - - - - - + + + + + + net8.0 + false + 12 + true + + + + + + + + + + \ No newline at end of file From 64fd31d7e61d2421fdb551f9f0429a2c5642989f Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Fri, 18 Oct 2024 23:54:01 +0200 Subject: [PATCH 20/97] fix: add NotNull attribute to MustNotBeNullOrEmpty for collections Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 20 +++++++++++++++++++ .../Check.EnumerableAssertions.cs | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 51e4e8b0..0d5c037d 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -346,4 +346,24 @@ static int TestMustHaveCountWithDelegate(string[]? input) return input.Length; } } + + [Fact] + public static void CheckMustNotBeNullOrEmpty() + { + TestMustNotBeNullOrEmpty([1, 2, 3]).Should().Be(3); + TestMustNotBeNullOrEmptyWithDelegate([1, 2, 3]).Should().Be(3); + return; + + static int TestMustNotBeNullOrEmpty(int[]? input) + { + input.MustNotBeNullOrEmpty(); + return input.Length; + } + + static int TestMustNotBeNullOrEmptyWithDelegate(int[]? input) + { + input.MustNotBeNullOrEmpty(_ => new Exception()); + return input.Length; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.EnumerableAssertions.cs b/Code/Light.GuardClauses/Check.EnumerableAssertions.cs index 9d36eb43..c1c1b85f 100644 --- a/Code/Light.GuardClauses/Check.EnumerableAssertions.cs +++ b/Code/Light.GuardClauses/Check.EnumerableAssertions.cs @@ -67,7 +67,7 @@ public static bool IsNullOrEmpty([NotNullWhen(false)] this IEnumerable? collecti /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static TCollection MustNotBeNullOrEmpty([ValidatedNotNull] this TCollection? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where TCollection : class, IEnumerable + public static TCollection MustNotBeNullOrEmpty([NotNull, ValidatedNotNull] this TCollection? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where TCollection : class, IEnumerable { if (parameter.Count(parameterName, message) == 0) Throw.EmptyCollection(parameterName, message); @@ -82,7 +82,7 @@ public static TCollection MustNotBeNullOrEmpty([ValidatedNotNull] t /// Thrown when has no items, or when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static TCollection MustNotBeNullOrEmpty([ValidatedNotNull] this TCollection? parameter, Func exceptionFactory) where TCollection : class, IEnumerable + public static TCollection MustNotBeNullOrEmpty([NotNull, ValidatedNotNull] this TCollection? parameter, Func exceptionFactory) where TCollection : class, IEnumerable { if (parameter is null || parameter.Count() == 0) Throw.CustomException(exceptionFactory, parameter); From 16b5d6ceae24b81a8f2d78c75d1b16ec1bb83dfc Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sat, 19 Oct 2024 06:15:25 +0200 Subject: [PATCH 21/97] fix: add NotNull attribute to MustContain for collections Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 20 +++++++++++++++++++ .../Check.EnumerableAssertions.cs | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 0d5c037d..2e77e97c 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -366,4 +366,24 @@ static int TestMustNotBeNullOrEmptyWithDelegate(int[]? input) return input.Length; } } + + [Fact] + public static void CheckMustContain() + { + TestMustContain([1, 2, 3]).Should().Be(3); + TestMustContainWithDelegate([1, 2, 3]).Should().Be(3); + return; + + static int TestMustContain(int[]? input) + { + input.MustContain(2); + return input.Length; + } + + static int TestMustContainWithDelegate(int[]? input) + { + input.MustContain(2, (_, _) => new Exception()); + return input.Length; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.EnumerableAssertions.cs b/Code/Light.GuardClauses/Check.EnumerableAssertions.cs index c1c1b85f..d5c5c008 100644 --- a/Code/Light.GuardClauses/Check.EnumerableAssertions.cs +++ b/Code/Light.GuardClauses/Check.EnumerableAssertions.cs @@ -100,7 +100,7 @@ public static TCollection MustNotBeNullOrEmpty([NotNull, ValidatedN /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static TCollection MustContain([ValidatedNotNull] this TCollection? parameter, TItem item, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where TCollection : class, IEnumerable + public static TCollection MustContain([NotNull, ValidatedNotNull] this TCollection? parameter, TItem item, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where TCollection : class, IEnumerable { if (parameter is ICollection collection) { @@ -123,7 +123,7 @@ public static TCollection MustContain([ValidatedNotNull] thi /// Your custom exception thrown when does not contain , or when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static TCollection MustContain([ValidatedNotNull] this TCollection? parameter, TItem item, Func exceptionFactory) where TCollection : class, IEnumerable + public static TCollection MustContain([NotNull, ValidatedNotNull] this TCollection? parameter, TItem item, Func exceptionFactory) where TCollection : class, IEnumerable { if (parameter is ICollection collection) { From 06fccd6d155ac600ec7674c3dc080819d0607ea2 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sat, 19 Oct 2024 06:23:01 +0200 Subject: [PATCH 22/97] fix: remove warnings and upgrade NuGet packages in main test project Signed-off-by: Kenny Pflug --- Code/Light.GuardClauses.AllProjects.sln.DotSettings | 1 + .../Issues/Issue72NotNullAttributeTests.cs | 3 +++ .../Light.GuardClauses.Tests.csproj | 11 +++++++---- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Code/Light.GuardClauses.AllProjects.sln.DotSettings b/Code/Light.GuardClauses.AllProjects.sln.DotSettings index 5c674a62..2c4519b4 100644 --- a/Code/Light.GuardClauses.AllProjects.sln.DotSettings +++ b/Code/Light.GuardClauses.AllProjects.sln.DotSettings @@ -249,6 +249,7 @@ True True True + True True True True diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 2e77e97c..7b3d574c 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -6,6 +6,9 @@ namespace Light.GuardClauses.Tests.Issues; +// This occurs for delegates that create exceptions, and we just turn it off for these tests +#pragma warning disable CS8622 // Nullability of reference types in type of parameter doesn't match the target delegate type. + public static class Issue72NotNullAttributeTests { [Fact] diff --git a/Code/Light.GuardClauses.Tests/Light.GuardClauses.Tests.csproj b/Code/Light.GuardClauses.Tests/Light.GuardClauses.Tests.csproj index f062d75c..34f0e4e0 100644 --- a/Code/Light.GuardClauses.Tests/Light.GuardClauses.Tests.csproj +++ b/Code/Light.GuardClauses.Tests/Light.GuardClauses.Tests.csproj @@ -10,10 +10,13 @@ - - - - + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + From 1e697fe46c6767b141435844de4078a3452415b4 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sat, 19 Oct 2024 06:27:24 +0200 Subject: [PATCH 23/97] fix: add NotNull attribute to MustNotContain Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 24 +++++++++++++++++-- .../Check.EnumerableAssertions.cs | 4 ++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 7b3d574c..237e8215 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -349,7 +349,7 @@ static int TestMustHaveCountWithDelegate(string[]? input) return input.Length; } } - + [Fact] public static void CheckMustNotBeNullOrEmpty() { @@ -369,7 +369,7 @@ static int TestMustNotBeNullOrEmptyWithDelegate(int[]? input) return input.Length; } } - + [Fact] public static void CheckMustContain() { @@ -389,4 +389,24 @@ static int TestMustContainWithDelegate(int[]? input) return input.Length; } } + + [Fact] + public static void CheckMustNotContain() + { + TestMustNotContain([1, 2, 3]).Should().Be(3); + TestMustNotContainWithDelegate([1, 2, 3]).Should().Be(3); + return; + + static int TestMustNotContain(int[]? input) + { + input.MustNotContain(4); + return input.Length; + } + + static int TestMustNotContainWithDelegate(int[]? input) + { + input.MustNotContain(4, (_, _) => new Exception()); + return input.Length; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.EnumerableAssertions.cs b/Code/Light.GuardClauses/Check.EnumerableAssertions.cs index d5c5c008..9fd34d74 100644 --- a/Code/Light.GuardClauses/Check.EnumerableAssertions.cs +++ b/Code/Light.GuardClauses/Check.EnumerableAssertions.cs @@ -148,7 +148,7 @@ public static TCollection MustContain([NotNull, ValidatedNot /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static TCollection MustNotContain([ValidatedNotNull] this TCollection? parameter, TItem item, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where TCollection : class, IEnumerable + public static TCollection MustNotContain([NotNull, ValidatedNotNull] this TCollection? parameter, TItem item, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where TCollection : class, IEnumerable { if (parameter is ICollection collection) { @@ -171,7 +171,7 @@ public static TCollection MustNotContain([ValidatedNotNull] /// Your custom exception thrown when contains . [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static TCollection MustNotContain([ValidatedNotNull] this TCollection? parameter, TItem item, Func exceptionFactory) where TCollection : class, IEnumerable + public static TCollection MustNotContain([NotNull, ValidatedNotNull] this TCollection? parameter, TItem item, Func exceptionFactory) where TCollection : class, IEnumerable { if (parameter is ICollection collection) { From 59474f0995583bc80365c805b186f6e612cd575e Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sat, 19 Oct 2024 06:35:53 +0200 Subject: [PATCH 24/97] fix: add NotNull attribute to IsOneOf Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 13 +++++++++++++ .../Check.EnumerableAssertions.cs | 3 ++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 237e8215..6a758dbf 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -409,4 +409,17 @@ static int TestMustNotContainWithDelegate(int[]? input) return input.Length; } } + + [Fact] + public static void CheckIsOneOf() + { + TestIsOneOf("foo").Should().Be(3); + return; + + static int TestIsOneOf(string? input) + { + 'o'.IsOneOf(input!); + return input.Length; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.EnumerableAssertions.cs b/Code/Light.GuardClauses/Check.EnumerableAssertions.cs index 9fd34d74..dc883f52 100644 --- a/Code/Light.GuardClauses/Check.EnumerableAssertions.cs +++ b/Code/Light.GuardClauses/Check.EnumerableAssertions.cs @@ -193,7 +193,8 @@ public static TCollection MustNotContain([NotNull, Validated /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("items:null => halt")] - public static bool IsOneOf(this TItem item, [ValidatedNotNull] IEnumerable items) + // ReSharper disable once RedundantNullableFlowAttribute - the attribute has an effect, see Issue72NotNullAttribute tests + public static bool IsOneOf(this TItem item, [NotNull, ValidatedNotNull] IEnumerable items) { if (items is ICollection collection) return collection.Contains(item); From 6e187744251c9be1caf827b08df6190e220ae6e2 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sat, 19 Oct 2024 06:41:20 +0200 Subject: [PATCH 25/97] fix: add NotNull attribute to MustBeOneOf Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 20 +++++++++++++++++++ .../Check.EnumerableAssertions.cs | 9 +++++---- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 6a758dbf..63145b4d 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -422,4 +422,24 @@ static int TestIsOneOf(string? input) return input.Length; } } + + [Fact] + public static void CheckMustBeOneOf() + { + TestMustBeOneOf("foo").Should().Be(3); + TestMustBeOneOfWithDelegate("foo").Should().Be(3); + return; + + static int TestMustBeOneOf(string? input) + { + 'o'.MustBeOneOf(input!); + return input.Length; + } + + static int TestMustBeOneOfWithDelegate(string? input) + { + 'o'.MustBeOneOf(input!, (_, _) => new Exception()); + return input.Length; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.EnumerableAssertions.cs b/Code/Light.GuardClauses/Check.EnumerableAssertions.cs index dc883f52..eb0b4ce3 100644 --- a/Code/Light.GuardClauses/Check.EnumerableAssertions.cs +++ b/Code/Light.GuardClauses/Check.EnumerableAssertions.cs @@ -193,7 +193,7 @@ public static TCollection MustNotContain([NotNull, Validated /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("items:null => halt")] - // ReSharper disable once RedundantNullableFlowAttribute - the attribute has an effect, see Issue72NotNullAttribute tests + // ReSharper disable once RedundantNullableFlowAttribute - the attribute has an effect, see Issue72NotNullAttribute tests public static bool IsOneOf(this TItem item, [NotNull, ValidatedNotNull] IEnumerable items) { if (items is ICollection collection) @@ -216,7 +216,8 @@ public static bool IsOneOf(this TItem item, [NotNull, ValidatedNotNull] I /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("items:null => halt")] - public static TItem MustBeOneOf(this TItem parameter, [ValidatedNotNull] IEnumerable items, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) + // ReSharper disable once RedundantNullableFlowAttribute - the attribute has an effect, see Issue72NotNullAttribute tests + public static TItem MustBeOneOf(this TItem parameter, [NotNull, ValidatedNotNull] IEnumerable items, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { // ReSharper disable PossibleMultipleEnumeration if (!parameter.IsOneOf(items.MustNotBeNull(nameof(items), message))) @@ -234,9 +235,9 @@ public static TItem MustBeOneOf(this TItem parameter, [ValidatedNotNull] /// Your custom exception thrown when is not equal to one of the specified , or when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("items:null => halt")] - public static TItem MustBeOneOf(this TItem parameter, [ValidatedNotNull] TCollection items, Func exceptionFactory) where TCollection : class, IEnumerable + public static TItem MustBeOneOf(this TItem parameter, [NotNull, ValidatedNotNull] TCollection items, Func exceptionFactory) where TCollection : class, IEnumerable { - // ReSharper disable once ConditionIsAlwaysTrueOrFalse - caller might have NRTs turned off + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off if (items is null || !parameter.IsOneOf(items)) Throw.CustomException(exceptionFactory, parameter, items!); return parameter; From e760f76df5305eaa7a38a3176c8074ad5067b2fc Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sat, 19 Oct 2024 06:43:42 +0200 Subject: [PATCH 26/97] fix: add NotNull attribute to MustNotBeOneOf Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 20 +++++++++++++++++++ .../Check.EnumerableAssertions.cs | 7 ++++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 63145b4d..e84c5014 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -442,4 +442,24 @@ static int TestMustBeOneOfWithDelegate(string? input) return input.Length; } } + + [Fact] + public static void CheckMustNotBeOneOf() + { + TestMustNotBeOneOf("bar").Should().Be(3); + TestMustNotBeOneOfWithDelegate("bar").Should().Be(3); + return; + + static int TestMustNotBeOneOf(string? input) + { + 'o'.MustNotBeOneOf(input!); + return input.Length; + } + + static int TestMustNotBeOneOfWithDelegate(string? input) + { + 'o'.MustNotBeOneOf(input!, (_, _) => new Exception()); + return input.Length; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.EnumerableAssertions.cs b/Code/Light.GuardClauses/Check.EnumerableAssertions.cs index eb0b4ce3..a1e7aaeb 100644 --- a/Code/Light.GuardClauses/Check.EnumerableAssertions.cs +++ b/Code/Light.GuardClauses/Check.EnumerableAssertions.cs @@ -254,7 +254,8 @@ public static TItem MustBeOneOf(this TItem parameter, [NotNu /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("items:null => halt")] - public static TItem MustNotBeOneOf(this TItem parameter, [ValidatedNotNull] IEnumerable items, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) + // ReSharper disable once RedundantNullableFlowAttribute - the attribute has an effect, see Issue72NotNullAttribute tests + public static TItem MustNotBeOneOf(this TItem parameter, [NotNull, ValidatedNotNull] IEnumerable items, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { // ReSharper disable PossibleMultipleEnumeration if (parameter.IsOneOf(items.MustNotBeNull(nameof(items), message))) @@ -272,9 +273,9 @@ public static TItem MustNotBeOneOf(this TItem parameter, [ValidatedNotNul /// Your custom exception thrown when is equal to one of the specified , or when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("items:null => halt")] - public static TItem MustNotBeOneOf(this TItem parameter, [ValidatedNotNull] TCollection items, Func exceptionFactory) where TCollection : class, IEnumerable + public static TItem MustNotBeOneOf(this TItem parameter, [NotNull, ValidatedNotNull] TCollection items, Func exceptionFactory) where TCollection : class, IEnumerable { - // ReSharper disable once ConditionIsAlwaysTrueOrFalse - caller might have NRTs turned off + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off if (items is null || parameter.IsOneOf(items)) Throw.CustomException(exceptionFactory, parameter, items!); return parameter; From edd94dd805fc2160855e6275fb4dd1a0b5b67ab5 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sat, 19 Oct 2024 06:45:53 +0200 Subject: [PATCH 27/97] chore: remove redundant null-forgiving operators in EnumerableAssertions Signed-off-by: Kenny Pflug --- .../Check.EnumerableAssertions.cs | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Code/Light.GuardClauses/Check.EnumerableAssertions.cs b/Code/Light.GuardClauses/Check.EnumerableAssertions.cs index a1e7aaeb..94cade61 100644 --- a/Code/Light.GuardClauses/Check.EnumerableAssertions.cs +++ b/Code/Light.GuardClauses/Check.EnumerableAssertions.cs @@ -27,8 +27,8 @@ public static partial class Check public static TCollection MustHaveCount([NotNull, ValidatedNotNull] this TCollection? parameter, int count, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where TCollection : class, IEnumerable { if (parameter!.Count(parameterName, message) != count) - Throw.InvalidCollectionCount(parameter!, count, parameterName, message); - return parameter!; + Throw.InvalidCollectionCount(parameter, count, parameterName, message); + return parameter; } /// @@ -71,7 +71,7 @@ public static TCollection MustNotBeNullOrEmpty([NotNull, ValidatedN { if (parameter.Count(parameterName, message) == 0) Throw.EmptyCollection(parameterName, message); - return parameter!; + return parameter; } /// @@ -110,8 +110,8 @@ public static TCollection MustContain([NotNull, ValidatedNot } if (!parameter.MustNotBeNull(parameterName, message).Contains(item)) - Throw.MissingItem(parameter!, item, parameterName, message); - return parameter!; + Throw.MissingItem(parameter, item, parameterName, message); + return parameter; } /// @@ -158,8 +158,8 @@ public static TCollection MustNotContain([NotNull, Validated } if (parameter.MustNotBeNull(parameterName, message).Contains(item)) - Throw.ExistingItem(parameter!, item, parameterName, message); - return parameter!; + Throw.ExistingItem(parameter, item, parameterName, message); + return parameter; } /// @@ -295,8 +295,8 @@ public static TItem MustNotBeOneOf(this TItem parameter, [No public static TCollection MustHaveMinimumCount([ValidatedNotNull] this TCollection? parameter, int count, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where TCollection : class, IEnumerable { if (parameter.Count(parameterName, message) < count) - Throw.InvalidMinimumCollectionCount(parameter!, count, parameterName, message); - return parameter!; + Throw.InvalidMinimumCollectionCount(parameter, count, parameterName, message); + return parameter; } /// @@ -329,8 +329,8 @@ public static TCollection MustHaveMinimumCount([ValidatedNotNull] t public static TCollection MustHaveMaximumCount([ValidatedNotNull] this TCollection? parameter, int count, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where TCollection : class, IEnumerable { if (parameter.Count(parameterName, message) > count) - Throw.InvalidMaximumCollectionCount(parameter!, count, parameterName, message); - return parameter!; + Throw.InvalidMaximumCollectionCount(parameter, count, parameterName, message); + return parameter; } /// From b06e9cecfcecc123858a26eb7cc5d5821189fac3 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sat, 19 Oct 2024 06:48:00 +0200 Subject: [PATCH 28/97] fix: add NotNull attribute to MustHaveMinimumCount Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 20 +++++++++++++++++++ .../Check.EnumerableAssertions.cs | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index e84c5014..613a31c9 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -462,4 +462,24 @@ static int TestMustNotBeOneOfWithDelegate(string? input) return input.Length; } } + + [Fact] + public static void CheckMustHaveMinimumCount() + { + TestMustHaveMinimumCount([1, 2, 3]).Should().Be(3); + TestMustHaveMinimumCountWithDelegate([1, 2, 3]).Should().Be(3); + return; + + static int TestMustHaveMinimumCount(int[]? input) + { + input.MustHaveMinimumCount(2); + return input.Length; + } + + static int TestMustHaveMinimumCountWithDelegate(int[]? input) + { + input.MustHaveMinimumCount(2, (_, _) => new Exception()); + return input.Length; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.EnumerableAssertions.cs b/Code/Light.GuardClauses/Check.EnumerableAssertions.cs index 94cade61..a266ed78 100644 --- a/Code/Light.GuardClauses/Check.EnumerableAssertions.cs +++ b/Code/Light.GuardClauses/Check.EnumerableAssertions.cs @@ -292,7 +292,7 @@ public static TItem MustNotBeOneOf(this TItem parameter, [No /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static TCollection MustHaveMinimumCount([ValidatedNotNull] this TCollection? parameter, int count, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where TCollection : class, IEnumerable + public static TCollection MustHaveMinimumCount([NotNull, ValidatedNotNull] this TCollection? parameter, int count, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where TCollection : class, IEnumerable { if (parameter.Count(parameterName, message) < count) Throw.InvalidMinimumCollectionCount(parameter, count, parameterName, message); @@ -308,7 +308,7 @@ public static TCollection MustHaveMinimumCount([ValidatedNotNull] t /// Your custom exception thrown when does not contain at least the specified number of items, or when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static TCollection MustHaveMinimumCount([ValidatedNotNull] this TCollection? parameter, int count, Func exceptionFactory) where TCollection : class, IEnumerable + public static TCollection MustHaveMinimumCount([NotNull, ValidatedNotNull] this TCollection? parameter, int count, Func exceptionFactory) where TCollection : class, IEnumerable { if (parameter is null || parameter.Count() < count) Throw.CustomException(exceptionFactory, parameter, count); From 431dc6fd3537c71d68a31caacfba91fe617981fe Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sat, 19 Oct 2024 06:49:39 +0200 Subject: [PATCH 29/97] fix: add NotNull attribute to MustHaveMaximumCount Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 20 +++++++++++++++++++ .../Check.EnumerableAssertions.cs | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 613a31c9..72235ba3 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -482,4 +482,24 @@ static int TestMustHaveMinimumCountWithDelegate(int[]? input) return input.Length; } } + + [Fact] + public static void CheckMustHaveMaximumCount() + { + TestMustHaveMaximumCount([1, 2, 3]).Should().Be(3); + TestMustHaveMaximumCountWithDelegate([1, 2, 3]).Should().Be(3); + return; + + static int TestMustHaveMaximumCount(int[]? input) + { + input.MustHaveMaximumCount(3); + return input.Length; + } + + static int TestMustHaveMaximumCountWithDelegate(int[]? input) + { + input.MustHaveMaximumCount(3, (_, _) => new Exception()); + return input.Length; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.EnumerableAssertions.cs b/Code/Light.GuardClauses/Check.EnumerableAssertions.cs index a266ed78..a67209bb 100644 --- a/Code/Light.GuardClauses/Check.EnumerableAssertions.cs +++ b/Code/Light.GuardClauses/Check.EnumerableAssertions.cs @@ -326,7 +326,7 @@ public static TCollection MustHaveMinimumCount([NotNull, ValidatedN /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static TCollection MustHaveMaximumCount([ValidatedNotNull] this TCollection? parameter, int count, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where TCollection : class, IEnumerable + public static TCollection MustHaveMaximumCount([NotNull, ValidatedNotNull] this TCollection? parameter, int count, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where TCollection : class, IEnumerable { if (parameter.Count(parameterName, message) > count) Throw.InvalidMaximumCollectionCount(parameter, count, parameterName, message); @@ -342,7 +342,7 @@ public static TCollection MustHaveMaximumCount([ValidatedNotNull] t /// Your custom exception thrown when does not contain at most the specified number of items, or when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static TCollection MustHaveMaximumCount([ValidatedNotNull] this TCollection? parameter, int count, Func exceptionFactory) where TCollection : class, IEnumerable + public static TCollection MustHaveMaximumCount([NotNull, ValidatedNotNull] this TCollection? parameter, int count, Func exceptionFactory) where TCollection : class, IEnumerable { if (parameter is null || parameter.Count() > count) Throw.CustomException(exceptionFactory, parameter, count); From 283bd90eb0251e79744b671a6212155952599eb2 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sat, 19 Oct 2024 07:03:49 +0200 Subject: [PATCH 30/97] chore: remove obsolete null-forgiving operators in StringAssertions Signed-off-by: Kenny Pflug --- .../Check.StringAssertions.cs | 82 +++++++++---------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/Code/Light.GuardClauses/Check.StringAssertions.cs b/Code/Light.GuardClauses/Check.StringAssertions.cs index 31815fbb..8a186156 100644 --- a/Code/Light.GuardClauses/Check.StringAssertions.cs +++ b/Code/Light.GuardClauses/Check.StringAssertions.cs @@ -283,8 +283,8 @@ public static string MustNotBeNullOrWhiteSpace([ValidatedNotNull] this string? p public static string MustMatch([ValidatedNotNull] this string? parameter, Regex regex, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (!regex.MustNotBeNull(nameof(regex), message).IsMatch(parameter.MustNotBeNull(parameterName, message))) - Throw.StringDoesNotMatch(parameter!, regex, parameterName, message); - return parameter!; + Throw.StringDoesNotMatch(parameter, regex, parameterName, message); + return parameter; } /// @@ -343,8 +343,8 @@ public static bool Equals(this string? @string, string? value, StringComparisonT public static string MustContain([ValidatedNotNull] this string? parameter, string? value, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (!parameter.MustNotBeNull(parameterName, message).Contains(value.MustNotBeNull(nameof(value), message))) - Throw.StringDoesNotContain(parameter!, value!, parameterName, message); - return parameter!; + Throw.StringDoesNotContain(parameter, value, parameterName, message); + return parameter; } /// @@ -384,8 +384,8 @@ public static string MustContain([ValidatedNotNull] this string? parameter, stri public static string MustContain([ValidatedNotNull] this string? parameter, string value, StringComparison comparisonType, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (parameter.MustNotBeNull(parameterName, message).IndexOf(value.MustNotBeNull(nameof(value), message), comparisonType) < 0) - Throw.StringDoesNotContain(parameter!, value, comparisonType, parameterName, message); - return parameter!; + Throw.StringDoesNotContain(parameter, value, comparisonType, parameterName, message); + return parameter; } /// @@ -425,8 +425,8 @@ public static string MustContain([ValidatedNotNull] this string? parameter, stri public static string MustNotContain([ValidatedNotNull] this string? parameter, string value, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (parameter.MustNotBeNull(parameterName, message).Contains(value.MustNotBeNull(nameof(value), message))) - Throw.StringContains(parameter!, value, parameterName, message); - return parameter!; + Throw.StringContains(parameter, value, parameterName, message); + return parameter; } /// @@ -466,8 +466,8 @@ public static string MustNotContain([ValidatedNotNull] this string? parameter, s public static string MustNotContain([ValidatedNotNull] this string? parameter, string value, StringComparison comparisonType, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (parameter.MustNotBeNull(parameterName, message).IndexOf(value.MustNotBeNull(nameof(value), message), comparisonType) >= 0) - Throw.StringContains(parameter!, value, comparisonType, parameterName, message); - return parameter!; + Throw.StringContains(parameter, value, comparisonType, parameterName, message); + return parameter; } /// @@ -547,8 +547,8 @@ public static bool IsSubstringOf(this string value, string other, StringComparis public static string MustBeSubstringOf([ValidatedNotNull] this string? parameter, string value, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (!value.MustNotBeNull(nameof(value), message).Contains(parameter.MustNotBeNull(parameterName, message))) - Throw.NotSubstring(parameter!, value, parameterName, message); - return parameter!; + Throw.NotSubstring(parameter, value, parameterName, message); + return parameter; } /// @@ -588,8 +588,8 @@ public static string MustBeSubstringOf([ValidatedNotNull] this string? parameter public static string MustBeSubstringOf([ValidatedNotNull] this string? parameter, string value, StringComparison comparisonType, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (value.MustNotBeNull(nameof(value), message).IndexOf(parameter.MustNotBeNull(parameterName, message), comparisonType) == -1) - Throw.NotSubstring(parameter!, value, comparisonType, parameterName, message); - return parameter!; + Throw.NotSubstring(parameter, value, comparisonType, parameterName, message); + return parameter; } /// @@ -629,8 +629,8 @@ public static string MustBeSubstringOf([ValidatedNotNull] this string? parameter public static string MustNotBeSubstringOf([ValidatedNotNull] this string? parameter, string value, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (value.MustNotBeNull(nameof(value), message).Contains(parameter.MustNotBeNull(parameterName, message))) - Throw.Substring(parameter!, value, parameterName, message); - return parameter!; + Throw.Substring(parameter, value, parameterName, message); + return parameter; } /// @@ -671,8 +671,8 @@ public static string MustNotBeSubstringOf([ValidatedNotNull] this string? parame public static string MustNotBeSubstringOf([ValidatedNotNull] this string? parameter, string value, StringComparison comparisonType, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (value.MustNotBeNull(nameof(value), message).IndexOf(parameter.MustNotBeNull(parameterName, message), comparisonType) != -1) - Throw.Substring(parameter!, value, comparisonType, parameterName, message); - return parameter!; + Throw.Substring(parameter, value, comparisonType, parameterName, message); + return parameter; } /// @@ -733,8 +733,8 @@ public static bool IsEmailAddress([NotNullWhen(true)] this string? emailAddress, public static string MustBeEmailAddress([ValidatedNotNull] this string? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (!parameter.MustNotBeNull(parameterName, message).IsEmailAddress()) - Throw.InvalidEmailAddress(parameter!, parameterName, message); - return parameter!; + Throw.InvalidEmailAddress(parameter, parameterName, message); + return parameter; } /// @@ -768,8 +768,8 @@ public static string MustBeEmailAddress([ValidatedNotNull] this string? paramete public static string MustBeEmailAddress([ValidatedNotNull] this string? parameter, Regex emailAddressPattern, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (!parameter.MustNotBeNull(parameterName, message).IsEmailAddress(emailAddressPattern)) - Throw.InvalidEmailAddress(parameter!, parameterName, message); - return parameter!; + Throw.InvalidEmailAddress(parameter, parameterName, message); + return parameter; } /// @@ -804,8 +804,8 @@ public static string MustBeEmailAddress([ValidatedNotNull] this string? paramete public static string MustBeShorterThan([ValidatedNotNull] this string? parameter, int length, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (parameter.MustNotBeNull(parameterName, message).Length >= length) - Throw.StringNotShorterThan(parameter!, length, parameterName, message); - return parameter!; + Throw.StringNotShorterThan(parameter, length, parameterName, message); + return parameter; } /// @@ -838,8 +838,8 @@ public static string MustBeShorterThan([ValidatedNotNull] this string? parameter public static string MustBeShorterThanOrEqualTo([ValidatedNotNull] this string? parameter, int length, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (parameter.MustNotBeNull(parameterName, message).Length > length) - Throw.StringNotShorterThanOrEqualTo(parameter!, length, parameterName, message); - return parameter!; + Throw.StringNotShorterThanOrEqualTo(parameter, length, parameterName, message); + return parameter; } /// @@ -865,15 +865,15 @@ public static string MustBeShorterThanOrEqualTo([ValidatedNotNull] this string? /// The asserted length of the string. /// The name of the parameter (optional). /// The message that will be passed to the resulting exception (optional). - /// Thrown when has a length different than . + /// Thrown when has a length other than . /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] public static string MustHaveLength([ValidatedNotNull] this string? parameter, int length, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (parameter.MustNotBeNull(parameterName, message).Length != length) - Throw.StringLengthNotEqualTo(parameter!, length, parameterName, message); - return parameter!; + Throw.StringLengthNotEqualTo(parameter, length, parameterName, message); + return parameter; } /// @@ -882,7 +882,7 @@ public static string MustHaveLength([ValidatedNotNull] this string? parameter, i /// The string to be checked. /// The asserted length of the string. /// The delegate that creates your custom exception. and are passed to this delegate. - /// Your custom exception thrown when is null or when it has a length different than . + /// Your custom exception thrown when is null or when it has a length other than . [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] public static string MustHaveLength([ValidatedNotNull] this string? parameter, int length, Func exceptionFactory) @@ -906,8 +906,8 @@ public static string MustHaveLength([ValidatedNotNull] this string? parameter, i public static string MustBeLongerThan([ValidatedNotNull] this string? parameter, int length, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (parameter.MustNotBeNull(parameterName, message).Length <= length) - Throw.StringNotLongerThan(parameter!, length, parameterName, message); - return parameter!; + Throw.StringNotLongerThan(parameter, length, parameterName, message); + return parameter; } /// @@ -940,8 +940,8 @@ public static string MustBeLongerThan([ValidatedNotNull] this string? parameter, public static string MustBeLongerThanOrEqualTo([ValidatedNotNull] this string? parameter, int length, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (parameter.MustNotBeNull(parameterName, message).Length < length) - Throw.StringNotLongerThanOrEqualTo(parameter!, length, parameterName, message); - return parameter!; + Throw.StringNotLongerThanOrEqualTo(parameter, length, parameterName, message); + return parameter; } /// @@ -974,8 +974,8 @@ public static string MustBeLongerThanOrEqualTo([ValidatedNotNull] this string? p public static string MustHaveLengthIn([ValidatedNotNull] this string? parameter, Range range, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (!range.IsValueWithinRange(parameter.MustNotBeNull(parameterName, message).Length)) - Throw.StringLengthNotInRange(parameter!, range, parameterName, message); - return parameter!; + Throw.StringLengthNotInRange(parameter, range, parameterName, message); + return parameter; } /// @@ -1015,8 +1015,8 @@ public static string MustHaveLengthIn([ValidatedNotNull] this string? parameter, public static string MustBeNewLine([ValidatedNotNull] this string? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (!parameter.MustNotBeNull(parameterName, message).IsNewLine()) - Throw.NotNewLine(parameter!, parameterName, message); - return parameter!; + Throw.NotNewLine(parameter, parameterName, message); + return parameter; } /// @@ -1085,7 +1085,7 @@ public static string MustBeTrimmed([ValidatedNotNull] this string? parameter, [C { if (!parameter.MustNotBeNull(parameterName, message).IsTrimmed()) Throw.NotTrimmed(parameter, parameterName, message); - return parameter!; + return parameter; } @@ -1153,7 +1153,7 @@ public static string MustBeTrimmedAtStart([ValidatedNotNull] this string? parame { if (!parameter.MustNotBeNull(parameterName, message).IsTrimmedAtStart()) Throw.NotTrimmedAtStart(parameter, parameterName, message); - return parameter!; + return parameter; } /// @@ -1220,7 +1220,7 @@ public static string MustBeTrimmedAtEnd([ValidatedNotNull] this string? paramete { if (!parameter.MustNotBeNull(parameterName, message).IsTrimmedAtEnd()) Throw.NotTrimmedAtEnd(parameter, parameterName, message); - return parameter!; + return parameter; } /// From e22a7c41c223c448a1e1234f3e19b5242dc5c4a4 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 20 Oct 2024 18:54:39 +0200 Subject: [PATCH 31/97] fix: add NotNull attribute to MustNotBeNullOrEmpty for strings Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 20 +++++++++++++++++++ .../Check.StringAssertions.cs | 13 +++++------- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 72235ba3..9e48327a 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -502,4 +502,24 @@ static int TestMustHaveMaximumCountWithDelegate(int[]? input) return input.Length; } } + + [Fact] + public static void CheckMustNotBeNullOrEmptyString() + { + TestMustNotBeNullOrEmptyString("foo").Should().Be(3); + TestMustNotBeNullOrEmptyStringWithDelegate("foo").Should().Be(3); + return; + + static int TestMustNotBeNullOrEmptyString(string? input) + { + input.MustNotBeNullOrEmpty(); + return input.Length; + } + + static int TestMustNotBeNullOrEmptyStringWithDelegate(string? input) + { + input.MustNotBeNullOrEmpty(_ => new Exception()); + return input.Length; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.StringAssertions.cs b/Code/Light.GuardClauses/Check.StringAssertions.cs index 8a186156..fca4a618 100644 --- a/Code/Light.GuardClauses/Check.StringAssertions.cs +++ b/Code/Light.GuardClauses/Check.StringAssertions.cs @@ -5,6 +5,7 @@ using Light.GuardClauses.Exceptions; using Light.GuardClauses.FrameworkExtensions; using System.Runtime.CompilerServices; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; namespace Light.GuardClauses; @@ -28,7 +29,7 @@ public static partial class Check /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustNotBeNullOrEmpty([ValidatedNotNull] this string? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) + public static string MustNotBeNullOrEmpty([NotNull, ValidatedNotNull] this string? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (parameter is null) Throw.ArgumentNull(parameterName, message); @@ -46,16 +47,12 @@ public static string MustNotBeNullOrEmpty([ValidatedNotNull] this string? parame /// Your custom exception thrown when is an empty string or null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] - public static string MustNotBeNullOrEmpty([ValidatedNotNull] this string? parameter, Func exceptionFactory) + public static string MustNotBeNullOrEmpty([NotNull, ValidatedNotNull] this string? parameter, Func exceptionFactory) { - if (string.IsNullOrEmpty(parameter)) + if (parameter.IsNullOrEmpty()) Throw.CustomException(exceptionFactory, parameter); - -#if NETSTANDARD2_0 - return parameter!; -#else + return parameter; -#endif } /// From f4ba4460167567c74b5a0b63d7f0bd1d899a80be Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 20 Oct 2024 18:59:37 +0200 Subject: [PATCH 32/97] fix: add NotNull attribute to MustNotBeNullOrWhiteSpace Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 20 +++++++++++++++++++ .../Check.StringAssertions.cs | 6 +++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 9e48327a..c49fc964 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -522,4 +522,24 @@ static int TestMustNotBeNullOrEmptyStringWithDelegate(string? input) return input.Length; } } + + [Fact] + public static void CheckMustNotBeNullOrWhiteSpace() + { + TestMustNotBeNullOrWhiteSpace("foo").Should().Be(3); + TestMustNotBeNullOrWhiteSpaceWithDelegate("foo").Should().Be(3); + return; + + static int TestMustNotBeNullOrWhiteSpace(string? input) + { + input.MustNotBeNullOrWhiteSpace(); + return input.Length; + } + + static int TestMustNotBeNullOrWhiteSpaceWithDelegate(string? input) + { + input.MustNotBeNullOrWhiteSpace(_ => new Exception()); + return input.Length; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.StringAssertions.cs b/Code/Light.GuardClauses/Check.StringAssertions.cs index fca4a618..f2d359fb 100644 --- a/Code/Light.GuardClauses/Check.StringAssertions.cs +++ b/Code/Light.GuardClauses/Check.StringAssertions.cs @@ -74,11 +74,11 @@ public static string MustNotBeNullOrEmpty([NotNull, ValidatedNotNull] this strin /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustNotBeNullOrWhiteSpace([ValidatedNotNull] this string? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) + public static string MustNotBeNullOrWhiteSpace([NotNull, ValidatedNotNull] this string? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { parameter.MustNotBeNullOrEmpty(parameterName, message); - foreach (var character in parameter!) + foreach (var character in parameter) { if (!character.IsWhiteSpace()) return parameter; @@ -96,7 +96,7 @@ public static string MustNotBeNullOrWhiteSpace([ValidatedNotNull] this string? p /// Your custom exception thrown when is null, empty, or contains only white space. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory: null => halt")] - public static string MustNotBeNullOrWhiteSpace([ValidatedNotNull] this string? parameter, Func exceptionFactory) + public static string MustNotBeNullOrWhiteSpace([NotNull, ValidatedNotNull] this string? parameter, Func exceptionFactory) { if (parameter.IsNullOrWhiteSpace()) Throw.CustomException(exceptionFactory, parameter); From 19e728fdad09f543eb29381c80884d05072d5d04 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 20 Oct 2024 19:02:55 +0200 Subject: [PATCH 33/97] fix: add NotNull attribute to MustMatch Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 25 +++++++++++++++++-- .../Check.StringAssertions.cs | 4 +-- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index c49fc964..158bd099 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -1,6 +1,7 @@ #nullable enable using System; +using System.Text.RegularExpressions; using FluentAssertions; using Xunit; @@ -502,7 +503,7 @@ static int TestMustHaveMaximumCountWithDelegate(int[]? input) return input.Length; } } - + [Fact] public static void CheckMustNotBeNullOrEmptyString() { @@ -522,7 +523,7 @@ static int TestMustNotBeNullOrEmptyStringWithDelegate(string? input) return input.Length; } } - + [Fact] public static void CheckMustNotBeNullOrWhiteSpace() { @@ -542,4 +543,24 @@ static int TestMustNotBeNullOrWhiteSpaceWithDelegate(string? input) return input.Length; } } + + [Fact] + public static void CheckMustMatch() + { + TestMustMatch("foo", "^f.*").Should().Be(3); + TestMustMatchWithDelegate("foo", "^f.*").Should().Be(3); + return; + + static int TestMustMatch(string? input, string pattern) + { + input.MustMatch(new Regex(pattern)); + return input.Length; + } + + static int TestMustMatchWithDelegate(string? input, string pattern) + { + input.MustMatch(new Regex(pattern), (_, _) => new Exception()); + return input.Length; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.StringAssertions.cs b/Code/Light.GuardClauses/Check.StringAssertions.cs index f2d359fb..a8366111 100644 --- a/Code/Light.GuardClauses/Check.StringAssertions.cs +++ b/Code/Light.GuardClauses/Check.StringAssertions.cs @@ -277,7 +277,7 @@ public static string MustNotBeNullOrWhiteSpace([NotNull, ValidatedNotNull] this /// Thrown when or is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; regex:null => halt")] - public static string MustMatch([ValidatedNotNull] this string? parameter, Regex regex, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) + public static string MustMatch([NotNull, ValidatedNotNull] this string? parameter, Regex regex, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (!regex.MustNotBeNull(nameof(regex), message).IsMatch(parameter.MustNotBeNull(parameterName, message))) Throw.StringDoesNotMatch(parameter, regex, parameterName, message); @@ -296,7 +296,7 @@ public static string MustMatch([ValidatedNotNull] this string? parameter, Regex /// or when is null. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static string MustMatch([ValidatedNotNull] this string? parameter, Regex regex, Func exceptionFactory) + public static string MustMatch([NotNull, ValidatedNotNull] this string? parameter, Regex regex, Func exceptionFactory) { // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off if (parameter is null || regex is null || !regex.IsMatch(parameter)) From e07463ac6c9fc27f9e10fb13f943e4e8b8139ab9 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 20 Oct 2024 19:08:08 +0200 Subject: [PATCH 34/97] fix: add NotNull attribute to MustContain for strings Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 36 ++++++++++++++++++- .../Check.StringAssertions.cs | 8 ++--- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 158bd099..de7621b6 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -372,7 +372,7 @@ static int TestMustNotBeNullOrEmptyWithDelegate(int[]? input) } [Fact] - public static void CheckMustContain() + public static void CheckMustContainForCollections() { TestMustContain([1, 2, 3]).Should().Be(3); TestMustContainWithDelegate([1, 2, 3]).Should().Be(3); @@ -563,4 +563,38 @@ static int TestMustMatchWithDelegate(string? input, string pattern) return input.Length; } } + + [Fact] + public static void CheckMustContainForStrings() + { + TestMustContain("foo").Should().Be(3); + TestMustContainWithDelegate("foo").Should().Be(3); + TestMustContainWithStringComparison("foo").Should().Be(3); + TestMustContainWithDelegateAndStringComparison("foo").Should().Be(3); + return; + + static int TestMustContain(string? input) + { + input.MustContain("oo"); + return input.Length; + } + + static int TestMustContainWithDelegate(string? input) + { + input.MustContain("oo", (_, _) => new Exception()); + return input.Length; + } + + static int TestMustContainWithStringComparison(string? input) + { + input.MustContain("OO", StringComparison.OrdinalIgnoreCase); + return input.Length; + } + + static int TestMustContainWithDelegateAndStringComparison(string? input) + { + input.MustContain("OO", StringComparison.OrdinalIgnoreCase, (_, _, _) => new Exception()); + return input.Length; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.StringAssertions.cs b/Code/Light.GuardClauses/Check.StringAssertions.cs index a8366111..aca06393 100644 --- a/Code/Light.GuardClauses/Check.StringAssertions.cs +++ b/Code/Light.GuardClauses/Check.StringAssertions.cs @@ -337,7 +337,7 @@ public static bool Equals(this string? @string, string? value, StringComparisonT /// Thrown when or is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustContain([ValidatedNotNull] this string? parameter, string? value, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) + public static string MustContain([NotNull, ValidatedNotNull] this string? parameter, string? value, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (!parameter.MustNotBeNull(parameterName, message).Contains(value.MustNotBeNull(nameof(value), message))) Throw.StringDoesNotContain(parameter, value, parameterName, message); @@ -357,7 +357,7 @@ public static string MustContain([ValidatedNotNull] this string? parameter, stri /// [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustContain([ValidatedNotNull] this string? parameter, string value, Func exceptionFactory) + public static string MustContain([NotNull, ValidatedNotNull] this string? parameter, string value, Func exceptionFactory) { // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off if (parameter is null || value is null || !parameter.Contains(value)) @@ -378,7 +378,7 @@ public static string MustContain([ValidatedNotNull] this string? parameter, stri /// Thrown when is not a valid value. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustContain([ValidatedNotNull] this string? parameter, string value, StringComparison comparisonType, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) + public static string MustContain([NotNull, ValidatedNotNull] this string? parameter, string value, StringComparison comparisonType, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (parameter.MustNotBeNull(parameterName, message).IndexOf(value.MustNotBeNull(nameof(value), message), comparisonType) < 0) Throw.StringDoesNotContain(parameter, value, comparisonType, parameterName, message); @@ -400,7 +400,7 @@ public static string MustContain([ValidatedNotNull] this string? parameter, stri /// [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustContain([ValidatedNotNull] this string? parameter, string value, StringComparison comparisonType, Func exceptionFactory) + public static string MustContain([NotNull, ValidatedNotNull] this string? parameter, string value, StringComparison comparisonType, Func exceptionFactory) { // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off if (parameter is null || value is null || !comparisonType.IsValidEnumValue() || parameter.IndexOf(value, comparisonType) < 0) From 64df624d52b86e0517918b40d4f08486cca13e01 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 20 Oct 2024 19:28:02 +0200 Subject: [PATCH 35/97] fix: add NotNull attribute to MustNotContain for strings Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 36 ++++++++++++++++++- .../Check.StringAssertions.cs | 8 ++--- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index de7621b6..3c1836e4 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -597,4 +597,38 @@ static int TestMustContainWithDelegateAndStringComparison(string? input) return input.Length; } } -} \ No newline at end of file + + [Fact] + public static void CheckMustNotContainForStrings() + { + TestMustNotContain("foo").Should().Be(3); + TestMustNotContainWithDelegate("foo").Should().Be(3); + TestMustNotContainWithStringComparison("foo").Should().Be(3); + TestMustNotContainWithDelegateAndStringComparison("foo").Should().Be(3); + return; + + static int TestMustNotContain(string? input) + { + input.MustNotContain("bar"); + return input.Length; + } + + static int TestMustNotContainWithDelegate(string? input) + { + input.MustNotContain("bar", (_, _) => new Exception()); + return input.Length; + } + + static int TestMustNotContainWithStringComparison(string? input) + { + input.MustNotContain("BAR", StringComparison.OrdinalIgnoreCase); + return input.Length; + } + + static int TestMustNotContainWithDelegateAndStringComparison(string? input) + { + input.MustNotContain("BAR", StringComparison.OrdinalIgnoreCase, (_, _, _) => new Exception()); + return input.Length; + } + } +} diff --git a/Code/Light.GuardClauses/Check.StringAssertions.cs b/Code/Light.GuardClauses/Check.StringAssertions.cs index aca06393..f5ca8cea 100644 --- a/Code/Light.GuardClauses/Check.StringAssertions.cs +++ b/Code/Light.GuardClauses/Check.StringAssertions.cs @@ -419,7 +419,7 @@ public static string MustContain([NotNull, ValidatedNotNull] this string? parame /// Thrown when or is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustNotContain([ValidatedNotNull] this string? parameter, string value, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) + public static string MustNotContain([NotNull, ValidatedNotNull] this string? parameter, string value, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (parameter.MustNotBeNull(parameterName, message).Contains(value.MustNotBeNull(nameof(value), message))) Throw.StringContains(parameter, value, parameterName, message); @@ -439,7 +439,7 @@ public static string MustNotContain([ValidatedNotNull] this string? parameter, s /// [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustNotContain([ValidatedNotNull] this string? parameter, string value, Func exceptionFactory) + public static string MustNotContain([NotNull, ValidatedNotNull] this string? parameter, string value, Func exceptionFactory) { // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off if (parameter is null || value is null || parameter.Contains(value)) @@ -460,7 +460,7 @@ public static string MustNotContain([ValidatedNotNull] this string? parameter, s /// Thrown when is not a valid value. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustNotContain([ValidatedNotNull] this string? parameter, string value, StringComparison comparisonType, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) + public static string MustNotContain([NotNull, ValidatedNotNull] this string? parameter, string value, StringComparison comparisonType, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (parameter.MustNotBeNull(parameterName, message).IndexOf(value.MustNotBeNull(nameof(value), message), comparisonType) >= 0) Throw.StringContains(parameter, value, comparisonType, parameterName, message); @@ -482,7 +482,7 @@ public static string MustNotContain([ValidatedNotNull] this string? parameter, s /// [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustNotContain([ValidatedNotNull] this string? parameter, string value, StringComparison comparisonType, Func exceptionFactory) + public static string MustNotContain([NotNull, ValidatedNotNull] this string? parameter, string value, StringComparison comparisonType, Func exceptionFactory) { // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off if (parameter is null || value is null || !comparisonType.IsValidEnumValue() || parameter.IndexOf(value, comparisonType) >= 0) From 85ad0d5cba3124a80505e32e0e891debeac18053 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 20 Oct 2024 19:34:53 +0200 Subject: [PATCH 36/97] fix: add NotNull attribute to Contains and IsSubstringOf extension methods Signed-off-by: Kenny Pflug --- Code/Light.GuardClauses/Check.StringAssertions.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Code/Light.GuardClauses/Check.StringAssertions.cs b/Code/Light.GuardClauses/Check.StringAssertions.cs index f5ca8cea..a674efe7 100644 --- a/Code/Light.GuardClauses/Check.StringAssertions.cs +++ b/Code/Light.GuardClauses/Check.StringAssertions.cs @@ -501,7 +501,8 @@ public static string MustNotContain([NotNull, ValidatedNotNull] this string? par /// Thrown when is not a valid value. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("string:null => halt; value:null => halt")] - public static bool Contains([ValidatedNotNull] this string @string, string value, StringComparison comparisonType) => + // ReSharper disable once RedundantNullableFlowAttribute + public static bool Contains([NotNull, ValidatedNotNull] this string @string, string value, StringComparison comparisonType) => @string.MustNotBeNull(nameof(@string)).IndexOf(value.MustNotBeNull(nameof(value)), comparisonType) >= 0; /// @@ -513,7 +514,8 @@ public static bool Contains([ValidatedNotNull] this string @string, string value /// Thrown when or is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("value:null => halt; other:null => halt")] - public static bool IsSubstringOf([ValidatedNotNull] this string value, [ValidatedNotNull] string other) => + // ReSharper disable once RedundantNullableFlowAttribute + public static bool IsSubstringOf([NotNull, ValidatedNotNull] this string value, [ValidatedNotNull] string other) => other.MustNotBeNull(nameof(other)).Contains(value); /// @@ -527,7 +529,8 @@ public static bool IsSubstringOf([ValidatedNotNull] this string value, [Validate /// Thrown when is not a valid value. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("value:null => halt; other:null => halt")] - public static bool IsSubstringOf(this string value, string other, StringComparison comparisonType) => + // ReSharper disable once RedundantNullableFlowAttribute + public static bool IsSubstringOf([NotNull] this string value, string other, StringComparison comparisonType) => other.MustNotBeNull(nameof(other)).IndexOf(value, comparisonType) != -1; /// From 8fecb796571bebfea16cefdebde30a2f740f387d Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 20 Oct 2024 19:41:00 +0200 Subject: [PATCH 37/97] fix: add NotNull attribute to MustBeSubstringOf Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 44 ++++++++++++++++--- .../Check.StringAssertions.cs | 8 ++-- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 3c1836e4..449f9ec2 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -584,13 +584,13 @@ static int TestMustContainWithDelegate(string? input) input.MustContain("oo", (_, _) => new Exception()); return input.Length; } - + static int TestMustContainWithStringComparison(string? input) { input.MustContain("OO", StringComparison.OrdinalIgnoreCase); return input.Length; } - + static int TestMustContainWithDelegateAndStringComparison(string? input) { input.MustContain("OO", StringComparison.OrdinalIgnoreCase, (_, _, _) => new Exception()); @@ -618,17 +618,51 @@ static int TestMustNotContainWithDelegate(string? input) input.MustNotContain("bar", (_, _) => new Exception()); return input.Length; } - + static int TestMustNotContainWithStringComparison(string? input) { input.MustNotContain("BAR", StringComparison.OrdinalIgnoreCase); return input.Length; } - + static int TestMustNotContainWithDelegateAndStringComparison(string? input) { input.MustNotContain("BAR", StringComparison.OrdinalIgnoreCase, (_, _, _) => new Exception()); return input.Length; } } -} + + [Fact] + public static void CheckMustBeSubstringOf() + { + TestMustBeSubstringOf("foo", "foobar").Should().Be(3); + TestMustBeSubstringOfWithDelegate("foo", "foobar").Should().Be(3); + TestMustBeSubstringOfWithStringComparison("OO").Should().Be(2); + TestMustBeSubstringOfWithDelegateAndStringComparison("OO").Should().Be(2); + return; + + static int TestMustBeSubstringOf(string? input, string target) + { + input.MustBeSubstringOf(target); + return input.Length; + } + + static int TestMustBeSubstringOfWithDelegate(string? input, string target) + { + input.MustBeSubstringOf(target, (_, _) => new Exception()); + return input.Length; + } + + static int TestMustBeSubstringOfWithStringComparison(string? input) + { + input.MustBeSubstringOf("foo", StringComparison.OrdinalIgnoreCase); + return input.Length; + } + + static int TestMustBeSubstringOfWithDelegateAndStringComparison(string? input) + { + input.MustBeSubstringOf("foo", StringComparison.OrdinalIgnoreCase, (_, _, _) => new Exception()); + return input.Length; + } + } +} \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.StringAssertions.cs b/Code/Light.GuardClauses/Check.StringAssertions.cs index a674efe7..b9956e81 100644 --- a/Code/Light.GuardClauses/Check.StringAssertions.cs +++ b/Code/Light.GuardClauses/Check.StringAssertions.cs @@ -544,7 +544,7 @@ public static bool IsSubstringOf([NotNull] this string value, string other, Stri /// Thrown when or is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt")] - public static string MustBeSubstringOf([ValidatedNotNull] this string? parameter, string value, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) + public static string MustBeSubstringOf([NotNull, ValidatedNotNull] this string? parameter, string value, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (!value.MustNotBeNull(nameof(value), message).Contains(parameter.MustNotBeNull(parameterName, message))) Throw.NotSubstring(parameter, value, parameterName, message); @@ -564,7 +564,7 @@ public static string MustBeSubstringOf([ValidatedNotNull] this string? parameter /// [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt")] - public static string MustBeSubstringOf([ValidatedNotNull] this string? parameter, string value, Func exceptionFactory) + public static string MustBeSubstringOf([NotNull, ValidatedNotNull] this string? parameter, string value, Func exceptionFactory) { // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off if (parameter is null || value is null || !value.Contains(parameter)) @@ -585,7 +585,7 @@ public static string MustBeSubstringOf([ValidatedNotNull] this string? parameter /// Thrown when is not a valid value. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt")] - public static string MustBeSubstringOf([ValidatedNotNull] this string? parameter, string value, StringComparison comparisonType, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) + public static string MustBeSubstringOf([NotNull, ValidatedNotNull] this string? parameter, string value, StringComparison comparisonType, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (value.MustNotBeNull(nameof(value), message).IndexOf(parameter.MustNotBeNull(parameterName, message), comparisonType) == -1) Throw.NotSubstring(parameter, value, comparisonType, parameterName, message); @@ -607,7 +607,7 @@ public static string MustBeSubstringOf([ValidatedNotNull] this string? parameter /// [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt")] - public static string MustBeSubstringOf([ValidatedNotNull] this string? parameter, string value, StringComparison comparisonType, Func exceptionFactory) + public static string MustBeSubstringOf([NotNull, ValidatedNotNull] this string? parameter, string value, StringComparison comparisonType, Func exceptionFactory) { // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off if (parameter is null || value is null || !comparisonType.IsValidEnumValue() || value.IndexOf(parameter, comparisonType) == -1) From 831aa41d9493c02a6c0d77a2f8914ddd9966e744 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 20 Oct 2024 19:43:09 +0200 Subject: [PATCH 38/97] fix: add NotNull attribute to MustNotBeSubstringOf Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 34 +++++++++++++++++++ .../Check.StringAssertions.cs | 8 ++--- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 449f9ec2..5e6bf8f8 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -665,4 +665,38 @@ static int TestMustBeSubstringOfWithDelegateAndStringComparison(string? input) return input.Length; } } + + [Fact] + public static void CheckMustNotBeSubstringOf() + { + TestMustNotBeSubstringOf("foo", "bar").Should().Be(3); + TestMustNotBeSubstringOfWithDelegate("foo", "bar").Should().Be(3); + TestMustNotBeSubstringOfWithStringComparison("FOO").Should().Be(3); + TestMustNotBeSubstringOfWithDelegateAndStringComparison("FOO").Should().Be(3); + return; + + static int TestMustNotBeSubstringOf(string? input, string target) + { + input.MustNotBeSubstringOf(target); + return input.Length; + } + + static int TestMustNotBeSubstringOfWithDelegate(string? input, string target) + { + input.MustNotBeSubstringOf(target, (_, _) => new Exception()); + return input.Length; + } + + static int TestMustNotBeSubstringOfWithStringComparison(string? input) + { + input.MustNotBeSubstringOf("bar", StringComparison.OrdinalIgnoreCase); + return input.Length; + } + + static int TestMustNotBeSubstringOfWithDelegateAndStringComparison(string? input) + { + input.MustNotBeSubstringOf("bar", StringComparison.OrdinalIgnoreCase, (_, _, _) => new Exception()); + return input.Length; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.StringAssertions.cs b/Code/Light.GuardClauses/Check.StringAssertions.cs index b9956e81..d178d9f1 100644 --- a/Code/Light.GuardClauses/Check.StringAssertions.cs +++ b/Code/Light.GuardClauses/Check.StringAssertions.cs @@ -626,7 +626,7 @@ public static string MustBeSubstringOf([NotNull, ValidatedNotNull] this string? /// Thrown when or is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt")] - public static string MustNotBeSubstringOf([ValidatedNotNull] this string? parameter, string value, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) + public static string MustNotBeSubstringOf([NotNull, ValidatedNotNull] this string? parameter, string value, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (value.MustNotBeNull(nameof(value), message).Contains(parameter.MustNotBeNull(parameterName, message))) Throw.Substring(parameter, value, parameterName, message); @@ -647,7 +647,7 @@ public static string MustNotBeSubstringOf([ValidatedNotNull] this string? parame /// Thrown when or is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt")] - public static string MustNotBeSubstringOf([ValidatedNotNull] this string? parameter, string value, Func exceptionFactory) + public static string MustNotBeSubstringOf([NotNull, ValidatedNotNull] this string? parameter, string value, Func exceptionFactory) { // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off if (parameter is null || value is null || value.Contains(parameter)) @@ -668,7 +668,7 @@ public static string MustNotBeSubstringOf([ValidatedNotNull] this string? parame /// Thrown when is not a valid value. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt")] - public static string MustNotBeSubstringOf([ValidatedNotNull] this string? parameter, string value, StringComparison comparisonType, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) + public static string MustNotBeSubstringOf([NotNull, ValidatedNotNull] this string? parameter, string value, StringComparison comparisonType, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (value.MustNotBeNull(nameof(value), message).IndexOf(parameter.MustNotBeNull(parameterName, message), comparisonType) != -1) Throw.Substring(parameter, value, comparisonType, parameterName, message); @@ -690,7 +690,7 @@ public static string MustNotBeSubstringOf([ValidatedNotNull] this string? parame /// Thrown when is not a valid value. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt")] - public static string MustNotBeSubstringOf([ValidatedNotNull] this string? parameter, string value, StringComparison comparisonType, Func exceptionFactory) + public static string MustNotBeSubstringOf([NotNull, ValidatedNotNull] this string? parameter, string value, StringComparison comparisonType, Func exceptionFactory) { // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off if (parameter is null || value is null || !comparisonType.IsValidEnumValue() || value.IndexOf(parameter, comparisonType) != -1) From 1b160fc6a8d1d8e104e9f25290f811a7df88e4ba Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 20 Oct 2024 19:45:51 +0200 Subject: [PATCH 39/97] fix: add NotNull attribute to MustBeEmailAddress Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 20 +++++++++++++++++++ .../Check.StringAssertions.cs | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 5e6bf8f8..d22e671d 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -699,4 +699,24 @@ static int TestMustNotBeSubstringOfWithDelegateAndStringComparison(string? input return input.Length; } } + + [Fact] + public static void CheckMustBeEmailAddress() + { + TestMustBeEmailAddress("test@example.com").Should().Be("test@example.com"); + TestMustBeEmailAddressWithDelegate("test@example.com").Should().Be("test@example.com"); + return; + + static string TestMustBeEmailAddress(string? input) + { + input.MustBeEmailAddress(); + return input; + } + + static string TestMustBeEmailAddressWithDelegate(string? input) + { + input.MustBeEmailAddress(_ => new Exception()); + return input; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.StringAssertions.cs b/Code/Light.GuardClauses/Check.StringAssertions.cs index d178d9f1..d9b55146 100644 --- a/Code/Light.GuardClauses/Check.StringAssertions.cs +++ b/Code/Light.GuardClauses/Check.StringAssertions.cs @@ -730,7 +730,7 @@ public static bool IsEmailAddress([NotNullWhen(true)] this string? emailAddress, /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustBeEmailAddress([ValidatedNotNull] this string? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) + public static string MustBeEmailAddress([NotNull, ValidatedNotNull] this string? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (!parameter.MustNotBeNull(parameterName, message).IsEmailAddress()) Throw.InvalidEmailAddress(parameter, parameterName, message); @@ -746,7 +746,7 @@ public static string MustBeEmailAddress([ValidatedNotNull] this string? paramete /// Your custom exception thrown when is null or no valid email address. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustBeEmailAddress([ValidatedNotNull] this string? parameter, Func exceptionFactory) + public static string MustBeEmailAddress([NotNull, ValidatedNotNull] this string? parameter, Func exceptionFactory) { if (!parameter.IsEmailAddress()) Throw.CustomException(exceptionFactory, parameter); From 6738e2484980dd12e2621aa7b66f667c2b21abb0 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 20 Oct 2024 19:51:28 +0200 Subject: [PATCH 40/97] fix: add NotNull attribute to CheckMustBeEmailAddress Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 14 ++++++++++++++ Code/Light.GuardClauses/Check.StringAssertions.cs | 4 ++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index d22e671d..ae76f4bb 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -705,6 +705,8 @@ public static void CheckMustBeEmailAddress() { TestMustBeEmailAddress("test@example.com").Should().Be("test@example.com"); TestMustBeEmailAddressWithDelegate("test@example.com").Should().Be("test@example.com"); + TestMustBeEmailAddressWithRegex("test@example.com").Should().Be("test@example.com"); + TestMustBeEmailAddressWithRegexAndDelegate("test@example.com").Should().Be("test@example.com"); return; static string TestMustBeEmailAddress(string? input) @@ -718,5 +720,17 @@ static string TestMustBeEmailAddressWithDelegate(string? input) input.MustBeEmailAddress(_ => new Exception()); return input; } + + static string TestMustBeEmailAddressWithRegex(string? input) + { + input.MustBeEmailAddress(new Regex(@"^[^@\s]+@[^@\s]+\.[^@\s]+$")); + return input; + } + + static string TestMustBeEmailAddressWithRegexAndDelegate(string? input) + { + input.MustBeEmailAddress(new Regex(@"^[^@\s]+@[^@\s]+\.[^@\s]+$"), (_, _) => new Exception()); + return input; + } } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.StringAssertions.cs b/Code/Light.GuardClauses/Check.StringAssertions.cs index d9b55146..9b478e01 100644 --- a/Code/Light.GuardClauses/Check.StringAssertions.cs +++ b/Code/Light.GuardClauses/Check.StringAssertions.cs @@ -765,7 +765,7 @@ public static string MustBeEmailAddress([NotNull, ValidatedNotNull] this string? /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; emailAddressPattern:null => halt")] - public static string MustBeEmailAddress([ValidatedNotNull] this string? parameter, Regex emailAddressPattern, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) + public static string MustBeEmailAddress([NotNull, ValidatedNotNull] this string? parameter, Regex emailAddressPattern, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (!parameter.MustNotBeNull(parameterName, message).IsEmailAddress(emailAddressPattern)) Throw.InvalidEmailAddress(parameter, parameterName, message); @@ -782,7 +782,7 @@ public static string MustBeEmailAddress([ValidatedNotNull] this string? paramete /// Your custom exception thrown when is null or no valid email address. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; emailAddressPattern:null => halt")] - public static string MustBeEmailAddress([ValidatedNotNull] this string? parameter, Regex emailAddressPattern, Func exceptionFactory) + public static string MustBeEmailAddress([NotNull, ValidatedNotNull] this string? parameter, Regex emailAddressPattern, Func exceptionFactory) { // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off if (emailAddressPattern is null || !parameter.IsEmailAddress(emailAddressPattern)) From efdb128f98d933d0d9f95f439975ee97991ea47b Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 20 Oct 2024 19:55:05 +0200 Subject: [PATCH 41/97] fix: add NotNull attribute to MustBeShorterThan Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 22 ++++++++++++++++++- .../Check.StringAssertions.cs | 4 ++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index ae76f4bb..9df82039 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -720,7 +720,7 @@ static string TestMustBeEmailAddressWithDelegate(string? input) input.MustBeEmailAddress(_ => new Exception()); return input; } - + static string TestMustBeEmailAddressWithRegex(string? input) { input.MustBeEmailAddress(new Regex(@"^[^@\s]+@[^@\s]+\.[^@\s]+$")); @@ -733,4 +733,24 @@ static string TestMustBeEmailAddressWithRegexAndDelegate(string? input) return input; } } + + [Fact] + public static void CheckMustBeShorterThan() + { + TestMustBeShorterThan("foo").Should().Be("foo"); + TestMustBeShorterThanWithDelegate("foo").Should().Be("foo"); + return; + + static string TestMustBeShorterThan(string? input) + { + input.MustBeShorterThan(5); + return input; + } + + static string TestMustBeShorterThanWithDelegate(string? input) + { + input.MustBeShorterThan(5, (_, _) => new Exception()); + return input; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.StringAssertions.cs b/Code/Light.GuardClauses/Check.StringAssertions.cs index 9b478e01..3dae16a8 100644 --- a/Code/Light.GuardClauses/Check.StringAssertions.cs +++ b/Code/Light.GuardClauses/Check.StringAssertions.cs @@ -801,7 +801,7 @@ public static string MustBeEmailAddress([NotNull, ValidatedNotNull] this string? /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustBeShorterThan([ValidatedNotNull] this string? parameter, int length, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) + public static string MustBeShorterThan([NotNull, ValidatedNotNull] this string? parameter, int length, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (parameter.MustNotBeNull(parameterName, message).Length >= length) Throw.StringNotShorterThan(parameter, length, parameterName, message); @@ -817,7 +817,7 @@ public static string MustBeShorterThan([ValidatedNotNull] this string? parameter /// Your custom exception thrown when is null or when it has a length greater than or equal to . [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustBeShorterThan([ValidatedNotNull] this string? parameter, int length, Func exceptionFactory) + public static string MustBeShorterThan([NotNull, ValidatedNotNull] this string? parameter, int length, Func exceptionFactory) { if (parameter is null || parameter.Length >= length) Throw.CustomException(exceptionFactory, parameter, length); From ae1247ef204aff09a516035c0df2d893800137b2 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 20 Oct 2024 19:56:17 +0200 Subject: [PATCH 42/97] fix: add NotNull attribute to MustBeShorterThanOrEqualTo Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 20 +++++++++++++++++++ .../Check.StringAssertions.cs | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 9df82039..72fb339e 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -753,4 +753,24 @@ static string TestMustBeShorterThanWithDelegate(string? input) return input; } } + + [Fact] + public static void CheckMustBeShorterThanOrEqualTo() + { + TestMustBeShorterThanOrEqualTo("foo").Should().Be("foo"); + TestMustBeShorterThanOrEqualToWithDelegate("foo").Should().Be("foo"); + return; + + static string TestMustBeShorterThanOrEqualTo(string? input) + { + input.MustBeShorterThanOrEqualTo(3); + return input; + } + + static string TestMustBeShorterThanOrEqualToWithDelegate(string? input) + { + input.MustBeShorterThanOrEqualTo(3, (_, _) => new Exception()); + return input; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.StringAssertions.cs b/Code/Light.GuardClauses/Check.StringAssertions.cs index 3dae16a8..a6a80c35 100644 --- a/Code/Light.GuardClauses/Check.StringAssertions.cs +++ b/Code/Light.GuardClauses/Check.StringAssertions.cs @@ -835,7 +835,7 @@ public static string MustBeShorterThan([NotNull, ValidatedNotNull] this string? /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustBeShorterThanOrEqualTo([ValidatedNotNull] this string? parameter, int length, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) + public static string MustBeShorterThanOrEqualTo([NotNull, ValidatedNotNull] this string? parameter, int length, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (parameter.MustNotBeNull(parameterName, message).Length > length) Throw.StringNotShorterThanOrEqualTo(parameter, length, parameterName, message); @@ -851,7 +851,7 @@ public static string MustBeShorterThanOrEqualTo([ValidatedNotNull] this string? /// Your custom exception thrown when is null or when it has a length greater than . [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustBeShorterThanOrEqualTo([ValidatedNotNull] this string? parameter, int length, Func exceptionFactory) + public static string MustBeShorterThanOrEqualTo([NotNull, ValidatedNotNull] this string? parameter, int length, Func exceptionFactory) { if (parameter is null || parameter.Length > length) Throw.CustomException(exceptionFactory, parameter, length); From bebbe813422c81a9af637c96ec979d030ee8f47d Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 20 Oct 2024 19:57:36 +0200 Subject: [PATCH 43/97] fix: add NotNull attribute to MustHaveLength for strings Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 20 +++++++++++++++++++ .../Check.StringAssertions.cs | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 72fb339e..f1837fbc 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -773,4 +773,24 @@ static string TestMustBeShorterThanOrEqualToWithDelegate(string? input) return input; } } + + [Fact] + public static void CheckMustHaveLength() + { + TestMustHaveLength("foo").Should().Be("foo"); + TestMustHaveLengthWithDelegate("foo").Should().Be("foo"); + return; + + static string TestMustHaveLength(string? input) + { + input.MustHaveLength(3); + return input; + } + + static string TestMustHaveLengthWithDelegate(string? input) + { + input.MustHaveLength(3, (_, _) => new Exception()); + return input; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.StringAssertions.cs b/Code/Light.GuardClauses/Check.StringAssertions.cs index a6a80c35..4af55cf2 100644 --- a/Code/Light.GuardClauses/Check.StringAssertions.cs +++ b/Code/Light.GuardClauses/Check.StringAssertions.cs @@ -869,7 +869,7 @@ public static string MustBeShorterThanOrEqualTo([NotNull, ValidatedNotNull] this /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustHaveLength([ValidatedNotNull] this string? parameter, int length, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) + public static string MustHaveLength([NotNull, ValidatedNotNull] this string? parameter, int length, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (parameter.MustNotBeNull(parameterName, message).Length != length) Throw.StringLengthNotEqualTo(parameter, length, parameterName, message); @@ -885,7 +885,7 @@ public static string MustHaveLength([ValidatedNotNull] this string? parameter, i /// Your custom exception thrown when is null or when it has a length other than . [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustHaveLength([ValidatedNotNull] this string? parameter, int length, Func exceptionFactory) + public static string MustHaveLength([NotNull, ValidatedNotNull] this string? parameter, int length, Func exceptionFactory) { if (parameter is null || parameter.Length != length) Throw.CustomException(exceptionFactory, parameter, length); From e833dcaec15d771da0a8993a1dc92ae2dcec33d5 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 20 Oct 2024 20:14:46 +0200 Subject: [PATCH 44/97] fix: add NotNull attribute to MustBeLongerThan Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 20 +++++++++++++++++++ .../Check.StringAssertions.cs | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index f1837fbc..5d6ae535 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -793,4 +793,24 @@ static string TestMustHaveLengthWithDelegate(string? input) return input; } } + + [Fact] + public static void CheckMustBeLongerThan() + { + TestMustBeLongerThan("foobar").Should().Be("foobar"); + TestMustBeLongerThanWithDelegate("foobar").Should().Be("foobar"); + return; + + static string TestMustBeLongerThan(string? input) + { + input.MustBeLongerThan(3); + return input; + } + + static string TestMustBeLongerThanWithDelegate(string? input) + { + input.MustBeLongerThan(3, (_, _) => new Exception()); + return input; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.StringAssertions.cs b/Code/Light.GuardClauses/Check.StringAssertions.cs index 4af55cf2..9f32443c 100644 --- a/Code/Light.GuardClauses/Check.StringAssertions.cs +++ b/Code/Light.GuardClauses/Check.StringAssertions.cs @@ -903,7 +903,7 @@ public static string MustHaveLength([NotNull, ValidatedNotNull] this string? par /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustBeLongerThan([ValidatedNotNull] this string? parameter, int length, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) + public static string MustBeLongerThan([NotNull, ValidatedNotNull] this string? parameter, int length, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (parameter.MustNotBeNull(parameterName, message).Length <= length) Throw.StringNotLongerThan(parameter, length, parameterName, message); @@ -919,7 +919,7 @@ public static string MustBeLongerThan([ValidatedNotNull] this string? parameter, /// Your custom exception thrown when is null or when it has a length shorter than or equal to . [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustBeLongerThan([ValidatedNotNull] this string? parameter, int length, Func exceptionFactory) + public static string MustBeLongerThan([NotNull, ValidatedNotNull] this string? parameter, int length, Func exceptionFactory) { if (parameter is null || parameter.Length <= length) Throw.CustomException(exceptionFactory, parameter, length); From 18f8118492a090bcaa9c39e5881421005f7ea4e3 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 20 Oct 2024 20:15:54 +0200 Subject: [PATCH 45/97] fix: add NotNull attribute to MustBeLongerThanOrEqualTo Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 20 +++++++++++++++++++ .../Check.StringAssertions.cs | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 5d6ae535..2f5e121a 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -813,4 +813,24 @@ static string TestMustBeLongerThanWithDelegate(string? input) return input; } } + + [Fact] + public static void CheckMustBeLongerThanOrEqualTo() + { + TestMustBeLongerThanOrEqualTo("foobar").Should().Be("foobar"); + TestMustBeLongerThanOrEqualToWithDelegate("foobar").Should().Be("foobar"); + return; + + static string TestMustBeLongerThanOrEqualTo(string? input) + { + input.MustBeLongerThanOrEqualTo(6); + return input; + } + + static string TestMustBeLongerThanOrEqualToWithDelegate(string? input) + { + input.MustBeLongerThanOrEqualTo(6, (_, _) => new Exception()); + return input; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.StringAssertions.cs b/Code/Light.GuardClauses/Check.StringAssertions.cs index 9f32443c..daa1822b 100644 --- a/Code/Light.GuardClauses/Check.StringAssertions.cs +++ b/Code/Light.GuardClauses/Check.StringAssertions.cs @@ -937,7 +937,7 @@ public static string MustBeLongerThan([NotNull, ValidatedNotNull] this string? p /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustBeLongerThanOrEqualTo([ValidatedNotNull] this string? parameter, int length, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) + public static string MustBeLongerThanOrEqualTo([NotNull, ValidatedNotNull] this string? parameter, int length, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (parameter.MustNotBeNull(parameterName, message).Length < length) Throw.StringNotLongerThanOrEqualTo(parameter, length, parameterName, message); @@ -953,7 +953,7 @@ public static string MustBeLongerThanOrEqualTo([ValidatedNotNull] this string? p /// Your custom exception thrown when is null or when it has a length shorter than . [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustBeLongerThanOrEqualTo([ValidatedNotNull] this string? parameter, int length, Func exceptionFactory) + public static string MustBeLongerThanOrEqualTo([NotNull, ValidatedNotNull] this string? parameter, int length, Func exceptionFactory) { if (parameter is null || parameter.Length < length) Throw.CustomException(exceptionFactory, parameter, length); From 50a77dcd06724f5fcd1cef403f7b3e38ce1393a5 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 20 Oct 2024 20:17:33 +0200 Subject: [PATCH 46/97] fix: add NotNull attribute to MustHaveLengthIn Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 20 +++++++++++++++++++ .../Check.StringAssertions.cs | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 2f5e121a..356c8036 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -833,4 +833,24 @@ static string TestMustBeLongerThanOrEqualToWithDelegate(string? input) return input; } } + + [Fact] + public static void CheckMustHaveLengthIn() + { + TestMustHaveLengthIn("foo").Should().Be("foo"); + TestMustHaveLengthInWithDelegate("foo").Should().Be("foo"); + return; + + static string TestMustHaveLengthIn(string? input) + { + input.MustHaveLengthIn(Range.FromInclusive(2).ToInclusive(4)); + return input; + } + + static string TestMustHaveLengthInWithDelegate(string? input) + { + input.MustHaveLengthIn(Range.FromInclusive(2).ToInclusive(4), (_, _) => new Exception()); + return input; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.StringAssertions.cs b/Code/Light.GuardClauses/Check.StringAssertions.cs index daa1822b..acfead56 100644 --- a/Code/Light.GuardClauses/Check.StringAssertions.cs +++ b/Code/Light.GuardClauses/Check.StringAssertions.cs @@ -971,7 +971,7 @@ public static string MustBeLongerThanOrEqualTo([NotNull, ValidatedNotNull] this /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustHaveLengthIn([ValidatedNotNull] this string? parameter, Range range, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) + public static string MustHaveLengthIn([NotNull, ValidatedNotNull] this string? parameter, Range range, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (!range.IsValueWithinRange(parameter.MustNotBeNull(parameterName, message).Length)) Throw.StringLengthNotInRange(parameter, range, parameterName, message); @@ -987,7 +987,7 @@ public static string MustHaveLengthIn([ValidatedNotNull] this string? parameter, /// Your custom exception thrown when is null or its length is not within the specified range. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustHaveLengthIn([ValidatedNotNull] this string? parameter, Range range, Func, Exception> exceptionFactory) + public static string MustHaveLengthIn([NotNull, ValidatedNotNull] this string? parameter, Range range, Func, Exception> exceptionFactory) { if (parameter is null || !range.IsValueWithinRange(parameter.Length)) Throw.CustomException(exceptionFactory, parameter, range); From 37554529d0603d911abe29830da9e28001c92cdb Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 20 Oct 2024 20:20:41 +0200 Subject: [PATCH 47/97] fix: add NotNull attribute to MustBeNewLine Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 20 +++++++++++++++++++ .../Check.StringAssertions.cs | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 356c8036..8c8be3a8 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -853,4 +853,24 @@ static string TestMustHaveLengthInWithDelegate(string? input) return input; } } + + [Fact] + public static void CheckMustBeNewLine() + { + TestMustBeNewLine("\n").Should().Be("\n"); + TestMustBeNewLineWithDelegate("\n").Should().Be("\n"); + return; + + static string TestMustBeNewLine(string? input) + { + input.MustBeNewLine(); + return input; + } + + static string TestMustBeNewLineWithDelegate(string? input) + { + input.MustBeNewLine(_ => new Exception()); + return input; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.StringAssertions.cs b/Code/Light.GuardClauses/Check.StringAssertions.cs index acfead56..43ba54ac 100644 --- a/Code/Light.GuardClauses/Check.StringAssertions.cs +++ b/Code/Light.GuardClauses/Check.StringAssertions.cs @@ -1012,7 +1012,7 @@ public static string MustHaveLengthIn([NotNull, ValidatedNotNull] this string? p /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustBeNewLine([ValidatedNotNull] this string? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) + public static string MustBeNewLine([NotNull, ValidatedNotNull] this string? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (!parameter.MustNotBeNull(parameterName, message).IsNewLine()) Throw.NotNewLine(parameter, parameterName, message); @@ -1027,7 +1027,7 @@ public static string MustBeNewLine([ValidatedNotNull] this string? parameter, [C /// Your custom exception thrown when is not equal to "\n" or "\r\n". [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustBeNewLine([ValidatedNotNull] this string? parameter, Func exceptionFactory) + public static string MustBeNewLine([NotNull, ValidatedNotNull] this string? parameter, Func exceptionFactory) { if (!parameter.IsNewLine()) Throw.CustomException(exceptionFactory, parameter); From 9a1ff4327d15e25bbbbffe4b66812096b805f03e Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 20 Oct 2024 20:27:36 +0200 Subject: [PATCH 48/97] fix: add NotNull attribute to MustBeTrimmed Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 20 +++++++++++++++++++ .../Check.StringAssertions.cs | 8 ++++---- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 8c8be3a8..8ad4a6aa 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -873,4 +873,24 @@ static string TestMustBeNewLineWithDelegate(string? input) return input; } } + + [Fact] + public static void CheckMustBeTrimmed() + { + TestMustBeTrimmed("foo").Should().Be("foo"); + TestMustBeTrimmedWithDelegate("foo").Should().Be("foo"); + return; + + static string TestMustBeTrimmed(string? input) + { + input.MustBeTrimmed(); + return input; + } + + static string TestMustBeTrimmedWithDelegate(string? input) + { + input.MustBeTrimmed(_ => new Exception()); + return input; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.StringAssertions.cs b/Code/Light.GuardClauses/Check.StringAssertions.cs index 43ba54ac..12de3d17 100644 --- a/Code/Light.GuardClauses/Check.StringAssertions.cs +++ b/Code/Light.GuardClauses/Check.StringAssertions.cs @@ -1081,7 +1081,7 @@ public static bool IsTrimmed(this ReadOnlySpan parameter) => /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustBeTrimmed([ValidatedNotNull] this string? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) + public static string MustBeTrimmed([NotNull, ValidatedNotNull] this string? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (!parameter.MustNotBeNull(parameterName, message).IsTrimmed()) Throw.NotTrimmed(parameter, parameterName, message); @@ -1098,11 +1098,11 @@ public static string MustBeTrimmed([ValidatedNotNull] this string? parameter, [C /// Your custom exception thrown when is null or not trimmed. Empty strings are regarded as trimmed. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustBeTrimmed([ValidatedNotNull] this string? parameter, Func exceptionFactory) + public static string MustBeTrimmed([NotNull, ValidatedNotNull] this string? parameter, Func exceptionFactory) { - if (!parameter.IsTrimmed(regardNullAsTrimmed: false)) + if (parameter is null || !parameter.AsSpan().IsTrimmed()) Throw.CustomException(exceptionFactory, parameter); - return parameter!; + return parameter; } /// From e981bf76f098aea6dde750b0504a86a5c03aeaf1 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 20 Oct 2024 20:31:01 +0200 Subject: [PATCH 49/97] fix: add NotNull attribute to MustBeTrimmedAtStart Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 20 +++++++++++++++++++ .../Check.StringAssertions.cs | 8 ++++---- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 8ad4a6aa..c07e9f50 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -893,4 +893,24 @@ static string TestMustBeTrimmedWithDelegate(string? input) return input; } } + + [Fact] + public static void CheckMustBeTrimmedAtStart() + { + TestMustBeTrimmedAtStart("foo").Should().Be("foo"); + TestMustBeTrimmedAtStartWithDelegate("foo").Should().Be("foo"); + return; + + static string TestMustBeTrimmedAtStart(string? input) + { + input.MustBeTrimmedAtStart(); + return input; + } + + static string TestMustBeTrimmedAtStartWithDelegate(string? input) + { + input.MustBeTrimmedAtStart(_ => new Exception()); + return input; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.StringAssertions.cs b/Code/Light.GuardClauses/Check.StringAssertions.cs index 12de3d17..28764d4b 100644 --- a/Code/Light.GuardClauses/Check.StringAssertions.cs +++ b/Code/Light.GuardClauses/Check.StringAssertions.cs @@ -1149,7 +1149,7 @@ public static bool IsTrimmedAtStart(this ReadOnlySpan parameter) => /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustBeTrimmedAtStart([ValidatedNotNull] this string? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) + public static string MustBeTrimmedAtStart([NotNull, ValidatedNotNull] this string? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (!parameter.MustNotBeNull(parameterName, message).IsTrimmedAtStart()) Throw.NotTrimmedAtStart(parameter, parameterName, message); @@ -1165,11 +1165,11 @@ public static string MustBeTrimmedAtStart([ValidatedNotNull] this string? parame /// Your custom exception thrown when is null or not trimmed at the start. Empty strings are regarded as trimmed. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustBeTrimmedAtStart([ValidatedNotNull] this string? parameter, Func exceptionFactory) + public static string MustBeTrimmedAtStart([NotNull, ValidatedNotNull] this string? parameter, Func exceptionFactory) { - if (!parameter.IsTrimmedAtStart(regardNullAsTrimmed: false)) + if (parameter is null || !parameter.AsSpan().IsTrimmedAtStart()) Throw.CustomException(exceptionFactory, parameter); - return parameter!; + return parameter; } /// From 43d0983999ed8968c4d3ac1aee64e6c561f696b9 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 20 Oct 2024 20:36:14 +0200 Subject: [PATCH 50/97] fix: add NotNull attribute to MustBeTrimmedAtEnd Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 20 +++++++++++++++++++ .../Check.StringAssertions.cs | 6 +++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index c07e9f50..6919a39d 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -913,4 +913,24 @@ static string TestMustBeTrimmedAtStartWithDelegate(string? input) return input; } } + + [Fact] + public static void CheckMustBeTrimmedAtEnd() + { + TestMustBeTrimmedAtEnd("foo").Should().Be("foo"); + TestMustBeTrimmedAtEndWithDelegate("foo").Should().Be("foo"); + return; + + static string TestMustBeTrimmedAtEnd(string? input) + { + input.MustBeTrimmedAtEnd(); + return input; + } + + static string TestMustBeTrimmedAtEndWithDelegate(string? input) + { + input.MustBeTrimmedAtEnd(_ => new Exception()); + return input; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.StringAssertions.cs b/Code/Light.GuardClauses/Check.StringAssertions.cs index 28764d4b..c51eb5d1 100644 --- a/Code/Light.GuardClauses/Check.StringAssertions.cs +++ b/Code/Light.GuardClauses/Check.StringAssertions.cs @@ -1216,7 +1216,7 @@ public static bool IsTrimmedAtEnd(this ReadOnlySpan parameter) => /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustBeTrimmedAtEnd([ValidatedNotNull] this string? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) + public static string MustBeTrimmedAtEnd([NotNull, ValidatedNotNull] this string? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (!parameter.MustNotBeNull(parameterName, message).IsTrimmedAtEnd()) Throw.NotTrimmedAtEnd(parameter, parameterName, message); @@ -1232,9 +1232,9 @@ public static string MustBeTrimmedAtEnd([ValidatedNotNull] this string? paramete /// Your custom exception thrown when is null or not trimmed at the end. Empty strings are regarded as trimmed. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustBeTrimmedAtEnd([ValidatedNotNull] this string? parameter, Func exceptionFactory) + public static string MustBeTrimmedAtEnd([NotNull, ValidatedNotNull] this string? parameter, Func exceptionFactory) { - if (!parameter.IsTrimmedAtEnd(regardNullAsTrimmed: false)) + if (parameter is null || !parameter.AsSpan().IsTrimmedAtEnd()) Throw.CustomException(exceptionFactory, parameter); return parameter!; } From c40c8a3e07a95ce593b391070c8ed3cfda6bdd6a Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Mon, 21 Oct 2024 07:52:25 +0200 Subject: [PATCH 51/97] fix: add NotNull attribute to Implements assertion Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 23 +++++++++++++++++++ .../Check.TypeAssertions.cs | 17 ++++++++------ 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 6919a39d..f45df24d 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -1,6 +1,9 @@ #nullable enable using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.Serialization; using System.Text.RegularExpressions; using FluentAssertions; using Xunit; @@ -933,4 +936,24 @@ static string TestMustBeTrimmedAtEndWithDelegate(string? input) return input; } } + + [Fact] + public static void CheckImplements() + { + TestImplements(typeof(FileInfo), typeof(ISerializable)).Should().Be((typeof(FileInfo), typeof(ISerializable))); + TestImplementsWithComparer(typeof(FileInfo), typeof(ISerializable)).Should().Be((typeof(FileInfo), typeof(ISerializable), EqualityComparer.Default)); + return; + + static (Type Type, Type InterfaceType) TestImplements(Type? type, Type? interfaceType) + { + type!.Implements(interfaceType!); + return (type, interfaceType); + } + + static (Type Type, Type InterfaceType, IEqualityComparer Comparer) TestImplementsWithComparer(Type? type, Type? interfaceType) + { + type!.Implements(interfaceType!, EqualityComparer.Default); + return (type, interfaceType, EqualityComparer.Default); + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.TypeAssertions.cs b/Code/Light.GuardClauses/Check.TypeAssertions.cs index a858cc8a..48b8c7b4 100644 --- a/Code/Light.GuardClauses/Check.TypeAssertions.cs +++ b/Code/Light.GuardClauses/Check.TypeAssertions.cs @@ -5,6 +5,7 @@ #if NET8_0 using System.Diagnostics.CodeAnalysis; #endif +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; namespace Light.GuardClauses; @@ -48,9 +49,10 @@ public static bool Implements( #if NET8_0 [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] #endif - [ValidatedNotNull] - this Type type, - [ValidatedNotNull] Type interfaceType + // ReSharper disable RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests + [NotNull, ValidatedNotNull] this Type type, + [NotNull, ValidatedNotNull] Type interfaceType + // ReSharper restore RedundantNullableFlowAttribute ) { type.MustNotBeNull(); @@ -79,10 +81,11 @@ public static bool Implements( #if NET8_0 [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] #endif - [ValidatedNotNull] - this Type type, - [ValidatedNotNull] Type interfaceType, - [ValidatedNotNull] IEqualityComparer typeComparer + // ReSharper disable RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests + [NotNull, ValidatedNotNull] this Type type, + [NotNull, ValidatedNotNull] Type interfaceType, + [NotNull, ValidatedNotNull] IEqualityComparer typeComparer + // ReSharper restore RedundantNullableFlowAttribute ) { type.MustNotBeNull(); From 80aeec9a36bef95383e9f6eae4bf98c10539cc51 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Mon, 21 Oct 2024 08:00:37 +0200 Subject: [PATCH 52/97] fix: add NotNull attribute to IsOrImplements assertion Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 20 +++++++++++++++++++ .../Check.TypeAssertions.cs | 14 ++++++++----- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index f45df24d..cf34aab5 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -956,4 +956,24 @@ public static void CheckImplements() return (type, interfaceType, EqualityComparer.Default); } } + + [Fact] + public static void CheckIsOrImplements() + { + TestIsOrImplements(typeof(FileInfo), typeof(ISerializable)).Should().Be((typeof(FileInfo), typeof(ISerializable))); + TestIsOrImplementsWithComparer(typeof(FileInfo), typeof(ISerializable)).Should().Be((typeof(FileInfo), typeof(ISerializable), EqualityComparer.Default)); + return; + + static (Type Type, Type InterfaceType) TestIsOrImplements(Type? type, Type? interfaceType) + { + type!.IsOrImplements(interfaceType!); + return (type, interfaceType); + } + + static (Type Type, Type InterfaceType, IEqualityComparer Comparer) TestIsOrImplementsWithComparer(Type? type, Type? interfaceType) + { + type!.IsOrImplements(interfaceType!, EqualityComparer.Default); + return (type, interfaceType, EqualityComparer.Default); + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.TypeAssertions.cs b/Code/Light.GuardClauses/Check.TypeAssertions.cs index 48b8c7b4..35211e48 100644 --- a/Code/Light.GuardClauses/Check.TypeAssertions.cs +++ b/Code/Light.GuardClauses/Check.TypeAssertions.cs @@ -115,8 +115,10 @@ public static bool IsOrImplements( #if NET8_0 [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] #endif - [ValidatedNotNull] this Type type, - [ValidatedNotNull] Type otherType) => + // ReSharper disable RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests + [NotNull, ValidatedNotNull] this Type type, + [NotNull, ValidatedNotNull] Type otherType) => + // ReSharper restore RedundantNullableFlowAttribute type.IsEquivalentTypeTo(otherType.MustNotBeNull(nameof(otherType))) || type.Implements(otherType); /// @@ -134,9 +136,11 @@ public static bool IsOrImplements( #if NET8_0 [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] #endif - [ValidatedNotNull] this Type type, - [ValidatedNotNull] Type otherType, - [ValidatedNotNull] IEqualityComparer typeComparer) => + // ReSharper disable RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests + [NotNull, ValidatedNotNull] this Type type, + [NotNull, ValidatedNotNull] Type otherType, + [NotNull, ValidatedNotNull] IEqualityComparer typeComparer) => + // ReSharper restore RedundantNullableFlowAttribute typeComparer.MustNotBeNull(nameof(typeComparer)).Equals(type.MustNotBeNull(nameof(type)), otherType.MustNotBeNull(nameof(otherType))) || type.Implements(otherType, typeComparer); /// From c39a9525fbe83c3a3a59a7d24187e1b6492b057d Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Mon, 21 Oct 2024 08:04:49 +0200 Subject: [PATCH 53/97] fix: add NotNull attribute to DerivesFrom assertion Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 20 +++++++++++++++++++ .../Check.TypeAssertions.cs | 8 ++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index cf34aab5..1abd580c 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -976,4 +976,24 @@ public static void CheckIsOrImplements() return (type, interfaceType, EqualityComparer.Default); } } + + [Fact] + public static void CheckDerivesFrom() + { + TestDerivesFrom(typeof(FileStream), typeof(Stream)).Should().Be((typeof(FileStream), typeof(Stream))); + TestDerivesFromWithTypeComparer(typeof(FileStream), typeof(Stream)).Should().Be((typeof(FileStream), typeof(Stream))); + return; + + static (Type Type, Type BaseType) TestDerivesFrom(Type? type, Type? baseType) + { + type!.DerivesFrom(baseType!); + return (type, baseType); + } + + static (Type Type, Type BaseType) TestDerivesFromWithTypeComparer(Type? type, Type? baseType) + { + type!.DerivesFrom(baseType!, EqualityComparer.Default); + return (type, baseType); + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.TypeAssertions.cs b/Code/Light.GuardClauses/Check.TypeAssertions.cs index 35211e48..527cac80 100644 --- a/Code/Light.GuardClauses/Check.TypeAssertions.cs +++ b/Code/Light.GuardClauses/Check.TypeAssertions.cs @@ -151,7 +151,9 @@ public static bool IsOrImplements( /// The base class that should derive from. /// Thrown when or is null. [ContractAnnotation("type:null => halt; baseClass:null => halt")] - public static bool DerivesFrom([ValidatedNotNull] this Type type, [ValidatedNotNull] Type baseClass) + // ReSharper disable RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests + public static bool DerivesFrom([NotNull, ValidatedNotNull] this Type type, [NotNull, ValidatedNotNull] Type baseClass) + // ReSharper restore RedundantNullableFlowAttribute { baseClass.MustNotBeNull(nameof(baseClass)); @@ -176,7 +178,9 @@ public static bool DerivesFrom([ValidatedNotNull] this Type type, [ValidatedNotN /// The equality comparer used to compare the types. /// Thrown when , or , or is null. [ContractAnnotation("type:null => halt; baseClass:null => halt; typeComparer:null => halt")] - public static bool DerivesFrom([ValidatedNotNull] this Type type, [ValidatedNotNull] Type baseClass, [ValidatedNotNull] IEqualityComparer typeComparer) + // ReSharper disable RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests + public static bool DerivesFrom([NotNull, ValidatedNotNull] this Type type, [NotNull, ValidatedNotNull] Type baseClass, [NotNull, ValidatedNotNull] IEqualityComparer typeComparer) + // ReSharper restore RedundantNullableFlowAttribute { baseClass.MustNotBeNull(nameof(baseClass)); typeComparer.MustNotBeNull(nameof(typeComparer)); From 268ad5947cdf28e4510d302aff8685cfe632c786 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Mon, 21 Oct 2024 08:08:39 +0200 Subject: [PATCH 54/97] fix: add NotNull attribute to IsOrInheritsFrom assertion Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 30 +++++++++++++++---- .../Check.TypeAssertions.cs | 14 +++++---- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 1abd580c..fd1a44df 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -943,13 +943,13 @@ public static void CheckImplements() TestImplements(typeof(FileInfo), typeof(ISerializable)).Should().Be((typeof(FileInfo), typeof(ISerializable))); TestImplementsWithComparer(typeof(FileInfo), typeof(ISerializable)).Should().Be((typeof(FileInfo), typeof(ISerializable), EqualityComparer.Default)); return; - + static (Type Type, Type InterfaceType) TestImplements(Type? type, Type? interfaceType) { type!.Implements(interfaceType!); return (type, interfaceType); } - + static (Type Type, Type InterfaceType, IEqualityComparer Comparer) TestImplementsWithComparer(Type? type, Type? interfaceType) { type!.Implements(interfaceType!, EqualityComparer.Default); @@ -969,7 +969,7 @@ public static void CheckIsOrImplements() type!.IsOrImplements(interfaceType!); return (type, interfaceType); } - + static (Type Type, Type InterfaceType, IEqualityComparer Comparer) TestIsOrImplementsWithComparer(Type? type, Type? interfaceType) { type!.IsOrImplements(interfaceType!, EqualityComparer.Default); @@ -983,17 +983,37 @@ public static void CheckDerivesFrom() TestDerivesFrom(typeof(FileStream), typeof(Stream)).Should().Be((typeof(FileStream), typeof(Stream))); TestDerivesFromWithTypeComparer(typeof(FileStream), typeof(Stream)).Should().Be((typeof(FileStream), typeof(Stream))); return; - + static (Type Type, Type BaseType) TestDerivesFrom(Type? type, Type? baseType) { type!.DerivesFrom(baseType!); return (type, baseType); } - + static (Type Type, Type BaseType) TestDerivesFromWithTypeComparer(Type? type, Type? baseType) { type!.DerivesFrom(baseType!, EqualityComparer.Default); return (type, baseType); } } + + [Fact] + public static void CheckIsOrInheritsFrom() + { + TestIsOrInheritsFrom(typeof(FileStream), typeof(Stream)).Should().Be((typeof(FileStream), typeof(Stream))); + TestIsOrInheritsFromWithComparer(typeof(FileStream), typeof(Stream)).Should().Be((typeof(FileStream), typeof(Stream), EqualityComparer.Default)); + return; + + static (Type Type, Type BaseType) TestIsOrInheritsFrom(Type? type, Type? baseType) + { + type!.IsOrInheritsFrom(baseType!); + return (type, baseType); + } + + static (Type Type, Type BaseType, IEqualityComparer Comparer) TestIsOrInheritsFromWithComparer(Type? type, Type? baseType) + { + type!.IsOrInheritsFrom(baseType!, EqualityComparer.Default); + return (type, baseType, EqualityComparer.Default); + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.TypeAssertions.cs b/Code/Light.GuardClauses/Check.TypeAssertions.cs index 527cac80..83c2bc2d 100644 --- a/Code/Light.GuardClauses/Check.TypeAssertions.cs +++ b/Code/Light.GuardClauses/Check.TypeAssertions.cs @@ -279,8 +279,10 @@ public static bool IsOrInheritsFrom( #if NET8_0 [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] #endif - [ValidatedNotNull] this Type type, - [ValidatedNotNull] Type otherType) => + // ReSharper disable RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests + [NotNull, ValidatedNotNull] this Type type, + [NotNull, ValidatedNotNull] Type otherType) => + // ReSharper restore RedundantNullableFlowAttribute type.IsEquivalentTypeTo(otherType.MustNotBeNull(nameof(otherType))) || type.InheritsFrom(otherType); @@ -298,9 +300,11 @@ public static bool IsOrInheritsFrom( #if NET8_0 [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] #endif - [ValidatedNotNull] this Type type, - [ValidatedNotNull] Type otherType, - [ValidatedNotNull] IEqualityComparer typeComparer) => + // ReSharper disable RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests + [NotNull, ValidatedNotNull] this Type type, + [NotNull, ValidatedNotNull] Type otherType, + [NotNull, ValidatedNotNull] IEqualityComparer typeComparer) => + // ReSharper restore RedundantNullableFlowAttribute typeComparer.MustNotBeNull(nameof(typeComparer)).Equals(type, otherType.MustNotBeNull(nameof(otherType))) || type.InheritsFrom(otherType, typeComparer); From 7990345c54c4a55ca7490303d564daf0df628b16 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Mon, 21 Oct 2024 08:11:22 +0200 Subject: [PATCH 55/97] fix: add NotNull attribute to InheritsFrom assertion Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 21 +++++++++++++++++++ .../Check.TypeAssertions.cs | 18 +++++++++------- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index fd1a44df..ee41bcbc 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -997,6 +997,27 @@ public static void CheckDerivesFrom() } } + [Fact] + public static void CheckInheritsFrom() + { + TestInheritsFrom(typeof(FileStream), typeof(Stream)).Should().Be((typeof(FileStream), typeof(Stream))); + TestInheritsFromWithTypeComparer(typeof(FileStream), typeof(Stream)).Should().Be((typeof(FileStream), typeof(Stream), EqualityComparer.Default)); + return; + + static (Type Type, Type BaseType) TestInheritsFrom(Type? type, Type? baseType) + { + type!.InheritsFrom(baseType!); + return (type, baseType); + } + + static (Type Type, Type BaseType, IEqualityComparer Comparer) TestInheritsFromWithTypeComparer(Type? type, Type? baseType) + { + type!.InheritsFrom(baseType!, EqualityComparer.Default); + return (type, baseType, EqualityComparer.Default); + } + } + + [Fact] public static void CheckIsOrInheritsFrom() { diff --git a/Code/Light.GuardClauses/Check.TypeAssertions.cs b/Code/Light.GuardClauses/Check.TypeAssertions.cs index 83c2bc2d..5892aa0f 100644 --- a/Code/Light.GuardClauses/Check.TypeAssertions.cs +++ b/Code/Light.GuardClauses/Check.TypeAssertions.cs @@ -235,9 +235,11 @@ public static bool IsOrDerivesFrom([ValidatedNotNull] this Type type, [Validated public static bool InheritsFrom( #if NET8_0 [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] -#endif - [ValidatedNotNull] this Type type, - [ValidatedNotNull] Type baseClassOrInterfaceType) => +#endif + // ReSharper disable RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests + [NotNull, ValidatedNotNull] this Type type, + [NotNull, ValidatedNotNull] Type baseClassOrInterfaceType) => + // ReSharper restore RedundantNullableFlowAttribute baseClassOrInterfaceType.MustNotBeNull(nameof(baseClassOrInterfaceType)) .IsInterface ? type.Implements(baseClassOrInterfaceType) : @@ -256,10 +258,12 @@ public static bool InheritsFrom( public static bool InheritsFrom( #if NET8_0 [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] -#endif - [ValidatedNotNull] this Type type, - [ValidatedNotNull] Type baseClassOrInterfaceType, - [ValidatedNotNull] IEqualityComparer typeComparer) => +#endif + // ReSharper disable RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests + [NotNull, ValidatedNotNull] this Type type, + [NotNull, ValidatedNotNull] Type baseClassOrInterfaceType, + [NotNull, ValidatedNotNull] IEqualityComparer typeComparer) => + // ReSharper restore RedundantNullableFlowAttribute baseClassOrInterfaceType.MustNotBeNull(nameof(baseClassOrInterfaceType)) .IsInterface ? type.Implements(baseClassOrInterfaceType, typeComparer) : From d10560fc8fa06b224e60a3c46f3c87a97c6a6563 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Mon, 21 Oct 2024 08:13:27 +0200 Subject: [PATCH 56/97] fix: add NotNull attribute to IsOrDerivesFrom assertion Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 20 +++++++++++++++++++ .../Check.TypeAssertions.cs | 8 ++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index ee41bcbc..41e2577b 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -997,6 +997,26 @@ public static void CheckDerivesFrom() } } + [Fact] + public static void CheckIsOrDerivesFrom() + { + TestIsOrDerivesFrom(typeof(FileStream), typeof(Stream)).Should().Be((typeof(FileStream), typeof(Stream))); + TestIsOrDerivesFromWithComparer(typeof(FileStream), typeof(Stream)).Should().Be((typeof(FileStream), typeof(Stream), EqualityComparer.Default)); + return; + + static (Type Type, Type BaseType) TestIsOrDerivesFrom(Type? type, Type? baseType) + { + type!.IsOrDerivesFrom(baseType!); + return (type, baseType); + } + + static (Type Type, Type BaseType, IEqualityComparer Comparer) TestIsOrDerivesFromWithComparer(Type? type, Type? baseType) + { + type!.IsOrDerivesFrom(baseType!, EqualityComparer.Default); + return (type, baseType, EqualityComparer.Default); + } + } + [Fact] public static void CheckInheritsFrom() { diff --git a/Code/Light.GuardClauses/Check.TypeAssertions.cs b/Code/Light.GuardClauses/Check.TypeAssertions.cs index 5892aa0f..c6133ba7 100644 --- a/Code/Light.GuardClauses/Check.TypeAssertions.cs +++ b/Code/Light.GuardClauses/Check.TypeAssertions.cs @@ -206,7 +206,9 @@ public static bool DerivesFrom([NotNull, ValidatedNotNull] this Type type, [NotN /// Thrown when or is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("type:null => halt; otherType:null => halt")] - public static bool IsOrDerivesFrom([ValidatedNotNull] this Type type, [ValidatedNotNull] Type otherType) => + // ReSharper disable RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests + public static bool IsOrDerivesFrom([NotNull, ValidatedNotNull] this Type type, [NotNull, ValidatedNotNull] Type otherType) => + // ReSharper restore RedundantNullableFlowAttribute type.IsEquivalentTypeTo(otherType.MustNotBeNull(nameof(otherType))) || type.DerivesFrom(otherType); /// @@ -219,7 +221,9 @@ public static bool IsOrDerivesFrom([ValidatedNotNull] this Type type, [Validated /// Thrown when , or , or is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("type:null => halt; otherType:null => halt; typeComparer:null => halt")] - public static bool IsOrDerivesFrom([ValidatedNotNull] this Type type, [ValidatedNotNull] Type otherType, [ValidatedNotNull] IEqualityComparer typeComparer) => + // ReSharper disable RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests + public static bool IsOrDerivesFrom([NotNull, ValidatedNotNull] this Type type, [NotNull, ValidatedNotNull] Type otherType, [NotNull, ValidatedNotNull] IEqualityComparer typeComparer) => + // ReSharper restore RedundantNullableFlowAttribute typeComparer.MustNotBeNull(nameof(typeComparer)).Equals(type, otherType.MustNotBeNull(nameof(otherType))) || type.DerivesFrom(otherType, typeComparer); From 7516907afb27c7e07fafa4c3820de5552365f0c1 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Mon, 21 Oct 2024 08:17:43 +0200 Subject: [PATCH 57/97] fix: add NotNull attribute to MustBeAbsoluteUri Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 20 +++++++++++++++++++ .../Light.GuardClauses/Check.UriAssertions.cs | 9 +++++---- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 41e2577b..826edc91 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -1057,4 +1057,24 @@ public static void CheckIsOrInheritsFrom() return (type, baseType, EqualityComparer.Default); } } + + [Fact] + public static void CheckMustBeAbsoluteUri() + { + TestMustBeAbsoluteUri(new Uri("https://example.com")).Should().Be(new Uri("https://example.com")); + TestMustBeAbsoluteUriWithDelegate(new Uri("https://example.com")).Should().Be(new Uri("https://example.com")); + return; + + static Uri TestMustBeAbsoluteUri(Uri? input) + { + input.MustBeAbsoluteUri(); + return input; + } + + static Uri TestMustBeAbsoluteUriWithDelegate(Uri? input) + { + input.MustBeAbsoluteUri(_ => new Exception()); + return input; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.UriAssertions.cs b/Code/Light.GuardClauses/Check.UriAssertions.cs index b894e1e2..3601468b 100644 --- a/Code/Light.GuardClauses/Check.UriAssertions.cs +++ b/Code/Light.GuardClauses/Check.UriAssertions.cs @@ -4,6 +4,7 @@ using JetBrains.Annotations; using Light.GuardClauses.Exceptions; using System.Runtime.CompilerServices; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; namespace Light.GuardClauses; @@ -19,11 +20,11 @@ public static partial class Check /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static Uri MustBeAbsoluteUri([ValidatedNotNull] this Uri? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) + public static Uri MustBeAbsoluteUri([NotNull, ValidatedNotNull] this Uri? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (parameter.MustNotBeNull(parameterName, message).IsAbsoluteUri == false) - Throw.MustBeAbsoluteUri(parameter!, parameterName, message); - return parameter!; + Throw.MustBeAbsoluteUri(parameter, parameterName, message); + return parameter; } /// @@ -34,7 +35,7 @@ public static Uri MustBeAbsoluteUri([ValidatedNotNull] this Uri? parameter, [Cal /// Your custom exception thrown when is not an absolute URI, or when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static Uri MustBeAbsoluteUri([ValidatedNotNull] this Uri? parameter, Func exceptionFactory) + public static Uri MustBeAbsoluteUri([NotNull, ValidatedNotNull] this Uri? parameter, Func exceptionFactory) { if (parameter is null || parameter.IsAbsoluteUri == false) Throw.CustomException(exceptionFactory, parameter); From 0e84bf74836462b593c0d1b9dee6609e3a3aa264 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Mon, 21 Oct 2024 08:18:54 +0200 Subject: [PATCH 58/97] fix: add NotNull attribute to MustBeRelativeUri Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 20 +++++++++++++++++++ .../Light.GuardClauses/Check.UriAssertions.cs | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 826edc91..72cca75f 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -1077,4 +1077,24 @@ static Uri TestMustBeAbsoluteUriWithDelegate(Uri? input) return input; } } + + [Fact] + public static void CheckMustBeRelativeUri() + { + TestMustBeRelativeUri(new Uri("/relative/path", UriKind.Relative)).Should().Be(new Uri("/relative/path", UriKind.Relative)); + TestMustBeRelativeUriWithDelegate(new Uri("/relative/path", UriKind.Relative)).Should().Be(new Uri("/relative/path", UriKind.Relative)); + return; + + static Uri TestMustBeRelativeUri(Uri? input) + { + input.MustBeRelativeUri(); + return input; + } + + static Uri TestMustBeRelativeUriWithDelegate(Uri? input) + { + input.MustBeRelativeUri(_ => new Exception()); + return input; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.UriAssertions.cs b/Code/Light.GuardClauses/Check.UriAssertions.cs index 3601468b..4fc9367d 100644 --- a/Code/Light.GuardClauses/Check.UriAssertions.cs +++ b/Code/Light.GuardClauses/Check.UriAssertions.cs @@ -52,7 +52,7 @@ public static Uri MustBeAbsoluteUri([NotNull, ValidatedNotNull] this Uri? parame /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static Uri MustBeRelativeUri([ValidatedNotNull] this Uri? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) + public static Uri MustBeRelativeUri([NotNull, ValidatedNotNull] this Uri? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (parameter.MustNotBeNull(parameterName, message).IsAbsoluteUri) Throw.MustBeRelativeUri(parameter!, parameterName, message); @@ -67,7 +67,7 @@ public static Uri MustBeRelativeUri([ValidatedNotNull] this Uri? parameter, [Cal /// Your custom exception thrown when is an absolute URI, or when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static Uri MustBeRelativeUri([ValidatedNotNull] this Uri? parameter, Func exceptionFactory) + public static Uri MustBeRelativeUri([NotNull, ValidatedNotNull] this Uri? parameter, Func exceptionFactory) { if (parameter is null || parameter.IsAbsoluteUri) Throw.CustomException(exceptionFactory, parameter); From eb04369c56d256a2913e22f906ff55d2066dc771 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Mon, 21 Oct 2024 08:21:04 +0200 Subject: [PATCH 59/97] fix: add NotNull attribute to MustHaveScheme Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 27 +++++++++++++++++++ .../Light.GuardClauses/Check.UriAssertions.cs | 6 ++--- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 72cca75f..50fecebd 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -1097,4 +1097,31 @@ static Uri TestMustBeRelativeUriWithDelegate(Uri? input) return input; } } + + [Fact] + public static void CheckMustHaveScheme() + { + TestMustHaveScheme(new Uri("https://example.com"), "https").Should().Be(new Uri("https://example.com")); + TestMustHaveSchemeWithDelegate(new Uri("https://example.com"), "https").Should().Be(new Uri("https://example.com")); + TestMustHaveSchemeWithSecondDelegate(new Uri("https://example.com"), "https").Should().Be(new Uri("https://example.com")); + return; + + static Uri TestMustHaveScheme(Uri? input, string scheme) + { + input.MustHaveScheme(scheme); + return input; + } + + static Uri TestMustHaveSchemeWithDelegate(Uri? input, string scheme) + { + input.MustHaveScheme(scheme, _ => new Exception()); + return input; + } + + static Uri TestMustHaveSchemeWithSecondDelegate(Uri? input, string scheme) + { + input.MustHaveScheme(scheme, (_, _) => new Exception()); + return input; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.UriAssertions.cs b/Code/Light.GuardClauses/Check.UriAssertions.cs index 4fc9367d..8d8ba1cc 100644 --- a/Code/Light.GuardClauses/Check.UriAssertions.cs +++ b/Code/Light.GuardClauses/Check.UriAssertions.cs @@ -86,7 +86,7 @@ public static Uri MustBeRelativeUri([NotNull, ValidatedNotNull] this Uri? parame /// Throw when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static Uri MustHaveScheme([ValidatedNotNull] this Uri? parameter, string scheme, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) + public static Uri MustHaveScheme([NotNull, ValidatedNotNull] this Uri? parameter, string scheme, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (string.Equals(parameter.MustBeAbsoluteUri(parameterName, message).Scheme, scheme) == false) Throw.UriMustHaveScheme(parameter!, scheme, parameterName, message); @@ -106,7 +106,7 @@ public static Uri MustHaveScheme([ValidatedNotNull] this Uri? parameter, string /// [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static Uri MustHaveScheme([ValidatedNotNull] this Uri? parameter, string scheme, Func exceptionFactory) + public static Uri MustHaveScheme([NotNull, ValidatedNotNull] this Uri? parameter, string scheme, Func exceptionFactory) { if (string.Equals(parameter.MustBeAbsoluteUri(exceptionFactory).Scheme, scheme) == false) Throw.CustomException(exceptionFactory, parameter); @@ -126,7 +126,7 @@ public static Uri MustHaveScheme([ValidatedNotNull] this Uri? parameter, string /// [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static Uri MustHaveScheme([ValidatedNotNull] this Uri? parameter, string scheme, Func exceptionFactory) + public static Uri MustHaveScheme([NotNull, ValidatedNotNull] this Uri? parameter, string scheme, Func exceptionFactory) { if (parameter is null || !parameter.IsAbsoluteUri || parameter.Scheme.Equals(scheme) == false) Throw.CustomException(exceptionFactory, parameter, scheme); From e8e352891fc08a267f69a8855920e229a10489f3 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Mon, 21 Oct 2024 08:22:42 +0200 Subject: [PATCH 60/97] fix: add NotNull attribute to MustBeHttpsUrl Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 20 +++++++++++++++++++ .../Light.GuardClauses/Check.UriAssertions.cs | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 50fecebd..e6534360 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -1124,4 +1124,24 @@ static Uri TestMustHaveSchemeWithSecondDelegate(Uri? input, string scheme) return input; } } + + [Fact] + public static void CheckMustBeHttpsUrl() + { + TestMustBeHttpsUrl(new Uri("https://example.com")).Should().Be(new Uri("https://example.com")); + TestMustBeHttpsUrlWithDelegate(new Uri("https://example.com")).Should().Be(new Uri("https://example.com")); + return; + + static Uri TestMustBeHttpsUrl(Uri? input) + { + input.MustBeHttpsUrl(); + return input; + } + + static Uri TestMustBeHttpsUrlWithDelegate(Uri? input) + { + input.MustBeHttpsUrl(_ => new Exception()); + return input; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.UriAssertions.cs b/Code/Light.GuardClauses/Check.UriAssertions.cs index 8d8ba1cc..36040566 100644 --- a/Code/Light.GuardClauses/Check.UriAssertions.cs +++ b/Code/Light.GuardClauses/Check.UriAssertions.cs @@ -144,7 +144,7 @@ public static Uri MustHaveScheme([NotNull, ValidatedNotNull] this Uri? parameter /// Throw when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static Uri MustBeHttpsUrl([ValidatedNotNull] this Uri? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) => parameter.MustHaveScheme("https", parameterName, message); + public static Uri MustBeHttpsUrl([NotNull, ValidatedNotNull] this Uri? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) => parameter.MustHaveScheme("https", parameterName, message); /// /// Ensures that the specified URI has the "https" scheme, or otherwise throws your custom exception. @@ -158,7 +158,7 @@ public static Uri MustHaveScheme([NotNull, ValidatedNotNull] this Uri? parameter /// [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static Uri MustBeHttpsUrl([ValidatedNotNull] this Uri? parameter, Func exceptionFactory) => parameter.MustHaveScheme("https", exceptionFactory); + public static Uri MustBeHttpsUrl([NotNull, ValidatedNotNull] this Uri? parameter, Func exceptionFactory) => parameter.MustHaveScheme("https", exceptionFactory); /// /// Ensures that the specified URI has the "http" scheme, or otherwise throws an . From 2b96b9597bdba2a0fccf52c823dab5929d076dc2 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Mon, 21 Oct 2024 08:24:10 +0200 Subject: [PATCH 61/97] fix: add NotNull attribute to MustBeHttpUrl Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 20 +++++++++++++++++++ .../Light.GuardClauses/Check.UriAssertions.cs | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index e6534360..c3b63747 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -1144,4 +1144,24 @@ static Uri TestMustBeHttpsUrlWithDelegate(Uri? input) return input; } } + + [Fact] + public static void CheckMustBeHttpUrl() + { + TestMustBeHttpUrl(new Uri("http://example.com")).Should().Be(new Uri("http://example.com")); + TestMustBeHttpUrlWithDelegate(new Uri("http://example.com")).Should().Be(new Uri("http://example.com")); + return; + + static Uri TestMustBeHttpUrl(Uri? input) + { + input.MustBeHttpUrl(); + return input; + } + + static Uri TestMustBeHttpUrlWithDelegate(Uri? input) + { + input.MustBeHttpUrl(_ => new Exception()); + return input; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.UriAssertions.cs b/Code/Light.GuardClauses/Check.UriAssertions.cs index 36040566..4bb7f987 100644 --- a/Code/Light.GuardClauses/Check.UriAssertions.cs +++ b/Code/Light.GuardClauses/Check.UriAssertions.cs @@ -171,7 +171,7 @@ public static Uri MustHaveScheme([NotNull, ValidatedNotNull] this Uri? parameter /// Throw when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static Uri MustBeHttpUrl([ValidatedNotNull] this Uri? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) => parameter.MustHaveScheme("http", parameterName, message); + public static Uri MustBeHttpUrl([NotNull, ValidatedNotNull] this Uri? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) => parameter.MustHaveScheme("http", parameterName, message); /// /// Ensures that the specified URI has the "http" scheme, or otherwise throws your custom exception. @@ -185,7 +185,7 @@ public static Uri MustHaveScheme([NotNull, ValidatedNotNull] this Uri? parameter /// [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static Uri MustBeHttpUrl([ValidatedNotNull] this Uri? parameter, Func exceptionFactory) => parameter.MustHaveScheme("http", exceptionFactory); + public static Uri MustBeHttpUrl([NotNull, ValidatedNotNull] this Uri? parameter, Func exceptionFactory) => parameter.MustHaveScheme("http", exceptionFactory); /// /// Ensures that the specified URI has the "http" or "https" scheme, or otherwise throws an . From 4e932896ac911d8f91e00e8e5aff1d137337f2b0 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Mon, 21 Oct 2024 08:25:26 +0200 Subject: [PATCH 62/97] fix: add NotNull attribute to MustBeHttpOrHttpsUrl Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 20 +++++++++++++++++++ .../Light.GuardClauses/Check.UriAssertions.cs | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index c3b63747..8b402357 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -1164,4 +1164,24 @@ static Uri TestMustBeHttpUrlWithDelegate(Uri? input) return input; } } + + [Fact] + public static void CheckMustBeHttpOrHttpsUrl() + { + TestMustBeHttpOrHttpsUrl(new Uri("https://example.com")).Should().Be(new Uri("https://example.com")); + TestMustBeHttpOrHttpsUrlWithDelegate(new Uri("https://example.com")).Should().Be(new Uri("https://example.com")); + return; + + static Uri TestMustBeHttpOrHttpsUrl(Uri? input) + { + input.MustBeHttpOrHttpsUrl(); + return input; + } + + static Uri TestMustBeHttpOrHttpsUrlWithDelegate(Uri? input) + { + input.MustBeHttpOrHttpsUrl(_ => new Exception()); + return input; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.UriAssertions.cs b/Code/Light.GuardClauses/Check.UriAssertions.cs index 4bb7f987..9c9dc4a6 100644 --- a/Code/Light.GuardClauses/Check.UriAssertions.cs +++ b/Code/Light.GuardClauses/Check.UriAssertions.cs @@ -198,7 +198,7 @@ public static Uri MustHaveScheme([NotNull, ValidatedNotNull] this Uri? parameter /// Throw when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static Uri MustBeHttpOrHttpsUrl([ValidatedNotNull] this Uri? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) + public static Uri MustBeHttpOrHttpsUrl([NotNull, ValidatedNotNull] this Uri? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (parameter.MustBeAbsoluteUri(parameterName, message).Scheme.Equals("https") == false && parameter!.Scheme.Equals("http") == false) Throw.UriMustHaveOneSchemeOf(parameter, new[] { "https", "http" }, parameterName, message); @@ -217,7 +217,7 @@ public static Uri MustBeHttpOrHttpsUrl([ValidatedNotNull] this Uri? parameter, [ /// [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static Uri MustBeHttpOrHttpsUrl([ValidatedNotNull] this Uri? parameter, Func exceptionFactory) + public static Uri MustBeHttpOrHttpsUrl([NotNull, ValidatedNotNull] this Uri? parameter, Func exceptionFactory) { if (parameter.MustBeAbsoluteUri(exceptionFactory).Scheme.Equals("https") == false && parameter!.Scheme.Equals("http") == false) Throw.CustomException(exceptionFactory, parameter); From 8a2e3a0205a5b06444608267196b05c3cfa3d505 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Mon, 21 Oct 2024 08:29:09 +0200 Subject: [PATCH 63/97] fix: add NotNull attribute to MustHaveOneSchemeOf Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 20 +++++++++++++++++++ .../Light.GuardClauses/Check.UriAssertions.cs | 6 +++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 8b402357..ee9f1162 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -1184,4 +1184,24 @@ static Uri TestMustBeHttpOrHttpsUrlWithDelegate(Uri? input) return input; } } + + [Fact] + public static void CheckMustHaveOneSchemeOf() + { + TestMustHaveOneSchemeOf(new Uri("https://example.com")).Should().Be(new Uri("https://example.com")); + TestMustHaveOneSchemeOfWithDelegate(new Uri("https://example.com")).Should().Be(new Uri("https://example.com")); + return; + + static Uri TestMustHaveOneSchemeOf(Uri? input) + { + input.MustHaveOneSchemeOf(["http", "https"]); + return input; + } + + static Uri TestMustHaveOneSchemeOfWithDelegate(Uri? input) + { + input.MustHaveOneSchemeOf(new[] { "http", "https" }, (_, _) => new Exception()); + return input; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.UriAssertions.cs b/Code/Light.GuardClauses/Check.UriAssertions.cs index 9c9dc4a6..c99dd0b5 100644 --- a/Code/Light.GuardClauses/Check.UriAssertions.cs +++ b/Code/Light.GuardClauses/Check.UriAssertions.cs @@ -236,7 +236,7 @@ public static Uri MustBeHttpOrHttpsUrl([NotNull, ValidatedNotNull] this Uri? par /// Throw when or is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; schemes:null => halt")] - public static Uri MustHaveOneSchemeOf([ValidatedNotNull] this Uri? parameter, IEnumerable schemes, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) + public static Uri MustHaveOneSchemeOf([NotNull, ValidatedNotNull] this Uri? parameter, IEnumerable schemes, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { // ReSharper disable PossibleMultipleEnumeration parameter.MustBeAbsoluteUri(parameterName, message); @@ -268,7 +268,7 @@ public static Uri MustHaveOneSchemeOf([ValidatedNotNull] this Uri? parameter, IE /// Throw when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static Uri MustHaveOneSchemeOf([ValidatedNotNull] this Uri? parameter, TCollection schemes, Func exceptionFactory) where TCollection : class, IEnumerable + public static Uri MustHaveOneSchemeOf([NotNull, ValidatedNotNull] this Uri? parameter, TCollection schemes, Func exceptionFactory) where TCollection : class, IEnumerable { if (parameter is null || !parameter.IsAbsoluteUri) Throw.CustomException(exceptionFactory, parameter, schemes); @@ -280,7 +280,7 @@ public static Uri MustHaveOneSchemeOf([ValidatedNotNull] this Uri? return parameter; } - // ReSharper disable once ConditionIsAlwaysTrueOrFalse - caller might have NRTs turned off + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off if (schemes is null || !schemes.Contains(parameter.Scheme)) Throw.CustomException(exceptionFactory, parameter, schemes!); return parameter; From 216757817c9488b6d5e97771beada4c3b8469900 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Mon, 21 Oct 2024 08:30:02 +0200 Subject: [PATCH 64/97] chore: remove redundant null-forgiving operators in Check.UriAssertions Signed-off-by: Kenny Pflug --- .../Light.GuardClauses/Check.UriAssertions.cs | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Code/Light.GuardClauses/Check.UriAssertions.cs b/Code/Light.GuardClauses/Check.UriAssertions.cs index c99dd0b5..a45d6c81 100644 --- a/Code/Light.GuardClauses/Check.UriAssertions.cs +++ b/Code/Light.GuardClauses/Check.UriAssertions.cs @@ -55,8 +55,8 @@ public static Uri MustBeAbsoluteUri([NotNull, ValidatedNotNull] this Uri? parame public static Uri MustBeRelativeUri([NotNull, ValidatedNotNull] this Uri? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (parameter.MustNotBeNull(parameterName, message).IsAbsoluteUri) - Throw.MustBeRelativeUri(parameter!, parameterName, message); - return parameter!; + Throw.MustBeRelativeUri(parameter, parameterName, message); + return parameter; } /// @@ -89,8 +89,8 @@ public static Uri MustBeRelativeUri([NotNull, ValidatedNotNull] this Uri? parame public static Uri MustHaveScheme([NotNull, ValidatedNotNull] this Uri? parameter, string scheme, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (string.Equals(parameter.MustBeAbsoluteUri(parameterName, message).Scheme, scheme) == false) - Throw.UriMustHaveScheme(parameter!, scheme, parameterName, message); - return parameter!; + Throw.UriMustHaveScheme(parameter, scheme, parameterName, message); + return parameter; } /// @@ -110,7 +110,7 @@ public static Uri MustHaveScheme([NotNull, ValidatedNotNull] this Uri? parameter { if (string.Equals(parameter.MustBeAbsoluteUri(exceptionFactory).Scheme, scheme) == false) Throw.CustomException(exceptionFactory, parameter); - return parameter!; + return parameter; } /// @@ -200,9 +200,9 @@ public static Uri MustHaveScheme([NotNull, ValidatedNotNull] this Uri? parameter [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] public static Uri MustBeHttpOrHttpsUrl([NotNull, ValidatedNotNull] this Uri? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { - if (parameter.MustBeAbsoluteUri(parameterName, message).Scheme.Equals("https") == false && parameter!.Scheme.Equals("http") == false) + if (parameter.MustBeAbsoluteUri(parameterName, message).Scheme.Equals("https") == false && parameter.Scheme.Equals("http") == false) Throw.UriMustHaveOneSchemeOf(parameter, new[] { "https", "http" }, parameterName, message); - return parameter!; + return parameter; } /// @@ -219,9 +219,9 @@ public static Uri MustBeHttpOrHttpsUrl([NotNull, ValidatedNotNull] this Uri? par [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] public static Uri MustBeHttpOrHttpsUrl([NotNull, ValidatedNotNull] this Uri? parameter, Func exceptionFactory) { - if (parameter.MustBeAbsoluteUri(exceptionFactory).Scheme.Equals("https") == false && parameter!.Scheme.Equals("http") == false) + if (parameter.MustBeAbsoluteUri(exceptionFactory).Scheme.Equals("https") == false && parameter.Scheme.Equals("http") == false) Throw.CustomException(exceptionFactory, parameter); - return parameter!; + return parameter; } /// @@ -243,12 +243,12 @@ public static Uri MustHaveOneSchemeOf([NotNull, ValidatedNotNull] this Uri? para if (schemes is ICollection collection) { - if (!collection.Contains(parameter!.Scheme)) + if (!collection.Contains(parameter.Scheme)) Throw.UriMustHaveOneSchemeOf(parameter, schemes, parameterName, message); return parameter; } - if (!schemes.MustNotBeNull(nameof(schemes), message).Contains(parameter!.Scheme)) + if (!schemes.MustNotBeNull(nameof(schemes), message).Contains(parameter.Scheme)) Throw.UriMustHaveOneSchemeOf(parameter, schemes, parameterName, message); return parameter; // ReSharper restore PossibleMultipleEnumeration From a77d73da9c788a82a520a239718793b708722c2a Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 27 Oct 2024 04:00:32 +0100 Subject: [PATCH 65/97] feat: add NotNull attribute to IsIn assertion Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 13 +++++++++++++ .../Check.ComparableAssertions.cs | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index ee9f1162..8ed10586 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -1204,4 +1204,17 @@ static Uri TestMustHaveOneSchemeOfWithDelegate(Uri? input) return input; } } + + [Fact] + public static void CheckIsIn() + { + TestIsIn("k").Should().Be("k"); + return; + + static string TestIsIn(string? input) + { + input!.IsIn(Range.FromInclusive("a").ToInclusive("z")); + return input; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.ComparableAssertions.cs b/Code/Light.GuardClauses/Check.ComparableAssertions.cs index 71ae9337..ef6e7da2 100644 --- a/Code/Light.GuardClauses/Check.ComparableAssertions.cs +++ b/Code/Light.GuardClauses/Check.ComparableAssertions.cs @@ -325,7 +325,7 @@ public static T MustBeLessThanOrEqualTo([NotNull, ValidatedNotNull] this T pa /// True if the parameter is within the specified range, else false. /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsIn([ValidatedNotNull] this T parameter, Range range) where T : IComparable => range.IsValueWithinRange(parameter); + public static bool IsIn([NotNull, ValidatedNotNull] this T parameter, Range range) where T : IComparable => range.IsValueWithinRange(parameter); /// /// Checks if the value is not within the specified range. From cef1818f194ff97b32a01064108003142757afa7 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 27 Oct 2024 04:02:23 +0100 Subject: [PATCH 66/97] feat: add NotNull attribute to IsNotIn assertion Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 13 +++++++++++++ .../Check.ComparableAssertions.cs | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 8ed10586..af0d3d02 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -1217,4 +1217,17 @@ static string TestIsIn(string? input) return input; } } + + [Fact] + public static void CheckIsNotIn() + { + TestIsNotIn("k").Should().Be("k"); + return; + + static string TestIsNotIn(string? input) + { + input!.IsNotIn(Range.FromInclusive("a").ToInclusive("h")); + return input; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.ComparableAssertions.cs b/Code/Light.GuardClauses/Check.ComparableAssertions.cs index ef6e7da2..0eb90208 100644 --- a/Code/Light.GuardClauses/Check.ComparableAssertions.cs +++ b/Code/Light.GuardClauses/Check.ComparableAssertions.cs @@ -335,7 +335,7 @@ public static T MustBeLessThanOrEqualTo([NotNull, ValidatedNotNull] this T pa /// True if the parameter is not within the specified range, else false. /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsNotIn([ValidatedNotNull] this T parameter, Range range) where T : IComparable => !range.IsValueWithinRange(parameter); + public static bool IsNotIn([NotNull, ValidatedNotNull] this T parameter, Range range) where T : IComparable => !range.IsValueWithinRange(parameter); /// /// Ensures that is within the specified range, or otherwise throws an . From f1e91a16eedb64d6371b8ee5e35f8b5bb0a9f345 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 27 Oct 2024 04:11:14 +0100 Subject: [PATCH 67/97] feat: add NotNull attribute to IsSubstringOf Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 20 +++++++++++++++++++ .../Check.StringAssertions.cs | 10 ++++++---- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index af0d3d02..1fa6edf4 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -1230,4 +1230,24 @@ static string TestIsNotIn(string? input) return input; } } + + [Fact] + public static void CheckIsSubstringOf() + { + TestIsSubstringOf("foo", "oo").Should().Be("foo"); + TestIsSubstringOfWithComparison("foo", "oo").Should().Be("foo"); + return; + + static string TestIsSubstringOf(string? input, string? comparison) + { + comparison!.IsSubstringOf(input!); + return input; + } + + static string TestIsSubstringOfWithComparison(string? input, string? comparison) + { + comparison!.IsSubstringOf(input!, StringComparison.OrdinalIgnoreCase); + return input; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.StringAssertions.cs b/Code/Light.GuardClauses/Check.StringAssertions.cs index c51eb5d1..b3f678da 100644 --- a/Code/Light.GuardClauses/Check.StringAssertions.cs +++ b/Code/Light.GuardClauses/Check.StringAssertions.cs @@ -514,9 +514,10 @@ public static bool Contains([NotNull, ValidatedNotNull] this string @string, str /// Thrown when or is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("value:null => halt; other:null => halt")] - // ReSharper disable once RedundantNullableFlowAttribute - public static bool IsSubstringOf([NotNull, ValidatedNotNull] this string value, [ValidatedNotNull] string other) => + // ReSharper disable RedundantNullableFlowAttribute + public static bool IsSubstringOf([NotNull, ValidatedNotNull] this string value, [NotNull, ValidatedNotNull] string other) => other.MustNotBeNull(nameof(other)).Contains(value); + // ReSharper restore RedundantNullableFlowAttribute /// /// Checks if the string is a substring of the other string. @@ -529,9 +530,10 @@ public static bool IsSubstringOf([NotNull, ValidatedNotNull] this string value, /// Thrown when is not a valid value. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("value:null => halt; other:null => halt")] - // ReSharper disable once RedundantNullableFlowAttribute - public static bool IsSubstringOf([NotNull] this string value, string other, StringComparison comparisonType) => + // ReSharper disable RedundantNullableFlowAttribute + public static bool IsSubstringOf([NotNull, ValidatedNotNull] this string value, [NotNull, ValidatedNotNull] string other, StringComparison comparisonType) => other.MustNotBeNull(nameof(other)).IndexOf(value, comparisonType) != -1; + // ReSharper disable RedundantNullableFlowAttribute /// /// Ensures that the string is a substring of the specified other string, or otherwise throws a . From 2e0ff63b48abe15f987b3ac34610edaeaeb581bc Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 27 Oct 2024 04:14:01 +0100 Subject: [PATCH 68/97] feat: add NotNullAttribute to IsOpenConstructedGenericType assertion Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 13 +++++++++++++ Code/Light.GuardClauses/Check.TypeAssertions.cs | 3 ++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 1fa6edf4..faa18fd0 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -1250,4 +1250,17 @@ static string TestIsSubstringOfWithComparison(string? input, string? comparison) return input; } } + + [Fact] + public static void CheckIsOpenConstructedGenericType() + { + TestIsOpenConstructedGenericType(typeof(List<>)).Should().Be(typeof(List<>)); + return; + + static Type TestIsOpenConstructedGenericType(Type? type) + { + type!.IsOpenConstructedGenericType(); + return type; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.TypeAssertions.cs b/Code/Light.GuardClauses/Check.TypeAssertions.cs index c6133ba7..3fd8a0dc 100644 --- a/Code/Light.GuardClauses/Check.TypeAssertions.cs +++ b/Code/Light.GuardClauses/Check.TypeAssertions.cs @@ -324,7 +324,8 @@ public static bool IsOrInheritsFrom( /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("type:null => halt")] - public static bool IsOpenConstructedGenericType([ValidatedNotNull] this Type type) => + // ReSharper disable once RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests + public static bool IsOpenConstructedGenericType([NotNull, ValidatedNotNull] this Type type) => type.MustNotBeNull(nameof(type)).IsGenericType && type.ContainsGenericParameters && type.IsGenericTypeDefinition == false; From ecc6a469ee4bfcf666f5d2f1a17435c88e538893 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 27 Oct 2024 04:19:21 +0100 Subject: [PATCH 69/97] feat: add NotNull attribute to AsList Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 21 +++++++++++++++++++ .../EnumerableExtensions.cs | 6 ++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index faa18fd0..977e67fd 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -6,6 +6,7 @@ using System.Runtime.Serialization; using System.Text.RegularExpressions; using FluentAssertions; +using Light.GuardClauses.FrameworkExtensions; using Xunit; namespace Light.GuardClauses.Tests.Issues; @@ -1263,4 +1264,24 @@ static Type TestIsOpenConstructedGenericType(Type? type) return type; } } + + [Fact] + public static void CheckAsList() + { + TestAsList(new List()).Should().Be(0); + TestAsListWithDelegate(new List()).Should().Be(0); + return; + + static int TestAsList(IList? list) + { + list!.AsList(); + return list.Count; + } + + static int TestAsListWithDelegate(IList? list) + { + list!.AsList(collection => new List(collection)); + return list.Count; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/FrameworkExtensions/EnumerableExtensions.cs b/Code/Light.GuardClauses/FrameworkExtensions/EnumerableExtensions.cs index 44001dc9..cd3c1596 100644 --- a/Code/Light.GuardClauses/FrameworkExtensions/EnumerableExtensions.cs +++ b/Code/Light.GuardClauses/FrameworkExtensions/EnumerableExtensions.cs @@ -24,7 +24,8 @@ public static class EnumerableExtensions /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("source:null => halt; source:notnull => notnull")] - public static IList AsList([ValidatedNotNull] this IEnumerable source) => + // ReSharper disable once RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests + public static IList AsList([NotNull, ValidatedNotNull] this IEnumerable source) => source as IList ?? source.ToList(); /// @@ -38,7 +39,8 @@ public static IList AsList([ValidatedNotNull] this IEnumerable source) /// Thrown when or is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("source:null => halt; source:notnull => notnull; createCollection:null => halt")] - public static IList AsList([ValidatedNotNull] this IEnumerable source, Func, IList> createCollection) => + // ReSharper disable once RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests + public static IList AsList([NotNull, ValidatedNotNull] this IEnumerable source, Func, IList> createCollection) => source as IList ?? createCollection.MustNotBeNull(nameof(createCollection))(source.MustNotBeNull(nameof(source))); /// From 56f1683156eb4a6ce6facd878238bee0e17790b1 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 27 Oct 2024 04:23:10 +0100 Subject: [PATCH 70/97] feat: add NotNull attribute to AsArray Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 13 +++++++++++++ .../FrameworkExtensions/EnumerableExtensions.cs | 3 ++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 977e67fd..17d83653 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -1284,4 +1284,17 @@ static int TestAsListWithDelegate(IList? list) return list.Count; } } + + [Fact] + public static void CheckAsArray() + { + TestAsArray([1, 2, 3]).Should().Be(3); + return; + + static int TestAsArray(int[]? array) + { + array!.AsArray(); + return array.Length; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/FrameworkExtensions/EnumerableExtensions.cs b/Code/Light.GuardClauses/FrameworkExtensions/EnumerableExtensions.cs index cd3c1596..452525ec 100644 --- a/Code/Light.GuardClauses/FrameworkExtensions/EnumerableExtensions.cs +++ b/Code/Light.GuardClauses/FrameworkExtensions/EnumerableExtensions.cs @@ -52,7 +52,8 @@ public static IList AsList([NotNull, ValidatedNotNull] this IEnumerable /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("source:null => halt; source:notnull => notnull")] - public static T[] AsArray([ValidatedNotNull] this IEnumerable source) => source as T[] ?? source.ToArray(); + // ReSharper disable once RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests + public static T[] AsArray([NotNull, ValidatedNotNull] this IEnumerable source) => source as T[] ?? source.ToArray(); /// /// Performs the action on each item of the specified enumerable. If the enumerable contains items that are null, this From 1cc620a277b5eab2ec11e9bd29af229386bb4317 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 27 Oct 2024 06:16:55 +0100 Subject: [PATCH 71/97] feat: add NotNull attribute to ForEach extensions method Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 13 +++++++++++++ .../FrameworkExtensions/EnumerableExtensions.cs | 3 ++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 17d83653..ad789f89 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -1297,4 +1297,17 @@ static int TestAsArray(int[]? array) return array.Length; } } + + [Fact] + public static void CheckForEach() + { + TestForEach(["foo", "bar"]).Should().Be(2); + return; + + static int TestForEach(string[]? array) + { + array!.ForEach(_ => { }); + return array.Length; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/FrameworkExtensions/EnumerableExtensions.cs b/Code/Light.GuardClauses/FrameworkExtensions/EnumerableExtensions.cs index 452525ec..e4186c93 100644 --- a/Code/Light.GuardClauses/FrameworkExtensions/EnumerableExtensions.cs +++ b/Code/Light.GuardClauses/FrameworkExtensions/EnumerableExtensions.cs @@ -65,7 +65,8 @@ public static IList AsList([NotNull, ValidatedNotNull] this IEnumerable /// The value indicating whether this method should throw a when any of the items is null (optional). Defaults to true. /// Thrown when or is null. /// Thrown when contains a value that is null and is set to true. - public static IEnumerable ForEach([ValidatedNotNull] this IEnumerable enumerable, Action action, bool throwWhenItemIsNull = true) + // ReSharper disable once RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests + public static IEnumerable ForEach([NotNull, ValidatedNotNull] this IEnumerable enumerable, Action action, bool throwWhenItemIsNull = true) { // ReSharper disable PossibleMultipleEnumeration action.MustNotBeNull(nameof(action)); From f8a2ac7b7fe441bda88cc8e92622215232c45817 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 27 Oct 2024 06:21:53 +0100 Subject: [PATCH 72/97] feat: add NotNull attribute to AsReadOnlyList Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 20 +++++++++++++++++++ .../EnumerableExtensions.cs | 8 ++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index ad789f89..69fc364f 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -1310,4 +1310,24 @@ static int TestForEach(string[]? array) return array.Length; } } + + [Fact] + public static void CheckAsReadOnlyList() + { + TestAsReadOnlyList([1, 2, 3]).Should().Be(3); + TestAsReadOnlyListWithDelegate([1, 2, 3], collection => new List(collection)).Should().Be(3); + return; + + static int TestAsReadOnlyList(int[]? array) + { + array!.AsReadOnlyList(); + return array.Length; + } + + static int TestAsReadOnlyListWithDelegate(int[]? array, Func, IReadOnlyList>? collectionFactory) + { + array!.AsReadOnlyList(collectionFactory!); + return array.Length; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/FrameworkExtensions/EnumerableExtensions.cs b/Code/Light.GuardClauses/FrameworkExtensions/EnumerableExtensions.cs index e4186c93..73f26a9a 100644 --- a/Code/Light.GuardClauses/FrameworkExtensions/EnumerableExtensions.cs +++ b/Code/Light.GuardClauses/FrameworkExtensions/EnumerableExtensions.cs @@ -116,7 +116,8 @@ public static IEnumerable ForEach([NotNull, ValidatedNotNull] this IEnumer /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("source:null => halt; source:notnull => notnull")] - public static IReadOnlyList AsReadOnlyList([ValidatedNotNull] this IEnumerable source) => + // ReSharper disable once RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests + public static IReadOnlyList AsReadOnlyList([NotNull, ValidatedNotNull] this IEnumerable source) => source as IReadOnlyList ?? source.ToList(); /// @@ -130,8 +131,11 @@ public static IReadOnlyList AsReadOnlyList([ValidatedNotNull] this IEnumer /// Thrown when or is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("source:null => halt; source:notnull => notnull; createCollection:null => halt")] - public static IReadOnlyList AsReadOnlyList([ValidatedNotNull] this IEnumerable source, Func, IReadOnlyList> createCollection) => + // ReSharper disable RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests + public static IReadOnlyList AsReadOnlyList([NotNull, ValidatedNotNull] this IEnumerable source, [NotNull, ValidatedNotNull] Func, IReadOnlyList> createCollection) => source as IReadOnlyList ?? createCollection.MustNotBeNull(nameof(createCollection))(source.MustNotBeNull(nameof(source))); + // ReSharper restore RedundantNullableFlowAttribute + /// /// Gets the count of the specified enumerable. From 12c856d7259fda6142bc3c19a4b9e2397d3fdc8f Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 27 Oct 2024 06:26:40 +0100 Subject: [PATCH 73/97] feat: add NotNull attribute to Count Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 45 ++++++++++++++----- .../EnumerableExtensions.cs | 3 +- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 69fc364f..9940473c 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -1,6 +1,7 @@ #nullable enable using System; +using System.Collections; using System.Collections.Generic; using System.IO; using System.Runtime.Serialization; @@ -1185,7 +1186,7 @@ static Uri TestMustBeHttpOrHttpsUrlWithDelegate(Uri? input) return input; } } - + [Fact] public static void CheckMustHaveOneSchemeOf() { @@ -1211,7 +1212,7 @@ public static void CheckIsIn() { TestIsIn("k").Should().Be("k"); return; - + static string TestIsIn(string? input) { input!.IsIn(Range.FromInclusive("a").ToInclusive("z")); @@ -1224,7 +1225,7 @@ public static void CheckIsNotIn() { TestIsNotIn("k").Should().Be("k"); return; - + static string TestIsNotIn(string? input) { input!.IsNotIn(Range.FromInclusive("a").ToInclusive("h")); @@ -1238,13 +1239,13 @@ public static void CheckIsSubstringOf() TestIsSubstringOf("foo", "oo").Should().Be("foo"); TestIsSubstringOfWithComparison("foo", "oo").Should().Be("foo"); return; - + static string TestIsSubstringOf(string? input, string? comparison) { comparison!.IsSubstringOf(input!); return input; } - + static string TestIsSubstringOfWithComparison(string? input, string? comparison) { comparison!.IsSubstringOf(input!, StringComparison.OrdinalIgnoreCase); @@ -1257,7 +1258,7 @@ public static void CheckIsOpenConstructedGenericType() { TestIsOpenConstructedGenericType(typeof(List<>)).Should().Be(typeof(List<>)); return; - + static Type TestIsOpenConstructedGenericType(Type? type) { type!.IsOpenConstructedGenericType(); @@ -1271,13 +1272,13 @@ public static void CheckAsList() TestAsList(new List()).Should().Be(0); TestAsListWithDelegate(new List()).Should().Be(0); return; - + static int TestAsList(IList? list) { list!.AsList(); return list.Count; } - + static int TestAsListWithDelegate(IList? list) { list!.AsList(collection => new List(collection)); @@ -1290,7 +1291,7 @@ public static void CheckAsArray() { TestAsArray([1, 2, 3]).Should().Be(3); return; - + static int TestAsArray(int[]? array) { array!.AsArray(); @@ -1303,7 +1304,7 @@ public static void CheckForEach() { TestForEach(["foo", "bar"]).Should().Be(2); return; - + static int TestForEach(string[]? array) { array!.ForEach(_ => { }); @@ -1317,17 +1318,37 @@ public static void CheckAsReadOnlyList() TestAsReadOnlyList([1, 2, 3]).Should().Be(3); TestAsReadOnlyListWithDelegate([1, 2, 3], collection => new List(collection)).Should().Be(3); return; - + static int TestAsReadOnlyList(int[]? array) { array!.AsReadOnlyList(); return array.Length; } - + static int TestAsReadOnlyListWithDelegate(int[]? array, Func, IReadOnlyList>? collectionFactory) { array!.AsReadOnlyList(collectionFactory!); return array.Length; } } + + [Fact] + public static void CheckCount() + { + TestCount(new ArrayList(new[]{ 1, 2, 3 })).Should().Be(3); + TestCountWithParameterNameAndMessage(new ArrayList(new[]{ 1, 2, 3 })).Should().Be(3); + return; + + static int TestCount(ICollection? collection) + { + collection!.Count(); + return collection.Count; + } + + static int TestCountWithParameterNameAndMessage(ICollection? collection) + { + collection!.Count(nameof(collection), "The collection must not be null"); + return collection.Count; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/FrameworkExtensions/EnumerableExtensions.cs b/Code/Light.GuardClauses/FrameworkExtensions/EnumerableExtensions.cs index 73f26a9a..6b0aa727 100644 --- a/Code/Light.GuardClauses/FrameworkExtensions/EnumerableExtensions.cs +++ b/Code/Light.GuardClauses/FrameworkExtensions/EnumerableExtensions.cs @@ -144,7 +144,8 @@ public static IReadOnlyList AsReadOnlyList([NotNull, ValidatedNotNull] thi /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("enumerable:null => halt")] - public static int Count([ValidatedNotNull] this IEnumerable enumerable) + // ReSharper disable once RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests + public static int Count([NotNull, ValidatedNotNull] this IEnumerable enumerable) { if (enumerable is ICollection collection) return collection.Count; From 5391e4e172ee346048f66a9a5e94c26d15ec46ef Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 27 Oct 2024 06:32:16 +0100 Subject: [PATCH 74/97] fix: DetermineCountViaEnumerating disposes the enumerator Signed-off-by: Kenny Pflug --- .../FrameworkExtensions/EnumerableExtensions.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Code/Light.GuardClauses/FrameworkExtensions/EnumerableExtensions.cs b/Code/Light.GuardClauses/FrameworkExtensions/EnumerableExtensions.cs index 6b0aa727..c3f6bd4c 100644 --- a/Code/Light.GuardClauses/FrameworkExtensions/EnumerableExtensions.cs +++ b/Code/Light.GuardClauses/FrameworkExtensions/EnumerableExtensions.cs @@ -237,6 +237,10 @@ private static int DetermineCountViaEnumerating(IEnumerable? enumerable) var enumerator = enumerable.MustNotBeNull(nameof(enumerable)).GetEnumerator(); while (enumerator.MoveNext()) count++; + if (enumerator is IDisposable disposable) + { + disposable.Dispose(); + } return count; } @@ -246,6 +250,10 @@ private static int DetermineCountViaEnumerating([NotNull] IEnumerable? enumerabl var enumerator = enumerable.MustNotBeNull(parameterName, message).GetEnumerator(); while (enumerator.MoveNext()) count++; + if (enumerator is IDisposable disposable) + { + disposable.Dispose(); + } return count; } From 0bc9c75e212fd90b4766a46348442551e14d7070 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 27 Oct 2024 06:49:38 +0100 Subject: [PATCH 75/97] feat: add NotNull attribute to GetCount Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 20 +++++++++++++++++++ .../EnumerableExtensions.cs | 5 +++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 9940473c..690e5bc4 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -1351,4 +1351,24 @@ static int TestCountWithParameterNameAndMessage(ICollection? collection) return collection.Count; } } + + [Fact] + public static void CheckGetCount() + { + TestGetCount([1, 2, 3]).Should().Be(3); + TestGetCountWithParameterNameAndMessage([1, 2, 3]).Should().Be(3); + return; + + static int TestGetCount(ICollection? collection) + { + collection!.GetCount(); + return collection.Count; + } + + static int TestGetCountWithParameterNameAndMessage(ICollection? collection) + { + collection!.GetCount(nameof(collection), "The collection must not be null"); + return collection.Count; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/FrameworkExtensions/EnumerableExtensions.cs b/Code/Light.GuardClauses/FrameworkExtensions/EnumerableExtensions.cs index c3f6bd4c..f204458e 100644 --- a/Code/Light.GuardClauses/FrameworkExtensions/EnumerableExtensions.cs +++ b/Code/Light.GuardClauses/FrameworkExtensions/EnumerableExtensions.cs @@ -181,7 +181,8 @@ public static int Count([NotNull, ValidatedNotNull] this IEnumerable? enumerable /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("enumerable:null => halt")] - public static int GetCount(this IEnumerable enumerable) + // ReSharper disable RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests + public static int GetCount([NotNull, ValidatedNotNull] this IEnumerable enumerable) { if (enumerable is ICollection collection) return collection.Count; @@ -202,7 +203,7 @@ public static int GetCount(this IEnumerable enumerable) /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("enumerable:null => halt")] - public static int GetCount(this IEnumerable enumerable, string? parameterName, string? message = null) + public static int GetCount([NotNull, ValidatedNotNull] this IEnumerable enumerable, string? parameterName, string? message = null) { if (enumerable is ICollection collection) return collection.Count; From 27250fc587a3ff2c4ac17031d544cf2454af4f7b Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 27 Oct 2024 06:59:18 +0100 Subject: [PATCH 76/97] fix: fix warnings and update NuGet packages Signed-off-by: Kenny Pflug --- ...t.GuardClauses.InternalRoslynAnalyzers.Tests.csproj | 10 +++++----- .../Light.GuardClauses.InternalRoslynAnalyzers.csproj | 3 ++- .../XmlCommentAnalyzer.cs | 2 +- ....GuardClauses.SourceCodeTransformation.Tests.csproj | 10 +++++----- .../Light.GuardClauses.SourceCodeTransformation.csproj | 10 +++++----- 5 files changed, 18 insertions(+), 17 deletions(-) diff --git a/Code/Light.GuardClauses.InternalRoslynAnalyzers.Tests/Light.GuardClauses.InternalRoslynAnalyzers.Tests.csproj b/Code/Light.GuardClauses.InternalRoslynAnalyzers.Tests/Light.GuardClauses.InternalRoslynAnalyzers.Tests.csproj index 814ef387..c15326f6 100644 --- a/Code/Light.GuardClauses.InternalRoslynAnalyzers.Tests/Light.GuardClauses.InternalRoslynAnalyzers.Tests.csproj +++ b/Code/Light.GuardClauses.InternalRoslynAnalyzers.Tests/Light.GuardClauses.InternalRoslynAnalyzers.Tests.csproj @@ -1,15 +1,15 @@  - net6.0 + net8.0 - - - - + + + + diff --git a/Code/Light.GuardClauses.InternalRoslynAnalyzers/Light.GuardClauses.InternalRoslynAnalyzers.csproj b/Code/Light.GuardClauses.InternalRoslynAnalyzers/Light.GuardClauses.InternalRoslynAnalyzers.csproj index 5ce7f446..1df3b66b 100644 --- a/Code/Light.GuardClauses.InternalRoslynAnalyzers/Light.GuardClauses.InternalRoslynAnalyzers.csproj +++ b/Code/Light.GuardClauses.InternalRoslynAnalyzers/Light.GuardClauses.InternalRoslynAnalyzers.csproj @@ -2,10 +2,11 @@ netstandard2.0 + true - + \ No newline at end of file diff --git a/Code/Light.GuardClauses.InternalRoslynAnalyzers/XmlCommentAnalyzer.cs b/Code/Light.GuardClauses.InternalRoslynAnalyzers/XmlCommentAnalyzer.cs index c96ef399..ec3d601a 100644 --- a/Code/Light.GuardClauses.InternalRoslynAnalyzers/XmlCommentAnalyzer.cs +++ b/Code/Light.GuardClauses.InternalRoslynAnalyzers/XmlCommentAnalyzer.cs @@ -37,7 +37,7 @@ private static void AnalyzeXmlCommentsForParameterNameAndMessage(SymbolAnalysisC if (methodSymbol.DeclaringSyntaxReferences.Length != 1 || !(methodSymbol.DeclaringSyntaxReferences[0].GetSyntax() is MethodDeclarationSyntax methodDeclarationSyntax) || !(methodDeclarationSyntax.DescendantTrivia() - .SingleOrDefault(trivia => trivia.Kind() == SyntaxKind.SingleLineDocumentationCommentTrivia) + .SingleOrDefault(trivia => trivia.IsKind(SyntaxKind.SingleLineDocumentationCommentTrivia)) .GetStructure() is DocumentationCommentTriviaSyntax documentationSyntax)) return; diff --git a/Code/Light.GuardClauses.SourceCodeTransformation.Tests/Light.GuardClauses.SourceCodeTransformation.Tests.csproj b/Code/Light.GuardClauses.SourceCodeTransformation.Tests/Light.GuardClauses.SourceCodeTransformation.Tests.csproj index 9a4eeec1..75dd49f0 100644 --- a/Code/Light.GuardClauses.SourceCodeTransformation.Tests/Light.GuardClauses.SourceCodeTransformation.Tests.csproj +++ b/Code/Light.GuardClauses.SourceCodeTransformation.Tests/Light.GuardClauses.SourceCodeTransformation.Tests.csproj @@ -6,11 +6,11 @@ - - - - - + + + + + \ No newline at end of file diff --git a/Code/Light.GuardClauses.SourceCodeTransformation/Light.GuardClauses.SourceCodeTransformation.csproj b/Code/Light.GuardClauses.SourceCodeTransformation/Light.GuardClauses.SourceCodeTransformation.csproj index de939067..f9959aed 100644 --- a/Code/Light.GuardClauses.SourceCodeTransformation/Light.GuardClauses.SourceCodeTransformation.csproj +++ b/Code/Light.GuardClauses.SourceCodeTransformation/Light.GuardClauses.SourceCodeTransformation.csproj @@ -4,16 +4,16 @@ Exe - net7.0 + net8.0 enable - - - - + + + + From a4f1682642b6af01243b3813fca31c62f69374e8 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 27 Oct 2024 08:52:29 +0100 Subject: [PATCH 77/97] feat: add NotNull attribute to ExtractProperty Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 20 ++++++++++++++++--- .../ExpressionExtensions.cs | 8 +++++--- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 690e5bc4..3fed82c9 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -4,6 +4,7 @@ using System.Collections; using System.Collections.Generic; using System.IO; +using System.Linq.Expressions; using System.Runtime.Serialization; using System.Text.RegularExpressions; using FluentAssertions; @@ -1335,8 +1336,8 @@ static int TestAsReadOnlyListWithDelegate(int[]? array, Func, I [Fact] public static void CheckCount() { - TestCount(new ArrayList(new[]{ 1, 2, 3 })).Should().Be(3); - TestCountWithParameterNameAndMessage(new ArrayList(new[]{ 1, 2, 3 })).Should().Be(3); + TestCount(new ArrayList(new[] { 1, 2, 3 })).Should().Be(3); + TestCountWithParameterNameAndMessage(new ArrayList(new[] { 1, 2, 3 })).Should().Be(3); return; static int TestCount(ICollection? collection) @@ -1358,7 +1359,7 @@ public static void CheckGetCount() TestGetCount([1, 2, 3]).Should().Be(3); TestGetCountWithParameterNameAndMessage([1, 2, 3]).Should().Be(3); return; - + static int TestGetCount(ICollection? collection) { collection!.GetCount(); @@ -1371,4 +1372,17 @@ static int TestGetCountWithParameterNameAndMessage(ICollection? collection return collection.Count; } } + + [Fact] + public static void CheckExtractProperty() + { + TestExtractProperty((string a) => a.Length).Should().NotBeNull(); + return; + + static Type TestExtractProperty(Expression>? expression) + { + expression!.ExtractProperty(); + return expression.Type; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/FrameworkExtensions/ExpressionExtensions.cs b/Code/Light.GuardClauses/FrameworkExtensions/ExpressionExtensions.cs index bb380fbe..85bb573d 100644 --- a/Code/Light.GuardClauses/FrameworkExtensions/ExpressionExtensions.cs +++ b/Code/Light.GuardClauses/FrameworkExtensions/ExpressionExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; using System.Linq.Expressions; using System.Reflection; @@ -10,7 +11,7 @@ namespace Light.GuardClauses.FrameworkExtensions; public static class ExpressionExtensions { /// - /// Extracts the from a expression of the shape "object => object.Property". + /// Extracts the from an expression of the shape "object => object.Property". /// /// The object type. /// The type of the property. @@ -19,7 +20,8 @@ public static class ExpressionExtensions /// /// Throw when the is not of the shape "object => object.Property". /// - public static PropertyInfo ExtractProperty([ValidatedNotNull] this Expression> expression) + // ReSharper disable once RedundantNullableFlowAttribute - NotNull is not redundant, see Issue72NotNullAttributeTests + public static PropertyInfo ExtractProperty([NotNull, ValidatedNotNull] this Expression> expression) { expression.MustNotBeNull(nameof(expression)); @@ -31,7 +33,7 @@ public static PropertyInfo ExtractProperty([ValidatedNotNull] this } /// - /// Extracts the from a expression of the shape "object => object.Field". + /// Extracts the from an expression of the shape "object => object.Field". /// /// The object type. /// The type of the field. From 55957d37d269035b4a94f34d76a37f0bb535aa94 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 27 Oct 2024 08:59:16 +0100 Subject: [PATCH 78/97] feat: add NotNull attribute to ExtractField Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 21 +++++++++++++++++++ .../ExpressionExtensions.cs | 3 ++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 3fed82c9..ca1db876 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -1385,4 +1385,25 @@ static Type TestExtractProperty(Expression>? ex return expression.Type; } } + + [Fact] + public static void CheckExtractField() + { + TestExtractField((TestClassWithPublicField x) => x.PublicField).Should().NotBeNull(); + return; + + static Type TestExtractField(Expression>? expression) + { + expression!.ExtractField(); + return expression.Type; + } + } + + private sealed class TestClassWithPublicField + { +#pragma warning disable CS0414 // Field is assigned but its value is never used + // ReSharper disable once ConvertToConstant.Local + public readonly int PublicField = 42; +#pragma warning restore CS0414 + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/FrameworkExtensions/ExpressionExtensions.cs b/Code/Light.GuardClauses/FrameworkExtensions/ExpressionExtensions.cs index 85bb573d..c695215b 100644 --- a/Code/Light.GuardClauses/FrameworkExtensions/ExpressionExtensions.cs +++ b/Code/Light.GuardClauses/FrameworkExtensions/ExpressionExtensions.cs @@ -42,7 +42,8 @@ public static PropertyInfo ExtractProperty([NotNull, ValidatedNotN /// /// Throw when the is not of the shape "object => object.Field". /// - public static FieldInfo ExtractField([ValidatedNotNull] this Expression> expression) + // ReSharper disable once RedundantNullableFlowAttribute - NotNull is not redundant, see Issue72NotNullAttributeTests + public static FieldInfo ExtractField([NotNull, ValidatedNotNull] this Expression> expression) { expression.MustNotBeNull(nameof(expression)); From 4ec3a6e4088f5a504751d22b566840c43802c4d9 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 27 Oct 2024 09:09:39 +0100 Subject: [PATCH 79/97] feat: add NotNull attribute to AppendCollectionContent Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 15 +++++++ .../FrameworkExtensions/TextExtensions.cs | 40 ++++++++++--------- 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index ca1db876..dc7924ab 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -6,6 +6,7 @@ using System.IO; using System.Linq.Expressions; using System.Runtime.Serialization; +using System.Text; using System.Text.RegularExpressions; using FluentAssertions; using Light.GuardClauses.FrameworkExtensions; @@ -1406,4 +1407,18 @@ private sealed class TestClassWithPublicField public readonly int PublicField = 42; #pragma warning restore CS0414 } + + [Fact] + public static void CheckAppendCollectionContent() + { + var stringBuilder = new StringBuilder(); + TestAppendCollectionContent(stringBuilder, [1, 2, 3]).Should().Be((stringBuilder, 3)); + return; + + static (StringBuilder, int) TestAppendCollectionContent(StringBuilder? stringBuilder, ICollection? items) + { + stringBuilder!.AppendCollectionContent(items!); + return (stringBuilder, items.Count); + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/FrameworkExtensions/TextExtensions.cs b/Code/Light.GuardClauses/FrameworkExtensions/TextExtensions.cs index 5a7cb2de..8211622d 100644 --- a/Code/Light.GuardClauses/FrameworkExtensions/TextExtensions.cs +++ b/Code/Light.GuardClauses/FrameworkExtensions/TextExtensions.cs @@ -4,6 +4,7 @@ using System.Runtime.CompilerServices; using System.Text; using JetBrains.Annotations; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; namespace Light.GuardClauses.FrameworkExtensions; @@ -21,21 +22,22 @@ public static class TextExtensions /// Gets the list of types that will not be surrounded by quotation marks in error messages. /// public static readonly ReadOnlyCollection UnquotedTypes = - new ReadOnlyCollection(new[] - { - typeof(int), - typeof(long), - typeof(short), - typeof(sbyte), - typeof(uint), - typeof(ulong), - typeof(ushort), - typeof(byte), - typeof(bool), - typeof(double), - typeof(decimal), - typeof(float) - }); + new ( + [ + typeof(int), + typeof(long), + typeof(short), + typeof(sbyte), + typeof(uint), + typeof(ulong), + typeof(ushort), + typeof(byte), + typeof(bool), + typeof(double), + typeof(decimal), + typeof(float) + ] + ); private static bool IsUnquotedType() { @@ -87,7 +89,7 @@ private static bool IsUnquotedType() { value.MustNotBeNullReference(nameof(value)); - var content = value!.ToString(); + var content = value.ToString(); if (IsUnquotedType() || content.IsNullOrEmpty()) return content; @@ -95,7 +97,7 @@ private static bool IsUnquotedType() if (content.Length <= 126) { Span span = stackalloc char[content.Length + 2]; - span[0] = span[span.Length -1] = '"'; + span[0] = span[span.Length - 1] = '"'; content.AsSpan().CopyTo(span.Slice(1, content.Length)); return span.ToString(); } @@ -120,10 +122,12 @@ private static bool IsUnquotedType() /// Thrown when or is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("stringBuilder:null => halt; items:null => halt; stringBuilder:notnull => notnull")] - public static StringBuilder AppendCollectionContent([ValidatedNotNull] this StringBuilder stringBuilder, [ValidatedNotNull] IEnumerable items, string headerLine = "Content of the collection:", bool finishWithNewLine = true) => + // ReSharper disable RedundantNullableFlowAttribute + public static StringBuilder AppendCollectionContent([NotNull, ValidatedNotNull] this StringBuilder stringBuilder, [NotNull, ValidatedNotNull] IEnumerable items, string headerLine = "Content of the collection:", bool finishWithNewLine = true) => stringBuilder.MustNotBeNull(nameof(stringBuilder)) .AppendLine(headerLine) .AppendItemsWithNewLine(items, finishWithNewLine: finishWithNewLine); + // ReSharper restore RedundantNullableFlowAttribute /// /// Appends the string representations of the specified items to the string builder. From ea7e756a256e41e56ab9a2b1ff80afcd711102f0 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 27 Oct 2024 09:13:30 +0100 Subject: [PATCH 80/97] feat: add NotNull attribute to ToStringRepresentation Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 13 +++++++++++++ .../FrameworkExtensions/TextExtensions.cs | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index dc7924ab..71616a7c 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -1421,4 +1421,17 @@ public static void CheckAppendCollectionContent() return (stringBuilder, items.Count); } } + + [Fact] + public static void CheckToStringRepresentation() + { + TestToStringRepresentation("foo").Should().Be(3); + return; + + static int TestToStringRepresentation(string? value) + { + value.ToStringRepresentation(); + return value.Length; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/FrameworkExtensions/TextExtensions.cs b/Code/Light.GuardClauses/FrameworkExtensions/TextExtensions.cs index 8211622d..85b3aa16 100644 --- a/Code/Light.GuardClauses/FrameworkExtensions/TextExtensions.cs +++ b/Code/Light.GuardClauses/FrameworkExtensions/TextExtensions.cs @@ -85,7 +85,7 @@ private static bool IsUnquotedType() /// /// The value whose string representation is requested. [ContractAnnotation("value:null => halt; value:notnull => notnull")] - public static string? ToStringRepresentation([ValidatedNotNull] this T value) + public static string? ToStringRepresentation([NotNull, ValidatedNotNull] this T value) { value.MustNotBeNullReference(nameof(value)); From 9ed981bba4e130cadf9a432ee7282ab98523b224 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 27 Oct 2024 09:16:37 +0100 Subject: [PATCH 81/97] feat: add NotNull attribute to AppendItemsWithNewLine Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 14 ++++++++++++++ .../FrameworkExtensions/TextExtensions.cs | 4 +++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 71616a7c..1a736cb1 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -1434,4 +1434,18 @@ static int TestToStringRepresentation(string? value) return value.Length; } } + + [Fact] + public static void CheckAppendItemsWithNewLine() + { + var stringBuilder = new StringBuilder(); + TestAppendItemsWithNewLine(stringBuilder, [1, 2, 3]).Should().Be((stringBuilder, 3)); + return; + + static (StringBuilder, int) TestAppendItemsWithNewLine(StringBuilder? stringBuilder, ICollection? items) + { + stringBuilder!.AppendItemsWithNewLine(items!); + return (stringBuilder, items.Count); + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/FrameworkExtensions/TextExtensions.cs b/Code/Light.GuardClauses/FrameworkExtensions/TextExtensions.cs index 85b3aa16..d803eb17 100644 --- a/Code/Light.GuardClauses/FrameworkExtensions/TextExtensions.cs +++ b/Code/Light.GuardClauses/FrameworkExtensions/TextExtensions.cs @@ -169,9 +169,11 @@ public static StringBuilder AppendItems([ValidatedNotNull] this StringBuilder /// Thrown when or is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("stringBuilder:null => halt; items:null => halt; stringBuilder:notnull => notnull")] - public static StringBuilder AppendItemsWithNewLine([ValidatedNotNull] this StringBuilder stringBuilder, [ValidatedNotNull] IEnumerable items, string emptyCollectionText = "empty collection", bool finishWithNewLine = true) => + // ReSharper disable RedundantNullableFlowAttribute + public static StringBuilder AppendItemsWithNewLine([NotNull, ValidatedNotNull] this StringBuilder stringBuilder, [NotNull, ValidatedNotNull] IEnumerable items, string emptyCollectionText = "empty collection", bool finishWithNewLine = true) => stringBuilder.AppendItems(items, DefaultNewLineSeparator, emptyCollectionText) .AppendLineIf(finishWithNewLine); + // ReSharper restore RedundantNullableFlowAttribute /// /// Appends the value to the specified string builder if the condition is true. From 0b59669e8a8d1d9c781dbece8a4f87f61ca63b91 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 27 Oct 2024 09:18:45 +0100 Subject: [PATCH 82/97] feat: add NotNull attribute to AppendIf Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 14 ++++++++++++++ .../FrameworkExtensions/TextExtensions.cs | 3 ++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 1a736cb1..47e61472 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -1448,4 +1448,18 @@ public static void CheckAppendItemsWithNewLine() return (stringBuilder, items.Count); } } + + [Fact] + public static void CheckAppendIf() + { + var stringBuilder = new StringBuilder(); + TestAppendIf(stringBuilder, true, "foo").Should().Be((stringBuilder, 3)); + return; + + static (StringBuilder, int) TestAppendIf(StringBuilder? stringBuilder, bool condition, string value) + { + stringBuilder!.AppendIf(condition, value); + return (stringBuilder, value.Length); + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/FrameworkExtensions/TextExtensions.cs b/Code/Light.GuardClauses/FrameworkExtensions/TextExtensions.cs index d803eb17..9bf18a17 100644 --- a/Code/Light.GuardClauses/FrameworkExtensions/TextExtensions.cs +++ b/Code/Light.GuardClauses/FrameworkExtensions/TextExtensions.cs @@ -184,7 +184,8 @@ public static StringBuilder AppendItemsWithNewLine([NotNull, ValidatedNotNull /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("stringBuilder:null => halt; stringBuilder:notnull => notnull")] - public static StringBuilder AppendIf([ValidatedNotNull] this StringBuilder stringBuilder, bool condition, string value) + // ReSharper disable once RedundantNullableFlowAttribute + public static StringBuilder AppendIf([NotNull, ValidatedNotNull] this StringBuilder stringBuilder, bool condition, string value) { if (condition) stringBuilder.MustNotBeNull(nameof(stringBuilder)).Append(value); From d8426f85460863afcd35afe05361500c290c72ce Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 27 Oct 2024 09:21:13 +0100 Subject: [PATCH 83/97] feat: add NotNull attribute to AppendLineIf Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 14 ++++++++++++++ .../FrameworkExtensions/TextExtensions.cs | 11 ++++++----- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 47e61472..f9378a44 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -1462,4 +1462,18 @@ public static void CheckAppendIf() return (stringBuilder, value.Length); } } + + [Fact] + public static void CheckAppendLineIf() + { + var stringBuilder = new StringBuilder(); + TestAppendLineIf(stringBuilder, true, "foo").Should().Be((stringBuilder, 3)); + return; + + static (StringBuilder, int) TestAppendLineIf(StringBuilder? stringBuilder, bool condition, string value) + { + stringBuilder!.AppendLineIf(condition, value); + return (stringBuilder, value.Length); + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/FrameworkExtensions/TextExtensions.cs b/Code/Light.GuardClauses/FrameworkExtensions/TextExtensions.cs index 9bf18a17..e50f1533 100644 --- a/Code/Light.GuardClauses/FrameworkExtensions/TextExtensions.cs +++ b/Code/Light.GuardClauses/FrameworkExtensions/TextExtensions.cs @@ -179,7 +179,7 @@ public static StringBuilder AppendItemsWithNewLine([NotNull, ValidatedNotNull /// Appends the value to the specified string builder if the condition is true. /// /// The string builder where will be appended to. - /// The boolean value indicating whether the append will be performed or not. + /// The boolean value indicating whether the append operation will be performed or not. /// The value to be appended to the string builder. /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -196,12 +196,13 @@ public static StringBuilder AppendIf([NotNull, ValidatedNotNull] this StringBuil /// Appends the value followed by a new line separator to the specified string builder if the condition is true. /// /// The string builder where will be appended to. - /// The boolean value indicating whether the append will be performed or not. + /// The boolean value indicating whether the append operation will be performed or not. /// The value to be appended to the string builder (optional). This value defaults to an empty string. /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("stringBuilder:null => halt; stringBuilder:notnull => notnull")] - public static StringBuilder AppendLineIf([ValidatedNotNull] this StringBuilder stringBuilder, bool condition, string value = "") + // ReSharper disable once RedundantNullableFlowAttribute + public static StringBuilder AppendLineIf([NotNull, ValidatedNotNull] this StringBuilder stringBuilder, bool condition, string value = "") { if (condition) stringBuilder.MustNotBeNull(nameof(stringBuilder)).AppendLine(value); @@ -259,7 +260,7 @@ public static bool EqualsOrdinalIgnoreWhiteSpace(this string? x, string? y) bool wasYSuccessful; // This condition of the while loop actually has to use the single '&' operator because // y.TryAdvanceToNextNonWhiteSpaceCharacter must be called even though it already returned - // false on x. Otherwise the 'wasXSuccessful == wasYSuccessful' comparison would not return + // false on x. Otherwise, the 'wasXSuccessful == wasYSuccessful' comparison would not return // the desired result. while ((wasXSuccessful = x.TryAdvanceToNextNonWhiteSpaceCharacter(ref indexX)) & (wasYSuccessful = y.TryAdvanceToNextNonWhiteSpaceCharacter(ref indexY))) @@ -292,7 +293,7 @@ public static bool EqualsOrdinalIgnoreCaseIgnoreWhiteSpace(this string? x, strin bool wasYSuccessful; // This condition of the while loop actually has to use the single '&' operator because // y.TryAdvanceToNextNonWhiteSpaceCharacter must be called even though it already returned - // false on x. Otherwise the 'wasXSuccessful == wasYSuccessful' comparison would not return + // false on x. Otherwise, the 'wasXSuccessful == wasYSuccessful' comparison would not return // the desired result. while ((wasXSuccessful = x.TryAdvanceToNextNonWhiteSpaceCharacter(ref indexX)) & (wasYSuccessful = y.TryAdvanceToNextNonWhiteSpaceCharacter(ref indexY))) From 9a961e72a177191df8d771f3d90185f43d768089 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 27 Oct 2024 09:22:57 +0100 Subject: [PATCH 84/97] feat: add NotNull attribute to AppendItems Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 14 ++++++++++++++ .../FrameworkExtensions/TextExtensions.cs | 4 +++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index f9378a44..92adf574 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -1476,4 +1476,18 @@ public static void CheckAppendLineIf() return (stringBuilder, value.Length); } } + + [Fact] + public static void CheckAppendItems() + { + var stringBuilder = new StringBuilder(); + TestAppendItems(stringBuilder, [1, 2, 3]).Should().Be((stringBuilder, 3)); + return; + + static (StringBuilder, int) TestAppendItems(StringBuilder? stringBuilder, ICollection? items) + { + stringBuilder!.AppendItems(items!); + return (stringBuilder, items.Count); + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/FrameworkExtensions/TextExtensions.cs b/Code/Light.GuardClauses/FrameworkExtensions/TextExtensions.cs index e50f1533..e3cb4dee 100644 --- a/Code/Light.GuardClauses/FrameworkExtensions/TextExtensions.cs +++ b/Code/Light.GuardClauses/FrameworkExtensions/TextExtensions.cs @@ -138,7 +138,9 @@ public static StringBuilder AppendCollectionContent([NotNull, ValidatedNotNul /// The text that is appended to the string builder when is empty. Defaults to "empty collection". /// Thrown when or is null. [ContractAnnotation("stringBuilder:null => halt; items:null => halt; stringBuilder:notnull => notnull")] - public static StringBuilder AppendItems([ValidatedNotNull] this StringBuilder stringBuilder, [ValidatedNotNull] IEnumerable items, string itemSeparator = ", ", string emptyCollectionText = "empty collection") + // ReSharper disable RedundantNullableFlowAttribute + public static StringBuilder AppendItems([NotNull, ValidatedNotNull] this StringBuilder stringBuilder, [NotNull, ValidatedNotNull] IEnumerable items, string itemSeparator = ", ", string emptyCollectionText = "empty collection") + // ReSharper restore RedundantNullableFlowAttribute { stringBuilder.MustNotBeNull(nameof(stringBuilder)); var list = items.MustNotBeNull(nameof(items)).AsList(); From 1b4b30d79c7a56d56ae51a304b781ce10cb46f47 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 27 Oct 2024 09:24:59 +0100 Subject: [PATCH 85/97] feat: add NotNull attribute to AppendExceptionMessages Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 14 ++++++++++++++ .../FrameworkExtensions/TextExtensions.cs | 4 +++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 92adf574..93725965 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -1490,4 +1490,18 @@ public static void CheckAppendItems() return (stringBuilder, items.Count); } } + + [Fact] + public static void CheckAppendExceptionMessages() + { + var stringBuilder = new StringBuilder(); + TestAppendExceptionMessages(stringBuilder, new Exception("foo")).Should().Be((stringBuilder, 3)); + return; + + static (StringBuilder, int) TestAppendExceptionMessages(StringBuilder? stringBuilder, Exception exception) + { + stringBuilder!.AppendExceptionMessages(exception); + return (stringBuilder, exception.Message.Length); + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/FrameworkExtensions/TextExtensions.cs b/Code/Light.GuardClauses/FrameworkExtensions/TextExtensions.cs index e3cb4dee..f6f36256 100644 --- a/Code/Light.GuardClauses/FrameworkExtensions/TextExtensions.cs +++ b/Code/Light.GuardClauses/FrameworkExtensions/TextExtensions.cs @@ -216,7 +216,9 @@ public static StringBuilder AppendLineIf([NotNull, ValidatedNotNull] this String /// specified . /// /// Thrown when any parameter is null. - public static StringBuilder AppendExceptionMessages([ValidatedNotNull] this StringBuilder stringBuilder, [ValidatedNotNull] Exception exception) + // ReSharper disable RedundantNullableFlowAttribute + public static StringBuilder AppendExceptionMessages([NotNull, ValidatedNotNull] this StringBuilder stringBuilder, [NotNull, ValidatedNotNull] Exception exception) + // ReSharper restore RedundantNullableFlowAttribute { stringBuilder.MustNotBeNull(nameof(stringBuilder)); exception.MustNotBeNull(nameof(exception)); From 9045fd35adea4afb8080273d42adf0e7be19dc95 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 27 Oct 2024 09:26:39 +0100 Subject: [PATCH 86/97] feat: add NotNull attribute to GetAllExceptionMessages Signed-off-by: Kenny Pflug --- .../Issues/Issue72NotNullAttributeTests.cs | 13 +++++++++++++ .../FrameworkExtensions/TextExtensions.cs | 3 ++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs index 93725965..c6c0123f 100644 --- a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs +++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs @@ -1504,4 +1504,17 @@ public static void CheckAppendExceptionMessages() return (stringBuilder, exception.Message.Length); } } + + [Fact] + public static void CheckGetAllExceptionMessages() + { + TestGetAllExceptionMessages(new Exception("foo")).Should().Be(3); + return; + + static int TestGetAllExceptionMessages(Exception? exception) + { + exception!.GetAllExceptionMessages(); + return exception.Message.Length; + } + } } \ No newline at end of file diff --git a/Code/Light.GuardClauses/FrameworkExtensions/TextExtensions.cs b/Code/Light.GuardClauses/FrameworkExtensions/TextExtensions.cs index f6f36256..10f3b7c7 100644 --- a/Code/Light.GuardClauses/FrameworkExtensions/TextExtensions.cs +++ b/Code/Light.GuardClauses/FrameworkExtensions/TextExtensions.cs @@ -240,7 +240,8 @@ public static StringBuilder AppendExceptionMessages([NotNull, ValidatedNotNull] /// a single string. /// /// Thrown when is null. - public static string GetAllExceptionMessages([ValidatedNotNull] this Exception exception) => + // ReSharper disable once RedundantNullableFlowAttribute + public static string GetAllExceptionMessages([NotNull, ValidatedNotNull] this Exception exception) => new StringBuilder().AppendExceptionMessages(exception).ToString(); /// From e7e75b82b3db38c05061fad9052dbddd5881c5b6 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 27 Oct 2024 09:53:32 +0100 Subject: [PATCH 87/97] chore: remove obsolete null-forgiving operator in MustBeTrimmedAtEnd Signed-off-by: Kenny Pflug --- Code/Light.GuardClauses/Check.StringAssertions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Light.GuardClauses/Check.StringAssertions.cs b/Code/Light.GuardClauses/Check.StringAssertions.cs index b3f678da..2e819e48 100644 --- a/Code/Light.GuardClauses/Check.StringAssertions.cs +++ b/Code/Light.GuardClauses/Check.StringAssertions.cs @@ -1238,6 +1238,6 @@ public static string MustBeTrimmedAtEnd([NotNull, ValidatedNotNull] this string? { if (parameter is null || !parameter.AsSpan().IsTrimmedAtEnd()) Throw.CustomException(exceptionFactory, parameter); - return parameter!; + return parameter; } } \ No newline at end of file From 7d85c60ae0794c4618076fbd3c8780542651817c Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 27 Oct 2024 10:49:55 +0100 Subject: [PATCH 88/97] docs: fix typo 'an' in Throw.cs Signed-off-by: Kenny Pflug --- Code/Light.GuardClauses/Exceptions/Throw.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Code/Light.GuardClauses/Exceptions/Throw.cs b/Code/Light.GuardClauses/Exceptions/Throw.cs index b2052c17..f14eeb81 100644 --- a/Code/Light.GuardClauses/Exceptions/Throw.cs +++ b/Code/Light.GuardClauses/Exceptions/Throw.cs @@ -271,6 +271,8 @@ public static void Substring(string parameter, string other, StringComparison co /// /// Throws the default indicating that a string is not shorter than the given length, using the optional parameter name an message. + [DoesNotReturn] + /// Throws the default indicating that a string is not shorter than the given length, using the optional parameter name and message. /// [ContractAnnotation("=> halt")] [DoesNotReturn] @@ -278,7 +280,7 @@ public static void StringNotShorterThan(string parameter, int length, [CallerArg throw new StringLengthException(parameterName, message ?? $"{parameterName ?? "The string"} must be shorter than {length}, but it actually has length {parameter.Length}."); /// - /// Throws the default indicating that a string is not shorter or equal to the given length, using the optional parameter name an message. + /// Throws the default indicating that a string is not shorter or equal to the given length, using the optional parameter name and message. /// [ContractAnnotation("=> halt")] [DoesNotReturn] @@ -286,7 +288,7 @@ public static void StringNotShorterThanOrEqualTo(string parameter, int length, [ throw new StringLengthException(parameterName, message ?? $"{parameterName ?? "The string"} must be shorter or equal to {length}, but it actually has length {parameter.Length}."); /// - /// Throws the default indicating that a string has a different length than the specified one, using the optional parameter name an message. + /// Throws the default indicating that a string has a different length than the specified one, using the optional parameter name and message. /// [ContractAnnotation("=> halt")] [DoesNotReturn] @@ -294,7 +296,7 @@ public static void StringLengthNotEqualTo(string parameter, int length, [CallerA throw new StringLengthException(parameterName, message ?? $"{parameterName ?? "The string"} must have length {length}, but it actually has length {parameter.Length}."); /// - /// Throws the default indicating that a string is not longer than the given length, using the optional parameter name an message. + /// Throws the default indicating that a string is not longer than the given length, using the optional parameter name and message. /// [ContractAnnotation("=> halt")] [DoesNotReturn] @@ -302,7 +304,7 @@ public static void StringNotLongerThan(string parameter, int length, [CallerArgu throw new StringLengthException(parameterName, message ?? $"{parameterName ?? "The string"} must be longer than {length}, but it actually has length {parameter.Length}."); /// - /// Throws the default indicating that a string is not longer or equal to the given length, using the optional parameter name an message. + /// Throws the default indicating that a string is not longer or equal to the given length, using the optional parameter name and message. /// [ContractAnnotation("=> halt")] [DoesNotReturn] @@ -310,7 +312,7 @@ public static void StringNotLongerThanOrEqualTo(string parameter, int length, [C throw new StringLengthException(parameterName, message ?? $"{parameterName ?? "The string"} must be longer than or equal to {length}, but it actually has length {parameter.Length}."); /// - /// Throws the default indicating that a string's length is not in between the given range, using the optional parameter name an message. + /// Throws the default indicating that a string's length is not in between the given range, using the optional parameter name and message. /// [ContractAnnotation("=> halt")] [DoesNotReturn] From 37d6efb89f610ad6a3a50872ec229cde3146190f Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 27 Oct 2024 10:51:59 +0100 Subject: [PATCH 89/97] fix [breaking]: Substring and Contain assertions now throw different exception when invalid StringComparison type is passed Signed-off-by: Kenny Pflug --- .../MustBeSubstringOfTests.cs | 1 - .../StringAssertions/MustContainTests.cs | 1 - .../MustNotBeSubstringOfTests.cs | 1 - .../StringAssertions/MustNotContainTests.cs | 1 - .../Check.StringAssertions.cs | 30 ++++++++++++------- 5 files changed, 20 insertions(+), 14 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/StringAssertions/MustBeSubstringOfTests.cs b/Code/Light.GuardClauses.Tests/StringAssertions/MustBeSubstringOfTests.cs index 3408d696..d6079be2 100644 --- a/Code/Light.GuardClauses.Tests/StringAssertions/MustBeSubstringOfTests.cs +++ b/Code/Light.GuardClauses.Tests/StringAssertions/MustBeSubstringOfTests.cs @@ -94,7 +94,6 @@ public static void CustomException(string first, string second) => [InlineData("Foo", "FOO", StringComparison.Ordinal)] [InlineData("Bar", null, StringComparison.OrdinalIgnoreCase)] [InlineData(null, "Baz", StringComparison.CurrentCulture)] - [InlineData("Qux", "Quux", (StringComparison) 509)] public static void CustomExceptionCustomComparisonType(string first, string second, StringComparison comparisonType) => Test.CustomException(first, second, diff --git a/Code/Light.GuardClauses.Tests/StringAssertions/MustContainTests.cs b/Code/Light.GuardClauses.Tests/StringAssertions/MustContainTests.cs index 70a594d9..3912163c 100644 --- a/Code/Light.GuardClauses.Tests/StringAssertions/MustContainTests.cs +++ b/Code/Light.GuardClauses.Tests/StringAssertions/MustContainTests.cs @@ -79,7 +79,6 @@ public static void CustomException(string first, string second) => [InlineData("Foo", "foo", StringComparison.Ordinal)] [InlineData(null, "Bar", StringComparison.OrdinalIgnoreCase)] [InlineData("Baz", null, StringComparison.CurrentCulture)] - [InlineData("Qux", "Qux", (StringComparison) 42)] public static void CustomExceptionCustomSearch(string x, string y, StringComparison comparison) => Test.CustomException(x, y, diff --git a/Code/Light.GuardClauses.Tests/StringAssertions/MustNotBeSubstringOfTests.cs b/Code/Light.GuardClauses.Tests/StringAssertions/MustNotBeSubstringOfTests.cs index 8c49034b..aac5a976 100644 --- a/Code/Light.GuardClauses.Tests/StringAssertions/MustNotBeSubstringOfTests.cs +++ b/Code/Light.GuardClauses.Tests/StringAssertions/MustNotBeSubstringOfTests.cs @@ -93,7 +93,6 @@ public static void CustomException(string first, string second) => [InlineData("Full of Possibilities", "Death is so terribly final, while life is full of possibilities", StringComparison.OrdinalIgnoreCase)] [InlineData(null, "Foo", StringComparison.Ordinal)] [InlineData("Bar", null, StringComparison.CurrentCulture)] - [InlineData("Baz", "Qux", (StringComparison) (-14))] public static void CustomExceptionCustomComparison(string a, string b, StringComparison comparisonType) => Test.CustomException(a, b, diff --git a/Code/Light.GuardClauses.Tests/StringAssertions/MustNotContainTests.cs b/Code/Light.GuardClauses.Tests/StringAssertions/MustNotContainTests.cs index e7511fce..923cc499 100644 --- a/Code/Light.GuardClauses.Tests/StringAssertions/MustNotContainTests.cs +++ b/Code/Light.GuardClauses.Tests/StringAssertions/MustNotContainTests.cs @@ -64,7 +64,6 @@ public static void CustomException(string first, string second) => [InlineData("Foo", "O", StringComparison.OrdinalIgnoreCase)] [InlineData("Bar", null, StringComparison.CurrentCulture)] [InlineData(null, "Baz", StringComparison.CurrentCultureIgnoreCase)] - [InlineData("Qux", "Quux", (StringComparison) 504)] public static void CustomExceptionCustomSearch(string first, string second, StringComparison comparisonType) => Test.CustomException(first, second, diff --git a/Code/Light.GuardClauses/Check.StringAssertions.cs b/Code/Light.GuardClauses/Check.StringAssertions.cs index 2e819e48..8835a244 100644 --- a/Code/Light.GuardClauses/Check.StringAssertions.cs +++ b/Code/Light.GuardClauses/Check.StringAssertions.cs @@ -340,7 +340,9 @@ public static bool Equals(this string? @string, string? value, StringComparisonT public static string MustContain([NotNull, ValidatedNotNull] this string? parameter, string? value, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (!parameter.MustNotBeNull(parameterName, message).Contains(value.MustNotBeNull(nameof(value), message))) + { Throw.StringDoesNotContain(parameter, value, parameterName, message); + } return parameter; } @@ -361,7 +363,9 @@ public static string MustContain([NotNull, ValidatedNotNull] this string? parame { // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off if (parameter is null || value is null || !parameter.Contains(value)) + { Throw.CustomException(exceptionFactory, parameter, value!); + } return parameter; } @@ -381,7 +385,9 @@ public static string MustContain([NotNull, ValidatedNotNull] this string? parame public static string MustContain([NotNull, ValidatedNotNull] this string? parameter, string value, StringComparison comparisonType, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (parameter.MustNotBeNull(parameterName, message).IndexOf(value.MustNotBeNull(nameof(value), message), comparisonType) < 0) + { Throw.StringDoesNotContain(parameter, value, comparisonType, parameterName, message); + } return parameter; } @@ -395,16 +401,18 @@ public static string MustContain([NotNull, ValidatedNotNull] this string? parame /// /// Your custom exception thrown when does not contain , /// or when is null, - /// or when is null, - /// or when is not a valid value from the enum. + /// or when is null. /// + /// Thrown when is not a valid value. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] public static string MustContain([NotNull, ValidatedNotNull] this string? parameter, string value, StringComparison comparisonType, Func exceptionFactory) { // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off - if (parameter is null || value is null || !comparisonType.IsValidEnumValue() || parameter.IndexOf(value, comparisonType) < 0) + if (parameter is null || value is null || parameter.IndexOf(value, comparisonType) < 0) + { Throw.CustomException(exceptionFactory, parameter, value!, comparisonType); + } return parameter; } @@ -422,7 +430,9 @@ public static string MustContain([NotNull, ValidatedNotNull] this string? parame public static string MustNotContain([NotNull, ValidatedNotNull] this string? parameter, string value, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { if (parameter.MustNotBeNull(parameterName, message).Contains(value.MustNotBeNull(nameof(value), message))) + { Throw.StringContains(parameter, value, parameterName, message); + } return parameter; } @@ -477,15 +487,15 @@ public static string MustNotContain([NotNull, ValidatedNotNull] this string? par /// /// Your custom exception thrown when contains , /// or when is null, - /// or when is null, - /// or when is not a valid value of the enum. + /// or when is null. /// + /// Thrown when is not a valid value. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] public static string MustNotContain([NotNull, ValidatedNotNull] this string? parameter, string value, StringComparison comparisonType, Func exceptionFactory) { // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off - if (parameter is null || value is null || !comparisonType.IsValidEnumValue() || parameter.IndexOf(value, comparisonType) >= 0) + if (parameter is null || value is null || parameter.IndexOf(value, comparisonType) >= 0) Throw.CustomException(exceptionFactory, parameter, value!, comparisonType); return parameter; } @@ -604,15 +614,15 @@ public static string MustBeSubstringOf([NotNull, ValidatedNotNull] this string? /// /// Your custom exception thrown when does not contain , /// or when is null, - /// or when is null, - /// or when is not a valid value of the enum. + /// or when is null. /// + /// Thrown when is not a valid value. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt")] public static string MustBeSubstringOf([NotNull, ValidatedNotNull] this string? parameter, string value, StringComparison comparisonType, Func exceptionFactory) { // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off - if (parameter is null || value is null || !comparisonType.IsValidEnumValue() || value.IndexOf(parameter, comparisonType) == -1) + if (parameter is null || value is null || value.IndexOf(parameter, comparisonType) == -1) Throw.CustomException(exceptionFactory, parameter, value!, comparisonType); return parameter; } @@ -695,7 +705,7 @@ public static string MustNotBeSubstringOf([NotNull, ValidatedNotNull] this strin public static string MustNotBeSubstringOf([NotNull, ValidatedNotNull] this string? parameter, string value, StringComparison comparisonType, Func exceptionFactory) { // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off - if (parameter is null || value is null || !comparisonType.IsValidEnumValue() || value.IndexOf(parameter, comparisonType) != -1) + if (parameter is null || value is null || value.IndexOf(parameter, comparisonType) != -1) Throw.CustomException(exceptionFactory, parameter, value!, comparisonType); return parameter; } From d7c6b42eef58957e184d82926534a3f16ebdeebc Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 27 Oct 2024 10:52:10 +0100 Subject: [PATCH 90/97] feat: add MustStartWith Signed-off-by: Kenny Pflug --- .../StringAssertions/MustStartWithTests.cs | 73 ++++++++++++++++ .../Check.StringAssertions.cs | 85 +++++++++++++++++++ Code/Light.GuardClauses/Exceptions/Throw.cs | 10 ++- 3 files changed, 166 insertions(+), 2 deletions(-) create mode 100644 Code/Light.GuardClauses.Tests/StringAssertions/MustStartWithTests.cs diff --git a/Code/Light.GuardClauses.Tests/StringAssertions/MustStartWithTests.cs b/Code/Light.GuardClauses.Tests/StringAssertions/MustStartWithTests.cs new file mode 100644 index 00000000..34d1237b --- /dev/null +++ b/Code/Light.GuardClauses.Tests/StringAssertions/MustStartWithTests.cs @@ -0,0 +1,73 @@ +using System; +using FluentAssertions; +using Light.GuardClauses.Exceptions; +using Xunit; + +namespace Light.GuardClauses.Tests.StringAssertions; + +public static class MustStartWithTests +{ + [Theory] + [InlineData("Foo", "Bar")] + [InlineData("When you play the game of thrones you win, or you die. There is no middle ground.", "Love and peace")] + public static void DoesNotStartWith(string x, string y) + { + var act = () => x.MustStartWith(y); + + var exception = act.Should().Throw().Which; + exception.Message.Should().StartWith($"{nameof(x)} must start with \"{y}\" (CurrentCulture), but it actually is \"{x}\"."); + exception.ParamName.Should().BeSameAs(nameof(x)); + } + + [Theory] + [InlineData("FooBar", "Foo", StringComparison.Ordinal)] + [InlineData("12345678", "1234", StringComparison.InvariantCultureIgnoreCase)] + public static void StartsWith(string x, string y, StringComparison comparisonType) => + x.MustStartWith(y, comparisonType).Should().BeSameAs(x); + + [Fact] + public static void ParameterNull() + { + var act = () => ((string) null).MustStartWith("Foo"); + + act.Should().Throw(); + } + + [Fact] + public static void ValueNull() + { + var act = () => "Foo".MustStartWith(null!); + + act.Should().Throw(); + } + + [Fact] + public static void CustomMessage() => + Test.CustomMessage(message => "Foo".MustStartWith("Bar", message: message)); + + [Fact] + public static void CustomMessageParameterNull() => + Test.CustomMessage(message => ((string) null).MustStartWith("Bar", message: message)); + + [Fact] + public static void StartsWithCustomException() => + "Foo".MustStartWith("F", (_, _) => new Exception()).Should().Be("Foo"); + + [Fact] + public static void StartsWithCustomExceptionAndComparisonType() => + "Foo".MustStartWith("f", StringComparison.OrdinalIgnoreCase, (_, _, _) => new Exception()).Should().Be("Foo"); + + [Theory] + [InlineData("Foo", "Bar")] + [InlineData("Foo", null)] + [InlineData(null, "Baz")] + public static void CustomException(string first, string second) => + Test.CustomException(first, second, (s1, s2, exceptionFactory) => s1.MustStartWith(s2, exceptionFactory)); + + [Theory] + [InlineData("Foo", "Bar", StringComparison.Ordinal)] + [InlineData(null, "Bar", StringComparison.Ordinal)] + [InlineData("Baz", null, StringComparison.Ordinal)] + public static void CustomExceptionWithComparisonType(string a, string b, StringComparison comparisonType) => + Test.CustomException(a, b, comparisonType, (s1, s2, ct, exceptionFactory) => s1.MustStartWith(s2, ct, exceptionFactory)); +} \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.StringAssertions.cs b/Code/Light.GuardClauses/Check.StringAssertions.cs index 8835a244..e41f7582 100644 --- a/Code/Light.GuardClauses/Check.StringAssertions.cs +++ b/Code/Light.GuardClauses/Check.StringAssertions.cs @@ -710,6 +710,91 @@ public static string MustNotBeSubstringOf([NotNull, ValidatedNotNull] this strin return parameter; } + /// + /// Ensures that the string starts with the specified value, or otherwise throws a . + /// + /// The string to be checked. + /// The other string must start with. + /// One of the enumeration values that specifies the rules for the search (optional). The default value is . + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when does not start with . + /// Thrown when or is null. + /// Thrown when is not a valid value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt")] + public static string MustStartWith( + [NotNull, ValidatedNotNull] this string? parameter, + [NotNull, ValidatedNotNull] string value, + StringComparison comparisonType = StringComparison.CurrentCulture, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (!parameter.MustNotBeNull(parameterName, message).StartsWith(value, comparisonType)) + { + Throw.StringDoesNotStartWith(parameter, value, comparisonType, parameterName, message); + } + return parameter; + } + + /// + /// Ensures that the string starts with the specified value, or otherwise throws your custom exception. + /// + /// The string to be checked. + /// The other string must start with. + /// The delegate that creates your custom exception. and are passed to this delegate. + /// + /// Your custom exception thrown when does not start with , + /// or when is null, + /// or when is null. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt; exceptionFactory:null => halt")] + public static string MustStartWith( + [NotNull, ValidatedNotNull] this string? parameter, + [NotNull, ValidatedNotNull] string value, + [NotNull, ValidatedNotNull] Func exceptionFactory + ) + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract -- caller might have NRTs turned off + if (parameter is null || value is null || !parameter.StartsWith(value)) + { + Throw.CustomException(exceptionFactory, parameter, value!); + } + return parameter; + } + + /// + /// Ensures that the string starts with the specified value, or otherwise throws your custom exception. + /// + /// The string to be checked. + /// The other string must start with. + /// One of the enumeration values that specifies the rules for the search. + /// The delegate that creates your custom exception. and are passed to this delegate. + /// + /// Your custom exception thrown when does not start with , + /// or when is null, + /// or when is null. + /// + /// Thrown when is not a valid value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt; exceptionFactory:null => halt")] + public static string MustStartWith( + [NotNull, ValidatedNotNull] this string? parameter, + [NotNull, ValidatedNotNull] string value, + StringComparison comparisonType, + [NotNull, ValidatedNotNull] Func exceptionFactory + ) + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract -- caller might have NRTs turned off + if (parameter is null || value is null || !comparisonType.IsValidEnumValue() || !parameter.StartsWith(value, comparisonType)) + { + Throw.CustomException(exceptionFactory, parameter, value!, comparisonType); + } + return parameter; + } + /// /// Checks if the specified string is an email address using the default email regular expression /// defined in . diff --git a/Code/Light.GuardClauses/Exceptions/Throw.cs b/Code/Light.GuardClauses/Exceptions/Throw.cs index f14eeb81..64e6bdce 100644 --- a/Code/Light.GuardClauses/Exceptions/Throw.cs +++ b/Code/Light.GuardClauses/Exceptions/Throw.cs @@ -268,10 +268,16 @@ public static void Substring(string parameter, string other, [CallerArgumentExpr [DoesNotReturn] public static void Substring(string parameter, string other, StringComparison comparisonType, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) => throw new SubstringException(parameterName, message ?? $"{parameterName ?? "The string"} must not be a substring of \"{other}\" ({comparisonType}), but it actually is {parameter.ToStringOrNull()}."); - + /// - /// Throws the default indicating that a string is not shorter than the given length, using the optional parameter name an message. + /// Throws the default indicating that a string is a substring of another one, using the optional parameter name and message. + /// + [ContractAnnotation("=> halt")] [DoesNotReturn] + public static void StringDoesNotStartWith(string parameter, string other, StringComparison comparisonType, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) => + throw new SubstringException(parameterName, message ?? $"{parameterName ?? "The string"} must start with \"{other}\" ({comparisonType}), but it actually is {parameter.ToStringOrNull()}."); + + /// /// Throws the default indicating that a string is not shorter than the given length, using the optional parameter name and message. /// [ContractAnnotation("=> halt")] From ac48045f96610c980afbf1e9a5cc45ff32e67a20 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 27 Oct 2024 11:23:40 +0100 Subject: [PATCH 91/97] feat: add MustEndWith Signed-off-by: Kenny Pflug --- .../StringAssertions/MustEndWithTests.cs | 73 +++++++++++++++++ .../Check.StringAssertions.cs | 82 +++++++++++++++++++ Code/Light.GuardClauses/Exceptions/Throw.cs | 10 ++- 3 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 Code/Light.GuardClauses.Tests/StringAssertions/MustEndWithTests.cs diff --git a/Code/Light.GuardClauses.Tests/StringAssertions/MustEndWithTests.cs b/Code/Light.GuardClauses.Tests/StringAssertions/MustEndWithTests.cs new file mode 100644 index 00000000..776665d5 --- /dev/null +++ b/Code/Light.GuardClauses.Tests/StringAssertions/MustEndWithTests.cs @@ -0,0 +1,73 @@ +using System; +using FluentAssertions; +using Light.GuardClauses.Exceptions; +using Xunit; + +namespace Light.GuardClauses.Tests.StringAssertions; + +public static class MustEndWithTests +{ + [Theory] + [InlineData("Foo", "Bar")] + [InlineData("When you play the game of thrones you win, or you die.", "you live")] + public static void DoesNotEndWith(string x, string y) + { + var act = () => x.MustEndWith(y); + + var exception = act.Should().Throw().Which; + exception.Message.Should().StartWith($"{nameof(x)} must end with \"{y}\" (CurrentCulture), but it actually is \"{x}\"."); + exception.ParamName.Should().BeSameAs(nameof(x)); + } + + [Theory] + [InlineData("FooBar", "Bar", StringComparison.Ordinal)] + [InlineData("12345678", "5678", StringComparison.InvariantCultureIgnoreCase)] + public static void EndsWith(string x, string y, StringComparison comparisonType) => + x.MustEndWith(y, comparisonType).Should().BeSameAs(x); + + [Fact] + public static void ParameterNull() + { + var act = () => ((string) null).MustEndWith("Foo"); + + act.Should().Throw(); + } + + [Fact] + public static void ValueNull() + { + var act = () => "Foo".MustEndWith(null!); + + act.Should().Throw(); + } + + [Fact] + public static void CustomMessage() => + Test.CustomMessage(message => "Foo".MustEndWith("Bar", message: message)); + + [Fact] + public static void CustomMessageParameterNull() => + Test.CustomMessage(message => ((string) null).MustEndWith("Bar", message: message)); + + [Fact] + public static void EndsWithCustomException() => + "Foo".MustEndWith("o", (_, _) => new Exception()).Should().Be("Foo"); + + [Fact] + public static void EndsWithCustomExceptionAndComparisonType() => + "Foo".MustEndWith("O", StringComparison.OrdinalIgnoreCase, (_, _, _) => new Exception()).Should().Be("Foo"); + + [Theory] + [InlineData("Foo", "Bar")] + [InlineData("Foo", null)] + [InlineData(null, "Baz")] + public static void CustomException(string first, string second) => + Test.CustomException(first, second, (s1, s2, exceptionFactory) => s1.MustEndWith(s2, exceptionFactory)); + + [Theory] + [InlineData("Foo", "Bar", StringComparison.Ordinal)] + [InlineData(null, "Bar", StringComparison.Ordinal)] + [InlineData("Baz", null, StringComparison.Ordinal)] + public static void CustomExceptionWithComparisonType(string a, string b, StringComparison comparisonType) => + Test.CustomException(a, b, comparisonType, (s1, s2, ct, exceptionFactory) => s1.MustEndWith(s2, ct, exceptionFactory)); +} diff --git a/Code/Light.GuardClauses/Check.StringAssertions.cs b/Code/Light.GuardClauses/Check.StringAssertions.cs index e41f7582..3eb015e1 100644 --- a/Code/Light.GuardClauses/Check.StringAssertions.cs +++ b/Code/Light.GuardClauses/Check.StringAssertions.cs @@ -794,6 +794,88 @@ public static string MustStartWith( } return parameter; } + + /// + /// Ensures that the string ends with the specified value, or otherwise throws a . + /// + /// The string to be checked. + /// The other string must end with. + /// One of the enumeration values that specifies the rules for the search (optional). The default value is . + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when does not end with . + /// Thrown when or is null. + /// Thrown when is not a valid value. + public static string MustEndWith( + [NotNull, ValidatedNotNull] this string? parameter, + [NotNull, ValidatedNotNull] string value, + StringComparison comparisonType = StringComparison.CurrentCulture, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (!parameter.MustNotBeNull(parameterName, message).EndsWith(value, comparisonType)) + { + Throw.StringDoesNotEndWith(parameter, value, comparisonType, parameterName, message); + } + return parameter; + } + + /// + /// Ensures that the string ends with the specified value, or otherwise throws a . + /// + /// The string to be checked. + /// The other string must end with. + /// The delegate that creates your custom exception. and are passed to this delegate. + /// + /// Your custom exception thrown when does not end with , + /// or when is null, + /// or when is null. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt; exceptionFactory:null => halt")] + public static string MustEndWith( + [NotNull, ValidatedNotNull] this string? parameter, + [NotNull, ValidatedNotNull] string value, + [NotNull, ValidatedNotNull] Func exceptionFactory + ) + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract -- caller might have NRTs turned off + if (parameter is null || value is null || !parameter.EndsWith(value)) + { + Throw.CustomException(exceptionFactory, parameter, value!); + } + return parameter; + } + + /// + /// Ensures that the string ends with the specified value, or otherwise throws a . + /// + /// The string to be checked. + /// The other string must end with. + /// One of the enumeration values that specifies the rules for the search (optional). The default value is . + /// The delegate that creates your custom exception. and are passed to this delegate. + /// + /// Your custom exception thrown when does not end with , + /// or when is null, + /// or when is null. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt; exceptionFactory:null => halt")] + public static string MustEndWith( + [NotNull, ValidatedNotNull] this string? parameter, + [NotNull, ValidatedNotNull] string value, + StringComparison comparisonType, + [NotNull, ValidatedNotNull] Func exceptionFactory + ) + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract -- caller might have NRTs turned off + if (parameter is null || value is null || !parameter.EndsWith(value, comparisonType)) + { + Throw.CustomException(exceptionFactory, parameter, value!, comparisonType); + } + return parameter; + } /// /// Checks if the specified string is an email address using the default email regular expression diff --git a/Code/Light.GuardClauses/Exceptions/Throw.cs b/Code/Light.GuardClauses/Exceptions/Throw.cs index 64e6bdce..04ca8313 100644 --- a/Code/Light.GuardClauses/Exceptions/Throw.cs +++ b/Code/Light.GuardClauses/Exceptions/Throw.cs @@ -270,12 +270,20 @@ public static void Substring(string parameter, string other, StringComparison co throw new SubstringException(parameterName, message ?? $"{parameterName ?? "The string"} must not be a substring of \"{other}\" ({comparisonType}), but it actually is {parameter.ToStringOrNull()}."); /// - /// Throws the default indicating that a string is a substring of another one, using the optional parameter name and message. + /// Throws the default indicating that a string does not start with another one, using the optional parameter name and message. /// [ContractAnnotation("=> halt")] [DoesNotReturn] public static void StringDoesNotStartWith(string parameter, string other, StringComparison comparisonType, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) => throw new SubstringException(parameterName, message ?? $"{parameterName ?? "The string"} must start with \"{other}\" ({comparisonType}), but it actually is {parameter.ToStringOrNull()}."); + + /// + /// Throws the default indicating that a string does not end with another one, using the optional parameter name and message. + /// + [ContractAnnotation("=> halt")] + [DoesNotReturn] + public static void StringDoesNotEndWith(string parameter, string other, StringComparison comparisonType, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) => + throw new SubstringException(parameterName, message ?? $"{parameterName ?? "The string"} must end with \"{other}\" ({comparisonType}), but it actually is {parameter.ToStringOrNull()}."); /// /// Throws the default indicating that a string is not shorter than the given length, using the optional parameter name and message. From a0b2e1a02470e3325b4a7764441eabe9e1029605 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 27 Oct 2024 11:44:11 +0100 Subject: [PATCH 92/97] feat: add MustNotStartWith Signed-off-by: Kenny Pflug --- .../StringAssertions/MustNotStartWithTests.cs | 85 +++++++++++++++++++ .../Check.StringAssertions.cs | 84 ++++++++++++++++++ Code/Light.GuardClauses/Exceptions/Throw.cs | 8 ++ 3 files changed, 177 insertions(+) create mode 100644 Code/Light.GuardClauses.Tests/StringAssertions/MustNotStartWithTests.cs diff --git a/Code/Light.GuardClauses.Tests/StringAssertions/MustNotStartWithTests.cs b/Code/Light.GuardClauses.Tests/StringAssertions/MustNotStartWithTests.cs new file mode 100644 index 00000000..5ad5160c --- /dev/null +++ b/Code/Light.GuardClauses.Tests/StringAssertions/MustNotStartWithTests.cs @@ -0,0 +1,85 @@ +using System; +using FluentAssertions; +using Light.GuardClauses.Exceptions; +using Xunit; + +namespace Light.GuardClauses.Tests.StringAssertions; + +public static class MustNotStartWithTests +{ + [Theory] + [InlineData("Bar", "Foo")] + [InlineData("When you play the game of thrones you win, or you die.", "Love and peace")] + public static void DoesNotStartWith(string x, string y) => + x.MustNotStartWith(y).Should().BeSameAs(x); + + [Theory] + [InlineData("FooBar", "Foo")] + [InlineData("12345678", "1234")] + public static void StartsWith(string x, string y) + { + var act = () => x.MustNotStartWith(y); + + var exception = act.Should().Throw().Which; + exception.Message.Should().StartWith($"{nameof(x)} must not start with \"{y}\" (CurrentCulture), but it actually is \"{x}\""); + exception.ParamName.Should().BeSameAs(nameof(x)); + } + + [Theory] + [InlineData("FooBar", "Foo", StringComparison.Ordinal)] + [InlineData("12345678", "1234", StringComparison.InvariantCultureIgnoreCase)] + public static void StartsWithComparisonType(string x, string y, StringComparison comparisonType) + { + var act = () => x.MustNotStartWith(y, comparisonType); + + var exception = act.Should().Throw().Which; + exception.Message.Should().StartWith($"{nameof(x)} must not start with \"{y}\" ({comparisonType}), but it actually is \"{x}\""); + exception.ParamName.Should().BeSameAs(nameof(x)); + } + + [Fact] + public static void ParameterNull() + { + var act = () => ((string)null).MustNotStartWith("Foo"); + + act.Should().Throw(); + } + + [Fact] + public static void ValueNull() + { + var act = () => "Foo".MustNotStartWith(null!); + + act.Should().Throw(); + } + + [Fact] + public static void CustomMessage() => + Test.CustomMessage(message => "FooBar".MustNotStartWith("Foo", message: message)); + + [Fact] + public static void CustomMessageParameterNull() => + Test.CustomMessage(message => ((string)null).MustNotStartWith("Bar", message: message)); + + [Fact] + public static void NotStartsWithCustomException() => + "Bar".MustNotStartWith("Foo", (_, _) => new Exception()).Should().Be("Bar"); + + [Fact] + public static void NotStartsWithCustomExceptionAndComparisonType() => + "Bar".MustNotStartWith("foo", StringComparison.OrdinalIgnoreCase, (_, _, _) => new Exception()).Should().Be("Bar"); + + [Theory] + [InlineData("Foo", "Foo")] + [InlineData("Foo", null)] + [InlineData(null, "Baz")] + public static void CustomException(string first, string second) => + Test.CustomException(first, second, (s1, s2, exceptionFactory) => s1.MustNotStartWith(s2, exceptionFactory)); + + [Theory] + [InlineData("Foo", "foo", StringComparison.OrdinalIgnoreCase)] + [InlineData(null, "Bar", StringComparison.Ordinal)] + [InlineData("Baz", null, StringComparison.Ordinal)] + public static void CustomExceptionWithComparisonType(string a, string b, StringComparison comparisonType) => + Test.CustomException(a, b, comparisonType, (s1, s2, ct, exceptionFactory) => s1.MustNotStartWith(s2, ct, exceptionFactory)); +} diff --git a/Code/Light.GuardClauses/Check.StringAssertions.cs b/Code/Light.GuardClauses/Check.StringAssertions.cs index 3eb015e1..090865f5 100644 --- a/Code/Light.GuardClauses/Check.StringAssertions.cs +++ b/Code/Light.GuardClauses/Check.StringAssertions.cs @@ -794,6 +794,90 @@ public static string MustStartWith( } return parameter; } + + /// + /// Ensures that the string does not start with the specified value, or otherwise throws a . + /// + /// The string to be checked. + /// The other string that must not start with. + /// One of the enumeration values that specifies the rules for the search (optional). The default value is . + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when starts with . + /// Thrown when or is null. + public static string MustNotStartWith( + [NotNull, ValidatedNotNull] this string? parameter, + [NotNull, ValidatedNotNull] string value, + StringComparison comparisonType = StringComparison.CurrentCulture, + [CallerArgumentExpression("parameter")] + string? parameterName = null, + string? message = null + ) + { + if (parameter.MustNotBeNull(parameterName, message).StartsWith(value, comparisonType)) + { + Throw.StringStartsWith(parameter, value, comparisonType, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the string does not start with the specified value, or otherwise throws your custom exception. + /// + /// The string to be checked. + /// The other string that must not start with. + /// The delegate that creates your custom exception. and are passed to this delegate. + /// + /// Your custom exception thrown when does not start with , + /// or when is null, + /// or when is null. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt; exceptionFactory:null => halt")] + public static string MustNotStartWith( + [NotNull, ValidatedNotNull] this string? parameter, + [NotNull, ValidatedNotNull] string value, + [NotNull, ValidatedNotNull] Func exceptionFactory + ) + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract -- caller might have NRTs turned off + if (parameter is null || value is null || parameter.StartsWith(value)) + { + Throw.CustomException(exceptionFactory, parameter, value!); + } + return parameter; + } + + /// + /// Ensures that the string does not start with the specified value, or otherwise throws your custom exception. + /// + /// The string to be checked. + /// The other string that must not start with. + /// One of the enumeration values that specifies the rules for the search. + /// The delegate that creates your custom exception. and are passed to this delegate. + /// + /// Your custom exception thrown when does not start with , + /// or when is null, + /// or when is null. + /// + /// Thrown when is not a valid value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt; exceptionFactory:null => halt")] + public static string MustNotStartWith( + [NotNull, ValidatedNotNull] this string? parameter, + [NotNull, ValidatedNotNull] string value, + StringComparison comparisonType, + [NotNull, ValidatedNotNull] Func exceptionFactory + ) + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract -- caller might have NRTs turned off + if (parameter is null || value is null || parameter.StartsWith(value, comparisonType)) + { + Throw.CustomException(exceptionFactory, parameter, value!, comparisonType); + } + return parameter; + } /// /// Ensures that the string ends with the specified value, or otherwise throws a . diff --git a/Code/Light.GuardClauses/Exceptions/Throw.cs b/Code/Light.GuardClauses/Exceptions/Throw.cs index 04ca8313..1b3d83a2 100644 --- a/Code/Light.GuardClauses/Exceptions/Throw.cs +++ b/Code/Light.GuardClauses/Exceptions/Throw.cs @@ -277,6 +277,14 @@ public static void Substring(string parameter, string other, StringComparison co public static void StringDoesNotStartWith(string parameter, string other, StringComparison comparisonType, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) => throw new SubstringException(parameterName, message ?? $"{parameterName ?? "The string"} must start with \"{other}\" ({comparisonType}), but it actually is {parameter.ToStringOrNull()}."); + /// + /// Throws the default indicating that a string does start with another one, using the optional parameter name and message. + /// + [ContractAnnotation("=> halt")] + [DoesNotReturn] + public static void StringStartsWith(string parameter, string other, StringComparison comparisonType, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) => + throw new SubstringException(parameterName, message ?? $"{parameterName ?? "The string"} must not start with \"{other}\" ({comparisonType}), but it actually is {parameter.ToStringOrNull()}."); + /// /// Throws the default indicating that a string does not end with another one, using the optional parameter name and message. /// From 9eaf70f6d7811896090e4437a7ae72389298e89b Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 27 Oct 2024 12:05:51 +0100 Subject: [PATCH 93/97] feat: add MustNotEndWith Signed-off-by: Kenny Pflug --- .../StringAssertions/MustNotEndWithTests.cs | 73 ++++++++++++++++ .../Check.StringAssertions.cs | 84 ++++++++++++++++++- Code/Light.GuardClauses/Exceptions/Throw.cs | 8 ++ 3 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 Code/Light.GuardClauses.Tests/StringAssertions/MustNotEndWithTests.cs diff --git a/Code/Light.GuardClauses.Tests/StringAssertions/MustNotEndWithTests.cs b/Code/Light.GuardClauses.Tests/StringAssertions/MustNotEndWithTests.cs new file mode 100644 index 00000000..d9508263 --- /dev/null +++ b/Code/Light.GuardClauses.Tests/StringAssertions/MustNotEndWithTests.cs @@ -0,0 +1,73 @@ +using System; +using FluentAssertions; +using Light.GuardClauses.Exceptions; +using Xunit; + +namespace Light.GuardClauses.Tests.StringAssertions; + +public static class MustNotEndWithTests +{ + [Theory] + [InlineData("FooBar", "Bar")] + [InlineData("When you play the game of thrones you win, or you die.", "die.")] + public static void DoesEndWith(string x, string y) + { + var act = () => x.MustNotEndWith(y); + + var exception = act.Should().Throw().Which; + exception.Message.Should().StartWith($"{nameof(x)} must not end with \"{y}\" (CurrentCulture), but it actually is \"{x}\"."); + exception.ParamName.Should().BeSameAs(nameof(x)); + } + + [Theory] + [InlineData("Foo", "Bar", StringComparison.Ordinal)] + [InlineData("12345", "1234", StringComparison.InvariantCultureIgnoreCase)] + public static void DoesNotEndWith(string x, string y, StringComparison comparisonType) => + x.MustNotEndWith(y, comparisonType).Should().BeSameAs(x); + + [Fact] + public static void ParameterNull() + { + var act = () => ((string) null).MustNotEndWith("Foo"); + + act.Should().Throw(); + } + + [Fact] + public static void ValueNull() + { + var act = () => "Foo".MustNotEndWith(null!); + + act.Should().Throw(); + } + + [Fact] + public static void CustomMessage() => + Test.CustomMessage(message => "FooBar".MustNotEndWith("Bar", message: message)); + + [Fact] + public static void CustomMessageParameterNull() => + Test.CustomMessage(message => ((string) null).MustNotEndWith("Bar", message: message)); + + [Fact] + public static void DoesNotEndWithCustomException() => + "Foo".MustNotEndWith("r", (_, _) => new Exception()).Should().Be("Foo"); + + [Fact] + public static void DoesNotEndWithCustomExceptionAndComparisonType() => + "Foo".MustNotEndWith("R", StringComparison.OrdinalIgnoreCase, (_, _, _) => new Exception()).Should().Be("Foo"); + + [Theory] + [InlineData("FooBar", "Bar")] + [InlineData("Foo", null)] + [InlineData(null, "Baz")] + public static void CustomException(string first, string second) => + Test.CustomException(first, second, (s1, s2, exceptionFactory) => s1.MustNotEndWith(s2, exceptionFactory)); + + [Theory] + [InlineData("FooBar", "Bar", StringComparison.Ordinal)] + [InlineData(null, "Bar", StringComparison.Ordinal)] + [InlineData("Baz", null, StringComparison.Ordinal)] + public static void CustomExceptionWithComparisonType(string a, string b, StringComparison comparisonType) => + Test.CustomException(a, b, comparisonType, (s1, s2, ct, exceptionFactory) => s1.MustNotEndWith(s2, ct, exceptionFactory)); +} diff --git a/Code/Light.GuardClauses/Check.StringAssertions.cs b/Code/Light.GuardClauses/Check.StringAssertions.cs index 090865f5..4e8e433a 100644 --- a/Code/Light.GuardClauses/Check.StringAssertions.cs +++ b/Code/Light.GuardClauses/Check.StringAssertions.cs @@ -937,7 +937,7 @@ public static string MustEndWith( /// /// The string to be checked. /// The other string must end with. - /// One of the enumeration values that specifies the rules for the search (optional). The default value is . + /// One of the enumeration values that specifies the rules for the search. /// The delegate that creates your custom exception. and are passed to this delegate. /// /// Your custom exception thrown when does not end with , @@ -960,6 +960,88 @@ public static string MustEndWith( } return parameter; } + + /// + /// Ensures that the string does not end with the specified value, or otherwise throws a . + /// + /// The string to be checked. + /// The other string must not end with. + /// One of the enumeration values that specifies the rules for the search (optional). The default value is . + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when ends with . + /// Thrown when or is null. + /// Thrown when is not a valid value. + public static string MustNotEndWith( + [NotNull, ValidatedNotNull] this string? parameter, + [NotNull, ValidatedNotNull] string value, + StringComparison comparisonType = StringComparison.CurrentCulture, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (parameter.MustNotBeNull(parameterName, message).EndsWith(value, comparisonType)) + { + Throw.StringEndsWith(parameter, value, comparisonType, parameterName, message); + } + return parameter; + } + + /// + /// Ensures that the string does not end with the specified value, or otherwise throws a . + /// + /// The string to be checked. + /// The other string must not end with. + /// The delegate that creates your custom exception. and are passed to this delegate. + /// + /// Your custom exception thrown when ends with , + /// or when is null, + /// or when is null. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt; exceptionFactory:null => halt")] + public static string MustNotEndWith( + [NotNull, ValidatedNotNull] this string? parameter, + [NotNull, ValidatedNotNull] string value, + [NotNull, ValidatedNotNull] Func exceptionFactory + ) + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract -- caller might have NRTs turned off + if (parameter is null || value is null || parameter.EndsWith(value)) + { + Throw.CustomException(exceptionFactory, parameter, value!); + } + return parameter; + } + + /// + /// Ensures that the string does not end with the specified value, or otherwise throws a . + /// + /// The string to be checked. + /// The other string must not end with. + /// One of the enumeration values that specifies the rules for the search. + /// The delegate that creates your custom exception. , , and are passed to this delegate. + /// + /// Your custom exception thrown when ends with , + /// or when is null, + /// or when is null. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt; exceptionFactory:null => halt")] + public static string MustNotEndWith( + [NotNull, ValidatedNotNull] this string? parameter, + [NotNull, ValidatedNotNull] string value, + StringComparison comparisonType, + [NotNull, ValidatedNotNull] Func exceptionFactory + ) + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract -- caller might have NRTs turned off + if (parameter is null || value is null || parameter.EndsWith(value, comparisonType)) + { + Throw.CustomException(exceptionFactory, parameter, value!, comparisonType); + } + return parameter; + } /// /// Checks if the specified string is an email address using the default email regular expression diff --git a/Code/Light.GuardClauses/Exceptions/Throw.cs b/Code/Light.GuardClauses/Exceptions/Throw.cs index 1b3d83a2..5b3bbf9c 100644 --- a/Code/Light.GuardClauses/Exceptions/Throw.cs +++ b/Code/Light.GuardClauses/Exceptions/Throw.cs @@ -292,6 +292,14 @@ public static void StringStartsWith(string parameter, string other, StringCompar [DoesNotReturn] public static void StringDoesNotEndWith(string parameter, string other, StringComparison comparisonType, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) => throw new SubstringException(parameterName, message ?? $"{parameterName ?? "The string"} must end with \"{other}\" ({comparisonType}), but it actually is {parameter.ToStringOrNull()}."); + + /// + /// Throws the default indicating that a string ends with another one, using the optional parameter name and message. + /// + [ContractAnnotation("=> halt")] + [DoesNotReturn] + public static void StringEndsWith(string parameter, string other, StringComparison comparisonType, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) => + throw new SubstringException(parameterName, message ?? $"{parameterName ?? "The string"} must not end with \"{other}\" ({comparisonType}), but it actually is {parameter.ToStringOrNull()}."); /// /// Throws the default indicating that a string is not shorter than the given length, using the optional parameter name and message. From 8a53d5164e373087db118cc52e8cd2247e9338a4 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 27 Oct 2024 12:30:36 +0100 Subject: [PATCH 94/97] chore: final cleanup Signed-off-by: Kenny Pflug --- .../StringAssertions/MustBeBenchmark.cs | 2 +- .../StringAssertions/MustNotBeBenchmark.cs | 2 +- .../StringAssertions/MustBeTests.cs | 6 ++-- .../StringAssertions/MustNotBeTests.cs | 3 +- .../Check.StringAssertions.cs | 34 +++++++++---------- 5 files changed, 25 insertions(+), 22 deletions(-) diff --git a/Code/Light.GuardClauses.Performance/StringAssertions/MustBeBenchmark.cs b/Code/Light.GuardClauses.Performance/StringAssertions/MustBeBenchmark.cs index 62310d7f..19f51c5a 100644 --- a/Code/Light.GuardClauses.Performance/StringAssertions/MustBeBenchmark.cs +++ b/Code/Light.GuardClauses.Performance/StringAssertions/MustBeBenchmark.cs @@ -22,6 +22,6 @@ public string ImperativeVersion() [Benchmark] public string LightGuardClausesCustomException() => - X.MustBe(Y, StringComparisonType.OrdinalIgnoreWhiteSpace, (x, y) => new Exception("The strings are not equal.")); + X.MustBe(Y, StringComparisonType.OrdinalIgnoreWhiteSpace, (_, _, _) => new Exception("The strings are not equal.")); } } \ No newline at end of file diff --git a/Code/Light.GuardClauses.Performance/StringAssertions/MustNotBeBenchmark.cs b/Code/Light.GuardClauses.Performance/StringAssertions/MustNotBeBenchmark.cs index 67f3c3c0..3b5da46e 100644 --- a/Code/Light.GuardClauses.Performance/StringAssertions/MustNotBeBenchmark.cs +++ b/Code/Light.GuardClauses.Performance/StringAssertions/MustNotBeBenchmark.cs @@ -25,6 +25,6 @@ public string ImperativeVersion() [Benchmark] public string LightGuardClausesCustomException() => - X.MustNotBe(Y, StringComparisonType.OrdinalIgnoreCaseIgnoreWhiteSpace, (x, y) => new Exception("The strings are equal.")); + X.MustNotBe(Y, StringComparisonType.OrdinalIgnoreCaseIgnoreWhiteSpace, (_, _, _) => new Exception("The strings are equal.")); } } \ No newline at end of file diff --git a/Code/Light.GuardClauses.Tests/StringAssertions/MustBeTests.cs b/Code/Light.GuardClauses.Tests/StringAssertions/MustBeTests.cs index 81b22850..6466858c 100644 --- a/Code/Light.GuardClauses.Tests/StringAssertions/MustBeTests.cs +++ b/Code/Light.GuardClauses.Tests/StringAssertions/MustBeTests.cs @@ -50,7 +50,8 @@ public static void StringsNotEqualIgnoreWhiteSpace(string first, string second, public static void CustomException() => Test.CustomException("Foo", "Bar", - (x, y, exceptionFactory) => x.MustBe(y, StringComparison.Ordinal, exceptionFactory)); + StringComparison.Ordinal, + (x, y, ct, exceptionFactory) => x.MustBe(y, ct, exceptionFactory)); [Fact] public static void CustomMessage() => @@ -60,7 +61,8 @@ public static void CustomMessage() => public static void CustomExceptionIgnoreWhiteSpace() => Test.CustomException("Foo", " foo", - (x, y, exceptionFactory) => x.MustBe(y, StringComparisonType.OrdinalIgnoreWhiteSpace, exceptionFactory)); + StringComparisonType.OrdinalIgnoreWhiteSpace, + (x, y, ct, exceptionFactory) => x.MustBe(y, ct, exceptionFactory)); [Fact] public static void CustomMessageIgnoreWhiteSpace() => diff --git a/Code/Light.GuardClauses.Tests/StringAssertions/MustNotBeTests.cs b/Code/Light.GuardClauses.Tests/StringAssertions/MustNotBeTests.cs index 6d6f28ad..b412c7cf 100644 --- a/Code/Light.GuardClauses.Tests/StringAssertions/MustNotBeTests.cs +++ b/Code/Light.GuardClauses.Tests/StringAssertions/MustNotBeTests.cs @@ -56,7 +56,8 @@ public static void CustomException() => public static void CustomExceptionIgnoreWhiteSpace() => Test.CustomException("Foo", " Foo", - (x, y, exceptionFactory) => x.MustNotBe(y, StringComparisonType.OrdinalIgnoreWhiteSpace, exceptionFactory)); + StringComparisonType.OrdinalIgnoreWhiteSpace, + (x, y, ct, exceptionFactory) => x.MustNotBe(y, ct, exceptionFactory)); [Fact] public static void CustomMessage() => diff --git a/Code/Light.GuardClauses/Check.StringAssertions.cs b/Code/Light.GuardClauses/Check.StringAssertions.cs index 4e8e433a..e8fff609 100644 --- a/Code/Light.GuardClauses/Check.StringAssertions.cs +++ b/Code/Light.GuardClauses/Check.StringAssertions.cs @@ -155,10 +155,10 @@ public static string MustNotBeNullOrWhiteSpace([NotNull, ValidatedNotNull] this /// Your custom exception thrown when is not equal to . /// Thrown when is not a valid value from the enum. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static string? MustBe(this string? parameter, string? other, StringComparison comparisonType, Func exceptionFactory) + public static string? MustBe(this string? parameter, string? other, StringComparison comparisonType, Func exceptionFactory) { if (!string.Equals(parameter, other, comparisonType)) - Throw.CustomException(exceptionFactory, parameter, other); + Throw.CustomException(exceptionFactory, parameter, other, comparisonType); return parameter; } @@ -171,7 +171,7 @@ public static string MustNotBeNullOrWhiteSpace([NotNull, ValidatedNotNull] this /// The name of the parameter (optional). /// The message that will be passed to the resulting exception (optional). /// Thrown when is not equal to . - /// Thrown when is not a valid value from the enum. + /// Thrown when is not a valid value from the enum. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static string? MustBe(this string? parameter, string? other, StringComparisonType comparisonType, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { @@ -188,11 +188,11 @@ public static string MustNotBeNullOrWhiteSpace([NotNull, ValidatedNotNull] this /// The enum value specifying how the two strings should be compared. /// The delegate that creates your custom exception. and are passed to this delegate. /// Your custom exception thrown when is not equal to . - /// Thrown when is not a valid value from the enum. - public static string? MustBe(this string? parameter, string? other, StringComparisonType comparisonType, Func exceptionFactory) + /// Thrown when is not a valid value from the enum. + public static string? MustBe(this string? parameter, string? other, StringComparisonType comparisonType, Func exceptionFactory) { if (!parameter.Equals(other, comparisonType)) - Throw.CustomException(exceptionFactory, parameter, other); + Throw.CustomException(exceptionFactory, parameter, other, comparisonType); return parameter; } @@ -220,7 +220,7 @@ public static string MustNotBeNullOrWhiteSpace([NotNull, ValidatedNotNull] this /// The first string to be compared. /// The second string to be compared. /// The enum value specifying how the two strings should be compared. - /// The delegate that creates your custom exception. and are passed to this delegate. + /// The delegate that creates your custom exception. , , and are passed to this delegate. /// Your custom exception thrown when is equal to . /// Thrown when is not a valid value from the enum. [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -240,7 +240,7 @@ public static string MustNotBeNullOrWhiteSpace([NotNull, ValidatedNotNull] this /// The name of the parameter (optional). /// The message that will be passed to the resulting exception (optional). /// Thrown when is equal to . - /// Thrown when is not a valid value from the enum. + /// Thrown when is not a valid value from the enum. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static string? MustNotBe(this string? parameter, string? other, StringComparisonType comparisonType, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) { @@ -255,14 +255,14 @@ public static string MustNotBeNullOrWhiteSpace([NotNull, ValidatedNotNull] this /// The first string to be compared. /// The second string to be compared. /// The enum value specifying how the two strings should be compared. - /// The delegate that creates your custom exception. and are passed to this delegate. + /// The delegate that creates your custom exception. , , and are passed to this delegate. /// Your custom exception thrown when is equal to . - /// Thrown when is not a valid value from the enum. + /// Thrown when is not a valid value from the enum. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static string? MustNotBe(this string? parameter, string? other, StringComparisonType comparisonType, Func exceptionFactory) + public static string? MustNotBe(this string? parameter, string? other, StringComparisonType comparisonType, Func exceptionFactory) { if (parameter.Equals(other, comparisonType)) - Throw.CustomException(exceptionFactory, parameter, other); + Throw.CustomException(exceptionFactory, parameter, other, comparisonType); return parameter; } @@ -441,7 +441,7 @@ public static string MustNotContain([NotNull, ValidatedNotNull] this string? par /// /// The string to be checked. /// The string that must not be part of . - /// The delegate that creates your custom exception (optional). and are passed to this + /// The delegate that creates your custom exception (optional). and are passed to this delegate. /// /// Your custom exception thrown when contains , /// or when is null, @@ -693,7 +693,7 @@ public static string MustNotBeSubstringOf([NotNull, ValidatedNotNull] this strin /// The string to be checked. /// The other string that must not contain . /// One of the enumeration values that specifies the rules for the search. - /// The delegate that creates your custom exception. and are passed to this delegate. + /// The delegate that creates your custom exception. , , and are passed to this delegate. /// /// Your custom exception thrown when contains , /// or when is null, @@ -771,7 +771,7 @@ public static string MustStartWith( /// The string to be checked. /// The other string must start with. /// One of the enumeration values that specifies the rules for the search. - /// The delegate that creates your custom exception. and are passed to this delegate. + /// The delegate that creates your custom exception. , , and are passed to this delegate. /// /// Your custom exception thrown when does not start with , /// or when is null, @@ -855,7 +855,7 @@ public static string MustNotStartWith( /// The string to be checked. /// The other string that must not start with. /// One of the enumeration values that specifies the rules for the search. - /// The delegate that creates your custom exception. and are passed to this delegate. + /// The delegate that creates your custom exception. , , and are passed to this delegate. /// /// Your custom exception thrown when does not start with , /// or when is null, @@ -938,7 +938,7 @@ public static string MustEndWith( /// The string to be checked. /// The other string must end with. /// One of the enumeration values that specifies the rules for the search. - /// The delegate that creates your custom exception. and are passed to this delegate. + /// The delegate that creates your custom exception. , , and are passed to this delegate. /// /// Your custom exception thrown when does not end with , /// or when is null, From 790235100bf893a8a32bfc4bd47248c1e4a9e77d Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 27 Oct 2024 18:55:16 +0100 Subject: [PATCH 95/97] feat: add ExclusiveBetween and InclusiveBetween for Ranges Signed-off-by: Kenny Pflug --- .../ComparableAssertions/RangeTests.cs | 74 ++++++++++++++++++- Code/Light.GuardClauses/Range.cs | 26 ++++++- 2 files changed, 96 insertions(+), 4 deletions(-) diff --git a/Code/Light.GuardClauses.Tests/ComparableAssertions/RangeTests.cs b/Code/Light.GuardClauses.Tests/ComparableAssertions/RangeTests.cs index 3b81b9fb..e2a848bf 100644 --- a/Code/Light.GuardClauses.Tests/ComparableAssertions/RangeTests.cs +++ b/Code/Light.GuardClauses.Tests/ComparableAssertions/RangeTests.cs @@ -55,6 +55,78 @@ public static void ConstructorException(int from, int to) .Message.Should().Contain($"{nameof(to)} must not be less than {from}, but it actually is {to}."); } + [Theory] + [InlineData(0, 10, 0)] // Lower boundary + [InlineData(0, 10, 5)] // Middle value + [InlineData(0, 10, 10)] // Upper boundary + public static void InclusiveBetween_ValuesInRange(int from, int to, int value) + { + var range = Range.InclusiveBetween(from, to); + + var result = range.IsValueWithinRange(value); + + result.Should().BeTrue(); + } + + [Theory] + [InlineData(0, 10, -1)] // Below range + [InlineData(0, 10, 11)] // Above range + public static void InclusiveBetween_ValuesOutOfRange(int from, int to, int value) + { + var range = Range.InclusiveBetween(from, to); + + var result = range.IsValueWithinRange(value); + + result.Should().BeFalse(); + } + + [Theory] + [InlineData(0, 10, 1)] // Just above lower boundary + [InlineData(0, 10, 5)] // Middle value + [InlineData(0, 10, 9)] // Just below upper boundary + public static void ExclusiveBetween_ValuesInRange(int from, int to, int value) + { + var range = Range.ExclusiveBetween(from, to); + + var result = range.IsValueWithinRange(value); + + result.Should().BeTrue(); + } + + [Theory] + [InlineData(0, 10, 0)] // Lower boundary + [InlineData(0, 10, 10)] // Upper boundary + [InlineData(0, 10, -1)] // Below range + [InlineData(0, 10, 11)] // Above range + public static void ExclusiveBetween_ValuesOutOfRange(int from, int to, int value) + { + var range = Range.ExclusiveBetween(from, to); + + var result = range.IsValueWithinRange(value); + + result.Should().BeFalse(); + } + + [Theory] + [InlineData(10, 5)] // To less than From + [InlineData(-5, -10)] // Negative To less than From + public static void InclusiveBetween_InvalidRange_ThrowsException(int from, int to) + { + Action inclusiveAct = () => Range.InclusiveBetween(from, to); + inclusiveAct.Should().Throw() + .And.Message.Should().Contain($"{nameof(to)} must not be less than {from}"); + } + + [Theory] + [InlineData(10, 5)] // To less than From + [InlineData(-5, -10)] // Negative To less than From + public static void ExclusiveBetween_InvalidRange_ThrowsException(int from, int to) + { + Action exclusiveAct = () => Range.ExclusiveBetween(from, to); + exclusiveAct.Should().Throw() + .And.Message.Should().Contain($"{nameof(to)} must not be less than {from}"); + } + [Theory] [MemberData(nameof(Collections))] public static void RangeForCollections(IEnumerable enumerable) @@ -164,4 +236,4 @@ public static void RangeForReadOnlySpan(Memory memory) Enumerable.Range(1, 500).ToArray(), Array.Empty() }; -} \ No newline at end of file +} diff --git a/Code/Light.GuardClauses/Range.cs b/Code/Light.GuardClauses/Range.cs index 1ecfe47e..623df259 100644 --- a/Code/Light.GuardClauses/Range.cs +++ b/Code/Light.GuardClauses/Range.cs @@ -133,7 +133,7 @@ public override string ToString() => $"Range from {CreateRangeDescriptionText()}"; /// - /// Returns either "inclusive" or "exclusive", depending whether is true or false. + /// Returns either "inclusive" or "exclusive", depending on whether is true or false. /// public string LowerBoundaryText { @@ -142,7 +142,7 @@ public string LowerBoundaryText } /// - /// Returns either "inclusive" or "exclusive", depending whether is true or false. + /// Returns either "inclusive" or "exclusive", depending on whether is true or false. /// public string UpperBoundaryText { @@ -216,6 +216,26 @@ public static class Range [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Range.RangeFromInfo FromExclusive(T value) where T : IComparable => new (value, false); + /// + /// Creates a range with both boundaries inclusive. + /// + /// The lower boundary of the range. + /// The upper boundary of the range. + /// A new range with both boundaries inclusive. + /// Thrown when is less than . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Range InclusiveBetween(T from, T to) where T : IComparable => new (from, to); + + /// + /// Creates a range with both boundaries exclusive. + /// + /// The lower boundary of the range. + /// The upper boundary of the range. + /// A new range with both boundaries exclusive. + /// Thrown when is less than . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Range ExclusiveBetween(T from, T to) where T : IComparable => new (from, to, false, false); + /// /// Creates a range for the specified enumerable that encompasses all valid indexes. /// @@ -288,4 +308,4 @@ public static Range For(ReadOnlyMemory memory) => [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Range For(ArraySegment segment) => new (0, segment.Count, isFromInclusive: true, isToInclusive: false); -} \ No newline at end of file +} From 8b7d8f705d562b595a74d2a295af50aa17f05654 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 27 Oct 2024 19:24:59 +0100 Subject: [PATCH 96/97] feat: prepare SourceCodeTransformation project for v12.0 release Signed-off-by: Kenny Pflug --- .../Light.GuardClauses.Source.csproj | 4 ++-- .../SourceFileMerger.cs | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Code/Light.GuardClauses.Source/Light.GuardClauses.Source.csproj b/Code/Light.GuardClauses.Source/Light.GuardClauses.Source.csproj index b30140ed..229eeab9 100644 --- a/Code/Light.GuardClauses.Source/Light.GuardClauses.Source.csproj +++ b/Code/Light.GuardClauses.Source/Light.GuardClauses.Source.csproj @@ -1,8 +1,8 @@  - netstandard2.0 - 10.0 + netstandard2.0 + 12.0 Kenny Pflug Kenny Pflug Copyright © Kenny Pflug 2016 - 2023 diff --git a/Code/Light.GuardClauses.SourceCodeTransformation/SourceFileMerger.cs b/Code/Light.GuardClauses.SourceCodeTransformation/SourceFileMerger.cs index 78f6bba3..6ceb25d7 100644 --- a/Code/Light.GuardClauses.SourceCodeTransformation/SourceFileMerger.cs +++ b/Code/Light.GuardClauses.SourceCodeTransformation/SourceFileMerger.cs @@ -34,7 +34,7 @@ public static void CreateSingleSourceFile(SourceFileMergeOptions options) .AppendLine($@"License information for Light.GuardClauses The MIT License (MIT) -Copyright (c) 2016, 2023 Kenny Pflug mailto:kenny.pflug@live.de +Copyright (c) 2016, 2024 Kenny Pflug mailto:kenny.pflug@live.de Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal @@ -69,6 +69,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE using System.Text.RegularExpressions; {(options.IncludeJetBrainsAnnotationsUsing ? "using JetBrains.Annotations;" + Environment.NewLine : string.Empty)}using {options.BaseNamespace}.Exceptions; using {options.BaseNamespace}.FrameworkExtensions; +{(options.IncludeJetBrainsAnnotationsUsing ? "using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute;" : "")} #nullable enable annotations From cb87ede1497f8e869bb420270c2ab0cf952bad71 Mon Sep 17 00:00:00 2001 From: Kenny Pflug Date: Sun, 27 Oct 2024 19:30:57 +0100 Subject: [PATCH 97/97] docs: update readme and package release notes for v12.0 Signed-off-by: Kenny Pflug --- Code/Light.GuardClauses/Light.GuardClauses.csproj | 12 ++++++------ Code/Version.props | 2 +- README.md | 8 ++++---- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Code/Light.GuardClauses/Light.GuardClauses.csproj b/Code/Light.GuardClauses/Light.GuardClauses.csproj index 6d29b410..2d7d6dcb 100644 --- a/Code/Light.GuardClauses/Light.GuardClauses.csproj +++ b/Code/Light.GuardClauses/Light.GuardClauses.csproj @@ -9,7 +9,7 @@ Kenny Pflug enable true - Copyright © Kenny Pflug 2016, 2023 + Copyright © Kenny Pflug 2016, 2024 12 true true @@ -26,12 +26,12 @@ true README.md -Light.GuardClauses 11.0.0 +Light.GuardClauses 12.0.0 -------------------------------- -- Light.GuardClauses now targets .NET 8 and is AOT-compatible -- breaking: EnumInfo<T> no longer has the UnderlyingType property -- In AOT scenarios, avoid the Type-related assertions, they are marked with the DynamicallyAccessedMembersAttribute +- Added support for NotNullAttribute +- Added Range.InclusiveBetween and Range.ExclusiveBetween to create Range instances even more easily +- breaking: String assertions that use a StringComparison parameter now throw an ArgumentException instead of forwarding an invalid value to the exception factory @@ -39,7 +39,7 @@ Light.GuardClauses 11.0.0 - + diff --git a/Code/Version.props b/Code/Version.props index 0bedeec5..1914f2fb 100644 --- a/Code/Version.props +++ b/Code/Version.props @@ -1,5 +1,5 @@  - 11.0.0 + 12.0.0 \ No newline at end of file diff --git a/README.md b/README.md index fae62157..dc3ed066 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ **A lightweight .NET library for expressive Guard Clauses.** [![License](https://img.shields.io/badge/License-MIT-green.svg?style=for-the-badge)](https://github.com/feO2x/Light.GuardClauses/blob/master/LICENSE) -[![NuGet](https://img.shields.io/badge/NuGet-11.0.0-blue.svg?style=for-the-badge)](https://www.nuget.org/packages/Light.GuardClauses/) -[![Source Code](https://img.shields.io/badge/Source%20Code-11.0.0-blue.svg?style=for-the-badge)](https://github.com/feO2x/Light.GuardClauses/blob/master/Light.GuardClauses.SingleFile.cs) +[![NuGet](https://img.shields.io/badge/NuGet-12.0.0-blue.svg?style=for-the-badge)](https://www.nuget.org/packages/Light.GuardClauses/) +[![Source Code](https://img.shields.io/badge/Source%20Code-12.0.0-blue.svg?style=for-the-badge)](https://github.com/feO2x/Light.GuardClauses/blob/master/Light.GuardClauses.SingleFile.cs) [![Documentation](https://img.shields.io/badge/Docs-Wiki-yellowgreen.svg?style=for-the-badge)](https://github.com/feO2x/Light.GuardClauses/wiki) [![Documentation](https://img.shields.io/badge/Docs-Changelog-yellowgreen.svg?style=for-the-badge)](https://github.com/feO2x/Light.GuardClauses/releases) @@ -60,7 +60,7 @@ public class ConsoleWriter public void SetMovieRating(Guid movieId, int numberOfStars) { movieId.MustNotBeEmpty(); - numberOfStars.MustBeIn(Range.FromInclusive(0).ToInclusive(5)); + numberOfStars.MustBeIn(Range.InclusiveBetween(0, 5)); var movie = _movieRepo.GetById(movieId); movie.AddRating(numberOfStars); @@ -114,7 +114,7 @@ Light.GuardClauses is available as a [NuGet package](https://www.nuget.org/packa - **dotnet CLI**: `dotnet add package Light.GuardClauses` - **Visual Studio Package Manager Console**: `Install-Package Light.GuardClauses` -- **Package Reference in csproj**: `` +- **Package Reference in csproj**: `` Also, you can incorporate Light.GuardClauses as a **single source file** where the API is changed to `internal`. This is especially interesting for framework / library developers that do not want to have a dependency on the Light.GuardClauses DLL. You can grab the default .NET Standard 2.0 version in [Light.GuardClauses.SingleFile.cs](https://github.com/feO2x/Light.GuardClauses/blob/master/Light.GuardClauses.SingleFile.cs) or you can use the [Light.GuardClauses.SourceCodeTransformation](https://github.com/feO2x/Light.GuardClauses/tree/master/Code/Light.GuardClauses.SourceCodeTransformation) project to create your custom file. You can learn more about it [here](https://github.com/feO2x/Light.GuardClauses/wiki/Including-Light.GuardClauses-as-source-code).