Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: support first argument being the null keyword #201

Merged
merged 1 commit into from
Jun 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions src/FluentAssertions.Analyzers.Tests/Tips/MsTestTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -326,14 +326,27 @@ public void AssertOptionalIntAreEqual_TestCodeFix(string oldAssertion, string ne
[AssertionDataTestMethod]
[AssertionDiagnostic("Assert.AreEqual(actual, null{0});")]
[Implemented]
public void AssertOptionalIntAndNullAreEqual_TestAnalyzer(string assertion) => VerifyCSharpDiagnostic<AssertAreEqualAnalyzer>("int? actual", assertion);
public void AssertOptionalIntAndNullAreEqual1_TestAnalyzer(string assertion) => VerifyCSharpDiagnostic<AssertAreEqualAnalyzer>("int? actual", assertion);

[AssertionDataTestMethod]
[AssertionCodeFix(
oldAssertion: "Assert.AreEqual(actual, null{0});",
newAssertion: "actual.Should().BeNull({0});")]
[Implemented]
public void AssertOptionalIntAndNullAreEqual_TestCodeFix(string oldAssertion, string newAssertion)
public void AssertOptionalIntAndNullAreEqual1_TestCodeFix(string oldAssertion, string newAssertion)
=> VerifyCSharpFix<AssertAreEqualCodeFix, AssertAreEqualAnalyzer>("int? actual", oldAssertion, newAssertion);

[AssertionDataTestMethod]
[AssertionDiagnostic("Assert.AreEqual(null, actual{0});")]
[Implemented]
public void AssertOptionalIntAndNullAreEqual2_TestAnalyzer(string assertion) => VerifyCSharpDiagnostic<AssertAreEqualAnalyzer>("int? actual", assertion);

[AssertionDataTestMethod]
[AssertionCodeFix(
oldAssertion: "Assert.AreEqual(null, actual{0});",
newAssertion: "actual.Should().BeNull({0});")]
[Implemented]
public void AssertOptionalIntAndNullAreEqual2_TestCodeFix(string oldAssertion, string newAssertion)
=> VerifyCSharpFix<AssertAreEqualCodeFix, AssertAreEqualAnalyzer>("int? actual", oldAssertion, newAssertion);

[AssertionDataTestMethod]
Expand Down
22 changes: 18 additions & 4 deletions src/FluentAssertions.Analyzers/Tips/MsTest/AssertAreEqual.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ protected override IEnumerable<FluentAssertionsCSharpSyntaxVisitor> Visitors
yield return new AssertFloatAreEqualWithDeltaSyntaxVisitor();
yield return new AssertDoubleAreEqualWithDeltaSyntaxVisitor();
yield return new AssertStringAreEqualSyntaxVisitor();
yield return new AssertObjectAreEqualNullSyntaxVisitor();
yield return new AssertObjectAreEqualNull1SyntaxVisitor();
yield return new AssertObjectAreEqualNull2SyntaxVisitor();
yield return new AssertObjectAreEqualSyntaxVisitor();
}
}
Expand Down Expand Up @@ -70,16 +71,26 @@ public AssertStringAreEqualSyntaxVisitor() : base(
}
}

public class AssertObjectAreEqualNullSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor
public class AssertObjectAreEqualNull1SyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor
{
public AssertObjectAreEqualNullSyntaxVisitor() : base(
public AssertObjectAreEqualNull1SyntaxVisitor() : base(
MemberValidator.ArgumentsMatch("AreEqual",
ArgumentValidator.IsIdentifier(),
ArgumentValidator.IsNull()))
{
}
}

public class AssertObjectAreEqualNull2SyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor
{
public AssertObjectAreEqualNull2SyntaxVisitor() : base(
MemberValidator.ArgumentsMatch("AreEqual",
ArgumentValidator.IsNull(),
ArgumentValidator.IsIdentifier()))
{
}
}

// public static void AreEqual<T>(T expected, T actual)
// public static void AreEqual(object expected, object actual)
public class AssertObjectAreEqualSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor
Expand Down Expand Up @@ -107,9 +118,12 @@ protected override async Task<ExpressionSyntax> GetNewExpressionAsync(Expression
case nameof(AssertAreEqualAnalyzer.AssertStringAreEqualSyntaxVisitor):
var semanticModel = await document.GetSemanticModelAsync(cancellationToken);
return GetNewExpressionForAreNotEqualOrAreEqualStrings(expression, semanticModel, "AreEqual", "Be", "BeEquivalentTo");
case nameof(AssertAreEqualAnalyzer.AssertObjectAreEqualNullSyntaxVisitor):
case nameof(AssertAreEqualAnalyzer.AssertObjectAreEqualNull1SyntaxVisitor):
expression = RenameMethodAndReplaceWithSubjectShould(expression, "AreEqual", "BeNull");
return GetNewExpression(expression, NodeReplacement.RemoveFirstArgument("BeNull"));
case nameof(AssertAreEqualAnalyzer.AssertObjectAreEqualNull2SyntaxVisitor):
expression = GetNewExpression(expression, NodeReplacement.RemoveFirstArgument("AreEqual"));
return RenameMethodAndReplaceWithSubjectShould(expression, "AreEqual", "BeNull");
default:
throw new System.InvalidOperationException($"Invalid visitor name - {properties.VisitorName}");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public class ArgumentValidator
public static ArgumentPredicate IsIdentifier()
=> (argument, semanticModel) => argument.Expression.IsKind(SyntaxKind.IdentifierName);
public static ArgumentPredicate IsType(Func<SemanticModel, INamedTypeSymbol> typeSelector)
=> (argument, semanticModel) => semanticModel.GetTypeInfo(argument.Expression).Type.Equals(typeSelector(semanticModel), SymbolEqualityComparer.Default);
=> (argument, semanticModel) => semanticModel.GetTypeInfo(argument.Expression).Type?.Equals(typeSelector(semanticModel), SymbolEqualityComparer.Default) ?? false;
public static ArgumentPredicate IsNull()
=> (argument, semanticModel) => argument.Expression is LiteralExpressionSyntax literal && literal.Token.IsKind(SyntaxKind.NullKeyword);
}
Expand Down