Skip to content

Commit 59b7b3b

Browse files
authored
feat: add xunit Null assertions (#191)
1 parent 4413adc commit 59b7b3b

File tree

4 files changed

+121
-0
lines changed

4 files changed

+121
-0
lines changed

src/FluentAssertions.Analyzers.Tests/Tips/XunitTests.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,33 @@ public void AssertObjectNotStrictEqual_TestAnalyzer(string assertion) =>
312312
public void AssertObjectNotStrictEqual_TestCodeFix(string oldAssertion, string newAssertion)
313313
=> VerifyCSharpFix<AssertNotStrictEqualCodeFix, AssertNotStrictEqualAnalyzer>("object actual, object expected", oldAssertion, newAssertion);
314314

315+
[DataTestMethod]
316+
[DataRow("Assert.Null(actual);")]
317+
[Implemented]
318+
public void AssertNull_TestAnalyzer(string assertion) =>
319+
VerifyCSharpDiagnostic<AssertNullAnalyzer>("object actual", assertion);
320+
321+
[DataTestMethod]
322+
[DataRow(
323+
/* oldAssertion: */ "Assert.Null(actual);",
324+
/* newAssertion: */ "actual.Should().BeNull();")]
325+
[Implemented]
326+
public void AssertNull_TestCodeFix(string oldAssertion, string newAssertion)
327+
=> VerifyCSharpFix<AssertNullCodeFix, AssertNullAnalyzer>("object actual", oldAssertion, newAssertion);
328+
329+
[DataTestMethod]
330+
[DataRow("Assert.NotNull(actual);")]
331+
[Implemented]
332+
public void AssertNotNull_TestAnalyzer(string assertion) =>
333+
VerifyCSharpDiagnostic<AssertNotNullAnalyzer>("object actual", assertion);
334+
335+
[DataTestMethod]
336+
[DataRow(
337+
/* oldAssertion: */ "Assert.NotNull(actual);",
338+
/* newAssertion: */ "actual.Should().NotBeNull();")]
339+
[Implemented]
340+
public void AssertNotNull_TestCodeFix(string oldAssertion, string newAssertion)
341+
=> VerifyCSharpFix<AssertNotNullCodeFix, AssertNotNullAnalyzer>("object actual", oldAssertion, newAssertion);
315342

316343
private void VerifyCSharpDiagnostic<TDiagnosticAnalyzer>(string methodArguments, string assertion) where TDiagnosticAnalyzer : Microsoft.CodeAnalysis.Diagnostics.DiagnosticAnalyzer, new()
317344
{

src/FluentAssertions.Analyzers/Constants.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ public static class Xunit
127127
public const string AssertStrictEqual = $"{DiagnosticProperties.IdPrefix}0705";
128128
public const string AssertNotEqual = $"{DiagnosticProperties.IdPrefix}0706";
129129
public const string AssertNotStrictEqual = $"{DiagnosticProperties.IdPrefix}0707";
130+
public const string AssertNull = $"{DiagnosticProperties.IdPrefix}0708";
131+
public const string AssertNotNull = $"{DiagnosticProperties.IdPrefix}0709";
130132
}
131133
}
132134

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using Microsoft.CodeAnalysis;
2+
using Microsoft.CodeAnalysis.CodeFixes;
3+
using Microsoft.CodeAnalysis.CSharp.Syntax;
4+
using Microsoft.CodeAnalysis.Diagnostics;
5+
using System.Collections.Generic;
6+
using System.Collections.Immutable;
7+
using System.Composition;
8+
9+
namespace FluentAssertions.Analyzers.Xunit
10+
{
11+
[DiagnosticAnalyzer(LanguageNames.CSharp)]
12+
public class AssertNotNullAnalyzer : XunitAnalyzer
13+
{
14+
public const string DiagnosticId = Constants.Tips.Xunit.AssertNotNull;
15+
public const string Category = Constants.Tips.Category;
16+
17+
public const string Message = "Use .Should().NotBeNull() instead.";
18+
19+
protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true);
20+
protected override IEnumerable<FluentAssertionsCSharpSyntaxVisitor> Visitors
21+
{
22+
get
23+
{
24+
yield return new AssertNotNullSyntaxVisitor();
25+
}
26+
}
27+
28+
public class AssertNotNullSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor
29+
{
30+
public AssertNotNullSyntaxVisitor() : base(new MemberValidator("NotNull"))
31+
{
32+
}
33+
}
34+
}
35+
36+
[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertNotNullCodeFix)), Shared]
37+
public class AssertNotNullCodeFix : XunitCodeFixProvider
38+
{
39+
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(AssertNotNullAnalyzer.DiagnosticId);
40+
41+
protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties)
42+
{
43+
return RenameMethodAndReplaceWithSubjectShould(expression, "NotNull", "NotBeNull");
44+
}
45+
}
46+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using Microsoft.CodeAnalysis;
2+
using Microsoft.CodeAnalysis.CodeFixes;
3+
using Microsoft.CodeAnalysis.CSharp.Syntax;
4+
using Microsoft.CodeAnalysis.Diagnostics;
5+
using System.Collections.Generic;
6+
using System.Collections.Immutable;
7+
using System.Composition;
8+
9+
namespace FluentAssertions.Analyzers.Xunit
10+
{
11+
[DiagnosticAnalyzer(LanguageNames.CSharp)]
12+
public class AssertNullAnalyzer : XunitAnalyzer
13+
{
14+
public const string DiagnosticId = Constants.Tips.Xunit.AssertNull;
15+
public const string Category = Constants.Tips.Category;
16+
17+
public const string Message = "Use .Should().BeNull() instead.";
18+
19+
protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true);
20+
protected override IEnumerable<FluentAssertionsCSharpSyntaxVisitor> Visitors
21+
{
22+
get
23+
{
24+
yield return new AssertNullSyntaxVisitor();
25+
}
26+
}
27+
28+
public class AssertNullSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor
29+
{
30+
public AssertNullSyntaxVisitor() : base(new MemberValidator("Null"))
31+
{
32+
}
33+
}
34+
}
35+
36+
[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertNullCodeFix)), Shared]
37+
public class AssertNullCodeFix : XunitCodeFixProvider
38+
{
39+
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(AssertNullAnalyzer.DiagnosticId);
40+
41+
protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties)
42+
{
43+
return RenameMethodAndReplaceWithSubjectShould(expression, "Null", "BeNull");
44+
}
45+
}
46+
}

0 commit comments

Comments
 (0)