From f57940c3b77d8c7410b62027fb1561458a50bcc1 Mon Sep 17 00:00:00 2001 From: Manfred Brands Date: Thu, 16 Nov 2023 17:16:28 +0800 Subject: [PATCH] Add support for Assert.MultipleAsync This affects: - DereferencePossiblyNullReferenceSuppressor - UseAssertMultipleAnalyzer --- .../Constants/NUnitFrameworkConstantsTests.cs | 5 ++++ ...ncePossiblyNullReferenceSuppressorTests.cs | 23 +++++++++++++++++++ .../UseAssertMultipleAnalyzerTests.cs | 20 ++++++++++++++++ .../Constants/NUnitFrameworkConstants.cs | 1 + ...eferencePossiblyNullReferenceSuppressor.cs | 2 +- src/nunit.analyzers/Helpers/AssertHelper.cs | 2 +- 6 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/nunit.analyzers.tests/Constants/NUnitFrameworkConstantsTests.cs b/src/nunit.analyzers.tests/Constants/NUnitFrameworkConstantsTests.cs index 0fed2337..8b45e271 100644 --- a/src/nunit.analyzers.tests/Constants/NUnitFrameworkConstantsTests.cs +++ b/src/nunit.analyzers.tests/Constants/NUnitFrameworkConstantsTests.cs @@ -69,6 +69,11 @@ public sealed class NUnitFrameworkConstantsTests (nameof(NUnitFrameworkConstants.NameOfHasMember), nameof(Has.Member)), (nameof(NUnitFrameworkConstants.NameOfMultiple), nameof(Assert.Multiple)), +#if NUNIT4 + (nameof(NUnitFrameworkConstants.NameOfMultipleAsync), nameof(Assert.MultipleAsync)), +#else + (nameof(NUnitFrameworkConstants.NameOfMultipleAsync), "MultipleAsync"), +#endif (nameof(NUnitFrameworkConstants.NameOfThrows), nameof(Throws)), (nameof(NUnitFrameworkConstants.NameOfThrowsArgumentException), nameof(Throws.ArgumentException)), diff --git a/src/nunit.analyzers.tests/DiagnosticSuppressors/DereferencePossiblyNullReferenceSuppressorTests.cs b/src/nunit.analyzers.tests/DiagnosticSuppressors/DereferencePossiblyNullReferenceSuppressorTests.cs index 927a7c07..441e48ab 100644 --- a/src/nunit.analyzers.tests/DiagnosticSuppressors/DereferencePossiblyNullReferenceSuppressorTests.cs +++ b/src/nunit.analyzers.tests/DiagnosticSuppressors/DereferencePossiblyNullReferenceSuppressorTests.cs @@ -362,6 +362,29 @@ public void Test(string? s) testCode); } +#if NUNIT4 + [Test] + public void InsideAssertMultipleAsync() + { + var testCode = TestUtility.WrapMethodInClassNamespaceAndAddUsings(@$" + [TestCase("""")] + public async Task Test(string? s) + {{ + await Assert.MultipleAsync(async () => + {{ + await Task.Yield(); + ClassicAssert.NotNull(s); + Assert.That(↓s.Length, Is.GreaterThan(0)); + }}); + }} + "); + + RoslynAssert.NotSuppressed(suppressor, + ExpectedDiagnostic.Create(DereferencePossiblyNullReferenceSuppressor.SuppressionDescriptors["CS8602"]), + testCode); + } +#endif + [TestCase("ClassicAssert.True(nullable.HasValue)")] [TestCase("ClassicAssert.IsTrue(nullable.HasValue)")] [TestCase("Assert.That(nullable.HasValue, \"Ensure Value is set\")")] diff --git a/src/nunit.analyzers.tests/UseAssertMultiple/UseAssertMultipleAnalyzerTests.cs b/src/nunit.analyzers.tests/UseAssertMultiple/UseAssertMultipleAnalyzerTests.cs index 5d8deeb6..3e9cf603 100644 --- a/src/nunit.analyzers.tests/UseAssertMultiple/UseAssertMultipleAnalyzerTests.cs +++ b/src/nunit.analyzers.tests/UseAssertMultiple/UseAssertMultipleAnalyzerTests.cs @@ -27,6 +27,26 @@ public void Test() RoslynAssert.Valid(this.analyzer, testCode); } +#if NUNIT4 + [Test] + public void AnalyzeWhenMultipleAsyncIsUsed() + { + var testCode = TestUtility.WrapMethodInClassNamespaceAndAddUsings(@" + public async Task Test() + { + await Assert.MultipleAsync(async () => + { + Assert.That(await Get1(), Is.Not.Null); + Assert.That(await Get2(), Is.Not.Null); + }); + + static Task Get1() => Task.FromResult(default(string)); + static Task Get2() => Task.FromResult(default(string)); + }"); + RoslynAssert.Valid(this.analyzer, testCode); + } +#endif + [Test] public void AnalyzeWhenDependent() { diff --git a/src/nunit.analyzers/Constants/NUnitFrameworkConstants.cs b/src/nunit.analyzers/Constants/NUnitFrameworkConstants.cs index ee52c578..9e7999fe 100644 --- a/src/nunit.analyzers/Constants/NUnitFrameworkConstants.cs +++ b/src/nunit.analyzers/Constants/NUnitFrameworkConstants.cs @@ -50,6 +50,7 @@ public static class NUnitFrameworkConstants public const string NameOfHasMember = "Member"; public const string NameOfMultiple = "Multiple"; + public const string NameOfMultipleAsync = "MultipleAsync"; public const string NameOfThrows = "Throws"; public const string NameOfThrowsArgumentException = "ArgumentException"; diff --git a/src/nunit.analyzers/DiagnosticSuppressors/DereferencePossiblyNullReferenceSuppressor.cs b/src/nunit.analyzers/DiagnosticSuppressors/DereferencePossiblyNullReferenceSuppressor.cs index 25d3596c..6b9b197f 100644 --- a/src/nunit.analyzers/DiagnosticSuppressors/DereferencePossiblyNullReferenceSuppressor.cs +++ b/src/nunit.analyzers/DiagnosticSuppressors/DereferencePossiblyNullReferenceSuppressor.cs @@ -357,7 +357,7 @@ private static bool IsValidatedNotNullByExpression(string possibleNullReference, return true; } } - else if (member == NUnitFrameworkConstants.NameOfMultiple) + else if (member is NUnitFrameworkConstants.NameOfMultiple or NUnitFrameworkConstants.NameOfMultipleAsync) { // Look up into the actual asserted parameter if (argumentList.Arguments.FirstOrDefault()?.Expression is AnonymousFunctionExpressionSyntax anonymousFunction) diff --git a/src/nunit.analyzers/Helpers/AssertHelper.cs b/src/nunit.analyzers/Helpers/AssertHelper.cs index 2f5de7f1..4138f3bb 100644 --- a/src/nunit.analyzers/Helpers/AssertHelper.cs +++ b/src/nunit.analyzers/Helpers/AssertHelper.cs @@ -99,7 +99,7 @@ public static bool IsInsideAssertMultiple(SyntaxNode node) while ((possibleAssertMultiple = node.Ancestors().OfType().FirstOrDefault()) is not null) { // Is the statement inside a Block which is part of an Assert.Multiple. - if (IsAssert(possibleAssertMultiple, NUnitFrameworkConstants.NameOfMultiple)) + if (IsAssert(possibleAssertMultiple, NUnitFrameworkConstants.NameOfMultiple, NUnitFrameworkConstants.NameOfMultipleAsync)) { return true; }