Skip to content

Commit

Permalink
Fix nunit#712: AreEqualClassicModelAssertUsageCodeFix no longer assum…
Browse files Browse the repository at this point in the history
…es that the first argument is expected and the second argument is actual
  • Loading branch information
Bartleby2718 authored and manfred-brands committed Apr 10, 2024
1 parent ea11a27 commit e809f3b
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,22 @@ public void TestMethod()
RoslynAssert.CodeFix(analyzer, fix, expectedDiagnostic, code, fixedCode, fixTitle: ClassicModelAssertUsageCodeFix.TransformToConstraintModelDescription);
}

[Test]
public void VerifyAreEqualFixWithNamedParametersInNonstandardOrder()
{
var code = TestUtility.WrapMethodInClassNamespaceAndAddUsings($@"
public void TestMethod()
{{
↓ClassicAssert.AreEqual(actual: 3d, expected: 2d);
}}");
var fixedCode = TestUtility.WrapMethodInClassNamespaceAndAddUsings(@"
public void TestMethod()
{
Assert.That(actual: 3d, Is.EqualTo(expected: 2d));
}");
RoslynAssert.CodeFix(analyzer, fix, expectedDiagnostic, code, fixedCode, fixTitle: ClassicModelAssertUsageCodeFix.TransformToConstraintModelDescription);
}

[Test]
public void VerifyAreEqualFixWithMessage()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ public sealed class AreEqualClassicModelAssertUsageCodeFix

protected override void UpdateArguments(Diagnostic diagnostic, List<ArgumentSyntax> arguments)
{
// If named parameters are used, we can't assume that the first argument is the expected one and the second is the actual.
// Therefore, start by finding the expected argument and the actual argument.
var expectedPosition = arguments.FindIndex(arg => arg.NameColon?.Name.Identifier.Text == NUnitFrameworkConstants.NameOfExpectedParameter);
var actualPosition = arguments.FindIndex(arg => arg.NameColon?.Name.Identifier.Text == NUnitFrameworkConstants.NameOfActualParameter);

// If named arguments are not used, the first argument is expected, and the second is actual.
var expectedArgument = expectedPosition != -1 ? arguments[expectedPosition] : arguments[0];
var actualArgument = actualPosition != -1 ? arguments[actualPosition] : arguments[1];

// Note that if there's a 3rd argument and it's a double,
// it has to be added to the "Is.EqualTo(1st argument)" with ".Within(3rd argument)"
var equalToInvocationNode = SyntaxFactory.InvocationExpression(
Expand All @@ -26,7 +35,7 @@ protected override void UpdateArguments(Diagnostic diagnostic, List<ArgumentSynt
SyntaxFactory.IdentifierName(NUnitFrameworkConstants.NameOfIs),
SyntaxFactory.IdentifierName(NUnitFrameworkConstants.NameOfIsEqualTo)))
.WithArgumentList(SyntaxFactory.ArgumentList(
SyntaxFactory.SingletonSeparatedList(arguments[0])));
SyntaxFactory.SingletonSeparatedList(expectedArgument)));

var hasToleranceValue = diagnostic.Properties[AnalyzerPropertyKeys.HasToleranceValue] == true.ToString();

Expand All @@ -50,6 +59,16 @@ protected override void UpdateArguments(Diagnostic diagnostic, List<ArgumentSynt
// Then we have to remove the 1st argument because that's now in the "Is.EqualTo()"
arguments.RemoveAt(0);

// If the now-first argument had a named parameter, we need to make sure it's actual.
if (arguments[0].NameColon?.Name.Identifier.Text is { } parameterName
&& parameterName != NUnitFrameworkConstants.NameOfActualParameter)
{
arguments[0] = SyntaxFactory.Argument(
SyntaxFactory.NameColon(NUnitFrameworkConstants.NameOfActualParameter),
actualArgument.RefKindKeyword,
actualArgument.Expression);
}

// ... and if the 3rd argument was a double, that has to go too.
if (hasToleranceValue)
{
Expand Down

0 comments on commit e809f3b

Please sign in to comment.