Skip to content
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
3 changes: 3 additions & 0 deletions docs/FluentAssertionsAnalyzer.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ var collection = new List<int>();
// old assertion:
collection.Any().Should().BeFalse();
collection.Count().Should().Be(0);
collection.Count.Should().Be(0);
collection.Should().HaveCount(0);

// new assertion:
Expand Down Expand Up @@ -126,6 +127,7 @@ var collection = new List<int> { 1, 2, 3 };

// old assertion:
collection.Count().Should().Be(3);
collection.Count.Should().Be(3);

// new assertion:
collection.Should().HaveCount(3);
Expand Down Expand Up @@ -165,6 +167,7 @@ var collection = new List<int> { 1 };

// old assertion:
collection.Count().Should().Be(1);
collection.Count.Should().Be(1);
collection.Should().HaveCount(1);

// new assertion:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public void CollectionShouldBeEmpty()
// old assertion:
collection.Any().Should().BeFalse();
collection.Count().Should().Be(0);
collection.Count.Should().Be(0);
collection.Should().HaveCount(0);

// new assertion:
Expand Down Expand Up @@ -111,6 +112,7 @@ public void CollectionShouldHaveCount_Count()

// old assertion:
collection.Count().Should().Be(3);
collection.Count.Should().Be(3);

// new assertion:
collection.Should().HaveCount(3);
Expand Down Expand Up @@ -150,6 +152,7 @@ public void CollectionShouldContainSingle()

// old assertion:
collection.Count().Should().Be(1);
collection.Count.Should().Be(1);
collection.Should().HaveCount(1);

// new assertion:
Expand Down
18 changes: 16 additions & 2 deletions src/FluentAssertions.Analyzers.Tests/Tips/CollectionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -293,8 +293,10 @@ public class CollectionTests
[AssertionDiagnostic("actual.Count().Should().Be(6{0});")]
[AssertionDiagnostic("actual.AsEnumerable().Count().Should().Be(k{0}).And.ToString();")]
[AssertionDiagnostic("actual.AsEnumerable().Count().Should().Be(6{0}).And.ToString();")]
[AssertionDiagnostic("actual.ToList().Count().Should().Be(k{0}).And.ToString();;")]
[AssertionDiagnostic("actual.ToList().Count().Should().Be(6{0}).And.ToString();;")]
[AssertionDiagnostic("actual.ToList().Count().Should().Be(k{0}).And.ToString();")]
[AssertionDiagnostic("actual.ToList().Count().Should().Be(6{0}).And.ToString();")]
[AssertionDiagnostic("actual.ToList().Count.Should().Be(k{0}).And.ToString();")]
[AssertionDiagnostic("actual.ToList().Count.Should().Be(6{0}).And.ToString();")]
[AssertionDiagnostic("actual.ToArray().Count().Should().Be(k{0}).And.ToString();")]
[AssertionDiagnostic("actual.ToArray().Count().Should().Be(6{0}).And.ToString();")]
[Implemented]
Expand Down Expand Up @@ -365,6 +367,18 @@ public void CollectionShouldHaveCount_LengthShouldBe_TestNoAnalyzer(string asser
[AssertionCodeFix(
oldAssertion: "actual.Count().Should().Be(6{0});",
newAssertion: "actual.Should().HaveCount(6{0});")]
[AssertionCodeFix(
oldAssertion: "actual.ToList().Count.Should().Be(k{0});",
newAssertion: "actual.ToList().Should().HaveCount(k{0});")]
[AssertionCodeFix(
oldAssertion: "actual.ToList().Count.Should().Be(0{0});",
newAssertion: "actual.ToList().Should().BeEmpty({0});")]
[AssertionCodeFix(
oldAssertion: "actual.ToList().Count.Should().Be(1{0});",
newAssertion: "actual.ToList().Should().ContainSingle({0});")]
[AssertionCodeFix(
oldAssertion: "actual.ToList().Count.Should().Be(6{0});",
newAssertion: "actual.ToList().Should().HaveCount(6{0});")]
[AssertionCodeFix(
oldAssertion: "actual.ToArray().Length.Should().Be(6{0});",
newAssertion: "actual.ToArray().Should().HaveCount(6{0});")]
Expand Down
2 changes: 2 additions & 0 deletions src/FluentAssertions.Analyzers/Tips/DiagnosticMetadata.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@ private DiagnosticMetadata(string message, string helpLink, [CallerMemberName] s
public static DiagnosticMetadata CollectionShouldNotHaveCount_CountShouldNotBe { get; } = new("Use .Should().NotHaveCount()", GetHelpLink("Collections-14"));
public static DiagnosticMetadata CollectionShouldContainSingle_ShouldHaveCount1 { get; } = new("Use .Should().ContainSingle()", GetHelpLink("Collections-15"));
public static DiagnosticMetadata CollectionShouldContainSingle_CountShouldBe1 { get; } = new("Use .Should().ContainSingle()", GetHelpLink("Collections-15"));
public static DiagnosticMetadata CollectionShouldContainSingle_CountPropertyShouldBe1 { get; } = new("Use .Should().ContainSingle()", GetHelpLink("Collections-15"));
public static DiagnosticMetadata CollectionShouldBeEmpty_ShouldHaveCount0 { get; } = new("Use .Should().BeEmpty()", GetHelpLink("Collections-16"));
public static DiagnosticMetadata CollectionShouldBeEmpty_CountShouldBe0 { get; } = new("Use .Should().BeEmpty()", GetHelpLink("Collections-16"));
public static DiagnosticMetadata CollectionShouldBeEmpty_CountPropertyShouldBe0 { get; } = new("Use .Should().BeEmpty()", GetHelpLink("Collections-16"));
public static DiagnosticMetadata CollectionShouldHaveSameCount_ShouldHaveCountOtherCollectionCount { get; } = new("Use .Should().HaveSameCount()", GetHelpLink("Collections-17"));
public static DiagnosticMetadata CollectionShouldNotHaveSameCount_CountShouldNotBeOtherCollectionCount { get; } = new("Use .Should().NotHaveSameCount()", GetHelpLink("Collections-18"));
public static DiagnosticMetadata CollectionShouldContainProperty_WhereShouldNotBeEmpty { get; } = new("Use .Should().Contain()", GetHelpLink("Collections-19"));
Expand Down
15 changes: 14 additions & 1 deletion src/FluentAssertions.Analyzers/Tips/FluentAssertionsAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System.Linq;
using FluentAssertions.Analyzers.Utilities;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations;

Expand Down Expand Up @@ -342,6 +341,20 @@ private static void AnalyzeInvocation(OperationAnalysisContext context, FluentAs
case nameof(string.Length) when propertyBeforeShould.IsContainedInType(SpecialType.System_String):
context.ReportDiagnostic(CreateDiagnostic(assertion, DiagnosticMetadata.StringShouldHaveLength_LengthShouldBe));
return;
case nameof(List<object>.Count) when propertyBeforeShould.ImplementsOrIsInterface(SpecialType.System_Collections_Generic_ICollection_T):
if (assertion.Arguments[0].IsLiteralValue(1))
{
context.ReportDiagnostic(CreateDiagnostic(assertion, DiagnosticMetadata.CollectionShouldContainSingle_CountPropertyShouldBe1));
}
else if (assertion.Arguments[0].IsLiteralValue(0))
{
context.ReportDiagnostic(CreateDiagnostic(assertion, DiagnosticMetadata.CollectionShouldBeEmpty_CountPropertyShouldBe0));
}
else
{
context.ReportDiagnostic(CreateDiagnostic(assertion, DiagnosticMetadata.CollectionShouldHaveCount_CountShouldBe));
}
return;
}
}
if (subject is IPropertyReferenceOperation propertyReference && propertyReference.Property.Name is WellKnownMemberNames.Indexer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,18 @@ CreateChangedDocument RemoveMethodBeforeShouldAndRenameAssertionWithoutFirstArgu
]);
}

// oldAssertion: subject.<method>(<argument1>).Should().<assertion>([arg1, arg2, arg3...]);
// oldAssertion: subject.<property>.Should().<assertion>([arg1, arg2, arg3...]);
// newAssertion: subject.Should().<newName>([argument1, arg1, arg2, arg3...]);
CreateChangedDocument RemoveExpressionBeforeShouldAndRenameAssertionWithoutFirstArgumentWithArgumentsFromRemoved(string newName)
{
return RewriteFluentAssertion(assertion, context, [
FluentAssertionsEditAction.RenameAssertion(newName),
FluentAssertionsEditAction.SkipExpressionBeforeShould(),
FluentAssertionsEditAction.RemoveAssertionArgument(index: 0)
]);
}

switch (visitorName)
{
case nameof(DiagnosticMetadata.CollectionShouldBeEmpty_AnyShouldBeFalse):
Expand Down Expand Up @@ -121,10 +133,14 @@ CreateChangedDocument RemoveMethodBeforeShouldAndRenameAssertionWithoutFirstArgu
editor.ReplaceNode(context.AssertionExpression.ArgumentList, arguments);
}
]);
case nameof(DiagnosticMetadata.CollectionShouldBeEmpty_CountPropertyShouldBe0):
return RemoveExpressionBeforeShouldAndRenameAssertionWithoutFirstArgumentWithArgumentsFromRemoved("BeEmpty");
case nameof(DiagnosticMetadata.CollectionShouldBeEmpty_CountShouldBe0):
return RemoveMethodBeforeShouldAndRenameAssertionWithoutFirstArgumentWithArgumentsFromRemoved("BeEmpty");
case nameof(DiagnosticMetadata.CollectionShouldContainSingle_CountShouldBe1):
return RemoveMethodBeforeShouldAndRenameAssertionWithoutFirstArgumentWithArgumentsFromRemoved("ContainSingle");
case nameof(DiagnosticMetadata.CollectionShouldContainSingle_CountPropertyShouldBe1):
return RemoveExpressionBeforeShouldAndRenameAssertionWithoutFirstArgumentWithArgumentsFromRemoved("ContainSingle");
case nameof(DiagnosticMetadata.CollectionShouldHaveCount_CountShouldBe):
return RemoveExpressionBeforeShouldAndRenameAssertion("HaveCount");
case nameof(DiagnosticMetadata.CollectionShouldHaveCount_LengthShouldBe):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ public static bool IsContainedInType(this IInvocationOperation invocation, Speci
=> invocation.TargetMethod.ContainingType.ConstructedFromType(type);
public static bool IsContainedInType(this IInvocationOperation invocation, INamedTypeSymbol type)
=> invocation.TargetMethod.ContainingType.ConstructedFromType(type);
public static bool ImplementsOrIsInterface(this IPropertyReferenceOperation property, SpecialType type)
=> property.Property.ContainingType.ImplementsOrIsInterface(type);
public static bool ImplementsOrIsInterface(this IInvocationOperation invocation, SpecialType type)
=> invocation.TargetMethod.ContainingType.ImplementsOrIsInterface(type);
public static bool ImplementsOrIsInterface(this IInvocationOperation invocation, INamedTypeSymbol type)
Expand Down