Skip to content

Commit 804395a

Browse files
Detect using (Assert.EnterMultipleScope()) as an Assert.Multiple context.
1 parent 568d5ea commit 804395a

File tree

4 files changed

+57
-5
lines changed

4 files changed

+57
-5
lines changed

src/nunit.analyzers.tests/Constants/NUnitFrameworkConstantsTests.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,10 @@ public sealed class NUnitFrameworkConstantsTests
7474
(nameof(NUnitFrameworkConstants.NameOfMultiple), nameof(Assert.Multiple)),
7575
#if NUNIT4
7676
(nameof(NUnitFrameworkConstants.NameOfMultipleAsync), nameof(Assert.MultipleAsync)),
77+
(nameof(NUnitFrameworkConstants.NameOfEnterMultipleScope), nameof(Assert.EnterMultipleScope)),
7778
#else
7879
(nameof(NUnitFrameworkConstants.NameOfMultipleAsync), "MultipleAsync"),
80+
(nameof(NUnitFrameworkConstants.NameOfEnterMultipleScope), "EnterMultipleScope"),
7981
#endif
8082

8183
(nameof(NUnitFrameworkConstants.NameOfOut), nameof(TestContext.Out)),

src/nunit.analyzers.tests/UseAssertMultiple/UseAssertMultipleAnalyzerTests.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,38 @@ await Assert.MultipleAsync(async () =>
4545
}");
4646
RoslynAssert.Valid(this.analyzer, testCode);
4747
}
48+
49+
#if WOULD_SOMEONE_ACTUALLY_USE_THIS
50+
[Test]
51+
public void AnalyzeWhenMultipleScopeDeclarationIsUsed()
52+
{
53+
var testCode = TestUtility.WrapMethodInClassNamespaceAndAddUsings(@"
54+
public void Test()
55+
{
56+
using IDisposable disposable = Assert.EnterMultipleScope();
57+
58+
Assert.That(true, Is.True);
59+
disposable.Dispose();
60+
Assert.That(false, Is.False);
61+
}");
62+
RoslynAssert.Valid(this.analyzer, testCode);
63+
}
64+
#endif
65+
66+
[Test]
67+
public void AnalyzeWhenMultipleScopeStatementIsUsed()
68+
{
69+
var testCode = TestUtility.WrapMethodInClassNamespaceAndAddUsings(@"
70+
public void Test()
71+
{
72+
using (Assert.EnterMultipleScope())
73+
{
74+
Assert.That(true, Is.True);
75+
Assert.That(false, Is.False);
76+
}
77+
}");
78+
RoslynAssert.Valid(this.analyzer, testCode);
79+
}
4880
#endif
4981

5082
[Test]

src/nunit.analyzers/Constants/NUnitFrameworkConstants.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ public static class NUnitFrameworkConstants
5353

5454
public const string NameOfMultiple = "Multiple";
5555
public const string NameOfMultipleAsync = "MultipleAsync";
56+
public const string NameOfEnterMultipleScope = "EnterMultipleScope";
5657

5758
public const string NameOfOut = "Out";
5859
public const string NameOfWrite = "Write";

src/nunit.analyzers/Helpers/AssertHelper.cs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,18 +95,35 @@ public static bool IsLiteralOperation(IOperation operation)
9595
/// </summary>
9696
public static bool IsInsideAssertMultiple(SyntaxNode node)
9797
{
98-
InvocationExpressionSyntax? possibleAssertMultiple;
99-
100-
while ((possibleAssertMultiple = node.Ancestors().OfType<InvocationExpressionSyntax>().FirstOrDefault()) is not null)
98+
// Look for Assert.Multiple(delegate) invocation.
99+
SyntaxNode currentNode = node;
100+
InvocationExpressionSyntax? possibleAssertMultipleInvocation;
101+
while ((possibleAssertMultipleInvocation = currentNode.Ancestors().OfType<InvocationExpressionSyntax>().FirstOrDefault()) is not null)
101102
{
102103
// Is the statement inside a Block which is part of an Assert.Multiple.
103-
if (IsAssert(possibleAssertMultiple, NUnitFrameworkConstants.NameOfMultiple, NUnitFrameworkConstants.NameOfMultipleAsync))
104+
if (IsAssert(possibleAssertMultipleInvocation, NUnitFrameworkConstants.NameOfMultiple, NUnitFrameworkConstants.NameOfMultipleAsync))
105+
{
106+
return true;
107+
}
108+
109+
// Keep looking at possible parent nested expression.
110+
currentNode = possibleAssertMultipleInvocation;
111+
}
112+
113+
// Look for using (Assert.EnterMultipleScope()) invocation.
114+
currentNode = node;
115+
UsingStatementSyntax? usingStatement;
116+
while ((usingStatement = currentNode.Ancestors().OfType<UsingStatementSyntax>().FirstOrDefault()) is not null)
117+
{
118+
// Is the using expression an Assert.EnterMultipleScope.
119+
if (usingStatement.Expression is InvocationExpressionSyntax usingInvocation &&
120+
IsAssert(usingInvocation, NUnitFrameworkConstants.NameOfEnterMultipleScope))
104121
{
105122
return true;
106123
}
107124

108125
// Keep looking at possible parent nested expression.
109-
node = possibleAssertMultiple;
126+
currentNode = usingStatement;
110127
}
111128

112129
return false;

0 commit comments

Comments
 (0)