From f18e992a4a2394498a71b7b81587cadef9b203ba Mon Sep 17 00:00:00 2001 From: Meir Blachman Date: Sun, 1 Oct 2023 09:02:27 +0300 Subject: [PATCH 1/3] add support for xunit StringAsserts EndsWith --- .../Tips/XunitTests.cs | 14 +++++ src/FluentAssertions.Analyzers/Constants.cs | 1 + .../Tips/Xunit/AssertEndsWith.cs | 57 +++++++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 src/FluentAssertions.Analyzers/Tips/Xunit/AssertEndsWith.cs diff --git a/src/FluentAssertions.Analyzers.Tests/Tips/XunitTests.cs b/src/FluentAssertions.Analyzers.Tests/Tips/XunitTests.cs index b2cb2e76..a4a7439e 100644 --- a/src/FluentAssertions.Analyzers.Tests/Tips/XunitTests.cs +++ b/src/FluentAssertions.Analyzers.Tests/Tips/XunitTests.cs @@ -438,6 +438,20 @@ public void AssertEmpty_String_TestAnalyzer(string assertion) => public void AssertEmpty_String_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFix("string actual", oldAssertion, newAssertion); + [DataTestMethod] + [DataRow("Assert.EndsWith(expected, actual);")] + [Implemented] + public void AssertEndsWith_TestAnalyzer(string assertion) => + VerifyCSharpDiagnostic("string actual, string expected", assertion); + + [DataTestMethod] + [DataRow( + /* oldAssertion: */ "Assert.EndsWith(expected, actual);", + /* newAssertion: */ "actual.Should().EndWith(expected);")] + [Implemented] + public void AssertEndsWith_TestCodeFix(string oldAssertion, string newAssertion) + => VerifyCSharpFix("string actual, string expected", oldAssertion, newAssertion); + private void VerifyCSharpDiagnostic(string methodArguments, string assertion) where TDiagnosticAnalyzer : Microsoft.CodeAnalysis.Diagnostics.DiagnosticAnalyzer, new() { var source = GenerateCode.XunitAssertion(methodArguments, assertion); diff --git a/src/FluentAssertions.Analyzers/Constants.cs b/src/FluentAssertions.Analyzers/Constants.cs index 8e54a6a4..c9b3efb6 100644 --- a/src/FluentAssertions.Analyzers/Constants.cs +++ b/src/FluentAssertions.Analyzers/Constants.cs @@ -134,6 +134,7 @@ public static class Xunit public const string AssertMatches = $"{DiagnosticProperties.IdPrefix}0712"; public const string AssertDoesNotMatch = $"{DiagnosticProperties.IdPrefix}0713"; public const string AssertEmpty = $"{DiagnosticProperties.IdPrefix}0714"; + public const string AssertEndsWith = $"{DiagnosticProperties.IdPrefix}0715"; } } diff --git a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertEndsWith.cs b/src/FluentAssertions.Analyzers/Tips/Xunit/AssertEndsWith.cs new file mode 100644 index 00000000..880ce0b7 --- /dev/null +++ b/src/FluentAssertions.Analyzers/Tips/Xunit/AssertEndsWith.cs @@ -0,0 +1,57 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Composition; +using FluentAssertions.Analyzers.Utilities; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace FluentAssertions.Analyzers.Xunit; + +[DiagnosticAnalyzer(LanguageNames.CSharp)] +public class AssertEndsWithAnalyzer : XunitAnalyzer +{ + public const string DiagnosticId = Constants.Tips.Xunit.AssertEndsWith; + public const string Category = Constants.Tips.Category; + + public const string Message = "Use .Should().NotMatchRegex()"; + + protected override DiagnosticDescriptor Rule => new(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); + + protected override IEnumerable Visitors => new FluentAssertionsCSharpSyntaxVisitor[] + { + new AssertEndsWithStringSyntaxVisitor() + }; + + //public static void EndsWith(string? expectedEndString, string? actualString) + public class AssertEndsWithStringSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor + { + public AssertEndsWithStringSyntaxVisitor() : base( + MemberValidator.ArgumentsMatch("EndsWith", + ArgumentValidator.IsType(TypeSelector.GetStringType), + ArgumentValidator.IsType(TypeSelector.GetStringType)) + ) + { + } + } +} + +[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertEndsWithCodeFix)), Shared] +public class AssertEndsWithCodeFix : XunitCodeFixProvider +{ + public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(AssertEndsWithAnalyzer.DiagnosticId); + + protected override ExpressionSyntax GetNewExpression( + ExpressionSyntax expression, + FluentAssertionsDiagnosticProperties properties) + { + switch (properties.VisitorName) + { + case nameof(AssertEndsWithAnalyzer.AssertEndsWithStringSyntaxVisitor): + return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "EndsWith", "EndWith"); + default: + throw new System.InvalidOperationException($"Invalid visitor name - {properties.VisitorName}"); + } + } +} \ No newline at end of file From 8492a7f79542d4cf320df6b2b8e7258b25340543 Mon Sep 17 00:00:00 2001 From: Meir Blachman Date: Sun, 1 Oct 2023 09:05:51 +0300 Subject: [PATCH 2/3] add support for xunit StringAsserts EndsWith --- src/FluentAssertions.Analyzers/Tips/Xunit/AssertEmpty.cs | 2 +- src/FluentAssertions.Analyzers/Tips/Xunit/AssertEndsWith.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertEmpty.cs b/src/FluentAssertions.Analyzers/Tips/Xunit/AssertEmpty.cs index 661e592b..d0e73f2b 100644 --- a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertEmpty.cs +++ b/src/FluentAssertions.Analyzers/Tips/Xunit/AssertEmpty.cs @@ -15,7 +15,7 @@ public class AssertEmptyAnalyzer : XunitAnalyzer public const string DiagnosticId = Constants.Tips.Xunit.AssertEmpty; public const string Category = Constants.Tips.Category; - public const string Message = "Use .Should().NotMatchRegex()"; + public const string Message = "Use .Should().BeEmpty()"; protected override DiagnosticDescriptor Rule => new(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); diff --git a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertEndsWith.cs b/src/FluentAssertions.Analyzers/Tips/Xunit/AssertEndsWith.cs index 880ce0b7..82c43812 100644 --- a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertEndsWith.cs +++ b/src/FluentAssertions.Analyzers/Tips/Xunit/AssertEndsWith.cs @@ -15,7 +15,7 @@ public class AssertEndsWithAnalyzer : XunitAnalyzer public const string DiagnosticId = Constants.Tips.Xunit.AssertEndsWith; public const string Category = Constants.Tips.Category; - public const string Message = "Use .Should().NotMatchRegex()"; + public const string Message = "Use .Should().EndWith()"; protected override DiagnosticDescriptor Rule => new(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); @@ -49,7 +49,7 @@ protected override ExpressionSyntax GetNewExpression( switch (properties.VisitorName) { case nameof(AssertEndsWithAnalyzer.AssertEndsWithStringSyntaxVisitor): - return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "EndsWith", "EndWith"); + return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "EndsWith", "EndWith"); default: throw new System.InvalidOperationException($"Invalid visitor name - {properties.VisitorName}"); } From 4e29cc0cd228df2f41c0eb6574bc77a8b42da22c Mon Sep 17 00:00:00 2001 From: Meir Blachman Date: Sun, 1 Oct 2023 09:07:49 +0300 Subject: [PATCH 3/3] add support for xunit StringAsserts EndsWith --- src/FluentAssertions.Analyzers.Tests/Tips/XunitTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/FluentAssertions.Analyzers.Tests/Tips/XunitTests.cs b/src/FluentAssertions.Analyzers.Tests/Tips/XunitTests.cs index a4a7439e..8487de4d 100644 --- a/src/FluentAssertions.Analyzers.Tests/Tips/XunitTests.cs +++ b/src/FluentAssertions.Analyzers.Tests/Tips/XunitTests.cs @@ -442,7 +442,7 @@ public void AssertEmpty_String_TestCodeFix(string oldAssertion, string newAssert [DataRow("Assert.EndsWith(expected, actual);")] [Implemented] public void AssertEndsWith_TestAnalyzer(string assertion) => - VerifyCSharpDiagnostic("string actual, string expected", assertion); + VerifyCSharpDiagnostic("string actual, string expected", assertion); [DataTestMethod] [DataRow( @@ -450,7 +450,7 @@ public void AssertEndsWith_TestAnalyzer(string assertion) => /* newAssertion: */ "actual.Should().EndWith(expected);")] [Implemented] public void AssertEndsWith_TestCodeFix(string oldAssertion, string newAssertion) - => VerifyCSharpFix("string actual, string expected", oldAssertion, newAssertion); + => VerifyCSharpFix("string actual, string expected", oldAssertion, newAssertion); private void VerifyCSharpDiagnostic(string methodArguments, string assertion) where TDiagnosticAnalyzer : Microsoft.CodeAnalysis.Diagnostics.DiagnosticAnalyzer, new() {