Skip to content

Commit b50a3a4

Browse files
committed
{EnumerableAnalyzer} - added orderBy assertions
1 parent f62d097 commit b50a3a4

10 files changed

+76
-74
lines changed

src/FluentAssertions.BestPractices.Tests/Tips/CollectionTests.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -316,26 +316,26 @@ public class CollectionTests
316316

317317
[AssertionDataTestMethod]
318318
[AssertionDiagnostic("actual.OrderBy(x => x.BooleanProperty).Should().Equal(actual{0});")]
319-
[NotImplemented]
319+
[Implemented]
320320
public void CollectionShouldBeInAscendingOrder_TestAnalyzer(string assertion) => VerifyCSharpDiagnostic<CollectionShouldBeInAscendingOrderAnalyzer>(assertion);
321321

322322
[AssertionDataTestMethod]
323323
[AssertionCodeFix(
324-
oldAssertion: "actual.OrderBy(x => x.BooleanProperty).Should().Equal(actual{0});",
325-
newAssertion: "actual.Should().BeInAscendingOrder(x => x.BooleanProperty{0});")]
326-
[NotImplemented]
324+
oldAssertion: "actual.OrderBy(x => x.BooleanProperty).Should().Equal(actual{0});",
325+
newAssertion: "actual.Should().BeInAscendingOrder(x => x.BooleanProperty{0});")]
326+
[Implemented]
327327
public void CollectionShouldBeInAscendingOrder_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFix<CollectionShouldBeInAscendingOrderCodeFix, CollectionShouldBeInAscendingOrderAnalyzer>(oldAssertion, newAssertion);
328328

329329
[AssertionDataTestMethod]
330330
[AssertionDiagnostic("actual.OrderByDescending(x => x.BooleanProperty).Should().Equal(actual{0});")]
331-
[NotImplemented]
331+
[Implemented]
332332
public void CollectionShouldBeInDescendingOrder_TestAnalyzer(string assertion) => VerifyCSharpDiagnostic<CollectionShouldBeInDescendingOrderAnalyzer>(assertion);
333333

334334
[AssertionDataTestMethod]
335335
[AssertionCodeFix(
336-
oldAssertion: "actual.OrderByDescending(x => x.BooleanProperty).Should().Equal(actual{0});",
337-
newAssertion: "actual.Should().BeInDescendingOrder(x => x.BooleanProperty{0});")]
338-
[NotImplemented]
336+
oldAssertion: "actual.OrderByDescending(x => x.BooleanProperty).Should().Equal(actual{0});",
337+
newAssertion: "actual.Should().BeInDescendingOrder(x => x.BooleanProperty{0});")]
338+
[Implemented]
339339
public void CollectionShouldBeInDescendingOrder_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFix<CollectionShouldBeInDescendingOrderCodeFix, CollectionShouldBeInDescendingOrderAnalyzer>(oldAssertion, newAssertion);
340340

341341
[AssertionDataTestMethod]

src/FluentAssertions.BestPractices/Constants.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ public static class DiagnosticProperties
66
{
77
public const string Title = nameof(Title);
88
public const string VariableName = nameof(VariableName);
9-
public const string PredicateString = nameof(PredicateString);
9+
public const string LambdaString = nameof(LambdaString);
1010
public const string ExpectedItemString = nameof(ExpectedItemString);
1111
public const string UnexpectedItemString = nameof(UnexpectedItemString);
1212
public const string BecauseArgumentsString = nameof(BecauseArgumentsString);
Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Microsoft.CodeAnalysis;
22
using Microsoft.CodeAnalysis.CodeFixes;
3+
using Microsoft.CodeAnalysis.CSharp;
34
using Microsoft.CodeAnalysis.CSharp.Syntax;
45
using Microsoft.CodeAnalysis.Diagnostics;
56
using System.Collections.Generic;
@@ -14,31 +15,39 @@ public class CollectionShouldBeInAscendingOrderAnalyzer : FluentAssertionsAnalyz
1415
public const string DiagnosticId = Constants.Tips.Collections.CollectionShouldBeInAscendingOrder;
1516
public const string Category = Constants.Tips.Category;
1617

17-
public const string Message = "Use {0} .Should() followed by ### instead.";
18+
public const string Message = "Use {0} .Should() followed by .BeInAscendingOrder() instead.";
1819

1920
protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true);
20-
21-
protected override Diagnostic AnalyzeExpressionStatement(ExpressionStatementSyntax statement)
21+
protected override IEnumerable<(FluentAssertionsCSharpSyntaxVisitor, BecauseArgumentsSyntaxVisitor)> Visitors
22+
{
23+
get
24+
{
25+
yield return (new OrderByShouldEqualSyntaxVisitor(), new BecauseArgumentsSyntaxVisitor("Equal", 1));
26+
}
27+
}
28+
private class OrderByShouldEqualSyntaxVisitor : FluentAssertionsWithLambdaArgumentCSharpSyntaxVisitor
2229
{
23-
return null;
24-
var visitor = new CollectionShouldBeInAscendingOrderSyntaxVisitor();
25-
statement.Accept(visitor);
30+
private bool _argumentIsSelf;
31+
protected override string MathodContainingLambda => "OrderBy";
32+
33+
public override bool IsValid => base.IsValid && _argumentIsSelf;
34+
35+
public OrderByShouldEqualSyntaxVisitor() : base("OrderBy", "Should", "Equal")
36+
{
37+
}
2638

27-
if (visitor.IsValid)
39+
public override void VisitArgumentList(ArgumentListSyntax node)
2840
{
29-
var properties = new Dictionary<string, string>
41+
if (!node.Arguments.Any()) return;
42+
if (CurrentMethod != "Equal")
3043
{
31-
[Constants.DiagnosticProperties.VariableName] = visitor.VariableName,
32-
[Constants.DiagnosticProperties.Title] = Title
33-
}.ToImmutableDictionary();
34-
35-
return Diagnostic.Create(
36-
descriptor: Rule,
37-
location: statement.Expression.GetLocation(),
38-
properties: properties,
39-
messageArgs: visitor.VariableName);
44+
base.VisitArgumentList(node);
45+
return;
46+
}
47+
48+
_argumentIsSelf = node.Arguments[0].Expression is IdentifierNameSyntax identifier
49+
&& identifier.Identifier.Text == VariableName;
4050
}
41-
return null;
4251
}
4352
}
4453

@@ -48,16 +57,6 @@ public class CollectionShouldBeInAscendingOrderCodeFix : FluentAssertionsCodeFix
4857
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldBeInAscendingOrderAnalyzer.DiagnosticId);
4958

5059
protected override StatementSyntax GetNewStatement(FluentAssertionsDiagnosticProperties properties)
51-
{
52-
throw new System.NotImplementedException();
53-
}
54-
}
55-
56-
public class CollectionShouldBeInAscendingOrderSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor
57-
{
58-
public CollectionShouldBeInAscendingOrderSyntaxVisitor() : base("###")
59-
{
60-
throw new System.NotImplementedException();
61-
}
60+
=> SyntaxFactory.ParseStatement($"{properties.VariableName}.Should().BeInAscendingOrder({properties.CombineWithBecauseArgumentsString(properties.LambdaString)});");
6261
}
6362
}
Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Microsoft.CodeAnalysis;
22
using Microsoft.CodeAnalysis.CodeFixes;
3+
using Microsoft.CodeAnalysis.CSharp;
34
using Microsoft.CodeAnalysis.CSharp.Syntax;
45
using Microsoft.CodeAnalysis.Diagnostics;
56
using System.Collections.Generic;
@@ -14,31 +15,39 @@ public class CollectionShouldBeInDescendingOrderAnalyzer : FluentAssertionsAnaly
1415
public const string DiagnosticId = Constants.Tips.Collections.CollectionShouldBeInDescendingOrder;
1516
public const string Category = Constants.Tips.Category;
1617

17-
public const string Message = "Use {0} .Should() followed by ### instead.";
18+
public const string Message = "Use {0} .Should() followed by .BeInDescendingOrder instead.";
1819

1920
protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true);
20-
21-
protected override Diagnostic AnalyzeExpressionStatement(ExpressionStatementSyntax statement)
21+
protected override IEnumerable<(FluentAssertionsCSharpSyntaxVisitor, BecauseArgumentsSyntaxVisitor)> Visitors
22+
{
23+
get
24+
{
25+
yield return (new OrderByDescendingShouldEqualSyntaxVisitor(), new BecauseArgumentsSyntaxVisitor("Equal", 1));
26+
}
27+
}
28+
private class OrderByDescendingShouldEqualSyntaxVisitor : FluentAssertionsWithLambdaArgumentCSharpSyntaxVisitor
2229
{
23-
return null;
24-
var visitor = new CollectionShouldBeInDescendingOrderSyntaxVisitor();
25-
statement.Accept(visitor);
30+
private bool _argumentIsSelf;
31+
protected override string MathodContainingLambda => "OrderByDescending";
32+
33+
public override bool IsValid => base.IsValid && _argumentIsSelf;
34+
35+
public OrderByDescendingShouldEqualSyntaxVisitor() : base("OrderByDescending", "Should", "Equal")
36+
{
37+
}
2638

27-
if (visitor.IsValid)
39+
public override void VisitArgumentList(ArgumentListSyntax node)
2840
{
29-
var properties = new Dictionary<string, string>
41+
if (!node.Arguments.Any()) return;
42+
if (CurrentMethod != "Equal")
3043
{
31-
[Constants.DiagnosticProperties.VariableName] = visitor.VariableName,
32-
[Constants.DiagnosticProperties.Title] = Title
33-
}.ToImmutableDictionary();
34-
35-
return Diagnostic.Create(
36-
descriptor: Rule,
37-
location: statement.Expression.GetLocation(),
38-
properties: properties,
39-
messageArgs: visitor.VariableName);
44+
base.VisitArgumentList(node);
45+
return;
46+
}
47+
48+
_argumentIsSelf = node.Arguments[0].Expression is IdentifierNameSyntax identifier
49+
&& identifier.Identifier.Text == VariableName;
4050
}
41-
return null;
4251
}
4352
}
4453

@@ -48,16 +57,6 @@ public class CollectionShouldBeInDescendingOrderCodeFix : FluentAssertionsCodeFi
4857
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldBeInDescendingOrderAnalyzer.DiagnosticId);
4958

5059
protected override StatementSyntax GetNewStatement(FluentAssertionsDiagnosticProperties properties)
51-
{
52-
throw new System.NotImplementedException();
53-
}
54-
}
55-
56-
public class CollectionShouldBeInDescendingOrderSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor
57-
{
58-
public CollectionShouldBeInDescendingOrderSyntaxVisitor() : base("###")
59-
{
60-
throw new System.NotImplementedException();
61-
}
60+
=> SyntaxFactory.ParseStatement($"{properties.VariableName}.Should().BeInDescendingOrder({properties.CombineWithBecauseArgumentsString(properties.LambdaString)});");
6261
}
6362
}

src/FluentAssertions.BestPractices/Tips/Collections/CollectionShouldContainProperty.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,6 @@ public class CollectionShouldContainPropertyCodeFix : FluentAssertionsCodeFixPro
4949
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldContainPropertyAnalyzer.DiagnosticId);
5050

5151
protected override StatementSyntax GetNewStatement(FluentAssertionsDiagnosticProperties properties)
52-
=> SyntaxFactory.ParseStatement($"{properties.VariableName}.Should().Contain({properties.CombineWithBecauseArgumentsString(properties.PredicateString)});");
52+
=> SyntaxFactory.ParseStatement($"{properties.VariableName}.Should().Contain({properties.CombineWithBecauseArgumentsString(properties.LambdaString)});");
5353
}
5454
}

src/FluentAssertions.BestPractices/Tips/Collections/CollectionShouldContainSingleProperty.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,11 @@ public WhereShouldHaveCount1SyntaxVisitor() : base("Where", "Should", "HaveCount
3939
public override void VisitArgumentList(ArgumentListSyntax node)
4040
{
4141
if (!node.Arguments.Any()) return;
42-
if (CurrentMethod != "HaveCount") base.VisitArgumentList(node); ;
42+
if (CurrentMethod != "HaveCount")
43+
{
44+
base.VisitArgumentList(node);
45+
return;
46+
}
4347

4448
_haveCountMethodHas1Argument =
4549
node.Arguments[0].Expression is LiteralExpressionSyntax literal
@@ -55,6 +59,6 @@ public class CollectionShouldContainSinglePropertyCodeFix : FluentAssertionsCode
5559
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldContainSinglePropertyAnalyzer.DiagnosticId);
5660

5761
protected override StatementSyntax GetNewStatement(FluentAssertionsDiagnosticProperties properties)
58-
=> SyntaxFactory.ParseStatement($"{properties.VariableName}.Should().ContainSingle({properties.CombineWithBecauseArgumentsString(properties.PredicateString)});");
62+
=> SyntaxFactory.ParseStatement($"{properties.VariableName}.Should().ContainSingle({properties.CombineWithBecauseArgumentsString(properties.LambdaString)});");
5963
}
6064
}

src/FluentAssertions.BestPractices/Tips/Collections/CollectionShouldNotContainProperty.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,6 @@ public class CollectionShouldNotContainPropertyCodeFix : FluentAssertionsCodeFix
4949
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldNotContainPropertyAnalyzer.DiagnosticId);
5050

5151
protected override StatementSyntax GetNewStatement(FluentAssertionsDiagnosticProperties properties)
52-
=> SyntaxFactory.ParseStatement($"{properties.VariableName}.Should().NotContain({properties.CombineWithBecauseArgumentsString(properties.PredicateString)});");
52+
=> SyntaxFactory.ParseStatement($"{properties.VariableName}.Should().NotContain({properties.CombineWithBecauseArgumentsString(properties.LambdaString)});");
5353
}
5454
}

src/FluentAssertions.BestPractices/Tips/Collections/CollectionShouldOnlyContainProperty.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,6 @@ public class CollectionShouldOnlyContainPropertyCodeFix : FluentAssertionsCodeFi
4242
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldOnlyContainPropertyAnalyzer.DiagnosticId);
4343

4444
protected override StatementSyntax GetNewStatement(FluentAssertionsDiagnosticProperties properties)
45-
=> SyntaxFactory.ParseStatement($"{properties.VariableName}.Should().OnlyContain({properties.CombineWithBecauseArgumentsString(properties.PredicateString)});");
45+
=> SyntaxFactory.ParseStatement($"{properties.VariableName}.Should().OnlyContain({properties.CombineWithBecauseArgumentsString(properties.LambdaString)});");
4646
}
4747
}

src/FluentAssertions.BestPractices/Utilities/FluentAssertionsDiagnosticProperties.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public FluentAssertionsDiagnosticProperties(ImmutableDictionary<string, string>
1515
public string Title => Properties[Constants.DiagnosticProperties.Title];
1616
public string VariableName => Properties[Constants.DiagnosticProperties.VariableName];
1717
public string BecauseArgumentsString => Properties[Constants.DiagnosticProperties.BecauseArgumentsString];
18-
public string PredicateString => Properties[Constants.DiagnosticProperties.PredicateString];
18+
public string LambdaString => Properties[Constants.DiagnosticProperties.LambdaString];
1919
public string ExpectedItemString => Properties[Constants.DiagnosticProperties.ExpectedItemString];
2020
public string UnexpectedItemString => Properties[Constants.DiagnosticProperties.UnexpectedItemString];
2121
public string ArgumentString => Properties[Constants.DiagnosticProperties.ArgumentString];

src/FluentAssertions.BestPractices/Utilities/FluentAssertionsWithLambdaArgumentCSharpSyntaxVisitor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ protected FluentAssertionsWithLambdaArgumentCSharpSyntaxVisitor(params string[]
1717
}
1818

1919
public override ImmutableDictionary<string, string> ToDiagnosticProperties()
20-
=> base.ToDiagnosticProperties().Add(Constants.DiagnosticProperties.PredicateString, PredicateString);
20+
=> base.ToDiagnosticProperties().Add(Constants.DiagnosticProperties.LambdaString, PredicateString);
2121

2222
public override void VisitArgumentList(ArgumentListSyntax node)
2323
{

0 commit comments

Comments
 (0)