Skip to content

Commit

Permalink
add support for StringAsserts Contains (#221)
Browse files Browse the repository at this point in the history
  • Loading branch information
Meir017 committed Sep 26, 2023
1 parent 88746ae commit 2b6059e
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 0 deletions.
14 changes: 14 additions & 0 deletions src/FluentAssertions.Analyzers.Tests/Tips/XunitTests.cs
Expand Up @@ -340,6 +340,20 @@ public void AssertNull_TestCodeFix(string oldAssertion, string newAssertion)
public void AssertNotNull_TestCodeFix(string oldAssertion, string newAssertion)
=> VerifyCSharpFix<AssertNotNullCodeFix, AssertNotNullAnalyzer>("object actual", oldAssertion, newAssertion);

[DataTestMethod]
[DataRow("Assert.Contains(expected, actual);")]
[Implemented]
public void AssertStringContains_TestAnalyzer(string assertion) =>
VerifyCSharpDiagnostic<AssertContainsAnalyzer>("string actual, string expected", assertion);

[DataTestMethod]
[DataRow(
/* oldAssertion: */ "Assert.Contains(expected, actual);",
/* newAssertion: */ "actual.Should().Contain(expected);")]
[Implemented]
public void AssertStringContains_TestCodeFix(string oldAssertion, string newAssertion)
=> VerifyCSharpFix<AssertContainsCodeFix, AssertContainsAnalyzer>("string actual, string expected", oldAssertion, newAssertion);

private void VerifyCSharpDiagnostic<TDiagnosticAnalyzer>(string methodArguments, string assertion) where TDiagnosticAnalyzer : Microsoft.CodeAnalysis.Diagnostics.DiagnosticAnalyzer, new()
{
var source = GenerateCode.XunitAssertion(methodArguments, assertion);
Expand Down
1 change: 1 addition & 0 deletions src/FluentAssertions.Analyzers/Constants.cs
Expand Up @@ -129,6 +129,7 @@ public static class Xunit
public const string AssertNotStrictEqual = $"{DiagnosticProperties.IdPrefix}0707";
public const string AssertNull = $"{DiagnosticProperties.IdPrefix}0708";
public const string AssertNotNull = $"{DiagnosticProperties.IdPrefix}0709";
public const string AssertContains = $"{DiagnosticProperties.IdPrefix}0710";
}
}

Expand Down
57 changes: 57 additions & 0 deletions src/FluentAssertions.Analyzers/Tips/Xunit/AssertContains.cs
@@ -0,0 +1,57 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Composition;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using TypeSelector = FluentAssertions.Analyzers.Utilities.SemanticModelTypeExtensions;

namespace FluentAssertions.Analyzers.Xunit;

[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class AssertContainsAnalyzer : XunitAnalyzer
{
public const string DiagnosticId = Constants.Tips.Xunit.AssertContains;
public const string Category = Constants.Tips.Category;

public const string Message = "Use .Should().Contain().";

protected override DiagnosticDescriptor Rule => new(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true);

protected override IEnumerable<FluentAssertionsCSharpSyntaxVisitor> Visitors => new FluentAssertionsCSharpSyntaxVisitor[]
{
new AssertContainsStringSyntaxVisitor()
};

//public static void Contains(string expectedSubstring, string? actualString)
public class AssertContainsStringSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor
{
public AssertContainsStringSyntaxVisitor() : base(
MemberValidator.ArgumentsMatch("Contains",
ArgumentValidator.IsType(TypeSelector.GetStringType),
ArgumentValidator.IsType(TypeSelector.GetStringType))
)
{
}
}
}

[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertContainsCodeFix)), Shared]
public class AssertContainsCodeFix : XunitCodeFixProvider
{
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(AssertContainsAnalyzer.DiagnosticId);

protected override ExpressionSyntax GetNewExpression(
ExpressionSyntax expression,
FluentAssertionsDiagnosticProperties properties)
{
switch (properties.VisitorName)
{
case nameof(AssertContainsAnalyzer.AssertContainsStringSyntaxVisitor):
return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "Contains", "Contain");
default:
throw new System.InvalidOperationException($"Invalid visitor name - {properties.VisitorName}");
}
}
}

0 comments on commit 2b6059e

Please sign in to comment.