Skip to content

Commit 0c87892

Browse files
committed
{EnumerableAnalyzer} - more assertions
1 parent 1de5127 commit 0c87892

File tree

6 files changed

+67
-118
lines changed

6 files changed

+67
-118
lines changed

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

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using Microsoft.CodeAnalysis;
22
using Microsoft.VisualStudio.TestTools.UnitTesting;
3-
using System.Reflection;
43

54
namespace FluentAssertions.BestPractices.Tests
65
{
@@ -257,7 +256,7 @@ public class CollectionTests
257256
newAssertion: "actual.Should().ContainSingle(x => x.BooleanProperty{0});")]
258257
[Implemented]
259258
public void CollectionShouldContainSingleProperty_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFix<CollectionShouldContainSinglePropertyCodeFix, CollectionShouldContainSinglePropertyAnalyzer>(oldAssertion, newAssertion);
260-
259+
261260
[AssertionDataTestMethod]
262261
[AssertionDiagnostic("actual.Should().NotBeNull().And.NotBeEmpty({0});")]
263262
[NotImplemented]
@@ -301,7 +300,7 @@ public class CollectionTests
301300
newAssertion: "actual.Should().HaveElementAt(6, expectedItem{0});")]
302301
[Implemented]
303302
public void CollectionShouldHaveElementAt_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFix<CollectionShouldHaveElementAtCodeFix, CollectionShouldHaveElementAtAnalyzer>(oldAssertion, newAssertion);
304-
303+
305304
[AssertionDataTestMethod]
306305
[AssertionDiagnostic("actual.OrderBy(x => x.BooleanProperty).Should().Equal(actual{0});")]
307306
[Implemented]
@@ -340,57 +339,62 @@ public class CollectionTests
340339

341340
[AssertionDataTestMethod]
342341
[AssertionDiagnostic("actual.Intersect(expected).Should().BeEmpty({0});")]
343-
[NotImplemented]
342+
[Implemented]
344343
public void CollectionShouldNotIntersectWith_TestAnalyzer(string assertion) => VerifyCSharpDiagnostic<CollectionShouldNotIntersectWithAnalyzer>(assertion);
345344

346345
[AssertionDataTestMethod]
347346
[AssertionCodeFix(
348347
oldAssertion: "actual.Intersect(expected).Should().BeEmpty({0});",
349348
newAssertion: "actual.Should().NotIntersectWith(expected{0});")]
350-
[NotImplemented]
349+
[Implemented]
351350
public void CollectionShouldNotIntersectWith_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFix<CollectionShouldNotIntersectWithCodeFix, CollectionShouldNotIntersectWithAnalyzer>(oldAssertion, newAssertion);
351+
352352
[AssertionDataTestMethod]
353353
[AssertionDiagnostic("actual.Intersect(expected).Should().NotBeEmpty({0});")]
354-
[NotImplemented]
354+
[Implemented]
355355
public void CollectionShouldIntersectWith_TestAnalyzer(string assertion) => VerifyCSharpDiagnostic<CollectionShouldIntersectWithAnalyzer>(assertion);
356356

357357
[AssertionDataTestMethod]
358358
[AssertionCodeFix(
359-
oldAssertion: "actual.Intersect(expected).Should().NotBeEmpty({0});",
360-
newAssertion: "actual.Should().IntersectWith(expected{0});")]
361-
[NotImplemented]
359+
oldAssertion: "actual.Intersect(expected).Should().NotBeEmpty({0});",
360+
newAssertion: "actual.Should().IntersectWith(expected{0});")]
361+
[Implemented]
362362
public void CollectionShouldIntersectWith_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFix<CollectionShouldIntersectWithCodeFix, CollectionShouldIntersectWithAnalyzer>(oldAssertion, newAssertion);
363+
363364
[AssertionDataTestMethod]
364365
[AssertionDiagnostic("actual.Select(x => x.BooleanProperty).Should().NotContainNulls({0});")]
365-
[NotImplemented]
366+
[Implemented]
366367
public void CollectionShouldNotContainNulls_TestAnalyzer(string assertion) => VerifyCSharpDiagnostic<CollectionShouldNotContainNullsAnalyzer>(assertion);
367368

368369
[AssertionDataTestMethod]
369370
[AssertionCodeFix(
370-
oldAssertion: "actual.Select(x => x.BooleanProperty).Should().NotContainNulls({0});",
371-
newAssertion: "actual.Should().NotContainNulls(e => e.OtherProperty{0});")]
372-
[NotImplemented]
371+
oldAssertion: "actual.Select(x => x.BooleanProperty).Should().NotContainNulls({0});",
372+
newAssertion: "actual.Should().NotContainNulls(x => x.BooleanProperty{0});")]
373+
[Implemented]
374+
[Ignore("Will be available in Fluent Assertions 5.0")]
373375
public void CollectionShouldNotContainNulls_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFix<CollectionShouldNotContainNullsCodeFix, CollectionShouldNotContainNullsAnalyzer>(oldAssertion, newAssertion);
376+
374377
[AssertionDataTestMethod]
375378
[AssertionDiagnostic("actual.Should().HaveSameCount(actual.Distinct(){0});")]
376379
[NotImplemented]
377380
public void CollectionShouldOnlyHaveUniqueItems_TestAnalyzer(string assertion) => VerifyCSharpDiagnostic<CollectionShouldOnlyHaveUniqueItemsAnalyzer>(assertion);
378381

379382
[AssertionDataTestMethod]
380383
[AssertionCodeFix(
381-
oldAssertion: "actual.Should().HaveSameCount(actual.Distinct(){0});",
382-
newAssertion: "actual.Should().OnlyHaveUniqueItems({0});")]
384+
oldAssertion: "actual.Should().HaveSameCount(actual.Distinct(){0});",
385+
newAssertion: "actual.Should().OnlyHaveUniqueItems({0});")]
383386
[NotImplemented]
384387
public void CollectionShouldOnlyHaveUniqueItems_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFix<CollectionShouldOnlyHaveUniqueItemsCodeFix, CollectionShouldOnlyHaveUniqueItemsAnalyzer>(oldAssertion, newAssertion);
388+
385389
[AssertionDataTestMethod]
386390
[AssertionDiagnostic("actual.Select(x => x.BooleanProperty).Should().OnlyHaveUniqueItems({0});")]
387391
[NotImplemented]
388392
public void CollectionShouldOnlyHaveUniqueItemsByComparer_TestAnalyzer(string assertion) => VerifyCSharpDiagnostic<CollectionShouldOnlyHaveUniqueItemsByComparerAnalyzer>(assertion);
389393

390394
[AssertionDataTestMethod]
391395
[AssertionCodeFix(
392-
oldAssertion: "actual.Select(x => x.BooleanProperty).Should().OnlyHaveUniqueItems({0});",
393-
newAssertion: "actual.Should().OnlyHaveUniqueItems(x => x.BooleanProperty{0});")]
396+
oldAssertion: "actual.Select(x => x.BooleanProperty).Should().OnlyHaveUniqueItems({0});",
397+
newAssertion: "actual.Should().OnlyHaveUniqueItems(x => x.BooleanProperty{0});")]
394398
[NotImplemented]
395399
public void CollectionShouldOnlyHaveUniqueItemsByComparer_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFix<CollectionShouldOnlyHaveUniqueItemsByComparerCodeFix, CollectionShouldOnlyHaveUniqueItemsByComparerAnalyzer>(oldAssertion, newAssertion);
396400
[AssertionDataTestMethod]
@@ -400,8 +404,8 @@ public class CollectionTests
400404

401405
[AssertionDataTestMethod]
402406
[AssertionCodeFix(
403-
oldAssertion: "actual.FirstOrDefault().Should().BeNull({0});",
404-
newAssertion: "actual.Should().HaveElementAt(0, null{0});")]
407+
oldAssertion: "actual.FirstOrDefault().Should().BeNull({0});",
408+
newAssertion: "actual.Should().HaveElementAt(0, null{0});")]
405409
[NotImplemented]
406410
public void CollectionShouldHaveElementAt0Null_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFix<CollectionShouldHaveElementAt0NullCodeFix, CollectionShouldHaveElementAt0NullAnalyzer>(oldAssertion, newAssertion);
407411

src/FluentAssertions.BestPractices/FluentAssertions.BestPractices.nuspec

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<metadata>
44
<id>FluentAssertions.BestPractices</id>
55
<title>Fluent Assertions Best Practice</title>
6-
<version>0.2.0</version>
6+
<version>0.2.1</version>
77
<owners>Meir Blachman</owners>
88
<authors>Meir Blachman</authors>
99
<summary>
@@ -16,12 +16,12 @@
1616
<licenseUrl>https://github.com/Meir017/fluentassertions.bestpractices/blob/master/LICENSE</licenseUrl>
1717
<iconUrl>https://raw.githubusercontent.com/fluentassertions/fluentassertions/release-5.0/Src/FluentAssertions.png</iconUrl>
1818
<projectUrl>http://www.fluentassertions.com</projectUrl>
19-
<requireLicenseAcceptance>false</requireLicenseAcceptance>
19+
<requireLicenseAcceptance>false</requireLicenseAcceptance>
2020
<tags>FluentAssertions Analyzers</tags>
21-
<frameworkAssemblies>
21+
<frameworkAssemblies>
2222
<frameworkAssembly assemblyName="System" targetFramework="" />
2323
</frameworkAssemblies>
24-
<copyright>Copyright Meir Blachman 2017-</copyright>
24+
<copyright>Copyright Meir Blachman 2017</copyright>
2525
<releaseNotes>
2626
See https://github.com/Meir017/fluentassertions.bestpractices/releases/
2727
</releaseNotes>
Lines changed: 13 additions & 31 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,32 +15,23 @@ public class CollectionShouldIntersectWithAnalyzer : FluentAssertionsAnalyzer
1415
public const string DiagnosticId = Constants.Tips.Collections.CollectionShouldIntersectWith;
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 .IntersectWith() 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
2222
{
23-
return null;
24-
var visitor = new CollectionShouldIntersectWithSyntaxVisitor();
25-
statement.Accept(visitor);
26-
27-
if (visitor.IsValid)
23+
get
2824
{
29-
var properties = new Dictionary<string, string>
30-
{
31-
[Constants.DiagnosticProperties.VariableName] = visitor.VariableName,
32-
[Constants.DiagnosticProperties.Title] = Title
33-
}.ToImmutableDictionary();
34-
throw new System.NotImplementedException();
25+
yield return (new IntersectShouldNotBeEmptySyntaxVisitor(), new BecauseArgumentsSyntaxVisitor("NotBeEmpty", 0));
26+
}
27+
}
3528

36-
return Diagnostic.Create(
37-
descriptor: Rule,
38-
location: statement.Expression.GetLocation(),
39-
properties: properties,
40-
messageArgs: visitor.VariableName);
29+
private class IntersectShouldNotBeEmptySyntaxVisitor : FluentAssertionsWithArgumentCSharpSyntaxVisitor
30+
{
31+
protected override string MethodContainingArgument => "Intersect";
32+
public IntersectShouldNotBeEmptySyntaxVisitor() : base("Intersect", "Should", "NotBeEmpty")
33+
{
4134
}
42-
return null;
4335
}
4436
}
4537

@@ -49,16 +41,6 @@ public class CollectionShouldIntersectWithCodeFix : FluentAssertionsCodeFixProvi
4941
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldIntersectWithAnalyzer.DiagnosticId);
5042

5143
protected override StatementSyntax GetNewStatement(FluentAssertionsDiagnosticProperties properties)
52-
{
53-
throw new System.NotImplementedException();
54-
}
55-
}
56-
57-
public class CollectionShouldIntersectWithSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor
58-
{
59-
public CollectionShouldIntersectWithSyntaxVisitor() : base("###")
60-
{
61-
throw new System.NotImplementedException();
62-
}
44+
=> SyntaxFactory.ParseStatement($"{properties.VariableName}.Should().IntersectWith({properties.CombineWithBecauseArgumentsString(properties.ArgumentString)});");
6345
}
6446
}
Lines changed: 12 additions & 30 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;
@@ -17,29 +18,20 @@ public class CollectionShouldNotContainNullsAnalyzer : FluentAssertionsAnalyzer
1718
public const string Message = "Use {0} .Should() followed by ### 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
2222
{
23-
return null;
24-
var visitor = new CollectionShouldNotContainNullsSyntaxVisitor();
25-
statement.Accept(visitor);
26-
27-
if (visitor.IsValid)
23+
get
2824
{
29-
var properties = new Dictionary<string, string>
30-
{
31-
[Constants.DiagnosticProperties.VariableName] = visitor.VariableName,
32-
[Constants.DiagnosticProperties.Title] = Title
33-
}.ToImmutableDictionary();
34-
throw new System.NotImplementedException();
25+
yield return (new SelectShouldNotContainNullsSyntaxVisitor(), new BecauseArgumentsSyntaxVisitor("NotContainNulls", 0));
26+
}
27+
}
3528

36-
return Diagnostic.Create(
37-
descriptor: Rule,
38-
location: statement.Expression.GetLocation(),
39-
properties: properties,
40-
messageArgs: visitor.VariableName);
29+
private class SelectShouldNotContainNullsSyntaxVisitor : FluentAssertionsWithLambdaArgumentCSharpSyntaxVisitor
30+
{
31+
protected override string MethodContainingLambda => "Select";
32+
public SelectShouldNotContainNullsSyntaxVisitor() : base("Select", "Should", "NotContainNulls")
33+
{
4134
}
42-
return null;
4335
}
4436
}
4537

@@ -49,16 +41,6 @@ public class CollectionShouldNotContainNullsCodeFix : FluentAssertionsCodeFixPro
4941
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldNotContainNullsAnalyzer.DiagnosticId);
5042

5143
protected override StatementSyntax GetNewStatement(FluentAssertionsDiagnosticProperties properties)
52-
{
53-
throw new System.NotImplementedException();
54-
}
55-
}
56-
57-
public class CollectionShouldNotContainNullsSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor
58-
{
59-
public CollectionShouldNotContainNullsSyntaxVisitor() : base("###")
60-
{
61-
throw new System.NotImplementedException();
62-
}
44+
=> SyntaxFactory.ParseStatement($"{properties.VariableName}.Should().NotContainNulls({properties.CombineWithBecauseArgumentsString(properties.LambdaString)});");
6345
}
6446
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public class CollectionShouldNotContainPropertyAnalyzer : FluentAssertionsAnalyz
1616
public const string Category = Constants.Tips.Category;
1717

1818
public const string Message = "Use {0} .Should() followed by .NotContain() instead.";
19-
19+
2020
protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true);
2121
protected override IEnumerable<(FluentAssertionsCSharpSyntaxVisitor, BecauseArgumentsSyntaxVisitor)> Visitors
2222
{
@@ -42,7 +42,7 @@ public WhereShouldBeEmptySyntaxVisitor() : base("Where", "Should", "BeEmpty")
4242
{
4343
}
4444
}
45-
// actual.Should().OnlyContain(e => !e.BooleanProperty{0});
45+
4646
private class ShouldOnlyContainNotSyntaxVisitor : FluentAssertionsWithLambdaArgumentCSharpSyntaxVisitor
4747
{
4848
protected override string MethodContainingLambda => "OnlyContain";
Lines changed: 13 additions & 32 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,32 +15,22 @@ public class CollectionShouldNotIntersectWithAnalyzer : FluentAssertionsAnalyzer
1415
public const string DiagnosticId = Constants.Tips.Collections.CollectionShouldNotIntersectWith;
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 .NotIntersectWith() 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
2222
{
23-
return null;
24-
var visitor = new CollectionShouldNotIntersectWithSyntaxVisitor();
25-
statement.Accept(visitor);
26-
27-
if (visitor.IsValid)
23+
get
24+
{
25+
yield return (new IntersectShouldBeEmptySyntaxVisitor(), new BecauseArgumentsSyntaxVisitor("BeEmpty", 0));
26+
}
27+
}
28+
private class IntersectShouldBeEmptySyntaxVisitor : FluentAssertionsWithArgumentCSharpSyntaxVisitor
29+
{
30+
protected override string MethodContainingArgument => "Intersect";
31+
public IntersectShouldBeEmptySyntaxVisitor() : base("Intersect", "Should", "BeEmpty")
2832
{
29-
var properties = new Dictionary<string, string>
30-
{
31-
[Constants.DiagnosticProperties.VariableName] = visitor.VariableName,
32-
[Constants.DiagnosticProperties.Title] = Title
33-
}.ToImmutableDictionary();
34-
throw new System.NotImplementedException();
35-
36-
return Diagnostic.Create(
37-
descriptor: Rule,
38-
location: statement.Expression.GetLocation(),
39-
properties: properties,
40-
messageArgs: visitor.VariableName);
4133
}
42-
return null;
4334
}
4435
}
4536

@@ -49,16 +40,6 @@ public class CollectionShouldNotIntersectWithCodeFix : FluentAssertionsCodeFixPr
4940
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldNotIntersectWithAnalyzer.DiagnosticId);
5041

5142
protected override StatementSyntax GetNewStatement(FluentAssertionsDiagnosticProperties properties)
52-
{
53-
throw new System.NotImplementedException();
54-
}
55-
}
56-
57-
public class CollectionShouldNotIntersectWithSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor
58-
{
59-
public CollectionShouldNotIntersectWithSyntaxVisitor() : base("###")
60-
{
61-
throw new System.NotImplementedException();
62-
}
43+
=> SyntaxFactory.ParseStatement($"{properties.VariableName}.Should().NotIntersectWith({properties.CombineWithBecauseArgumentsString(properties.ArgumentString)});");
6344
}
6445
}

0 commit comments

Comments
 (0)