From dd3a22eea3fad26ae3d520dce36f0f3d15950af4 Mon Sep 17 00:00:00 2001 From: Meir Blachman Date: Tue, 12 Dec 2023 06:55:20 +0200 Subject: [PATCH] introduce single CollectionAnalyzer for collection assertions (#251) * introduce single CollectionAnalyzer for collection assertions * Restore help links for collection assertions * cleanup * consolidate CollectionShouldNotContainProperty into collection analyzer * Update CollectionTests.cs and remove CollectionShouldHaveElementAt0Null.cs * Refactor collection intersection code * revert some changes * update TODOs * cleanup collections --- .../Tips/CollectionTests.cs | 112 ++++---- .../Tips/SanityTests.cs | 4 +- src/FluentAssertions.Analyzers/Constants.cs | 27 +- .../Tips/Collections/CollectionAnalyzer.cs | 239 +++++++++++++++++- .../Collections/CollectionBaseAnalyzer.cs | 19 ++ .../Collections/CollectionShouldBeEmpty.cs | 45 +--- .../CollectionShouldBeInAscendingOrder.cs | 45 +--- .../CollectionShouldBeInDescendingOrder.cs | 45 +--- .../CollectionShouldContainItem.cs | 44 +--- .../CollectionShouldContainProperty.cs | 59 +---- .../CollectionShouldContainSingle.cs | 64 +---- ...ionShouldEqualOtherCollectionByComparer.cs | 30 +-- .../Collections/CollectionShouldHaveCount.cs | 59 +---- ...llectionShouldHaveCountGreaterOrEqualTo.cs | 40 +-- .../CollectionShouldHaveCountGreaterThan.cs | 40 +-- .../CollectionShouldHaveCountLessOrEqualTo.cs | 38 +-- .../CollectionShouldHaveCountLessThan.cs | 40 +-- .../CollectionShouldHaveElementAt.cs | 4 +- .../CollectionShouldHaveElementAt0Null.cs | 39 --- .../CollectionShouldHaveSameCount.cs | 35 +-- .../CollectionShouldIntersectWith.cs | 43 +--- .../Collections/CollectionShouldNotBeEmpty.cs | 42 +-- .../CollectionShouldNotBeNullOrEmpty.cs | 2 +- .../CollectionShouldNotContainItem.cs | 43 +--- .../CollectionShouldNotContainNulls.cs | 43 +--- .../CollectionShouldNotContainProperty.cs | 66 +---- .../CollectionShouldNotHaveCount.cs | 40 +-- .../CollectionShouldNotHaveSameCount.cs | 38 +-- .../CollectionShouldNotIntersectWith.cs | 42 +-- .../CollectionShouldOnlyContainProperty.cs | 44 +--- .../CollectionShouldOnlyHaveUniqueItems.cs | 36 +-- ...tionShouldOnlyHaveUniqueItemsByComparer.cs | 44 +--- .../Utilities/HelpLinks.cs | 62 ++--- 33 files changed, 413 insertions(+), 1160 deletions(-) create mode 100644 src/FluentAssertions.Analyzers/Tips/Collections/CollectionBaseAnalyzer.cs delete mode 100644 src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldHaveElementAt0Null.cs diff --git a/src/FluentAssertions.Analyzers.Tests/Tips/CollectionTests.cs b/src/FluentAssertions.Analyzers.Tests/Tips/CollectionTests.cs index c027e735..477c2c1c 100644 --- a/src/FluentAssertions.Analyzers.Tests/Tips/CollectionTests.cs +++ b/src/FluentAssertions.Analyzers.Tests/Tips/CollectionTests.cs @@ -11,7 +11,7 @@ public class CollectionTests [AssertionDiagnostic("actual.Any().Should().BeTrue({0});")] [AssertionDiagnostic("actual.AsEnumerable().Any().Should().BeTrue({0}).And.ToString();")] [Implemented] - public void ExpressionBodyAssertion_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticExpressionBody(assertion); + public void ExpressionBodyAssertion_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticExpressionBody(assertion); [AssertionDataTestMethod] [AssertionCodeFix( @@ -21,13 +21,13 @@ public class CollectionTests oldAssertion: "actual.AsEnumerable().Any().Should().BeTrue({0}).And.ToString();", newAssertion: "actual.AsEnumerable().Should().NotBeEmpty({0}).And.ToString();")] [Implemented] - public void ExpressionBodyAssertion_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixExpressionBody(oldAssertion, newAssertion); + public void ExpressionBodyAssertion_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixExpressionBody(oldAssertion, newAssertion); [AssertionDataTestMethod] [AssertionDiagnostic("actual.Any().Should().BeTrue({0});")] [AssertionDiagnostic("actual.AsEnumerable().Any().Should().BeTrue({0}).And.ToString();")] [Implemented] - public void CollectionsShouldNotBeEmpty_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); + public void CollectionsShouldNotBeEmpty_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); [AssertionDataTestMethod] [AssertionCodeFix( @@ -37,13 +37,13 @@ public class CollectionTests oldAssertion: "actual.AsEnumerable().Any().Should().BeTrue({0}).And.ToString();", newAssertion: "actual.AsEnumerable().Should().NotBeEmpty({0}).And.ToString();")] [Implemented] - public void CollectionsShouldNotBeEmpty_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); + public void CollectionsShouldNotBeEmpty_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); [AssertionDataTestMethod] [AssertionDiagnostic("actual.Any().Should().BeTrue({0});")] [AssertionDiagnostic("actual.AsEnumerable().Any().Should().BeTrue({0}).And.ToString();")] [Implemented] - public void CollectionsShouldNotBeEmpty_Array_TestAnalyzer(string assertion) => VerifyArrayCSharpDiagnosticCodeBlock(assertion); + public void CollectionsShouldNotBeEmpty_Array_TestAnalyzer(string assertion) => VerifyArrayCSharpDiagnosticCodeBlock(assertion); [AssertionDataTestMethod] [AssertionCodeFix( @@ -53,7 +53,7 @@ public class CollectionTests oldAssertion: "actual.AsEnumerable().Any().Should().BeTrue({0}).And.ToString();", newAssertion: "actual.AsEnumerable().Should().NotBeEmpty({0}).And.ToString();")] [Implemented] - public void CollectionsShouldNotBeEmpty_Array_TestCodeFix(string oldAssertion, string newAssertion) => VerifyArrayCSharpFixCodeBlock(oldAssertion, newAssertion); + public void CollectionsShouldNotBeEmpty_Array_TestCodeFix(string oldAssertion, string newAssertion) => VerifyArrayCSharpFixCodeBlock(oldAssertion, newAssertion); [AssertionDataTestMethod] [AssertionDiagnostic("actual.Any().Should().BeFalse({0});")] @@ -61,7 +61,7 @@ public class CollectionTests [AssertionDiagnostic("actual.AsEnumerable().Any().Should().BeFalse({0}).And.ToString();")] [AssertionDiagnostic("actual.AsEnumerable().Should().HaveCount(0{0}).And.ToString();")] [Implemented] - public void CollectionsShouldBeEmpty_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); + public void CollectionsShouldBeEmpty_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); [AssertionDataTestMethod] [AssertionCodeFix( @@ -77,7 +77,7 @@ public class CollectionTests oldAssertion: "actual.AsEnumerable().Should().HaveCount(0{0}).And.ToString();", newAssertion: "actual.AsEnumerable().Should().BeEmpty({0}).And.ToString();")] [Implemented] - public void CollectionsShouldBeEmpty_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); + public void CollectionsShouldBeEmpty_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); [AssertionDataTestMethod] [AssertionDiagnostic("actual.Any(x => x.BooleanProperty).Should().BeTrue({0});")] @@ -85,7 +85,7 @@ public class CollectionTests [AssertionDiagnostic("actual.AsEnumerable().Any(x => x.BooleanProperty).Should().BeTrue({0}).And.ToString();")] [AssertionDiagnostic("actual.AsEnumerable().Where(x => x.BooleanProperty).Should().NotBeEmpty({0}).And.ToString();")] [Implemented] - public void CollectionShouldContainProperty_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); + public void CollectionShouldContainProperty_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); [AssertionDataTestMethod] [AssertionCodeFix( @@ -101,7 +101,7 @@ public class CollectionTests oldAssertion: "actual.AsEnumerable().Where(x => x.BooleanProperty).Should().NotBeEmpty({0}).And.ToString();", newAssertion: "actual.AsEnumerable().Should().Contain(x => x.BooleanProperty{0}).And.ToString();")] [Implemented] - public void CollectionShouldContainProperty_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); + public void CollectionShouldContainProperty_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); [AssertionDataTestMethod] [AssertionDiagnostic("actual.Any(x => x.BooleanProperty).Should().BeFalse({0});")] @@ -111,7 +111,7 @@ public class CollectionTests [AssertionDiagnostic("actual.AsEnumerable().Where(x => x.BooleanProperty).Should().BeEmpty({0}).And.ToString();")] [AssertionDiagnostic("actual.AsEnumerable().Should().OnlyContain(x => !x.BooleanProperty{0}).And.ToString();", ignore: true)] [Implemented] - public void CollectionShouldNotContainProperty_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); + public void CollectionShouldNotContainProperty_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); [AssertionDataTestMethod] [AssertionCodeFix( @@ -135,13 +135,13 @@ public class CollectionTests newAssertion: "actual.AsEnumerable().Should().NotContain(x => x.BooleanProperty{0}).And.ToString();", ignore: true)] [Implemented] - public void CollectionShouldNotContainProperty_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); + public void CollectionShouldNotContainProperty_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); [AssertionDataTestMethod] [AssertionDiagnostic("actual.All(x => x.BooleanProperty).Should().BeTrue({0});")] [AssertionDiagnostic("actual.AsEnumerable().All(x => x.BooleanProperty).Should().BeTrue({0}).And.ToString();")] [Implemented] - public void CollectionShouldOnlyContainProperty_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); + public void CollectionShouldOnlyContainProperty_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); [AssertionDataTestMethod] [AssertionCodeFix( @@ -151,13 +151,13 @@ public class CollectionTests oldAssertion: "actual.AsEnumerable().All(x => x.BooleanProperty).Should().BeTrue({0}).And.ToString();", newAssertion: "actual.AsEnumerable().Should().OnlyContain(x => x.BooleanProperty{0}).And.ToString();")] [Implemented] - public void CollectionShouldOnlyContainProperty_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); + public void CollectionShouldOnlyContainProperty_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); [AssertionDataTestMethod] [AssertionDiagnostic("actual.Contains(expectedItem).Should().BeTrue({0});")] [AssertionDiagnostic("actual.AsEnumerable().Contains(expectedItem).Should().BeTrue({0}).And.ToString();")] [Implemented] - public void CollectionShouldContainItem_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); + public void CollectionShouldContainItem_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); [AssertionDataTestMethod] [AssertionCodeFix( @@ -167,13 +167,13 @@ public class CollectionTests oldAssertion: "actual.AsEnumerable().Contains(expectedItem).Should().BeTrue({0}).And.ToString();", newAssertion: "actual.AsEnumerable().Should().Contain(expectedItem{0}).And.ToString();")] [Implemented] - public void CollectionShouldContainItem_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); + public void CollectionShouldContainItem_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); [AssertionDataTestMethod] [AssertionDiagnostic("actual.Contains(unexpectedItem).Should().BeFalse({0});")] [AssertionDiagnostic("actual.AsEnumerable().Contains(unexpectedItem).Should().BeFalse({0}).And.ToString();")] [Implemented] - public void CollectionShouldNotContainItem_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); + public void CollectionShouldNotContainItem_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); [AssertionDataTestMethod] [AssertionCodeFix( @@ -183,7 +183,7 @@ public class CollectionTests oldAssertion: "actual.AsEnumerable().Contains(unexpectedItem).Should().BeFalse({0}).And.ToString();", newAssertion: "actual.AsEnumerable().Should().NotContain(unexpectedItem{0}).And.ToString();")] [Implemented] - public void CollectionShouldNotContainItem_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); + public void CollectionShouldNotContainItem_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); [AssertionDataTestMethod] [AssertionDiagnostic("actual.Count().Should().Be(k{0});")] @@ -195,7 +195,7 @@ public class CollectionTests [AssertionDiagnostic("actual.ToArray().Length.Should().Be(k{0}).And.ToString();")] [AssertionDiagnostic("actual.ToArray().Length.Should().Be(6{0}).And.ToString();")] [Implemented] - public void CollectionShouldHaveCount_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); + public void CollectionShouldHaveCount_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); [AssertionDataTestMethod] [AssertionCodeFix( @@ -232,7 +232,7 @@ public class CollectionTests oldAssertion: "actual.ToArray().Length.Should().Be(6{0}).And.ToString();", newAssertion: "actual.ToArray().Should().HaveCount(6{0}).And.ToString();")] [Implemented] - public void CollectionShouldHaveCount_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); + public void CollectionShouldHaveCount_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); [AssertionDataTestMethod] [AssertionDiagnostic("actual.Count().Should().BeGreaterThan(k{0});")] @@ -240,7 +240,7 @@ public class CollectionTests [AssertionDiagnostic("actual.AsEnumerable().Count().Should().BeGreaterThan(k{0}).And.ToString();")] [AssertionDiagnostic("actual.AsEnumerable().Count().Should().BeGreaterThan(6{0}).And.ToString();")] [Implemented] - public void CollectionShouldHaveCountGreaterThan_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); + public void CollectionShouldHaveCountGreaterThan_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); [AssertionDataTestMethod] [AssertionCodeFix( @@ -256,7 +256,7 @@ public class CollectionTests oldAssertion: "actual.AsEnumerable().Count().Should().BeGreaterThan(6{0}).And.ToString();", newAssertion: "actual.AsEnumerable().Should().HaveCountGreaterThan(6{0}).And.ToString();")] [Implemented] - public void CollectionShouldHaveCountGreaterThan_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); + public void CollectionShouldHaveCountGreaterThan_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); [AssertionDataTestMethod] [AssertionDiagnostic("actual.Count().Should().BeGreaterOrEqualTo(k{0});")] @@ -264,7 +264,7 @@ public class CollectionTests [AssertionDiagnostic("actual.AsEnumerable().Count().Should().BeGreaterOrEqualTo(k{0}).And.ToString();")] [AssertionDiagnostic("actual.AsEnumerable().Count().Should().BeGreaterOrEqualTo(6{0}).And.ToString();")] [Implemented] - public void CollectionShouldHaveCountGreaterOrEqualTo_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); + public void CollectionShouldHaveCountGreaterOrEqualTo_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); [AssertionDataTestMethod] [AssertionCodeFix( @@ -280,7 +280,7 @@ public class CollectionTests oldAssertion: "actual.AsEnumerable().Count().Should().BeGreaterOrEqualTo(6{0}).And.ToString();", newAssertion: "actual.AsEnumerable().Should().HaveCountGreaterOrEqualTo(6{0}).And.ToString();")] [Implemented] - public void CollectionShouldHaveCountGreaterOrEqualTo_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); + public void CollectionShouldHaveCountGreaterOrEqualTo_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); [AssertionDataTestMethod] [AssertionDiagnostic("actual.Count().Should().BeLessThan(k{0});")] @@ -288,7 +288,7 @@ public class CollectionTests [AssertionDiagnostic("actual.AsEnumerable().Count().Should().BeLessThan(k{0}).And.ToString();")] [AssertionDiagnostic("actual.AsEnumerable().Count().Should().BeLessThan(6{0}).And.ToString();")] [Implemented] - public void CollectionShouldHaveCountLessThan_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); + public void CollectionShouldHaveCountLessThan_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); [AssertionDataTestMethod] [AssertionCodeFix( @@ -304,7 +304,7 @@ public class CollectionTests oldAssertion: "actual.AsEnumerable().Count().Should().BeLessThan(6{0}).And.ToString();", newAssertion: "actual.AsEnumerable().Should().HaveCountLessThan(6{0}).And.ToString();")] [Implemented] - public void CollectionShouldHaveCountLessThan_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); + public void CollectionShouldHaveCountLessThan_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); [AssertionDataTestMethod] [AssertionDiagnostic("actual.Count().Should().BeLessOrEqualTo(k{0});")] @@ -312,7 +312,7 @@ public class CollectionTests [AssertionDiagnostic("actual.AsEnumerable().Count().Should().BeLessOrEqualTo(k{0}).And.ToString();")] [AssertionDiagnostic("actual.AsEnumerable().Count().Should().BeLessOrEqualTo(6{0}).And.ToString();")] [Implemented] - public void CollectionShouldHaveCountLessOrEqualTo_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); + public void CollectionShouldHaveCountLessOrEqualTo_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); [AssertionDataTestMethod] [AssertionCodeFix( @@ -328,7 +328,7 @@ public class CollectionTests oldAssertion: "actual.AsEnumerable().Count().Should().BeLessOrEqualTo(6{0}).And.ToString();", newAssertion: "actual.AsEnumerable().Should().HaveCountLessOrEqualTo(6{0}).And.ToString();")] [Implemented] - public void CollectionShouldHaveCountLessOrEqualTo_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); + public void CollectionShouldHaveCountLessOrEqualTo_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); [AssertionDataTestMethod] [AssertionDiagnostic("actual.Count().Should().NotBe(k{0});")] @@ -336,7 +336,7 @@ public class CollectionTests [AssertionDiagnostic("actual.AsEnumerable().Count().Should().NotBe(k{0}).And.ToString();")] [AssertionDiagnostic("actual.AsEnumerable().Count().Should().NotBe(6{0}).And.ToString();")] [Implemented] - public void CollectionShouldNotHaveCount_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); + public void CollectionShouldNotHaveCount_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); [AssertionDataTestMethod] [AssertionCodeFix( @@ -352,13 +352,13 @@ public class CollectionTests oldAssertion: "actual.AsEnumerable().Count().Should().NotBe(6{0}).And.ToString();", newAssertion: "actual.AsEnumerable().Should().NotHaveCount(6{0}).And.ToString();")] [Implemented] - public void CollectionShouldNotHaveCount_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); + public void CollectionShouldNotHaveCount_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); [AssertionDataTestMethod] [AssertionDiagnostic("actual.Should().HaveCount(expected.Count(){0});")] [AssertionDiagnostic("actual.AsEnumerable().Should().HaveCount(expected.Count(){0}).And.ToString();")] [Implemented] - public void CollectionShouldHaveSameCount_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); + public void CollectionShouldHaveSameCount_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); [AssertionDataTestMethod] [AssertionCodeFix( @@ -368,13 +368,13 @@ public class CollectionTests oldAssertion: "actual.AsEnumerable().Should().HaveCount(expected.Count(){0}).And.ToString();", newAssertion: "actual.AsEnumerable().Should().HaveSameCount(expected{0}).And.ToString();")] [Implemented] - public void CollectionShouldHaveSameCount_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); + public void CollectionShouldHaveSameCount_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); [AssertionDataTestMethod] [AssertionDiagnostic("actual.Count().Should().NotBe(unexpected.Count(){0});")] [AssertionDiagnostic("actual.AsEnumerable().Count().Should().NotBe(unexpected.Count(){0}).And.ToString();")] [Implemented] - public void CollectionShouldNotHaveSameCount_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); + public void CollectionShouldNotHaveSameCount_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); [AssertionDataTestMethod] [AssertionCodeFix( @@ -384,7 +384,7 @@ public class CollectionTests oldAssertion: "actual.AsEnumerable().Count().Should().NotBe(unexpected.Count(){0}).And.ToString();", newAssertion: "actual.AsEnumerable().Should().NotHaveSameCount(unexpected{0}).And.ToString();")] [Implemented] - public void CollectionShouldNotHaveSameCount_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); + public void CollectionShouldNotHaveSameCount_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); [AssertionDataTestMethod] [AssertionDiagnostic("actual.Should().HaveCount(1{0});")] @@ -395,8 +395,8 @@ public void CollectionShouldContainSingle_TestAnalyzer_GenericIEnumerableShouldR DiagnosticVerifier.VerifyCSharpDiagnosticUsingAllAnalyzers(source, new DiagnosticResult { - Id = CollectionShouldContainSingleAnalyzer.DiagnosticId, - Message = CollectionShouldContainSingleAnalyzer.Message, + Id = CollectionAnalyzer.DiagnosticId, + Message = CollectionAnalyzer.Message, Locations = new DiagnosticResultLocation[] { new DiagnosticResultLocation("Test0.cs", 11,13) @@ -411,7 +411,7 @@ public void CollectionShouldContainSingle_TestAnalyzer_GenericIEnumerableShouldR [AssertionDiagnostic("actual.AsEnumerable().Should().HaveCount(1{0}).And.ToString();")] [AssertionDiagnostic("actual.AsEnumerable().Where(x => x.BooleanProperty).Should().HaveCount(1{0}).And.ToString();")] [Implemented] - public void CollectionShouldContainSingle_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); + public void CollectionShouldContainSingle_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); [AssertionDataTestMethod] [AssertionCodeFix( @@ -427,7 +427,7 @@ public void CollectionShouldContainSingle_TestAnalyzer_GenericIEnumerableShouldR oldAssertion: "actual.AsEnumerable().Should().HaveCount(1{0}).And.ToString();", newAssertion: "actual.AsEnumerable().Should().ContainSingle({0}).And.ToString();")] [Implemented] - public void CollectionShouldContainSingle_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); + public void CollectionShouldContainSingle_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); [AssertionDataTestMethod] [AssertionDiagnostic("actual.Should().NotBeNull().And.NotBeEmpty({0});")] @@ -513,7 +513,7 @@ public void CollectionShouldContainSingle_TestAnalyzer_GenericIEnumerableShouldR [AssertionDiagnostic("actual.OrderBy(x => x.BooleanProperty).Should().Equal(actual{0});")] [AssertionDiagnostic("actual.AsEnumerable().OrderBy(x => x.BooleanProperty).Should().Equal(actual{0}).And.ToString();")] [Implemented] - public void CollectionShouldBeInAscendingOrder_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); + public void CollectionShouldBeInAscendingOrder_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); [AssertionDataTestMethod] [AssertionCodeFix( @@ -523,13 +523,13 @@ public void CollectionShouldContainSingle_TestAnalyzer_GenericIEnumerableShouldR oldAssertion: "actual.AsEnumerable().OrderBy(x => x.BooleanProperty).Should().Equal(actual{0}).And.ToString();", newAssertion: "actual.AsEnumerable().Should().BeInAscendingOrder(x => x.BooleanProperty{0}).And.ToString();")] [Implemented] - public void CollectionShouldBeInAscendingOrder_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); + public void CollectionShouldBeInAscendingOrder_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); [AssertionDataTestMethod] [AssertionDiagnostic("actual.OrderByDescending(x => x.BooleanProperty).Should().Equal(actual{0});")] [AssertionDiagnostic("actual.AsEnumerable().OrderByDescending(x => x.BooleanProperty).Should().Equal(actual{0}).And.ToString();")] [Implemented] - public void CollectionShouldBeInDescendingOrder_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); + public void CollectionShouldBeInDescendingOrder_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); [AssertionDataTestMethod] [AssertionCodeFix( @@ -539,13 +539,13 @@ public void CollectionShouldContainSingle_TestAnalyzer_GenericIEnumerableShouldR oldAssertion: "actual.AsEnumerable().OrderByDescending(x => x.BooleanProperty).Should().Equal(actual{0}).And.ToString();", newAssertion: "actual.AsEnumerable().Should().BeInDescendingOrder(x => x.BooleanProperty{0}).And.ToString();")] [Implemented] - public void CollectionShouldBeInDescendingOrder_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); + public void CollectionShouldBeInDescendingOrder_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); [AssertionDataTestMethod] [AssertionDiagnostic("actual.Select(e1 => e1.BooleanProperty).Should().Equal(expected.Select(e2 => e2.BooleanProperty){0});")] [AssertionDiagnostic("actual.AsEnumerable().Select(e1 => e1.BooleanProperty).Should().Equal(expected.Select(e2 => e2.BooleanProperty){0}).And.ToString();")] [Implemented] - public void CollectionShouldEqualOtherCollectionByComparer_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); + public void CollectionShouldEqualOtherCollectionByComparer_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); [AssertionDataTestMethod] [AssertionCodeFix( @@ -555,13 +555,13 @@ public void CollectionShouldContainSingle_TestAnalyzer_GenericIEnumerableShouldR oldAssertion: "actual.AsEnumerable().Select(e1 => e1.BooleanProperty).Should().Equal(expected.Select(e2 => e2.BooleanProperty){0}).And.ToString();", newAssertion: "actual.AsEnumerable().Should().Equal(expected, (e1, e2) => e1.BooleanProperty == e2.BooleanProperty{0}).And.ToString();")] [Implemented] - public void CollectionShouldEqualOtherCollectionByComparer_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); + public void CollectionShouldEqualOtherCollectionByComparer_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); [AssertionDataTestMethod] [AssertionDiagnostic("actual.Intersect(expected).Should().BeEmpty({0});")] [AssertionDiagnostic("actual.AsEnumerable().Intersect(expected).Should().BeEmpty({0}).And.ToString();")] [Implemented] - public void CollectionShouldNotIntersectWith_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); + public void CollectionShouldNotIntersectWith_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); [AssertionDataTestMethod] [AssertionCodeFix( @@ -571,13 +571,13 @@ public void CollectionShouldContainSingle_TestAnalyzer_GenericIEnumerableShouldR oldAssertion: "actual.AsEnumerable().Intersect(expected).Should().BeEmpty({0}).And.ToString();", newAssertion: "actual.AsEnumerable().Should().NotIntersectWith(expected{0}).And.ToString();")] [Implemented] - public void CollectionShouldNotIntersectWith_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); + public void CollectionShouldNotIntersectWith_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); [AssertionDataTestMethod] [AssertionDiagnostic("actual.Intersect(expected).Should().NotBeEmpty({0});")] [AssertionDiagnostic("actual.AsEnumerable().Intersect(expected).Should().NotBeEmpty({0}).And.ToString();")] [Implemented] - public void CollectionShouldIntersectWith_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); + public void CollectionShouldIntersectWith_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); [AssertionDataTestMethod] [AssertionCodeFix( @@ -587,13 +587,13 @@ public void CollectionShouldContainSingle_TestAnalyzer_GenericIEnumerableShouldR oldAssertion: "actual.AsEnumerable().Intersect(expected).Should().NotBeEmpty({0}).And.ToString();", newAssertion: "actual.AsEnumerable().Should().IntersectWith(expected{0}).And.ToString();")] [Implemented] - public void CollectionShouldIntersectWith_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); + public void CollectionShouldIntersectWith_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); [AssertionDataTestMethod] [AssertionDiagnostic("actual.Select(x => x.BooleanProperty).Should().NotContainNulls({0});")] [AssertionDiagnostic("actual.AsEnumerable().Select(x => x.BooleanProperty).Should().NotContainNulls({0}).And.ToString();")] [Implemented] - public void CollectionShouldNotContainNulls_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); + public void CollectionShouldNotContainNulls_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); [AssertionDataTestMethod] [AssertionCodeFix( @@ -604,13 +604,13 @@ public void CollectionShouldContainSingle_TestAnalyzer_GenericIEnumerableShouldR newAssertion: "actual.AsEnumerable().Should().NotContainNulls(x => x.BooleanProperty{0}).And.ToString();")] [Implemented] [Ignore("What Should Happen?")] - public void CollectionShouldNotContainNulls_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); + public void CollectionShouldNotContainNulls_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); [AssertionDataTestMethod] [AssertionDiagnostic("actual.Should().HaveSameCount(actual.Distinct(){0});")] [AssertionDiagnostic("actual.AsEnumerable().Should().HaveSameCount(actual.AsEnumerable().Distinct(){0}).And.ToString();")] [Implemented] - public void CollectionShouldOnlyHaveUniqueItems_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); + public void CollectionShouldOnlyHaveUniqueItems_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); [AssertionDataTestMethod] [AssertionCodeFix( @@ -620,13 +620,13 @@ public void CollectionShouldContainSingle_TestAnalyzer_GenericIEnumerableShouldR oldAssertion: "actual.AsEnumerable().Should().HaveSameCount(actual.AsEnumerable().Distinct(){0}).And.ToString();", newAssertion: "actual.AsEnumerable().Should().OnlyHaveUniqueItems({0}).And.ToString();")] [Implemented] - public void CollectionShouldOnlyHaveUniqueItems_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); + public void CollectionShouldOnlyHaveUniqueItems_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); [AssertionDataTestMethod] [AssertionDiagnostic("actual.Select(x => x.BooleanProperty).Should().OnlyHaveUniqueItems({0});")] [AssertionDiagnostic("actual.AsEnumerable().Select(x => x.BooleanProperty).Should().OnlyHaveUniqueItems({0}).And.ToString();")] [Implemented] - public void CollectionShouldOnlyHaveUniqueItemsByComparer_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); + public void CollectionShouldOnlyHaveUniqueItemsByComparer_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); [AssertionDataTestMethod] [AssertionCodeFix( @@ -636,14 +636,14 @@ public void CollectionShouldContainSingle_TestAnalyzer_GenericIEnumerableShouldR [AssertionCodeFix( oldAssertion: "actual.AsEnumerable().Select(x => x.BooleanProperty).Should().OnlyHaveUniqueItems({0}).And.ToString();", newAssertion: "actual.AsEnumerable().Should().OnlyHaveUniqueItems(x => x.BooleanProperty{0}).And.ToString();")] - public void CollectionShouldOnlyHaveUniqueItemsByComparer_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); + public void CollectionShouldOnlyHaveUniqueItemsByComparer_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); [AssertionDataTestMethod] [AssertionDiagnostic("actual.FirstOrDefault().Should().BeNull({0});")] [NotImplemented] [AssertionDiagnostic("actual.AsEnumerable().FirstOrDefault().Should().BeNull({0}).And.ToString();")] [Ignore("What Should Happen?")] - public void CollectionShouldHaveElementAt0Null_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); + public void CollectionShouldHaveElementAt0Null_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion); [AssertionDataTestMethod] [AssertionCodeFix( @@ -654,7 +654,7 @@ public void CollectionShouldContainSingle_TestAnalyzer_GenericIEnumerableShouldR oldAssertion: "actual.AsEnumerable().FirstOrDefault().Should().BeNull({0}).And.ToString();", newAssertion: "actual.AsEnumerable().Should().HaveElementAt(0, null{0}).And.ToString();")] [Ignore("What Should Happen?")] - public void CollectionShouldHaveElementAt0Null_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); + public void CollectionShouldHaveElementAt0Null_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFixCodeBlock(oldAssertion, newAssertion); private void VerifyCSharpDiagnosticCodeBlock(string sourceAssertion) where TDiagnosticAnalyzer : Microsoft.CodeAnalysis.Diagnostics.DiagnosticAnalyzer, new() { diff --git a/src/FluentAssertions.Analyzers.Tests/Tips/SanityTests.cs b/src/FluentAssertions.Analyzers.Tests/Tips/SanityTests.cs index 9b544abc..4ec54087 100644 --- a/src/FluentAssertions.Analyzers.Tests/Tips/SanityTests.cs +++ b/src/FluentAssertions.Analyzers.Tests/Tips/SanityTests.cs @@ -349,8 +349,8 @@ public class TestType3 DiagnosticVerifier.VerifyCSharpDiagnosticUsingAllAnalyzers(new[] { source }, new DiagnosticResult() { - Id = CollectionShouldNotBeEmptyAnalyzer.DiagnosticId, - Message = CollectionShouldNotBeEmptyAnalyzer.Message, + Id = CollectionAnalyzer.DiagnosticId, + Message = CollectionAnalyzer.Message, Severity = DiagnosticSeverity.Info, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 12, 9) } }); diff --git a/src/FluentAssertions.Analyzers/Constants.cs b/src/FluentAssertions.Analyzers/Constants.cs index 774d4ce5..3e54db57 100644 --- a/src/FluentAssertions.Analyzers/Constants.cs +++ b/src/FluentAssertions.Analyzers/Constants.cs @@ -4,6 +4,7 @@ public static class Constants { public static class DiagnosticProperties { + public const string RuleId = nameof(RuleId); public const string Title = nameof(Title); public const string VisitorName = nameof(VisitorName); public const string HelpLink = nameof(HelpLink); @@ -15,34 +16,8 @@ public static class Tips public const string Category = "FluentAssertionTips"; public static class Collections { - public const string CollectionsShouldBeEmpty = $"{DiagnosticProperties.IdPrefix}0000"; - public const string CollectionsShouldNotBeEmpty = $"{DiagnosticProperties.IdPrefix}0001"; - public const string CollectionShouldContainProperty = $"{DiagnosticProperties.IdPrefix}0002"; - public const string CollectionShouldNotContainProperty = $"{DiagnosticProperties.IdPrefix}0003"; - public const string CollectionShouldContainItem = $"{DiagnosticProperties.IdPrefix}0004"; - public const string CollectionShouldNotContainItem = $"{DiagnosticProperties.IdPrefix}0005"; - public const string CollectionShouldHaveCount = $"{DiagnosticProperties.IdPrefix}0006"; - public const string CollectionShouldHaveCountGreaterThan = $"{DiagnosticProperties.IdPrefix}0007"; - public const string CollectionShouldHaveCountGreaterOrEqualTo = $"{DiagnosticProperties.IdPrefix}0008"; - public const string CollectionShouldHaveCountLessThan = $"{DiagnosticProperties.IdPrefix}0009"; - public const string CollectionShouldHaveCountLessOrEqualTo = $"{DiagnosticProperties.IdPrefix}0010"; - public const string CollectionShouldNotHaveCount = $"{DiagnosticProperties.IdPrefix}0011"; - public const string CollectionShouldContainSingle = $"{DiagnosticProperties.IdPrefix}0012"; - public const string CollectionShouldOnlyContainProperty = $"{DiagnosticProperties.IdPrefix}0013"; - public const string CollectionShouldHaveSameCount = $"{DiagnosticProperties.IdPrefix}0014"; - public const string CollectionShouldNotHaveSameCount = $"{DiagnosticProperties.IdPrefix}0015"; - public const string CollectionShouldContainSingleProperty = $"{DiagnosticProperties.IdPrefix}0016"; public const string CollectionShouldNotBeNullOrEmpty = $"{DiagnosticProperties.IdPrefix}0017"; public const string CollectionShouldHaveElementAt = $"{DiagnosticProperties.IdPrefix}0018"; - public const string CollectionShouldBeInAscendingOrder = $"{DiagnosticProperties.IdPrefix}0019"; - public const string CollectionShouldBeInDescendingOrder = $"{DiagnosticProperties.IdPrefix}0020"; - public const string CollectionShouldEqualOtherCollectionByComparer = $"{DiagnosticProperties.IdPrefix}0021"; - public const string CollectionShouldNotIntersectWith = $"{DiagnosticProperties.IdPrefix}0022"; - public const string CollectionShouldIntersectWith = $"{DiagnosticProperties.IdPrefix}0023"; - public const string CollectionShouldNotContainNulls = $"{DiagnosticProperties.IdPrefix}0024"; - public const string CollectionShouldOnlyHaveUniqueItems = $"{DiagnosticProperties.IdPrefix}0025"; - public const string CollectionShouldOnlyHaveUniqueItemsByComparer = $"{DiagnosticProperties.IdPrefix}0026"; - public const string CollectionShouldHaveElementAt0Null = $"{DiagnosticProperties.IdPrefix}0027"; } public static class Dictionaries diff --git a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionAnalyzer.cs b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionAnalyzer.cs index b3376aed..9b715ac0 100644 --- a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionAnalyzer.cs +++ b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionAnalyzer.cs @@ -1,20 +1,239 @@ -using FluentAssertions.Analyzers.Utilities; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Composition; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; namespace FluentAssertions.Analyzers; -public abstract class CollectionAnalyzer : FluentAssertionsAnalyzer +[DiagnosticAnalyzer(LanguageNames.CSharp)] +public class CollectionAnalyzer : CollectionBaseAnalyzer { - protected override bool ShouldAnalyzeVariableNamedType(INamedTypeSymbol type, SemanticModel semanticModel) + public const string DiagnosticId = "FAA0001"; + public const string Message = "Clean up FluentAssertion usage."; + + protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Constants.Tips.Category, DiagnosticSeverity.Info, true); + + protected override IEnumerable Visitors { - return type.SpecialType != SpecialType.System_String - && type.IsTypeOrConstructedFromTypeOrImplementsType(SpecialType.System_Collections_Generic_IEnumerable_T); + get + { + yield return new CollectionShouldBeEmpty.AnyShouldBeFalseSyntaxVisitor(); + yield return new CollectionShouldBeEmpty.ShouldHaveCount0SyntaxVisitor(); + + yield return new CollectionShouldNotBeEmpty.AnyShouldBeTrueSyntaxVisitor(); + + yield return new CollectionShouldBeInAscendingOrder.OrderByShouldEqualSyntaxVisitor(); + yield return new CollectionShouldBeInDescendingOrder.OrderByDescendingShouldEqualSyntaxVisitor(); + + yield return new CollectionShouldContainItem.ContainsShouldBeTrueSyntaxVisitor(); + + yield return new CollectionShouldContainProperty.AnyWithLambdaShouldBeTrueSyntaxVisitor(); + yield return new CollectionShouldContainProperty.WhereShouldNotBeEmptySyntaxVisitor(); + + yield return new CollectionShouldContainSingle.WhereShouldHaveCount1SyntaxVisitor(); + yield return new CollectionShouldContainSingle.ShouldHaveCount1SyntaxVisitor(); + + yield return new CollectionShouldEqualOtherCollectionByComparer.SelectShouldEqualOtherCollectionSelectSyntaxVisitor(); + + yield return new CollectionShouldHaveCount.CountShouldBe0SyntaxVisitor(); + yield return new CollectionShouldHaveCount.CountShouldBe1SyntaxVisitor(); + yield return new CollectionShouldHaveCount.CountShouldBeSyntaxVisitor(); + yield return new CollectionShouldHaveCount.LengthShouldBeSyntaxVisitor(); + + yield return new CollectionShouldHaveCountGreaterOrEqualTo.CountShouldBeGreaterOrEqualToSyntaxVisitor(); + yield return new CollectionShouldHaveCountGreaterThan.CountShouldBeGreaterThanSyntaxVisitor(); + yield return new CollectionShouldHaveCountLessOrEqualTo.CountShouldBeLessOrEqualToSyntaxVisitor(); + yield return new CollectionShouldHaveCountLessThan.CountShouldBeLessThanSyntaxVisitor(); + + // TODO: Add support for CollectionShouldHaveElementAtAnalyzer + // TODO: Add support for CollectionShouldNotBeNullOrEmptyAnalyzer + + yield return new CollectionShouldIntersectWith.IntersectShouldNotBeEmptySyntaxVisitor(); + + yield return new CollectionShouldHaveSameCount.ShouldHaveCountOtherCollectionCountSyntaxVisitor(); + + yield return new CollectionShouldNotContainItem.ContainsShouldBeFalseSyntaxVisitor(); + + yield return new CollectionShouldNotContainNulls.SelectShouldNotContainNullsSyntaxVisitor(); + + yield return new CollectionShouldNotContainProperty.AnyLambdaShouldBeFalseSyntaxVisitor(); + yield return new CollectionShouldNotContainProperty.WhereShouldBeEmptySyntaxVisitor(); + // TODO: enable this: + // yield return new CollectionShouldNotContainProperty.ShouldOnlyContainNotSyntaxVisitor(); + + yield return new CollectionShouldNotHaveCount.CountShouldNotBeSyntaxVisitor(); + yield return new CollectionShouldNotHaveSameCount.CountShouldNotBeOtherCollectionCountSyntaxVisitor(); + + yield return new CollectionShouldNotIntersectWith.IntersectShouldBeEmptySyntaxVisitor(); + + yield return new CollectionShouldOnlyContainProperty.AllShouldBeTrueSyntaxVisitor(); + + yield return new CollectionShouldOnlyHaveUniqueItems.ShouldHaveSameCountThisCollectionDistinctSyntaxVisitor(); + yield return new CollectionShouldOnlyHaveUniqueItemsByComparer.SelectShouldOnlyHaveUniqueItemsSyntaxVisitor(); + } } +} - override protected bool ShouldAnalyzeVariableType(ITypeSymbol type, SemanticModel semanticModel) +[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(CollectionCodeFix)), Shared] +public partial class CollectionCodeFix : FluentAssertionsCodeFixProvider +{ + public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(CollectionAnalyzer.DiagnosticId); + + protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties) { - return type.SpecialType != SpecialType.System_String - && type.IsTypeOrConstructedFromTypeOrImplementsType(SpecialType.System_Collections_Generic_IEnumerable_T); - } + switch (properties.VisitorName) + { + case nameof(CollectionShouldBeEmpty.AnyShouldBeFalseSyntaxVisitor): + return GetNewExpression(expression, NodeReplacement.Remove("Any"), NodeReplacement.Rename("BeFalse", "BeEmpty")); + case nameof(CollectionShouldBeEmpty.ShouldHaveCount0SyntaxVisitor): + return GetNewExpression(expression, new CollectionShouldBeEmpty.HaveCountNodeReplacement()); + case nameof(CollectionShouldNotBeEmpty.AnyShouldBeTrueSyntaxVisitor): + return GetNewExpression(expression, NodeReplacement.Remove("Any"), NodeReplacement.Rename("BeTrue", "NotBeEmpty")); + case nameof(CollectionShouldBeInAscendingOrder.OrderByShouldEqualSyntaxVisitor): + { + var remove = NodeReplacement.RemoveAndExtractArguments("OrderBy"); + var newExpression = GetNewExpression(expression, remove); -} + newExpression = GetNewExpression(newExpression, NodeReplacement.RenameAndRemoveFirstArgument("Equal", "BeInAscendingOrder")); + + return GetNewExpression(newExpression, NodeReplacement.PrependArguments("BeInAscendingOrder", remove.Arguments)); + } + case nameof(CollectionShouldBeInDescendingOrder.OrderByDescendingShouldEqualSyntaxVisitor): + { + var remove = NodeReplacement.RemoveAndExtractArguments("OrderByDescending"); + var newExpression = GetNewExpression(expression, remove); + + newExpression = GetNewExpression(newExpression, NodeReplacement.RenameAndRemoveFirstArgument("Equal", "BeInDescendingOrder")); + + return GetNewExpression(newExpression, NodeReplacement.PrependArguments("BeInDescendingOrder", remove.Arguments)); + } + case nameof(CollectionShouldContainItem.ContainsShouldBeTrueSyntaxVisitor): + { + var remove = NodeReplacement.RemoveAndExtractArguments("Contains"); + var newExpression = GetNewExpression(expression, remove); + + return GetNewExpression(newExpression, NodeReplacement.RenameAndPrependArguments("BeTrue", "Contain", remove.Arguments)); + } + case nameof(CollectionShouldContainProperty.AnyWithLambdaShouldBeTrueSyntaxVisitor): + { + var remove = NodeReplacement.RemoveAndExtractArguments("Any"); + var newExpression = GetNewExpression(expression, remove); + + return GetNewExpression(newExpression, NodeReplacement.RenameAndPrependArguments("BeTrue", "Contain", remove.Arguments)); + } + case nameof(CollectionShouldContainProperty.WhereShouldNotBeEmptySyntaxVisitor): + { + var remove = NodeReplacement.RemoveAndExtractArguments("Where"); + var newExpression = GetNewExpression(expression, remove); + + return GetNewExpression(newExpression, NodeReplacement.RenameAndPrependArguments("NotBeEmpty", "Contain", remove.Arguments)); + } + case nameof(CollectionShouldContainSingle.ShouldHaveCount1SyntaxVisitor): + return GetNewExpression(expression, NodeReplacement.RenameAndRemoveFirstArgument("HaveCount", "ContainSingle")); + case nameof(CollectionShouldContainSingle.WhereShouldHaveCount1SyntaxVisitor): + { + var newExpression = GetNewExpression(expression, NodeReplacement.RenameAndRemoveFirstArgument("HaveCount", "ContainSingle")); + var remove = NodeReplacement.RemoveAndExtractArguments("Where"); + newExpression = GetNewExpression(newExpression, remove); + + return GetNewExpression(newExpression, NodeReplacement.PrependArguments("ContainSingle", remove.Arguments)); + } + case nameof(CollectionShouldEqualOtherCollectionByComparer.SelectShouldEqualOtherCollectionSelectSyntaxVisitor): + return GetNewExpressionForSelectShouldEqualOtherCollectionSelectSyntaxVisitor(expression); + case nameof(CollectionShouldHaveCount.CountShouldBe0SyntaxVisitor): + return GetNewExpression(expression, NodeReplacement.Remove("Count"), NodeReplacement.RenameAndRemoveFirstArgument("Be", "BeEmpty")); + case nameof(CollectionShouldHaveCount.CountShouldBe1SyntaxVisitor): + return GetNewExpression(expression, NodeReplacement.Remove("Count"), NodeReplacement.RenameAndRemoveFirstArgument("Be", "ContainSingle")); + case nameof(CollectionShouldHaveCount.CountShouldBeSyntaxVisitor): + return GetNewExpression(expression, NodeReplacement.Remove("Count"), NodeReplacement.Rename("Be", "HaveCount")); + case nameof(CollectionShouldHaveCount.LengthShouldBeSyntaxVisitor): + return GetNewExpression(expression, NodeReplacement.Remove("Length"), NodeReplacement.Rename("Be", "HaveCount")); + case nameof(CollectionShouldHaveCountGreaterOrEqualTo.CountShouldBeGreaterOrEqualToSyntaxVisitor): + return GetNewExpression(expression, NodeReplacement.Remove("Count"), NodeReplacement.Rename("BeGreaterOrEqualTo", "HaveCountGreaterOrEqualTo")); + case nameof(CollectionShouldHaveCountGreaterThan.CountShouldBeGreaterThanSyntaxVisitor): + return GetNewExpression(expression, NodeReplacement.Remove("Count"), NodeReplacement.Rename("BeGreaterThan", "HaveCountGreaterThan")); + case nameof(CollectionShouldHaveCountLessOrEqualTo.CountShouldBeLessOrEqualToSyntaxVisitor): + return GetNewExpression(expression, NodeReplacement.Remove("Count"), NodeReplacement.Rename("BeLessOrEqualTo", "HaveCountLessOrEqualTo")); + case nameof(CollectionShouldHaveCountLessThan.CountShouldBeLessThanSyntaxVisitor): + return GetNewExpression(expression, NodeReplacement.Remove("Count"), NodeReplacement.Rename("BeLessThan", "HaveCountLessThan")); + case nameof(CollectionShouldIntersectWith.IntersectShouldNotBeEmptySyntaxVisitor): + { + var remove = NodeReplacement.RemoveAndExtractArguments("Intersect"); + var newExpression = GetNewExpression(expression, remove); + + return GetNewExpression(newExpression, NodeReplacement.RenameAndPrependArguments("NotBeEmpty", "IntersectWith", remove.Arguments)); + } + case nameof(CollectionShouldHaveSameCount.ShouldHaveCountOtherCollectionCountSyntaxVisitor): + return GetNewExpression(expression, NodeReplacement.RenameAndRemoveInvocationOfMethodOnFirstArgument("HaveCount", "HaveSameCount")); + case nameof(CollectionShouldNotContainItem.ContainsShouldBeFalseSyntaxVisitor): + { + var remove = NodeReplacement.RemoveAndExtractArguments("Contains"); + var newExpression = GetNewExpression(expression, remove); + + return GetNewExpression(newExpression, NodeReplacement.RenameAndPrependArguments("BeFalse", "NotContain", remove.Arguments)); + } + case nameof(CollectionShouldNotContainNulls.SelectShouldNotContainNullsSyntaxVisitor): + { + var remove = NodeReplacement.RemoveAndExtractArguments("Select"); + var newExpression = GetNewExpression(expression, remove); + + return GetNewExpression(newExpression, NodeReplacement.PrependArguments("NotContainNulls", remove.Arguments)); + } + case nameof(CollectionShouldNotContainProperty.AnyLambdaShouldBeFalseSyntaxVisitor): + { + var remove = NodeReplacement.RemoveAndExtractArguments("Any"); + var newExpression = GetNewExpression(expression, remove); + + return GetNewExpression(newExpression, NodeReplacement.RenameAndPrependArguments("BeFalse", "NotContain", remove.Arguments)); + } + case nameof(CollectionShouldNotContainProperty.WhereShouldBeEmptySyntaxVisitor): + { + var remove = NodeReplacement.RemoveAndExtractArguments("Where"); + var newExpression = GetNewExpression(expression, remove); + + return GetNewExpression(newExpression, NodeReplacement.RenameAndPrependArguments("BeEmpty", "NotContain", remove.Arguments)); + } + /* + case nameof(CollectionShouldNotContainProperty.ShouldOnlyContainNotSyntaxVisitor): + { + return GetNewExpression(expression, NodeReplacement.RenameAndNegateLambda("OnlyContain", "NotContain")); + } + */ + + case nameof(CollectionShouldNotHaveCount.CountShouldNotBeSyntaxVisitor): + return GetNewExpression(expression, NodeReplacement.Remove("Count"), NodeReplacement.Rename("NotBe", "NotHaveCount")); ; + case nameof(CollectionShouldNotHaveSameCount.CountShouldNotBeOtherCollectionCountSyntaxVisitor): + return GetNewExpression(expression, + NodeReplacement.Remove("Count"), + NodeReplacement.RenameAndRemoveInvocationOfMethodOnFirstArgument("NotBe", "NotHaveSameCount") + ); + case nameof(CollectionShouldNotIntersectWith.IntersectShouldBeEmptySyntaxVisitor): + { + var remove = NodeReplacement.RemoveAndExtractArguments("Intersect"); + var newExpression = GetNewExpression(expression, remove); + + return GetNewExpression(newExpression, NodeReplacement.RenameAndPrependArguments("BeEmpty", "NotIntersectWith", remove.Arguments)); + } + case nameof(CollectionShouldOnlyContainProperty.AllShouldBeTrueSyntaxVisitor): + { + var remove = NodeReplacement.RemoveAndExtractArguments("All"); + var newExpression = GetNewExpression(expression, remove); + + return GetNewExpression(newExpression, NodeReplacement.RenameAndPrependArguments("BeTrue", "OnlyContain", remove.Arguments)); + } + case nameof(CollectionShouldOnlyHaveUniqueItems.ShouldHaveSameCountThisCollectionDistinctSyntaxVisitor): + return GetNewExpression(expression, NodeReplacement.RenameAndRemoveFirstArgument("HaveSameCount", "OnlyHaveUniqueItems")); + case nameof(CollectionShouldOnlyHaveUniqueItemsByComparer.SelectShouldOnlyHaveUniqueItemsSyntaxVisitor): + { + var remove = NodeReplacement.RemoveAndExtractArguments("Select"); + var newExpression = GetNewExpression(expression, remove); + + return GetNewExpression(newExpression, NodeReplacement.PrependArguments("OnlyHaveUniqueItems", remove.Arguments)); + } + default: throw new System.InvalidOperationException($"Invalid visitor name - {properties.VisitorName}"); + }; + } +} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionBaseAnalyzer.cs b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionBaseAnalyzer.cs new file mode 100644 index 00000000..ecd23cbd --- /dev/null +++ b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionBaseAnalyzer.cs @@ -0,0 +1,19 @@ +using FluentAssertions.Analyzers.Utilities; +using Microsoft.CodeAnalysis; + +namespace FluentAssertions.Analyzers; + +public abstract class CollectionBaseAnalyzer : FluentAssertionsAnalyzer +{ + protected override bool ShouldAnalyzeVariableNamedType(INamedTypeSymbol type, SemanticModel semanticModel) + { + return type.SpecialType != SpecialType.System_String + && type.IsTypeOrConstructedFromTypeOrImplementsType(SpecialType.System_Collections_Generic_IEnumerable_T); + } + + protected override bool ShouldAnalyzeVariableType(ITypeSymbol type, SemanticModel semanticModel) + { + return type.SpecialType != SpecialType.System_String + && type.IsTypeOrConstructedFromTypeOrImplementsType(SpecialType.System_Collections_Generic_IEnumerable_T); + } +} diff --git a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldBeEmpty.cs b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldBeEmpty.cs index 2950b464..a7ead672 100644 --- a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldBeEmpty.cs +++ b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldBeEmpty.cs @@ -1,32 +1,12 @@ using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; namespace FluentAssertions.Analyzers; -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class CollectionShouldBeEmptyAnalyzer : CollectionAnalyzer +public static class CollectionShouldBeEmpty { - public const string DiagnosticId = Constants.Tips.Collections.CollectionsShouldBeEmpty; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().BeEmpty() instead."; - - protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - protected override IEnumerable Visitors - { - get - { - yield return new AnyShouldBeFalseSyntaxVisitor(); - yield return new ShouldHaveCount0SyntaxVisitor(); - } - } - public class AnyShouldBeFalseSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor { public AnyShouldBeFalseSyntaxVisitor() : base(MemberValidator.MethodNotContainingLambda("Any"), MemberValidator.Should, new MemberValidator("BeFalse")) @@ -49,27 +29,8 @@ private static bool HaveCountArgumentsValidator(SeparatedSyntaxList FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldBeEmptyAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties) - { - switch (properties.VisitorName) - { - case nameof(CollectionShouldBeEmptyAnalyzer.AnyShouldBeFalseSyntaxVisitor): - return GetNewExpression(expression, NodeReplacement.Remove("Any"), NodeReplacement.Rename("BeFalse", "BeEmpty")); - case nameof(CollectionShouldBeEmptyAnalyzer.ShouldHaveCount0SyntaxVisitor): - return GetNewExpression(expression, new HaveCountNodeReplacement()); - default: - throw new System.InvalidOperationException($"Invalid visitor name - {properties.VisitorName}"); - } - } - private class HaveCountNodeReplacement : NodeReplacement + public class HaveCountNodeReplacement : NodeReplacement { public override bool IsValidNode(LinkedListNode listNode) => listNode.Value.Name.Identifier.Text == "HaveCount"; public override SyntaxNode ComputeOld(LinkedListNode listNode) => listNode.Value.Parent; @@ -85,4 +46,4 @@ public override SyntaxNode ComputeNew(LinkedListNode new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - protected override IEnumerable Visitors - { - get - { - yield return new OrderByShouldEqualSyntaxVisitor(); - } - } - public class OrderByShouldEqualSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor { public OrderByShouldEqualSyntaxVisitor() : base(MemberValidator.MethodContainingLambda("OrderBy"), MemberValidator.Should, MemberValidator.ArgumentIsVariable("Equal")) { } } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(CollectionShouldBeInAscendingOrderCodeFix)), Shared] -public class CollectionShouldBeInAscendingOrderCodeFix : FluentAssertionsCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldBeInAscendingOrderAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties) - { - var remove = NodeReplacement.RemoveAndExtractArguments("OrderBy"); - var newExpression = GetNewExpression(expression, remove); - - newExpression = GetNewExpression(newExpression, NodeReplacement.RenameAndRemoveFirstArgument("Equal", "BeInAscendingOrder")); - - return GetNewExpression(newExpression, NodeReplacement.PrependArguments("BeInAscendingOrder", remove.Arguments)); - } -} +} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldBeInDescendingOrder.cs b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldBeInDescendingOrder.cs index 2c4f705e..ef3d8c40 100644 --- a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldBeInDescendingOrder.cs +++ b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldBeInDescendingOrder.cs @@ -1,50 +1,11 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; +namespace FluentAssertions.Analyzers; -namespace FluentAssertions.Analyzers; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class CollectionShouldBeInDescendingOrderAnalyzer : CollectionAnalyzer +public static class CollectionShouldBeInDescendingOrder { - public const string DiagnosticId = Constants.Tips.Collections.CollectionShouldBeInDescendingOrder; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().BeInDescendingOrder() instead."; - - protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - protected override IEnumerable Visitors - { - get - { - yield return new OrderByDescendingShouldEqualSyntaxVisitor(); - } - } - public class OrderByDescendingShouldEqualSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor { public OrderByDescendingShouldEqualSyntaxVisitor() : base(MemberValidator.MethodContainingLambda("OrderByDescending"), MemberValidator.Should, MemberValidator.ArgumentIsVariable("Equal")) { } } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(CollectionShouldBeInDescendingOrderCodeFix)), Shared] -public class CollectionShouldBeInDescendingOrderCodeFix : FluentAssertionsCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldBeInDescendingOrderAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties) - { - var remove = NodeReplacement.RemoveAndExtractArguments("OrderByDescending"); - var newExpression = GetNewExpression(expression, remove); - - newExpression = GetNewExpression(newExpression, NodeReplacement.RenameAndRemoveFirstArgument("Equal", "BeInDescendingOrder")); - - return GetNewExpression(newExpression, NodeReplacement.PrependArguments("BeInDescendingOrder", remove.Arguments)); - } -} +} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldContainItem.cs b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldContainItem.cs index 76ea7849..4f27d41b 100644 --- a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldContainItem.cs +++ b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldContainItem.cs @@ -1,49 +1,11 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; +namespace FluentAssertions.Analyzers; -namespace FluentAssertions.Analyzers; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class CollectionShouldContainItemAnalyzer : CollectionAnalyzer +public static class CollectionShouldContainItem { - public const string DiagnosticId = Constants.Tips.Collections.CollectionShouldContainItem; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().Contain() instead."; - - protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - - protected override IEnumerable Visitors - { - get - { - yield return new ContainsShouldBeTrueSyntaxVisitor(); - } - } - public class ContainsShouldBeTrueSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor { public ContainsShouldBeTrueSyntaxVisitor() : base(new MemberValidator("Contains"), MemberValidator.Should, new MemberValidator("BeTrue")) { } } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(CollectionShouldContainItemCodeFix)), Shared] -public class CollectionShouldContainItemCodeFix : FluentAssertionsCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldContainItemAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties) - { - var remove = NodeReplacement.RemoveAndExtractArguments("Contains"); - var newExpression = GetNewExpression(expression, remove); - - return GetNewExpression(newExpression, NodeReplacement.RenameAndPrependArguments("BeTrue", "Contain", remove.Arguments)); - } -} +} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldContainProperty.cs b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldContainProperty.cs index be113509..5eb0746e 100644 --- a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldContainProperty.cs +++ b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldContainProperty.cs @@ -1,34 +1,10 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; +namespace FluentAssertions.Analyzers; -namespace FluentAssertions.Analyzers; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class CollectionShouldContainPropertyAnalyzer : CollectionAnalyzer +public static class CollectionShouldContainProperty { - public const string DiagnosticId = Constants.Tips.Collections.CollectionShouldContainProperty; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().Contain() instead."; - - protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - protected override IEnumerable Visitors + public class AnyWithLambdaShouldBeTrueSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor { - get - { - yield return new AnyShouldBeTrueSyntaxVisitor(); - yield return new WhereShouldNotBeEmptySyntaxVisitor(); - } - } - - public class AnyShouldBeTrueSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AnyShouldBeTrueSyntaxVisitor() : base(MemberValidator.MethodContainingLambda("Any"), MemberValidator.Should, new MemberValidator("BeTrue")) + public AnyWithLambdaShouldBeTrueSyntaxVisitor() : base(MemberValidator.MethodContainingLambda("Any"), MemberValidator.Should, new MemberValidator("BeTrue")) { } } @@ -39,29 +15,4 @@ public class WhereShouldNotBeEmptySyntaxVisitor : FluentAssertionsCSharpSyntaxVi { } } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(CollectionShouldContainPropertyCodeFix)), Shared] -public class CollectionShouldContainPropertyCodeFix : FluentAssertionsCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldContainPropertyAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties) - { - if (properties.VisitorName == nameof(CollectionShouldContainPropertyAnalyzer.AnyShouldBeTrueSyntaxVisitor)) - { - var remove = NodeReplacement.RemoveAndExtractArguments("Any"); - var newExpression = GetNewExpression(expression, remove); - - return GetNewExpression(newExpression, NodeReplacement.RenameAndPrependArguments("BeTrue", "Contain", remove.Arguments)); - } - else if (properties.VisitorName == nameof(CollectionShouldContainPropertyAnalyzer.WhereShouldNotBeEmptySyntaxVisitor)) - { - var remove = NodeReplacement.RemoveAndExtractArguments("Where"); - var newExpression = GetNewExpression(expression, remove); - - return GetNewExpression(newExpression, NodeReplacement.RenameAndPrependArguments("NotBeEmpty", "Contain", remove.Arguments)); - } - throw new System.InvalidOperationException($"Invalid visitor name - {properties.VisitorName}"); - } -} +} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldContainSingle.cs b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldContainSingle.cs index ef35a1d6..493d5376 100644 --- a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldContainSingle.cs +++ b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldContainSingle.cs @@ -1,42 +1,7 @@ -using FluentAssertions.Analyzers.Utilities; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; +namespace FluentAssertions.Analyzers; -namespace FluentAssertions.Analyzers; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class CollectionShouldContainSingleAnalyzer : CollectionAnalyzer +public static class CollectionShouldContainSingle { - public const string DiagnosticId = Constants.Tips.Collections.CollectionShouldContainSingle; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().ContainSingle() instead."; - - protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - protected override IEnumerable Visitors - { - get - { - yield return new WhereShouldHaveCount1SyntaxVisitor(); - yield return new ShouldHaveCount1SyntaxVisitor(); - } - } - - protected override bool ShouldAnalyzeVariableNamedType(INamedTypeSymbol type, SemanticModel semanticModel) - { - if (!type.IsTypeOrConstructedFromTypeOrImplementsType(SpecialType.System_Collections_Generic_IEnumerable_T)) - { - return false; - } - - return base.ShouldAnalyzeVariableNamedType(type, semanticModel); - } - public class WhereShouldHaveCount1SyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor { public WhereShouldHaveCount1SyntaxVisitor() : base(MemberValidator.MethodContainingLambda("Where"), MemberValidator.Should, MemberValidator.ArgumentIsLiteral("HaveCount", 1)) @@ -50,27 +15,4 @@ public ShouldHaveCount1SyntaxVisitor() : base(MemberValidator.Should, MemberVali { } } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(CollectionShouldContainSingleCodeFix)), Shared] -public class CollectionShouldContainSingleCodeFix : FluentAssertionsCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldContainSingleAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties) - { - var newExpression = GetNewExpression(expression, NodeReplacement.RenameAndRemoveFirstArgument("HaveCount", "ContainSingle")); - if (properties.VisitorName == nameof(CollectionShouldContainSingleAnalyzer.ShouldHaveCount1SyntaxVisitor)) - { - return newExpression; - } - else if (properties.VisitorName == nameof(CollectionShouldContainSingleAnalyzer.WhereShouldHaveCount1SyntaxVisitor)) - { - var remove = NodeReplacement.RemoveAndExtractArguments("Where"); - newExpression = GetNewExpression(newExpression, remove); - - return GetNewExpression(newExpression, NodeReplacement.PrependArguments("ContainSingle", remove.Arguments)); - } - throw new System.InvalidOperationException($"Invalid visitor name - {properties.VisitorName}"); - } -} +} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldEqualOtherCollectionByComparer.cs b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldEqualOtherCollectionByComparer.cs index 57029f73..6397cfed 100644 --- a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldEqualOtherCollectionByComparer.cs +++ b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldEqualOtherCollectionByComparer.cs @@ -1,32 +1,11 @@ using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; namespace FluentAssertions.Analyzers; -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class CollectionShouldEqualOtherCollectionByComparerAnalyzer : CollectionAnalyzer +public static class CollectionShouldEqualOtherCollectionByComparer { - public const string DiagnosticId = Constants.Tips.Collections.CollectionShouldEqualOtherCollectionByComparer; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().Equal() instead."; - - protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - - protected override IEnumerable Visitors - { - get - { - yield return new SelectShouldEqualOtherCollectionSelectSyntaxVisitor(); - } - } - public class SelectShouldEqualOtherCollectionSelectSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor { public SelectShouldEqualOtherCollectionSelectSyntaxVisitor() @@ -44,12 +23,9 @@ private static bool MathodContainingArgumentInvokingLambda(SeparatedSyntaxList FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldEqualOtherCollectionByComparerAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties) + private ExpressionSyntax GetNewExpressionForSelectShouldEqualOtherCollectionSelectSyntaxVisitor(ExpressionSyntax expression) { var removeMethodContainingFirstLambda = NodeReplacement.RemoveAndExtractArguments("Select"); var newExpression = GetNewExpression(expression, removeMethodContainingFirstLambda); diff --git a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldHaveCount.cs b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldHaveCount.cs index fe1d5b80..4b784163 100644 --- a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldHaveCount.cs +++ b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldHaveCount.cs @@ -1,33 +1,7 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; +namespace FluentAssertions.Analyzers; -namespace FluentAssertions.Analyzers; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class CollectionShouldHaveCountAnalyzer : CollectionAnalyzer +public static class CollectionShouldHaveCount { - public const string DiagnosticId = Constants.Tips.Collections.CollectionShouldHaveCount; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().HaveCount() instead."; - - protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - protected override IEnumerable Visitors - { - get - { - yield return new CountShouldBe0SyntaxVisitor(); - yield return new CountShouldBe1SyntaxVisitor(); - yield return new CountShouldBeSyntaxVisitor(); - yield return new LengthShouldBeSyntaxVisitor(); - } - } - public class CountShouldBe0SyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor { public CountShouldBe0SyntaxVisitor() : base(MemberValidator.MethodNotContainingLambda("Count"), MemberValidator.Should, MemberValidator.ArgumentIsLiteral("Be", 0)) @@ -55,31 +29,4 @@ public class LengthShouldBeSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor { } } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(CollectionShouldHaveCountCodeFix)), Shared] -public class CollectionShouldHaveCountCodeFix : FluentAssertionsCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldHaveCountAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties) - { - if (properties.VisitorName == nameof(CollectionShouldHaveCountAnalyzer.CountShouldBe0SyntaxVisitor)) - { - return GetNewExpression(expression, NodeReplacement.Remove("Count"), NodeReplacement.RenameAndRemoveFirstArgument("Be", "BeEmpty")); - } - else if (properties.VisitorName == nameof(CollectionShouldHaveCountAnalyzer.CountShouldBe1SyntaxVisitor)) - { - return GetNewExpression(expression, NodeReplacement.Remove("Count"), NodeReplacement.RenameAndRemoveFirstArgument("Be", "ContainSingle")); - } - else if (properties.VisitorName == nameof(CollectionShouldHaveCountAnalyzer.CountShouldBeSyntaxVisitor)) - { - return GetNewExpression(expression, NodeReplacement.Remove("Count"), NodeReplacement.Rename("Be", "HaveCount")); - } - else if (properties.VisitorName == nameof(CollectionShouldHaveCountAnalyzer.LengthShouldBeSyntaxVisitor)) - { - return GetNewExpression(expression, NodeReplacement.Remove("Length"), NodeReplacement.Rename("Be", "HaveCount")); - } - throw new System.InvalidOperationException($"Invalid visitor name - {properties.VisitorName}"); - } -} +} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldHaveCountGreaterOrEqualTo.cs b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldHaveCountGreaterOrEqualTo.cs index 7fd3846c..75fd25a7 100644 --- a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldHaveCountGreaterOrEqualTo.cs +++ b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldHaveCountGreaterOrEqualTo.cs @@ -1,45 +1,11 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; +namespace FluentAssertions.Analyzers; -namespace FluentAssertions.Analyzers; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class CollectionShouldHaveCountGreaterOrEqualToAnalyzer : CollectionAnalyzer +public static class CollectionShouldHaveCountGreaterOrEqualTo { - public const string DiagnosticId = Constants.Tips.Collections.CollectionShouldHaveCountGreaterOrEqualTo; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().HaveCountGreaterOrEqualTo() instead."; - - protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - protected override IEnumerable Visitors - { - get - { - yield return new CountShouldBeGreaterOrEqualToSyntaxVisitor(); - } - } - public class CountShouldBeGreaterOrEqualToSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor { public CountShouldBeGreaterOrEqualToSyntaxVisitor() : base(new MemberValidator("Count"), MemberValidator.Should, new MemberValidator("BeGreaterOrEqualTo")) { } } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(CollectionShouldHaveCountGreaterOrEqualToCodeFix)), Shared] -public class CollectionShouldHaveCountGreaterOrEqualToCodeFix : FluentAssertionsCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldHaveCountGreaterOrEqualToAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties) - { - return GetNewExpression(expression, NodeReplacement.Remove("Count"), NodeReplacement.Rename("BeGreaterOrEqualTo", "HaveCountGreaterOrEqualTo")); - } -} +} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldHaveCountGreaterThan.cs b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldHaveCountGreaterThan.cs index 11a9c12f..ae9cbc49 100644 --- a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldHaveCountGreaterThan.cs +++ b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldHaveCountGreaterThan.cs @@ -1,45 +1,11 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; +namespace FluentAssertions.Analyzers; -namespace FluentAssertions.Analyzers; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class CollectionShouldHaveCountGreaterThanAnalyzer : CollectionAnalyzer +public static class CollectionShouldHaveCountGreaterThan { - public const string DiagnosticId = Constants.Tips.Collections.CollectionShouldHaveCountGreaterThan; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().HaveCountGreaterThan() instead."; - - protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - protected override IEnumerable Visitors - { - get - { - yield return new CountShouldBeGreaterThanSyntaxVisitor(); - } - } - public class CountShouldBeGreaterThanSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor { public CountShouldBeGreaterThanSyntaxVisitor() : base(new MemberValidator("Count"), MemberValidator.Should, new MemberValidator("BeGreaterThan")) { } } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(CollectionShouldHaveCountGreaterThanCodeFix)), Shared] -public class CollectionShouldHaveCountGreaterThanCodeFix : FluentAssertionsCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldHaveCountGreaterThanAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties) - { - return GetNewExpression(expression, NodeReplacement.Remove("Count"), NodeReplacement.Rename("BeGreaterThan", "HaveCountGreaterThan")); - } -} +} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldHaveCountLessOrEqualTo.cs b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldHaveCountLessOrEqualTo.cs index 2effb4f1..7692ca6c 100644 --- a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldHaveCountLessOrEqualTo.cs +++ b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldHaveCountLessOrEqualTo.cs @@ -1,45 +1,11 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; +namespace FluentAssertions.Analyzers; -namespace FluentAssertions.Analyzers; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class CollectionShouldHaveCountLessOrEqualToAnalyzer : CollectionAnalyzer +public static class CollectionShouldHaveCountLessOrEqualTo { - public const string DiagnosticId = Constants.Tips.Collections.CollectionShouldHaveCountLessOrEqualTo; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().HaveCountLessOrEqualTo() instead."; - - protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - - protected override IEnumerable Visitors - { - get - { - yield return new CountShouldBeLessOrEqualToSyntaxVisitor(); - } - } public class CountShouldBeLessOrEqualToSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor { public CountShouldBeLessOrEqualToSyntaxVisitor() : base(new MemberValidator("Count"), MemberValidator.Should, new MemberValidator("BeLessOrEqualTo")) { } } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(CollectionShouldHaveCountLessOrEqualToCodeFix)), Shared] -public class CollectionShouldHaveCountLessOrEqualToCodeFix : FluentAssertionsCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldHaveCountLessOrEqualToAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties) - { - return GetNewExpression(expression, NodeReplacement.Remove("Count"), NodeReplacement.Rename("BeLessOrEqualTo", "HaveCountLessOrEqualTo")); - } } \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldHaveCountLessThan.cs b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldHaveCountLessThan.cs index 52693bdb..12a3cb41 100644 --- a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldHaveCountLessThan.cs +++ b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldHaveCountLessThan.cs @@ -1,45 +1,11 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; +namespace FluentAssertions.Analyzers; -namespace FluentAssertions.Analyzers; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class CollectionShouldHaveCountLessThanAnalyzer : CollectionAnalyzer +public static class CollectionShouldHaveCountLessThan { - public const string DiagnosticId = Constants.Tips.Collections.CollectionShouldHaveCountLessThan; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().HaveCountLessThan() instead."; - - protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - protected override IEnumerable Visitors - { - get - { - yield return new CountShouldBeLessThanSyntaxVisitor(); - } - } - public class CountShouldBeLessThanSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor { public CountShouldBeLessThanSyntaxVisitor() : base(new MemberValidator("Count"), MemberValidator.Should, new MemberValidator("BeLessThan")) { } } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(CollectionShouldHaveCountLessThanCodeFix)), Shared] -public class CollectionShouldHaveCountLessThanCodeFix : FluentAssertionsCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldHaveCountLessThanAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties) - { - return GetNewExpression(expression, NodeReplacement.Remove("Count"), NodeReplacement.Rename("BeLessThan", "HaveCountLessThan")); - } -} +} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldHaveElementAt.cs b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldHaveElementAt.cs index 14bfbd66..833f7b07 100644 --- a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldHaveElementAt.cs +++ b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldHaveElementAt.cs @@ -10,7 +10,7 @@ namespace FluentAssertions.Analyzers; [DiagnosticAnalyzer(LanguageNames.CSharp)] -public class CollectionShouldHaveElementAtAnalyzer : CollectionAnalyzer +public class CollectionShouldHaveElementAtAnalyzer : CollectionBaseAnalyzer { public const string DiagnosticId = Constants.Tips.Collections.CollectionShouldHaveElementAt; public const string Category = Constants.Tips.Category; @@ -93,4 +93,4 @@ protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression } throw new System.InvalidOperationException($"Invalid visitor name - {properties.VisitorName}"); } -} +} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldHaveElementAt0Null.cs b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldHaveElementAt0Null.cs deleted file mode 100644 index 54fdd7a2..00000000 --- a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldHaveElementAt0Null.cs +++ /dev/null @@ -1,39 +0,0 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; -using System.Linq; - -namespace FluentAssertions.Analyzers; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class CollectionShouldHaveElementAt0NullAnalyzer : CollectionAnalyzer -{ - public const string DiagnosticId = Constants.Tips.Collections.CollectionShouldHaveElementAt0Null; - public const string Category = Constants.Tips.Category; - - public const string Message = "TODO"; - - protected override IEnumerable Visitors { get; } = Enumerable.Empty(); - - protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - - protected override Diagnostic AnalyzeExpression(ExpressionSyntax expression, SemanticModel semanticModel) - { - return null; - } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(CollectionShouldHaveElementAt0NullCodeFix)), Shared] -public class CollectionShouldHaveElementAt0NullCodeFix : FluentAssertionsCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldHaveElementAt0NullAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties) - { - throw new System.NotImplementedException(); - } -} diff --git a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldHaveSameCount.cs b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldHaveSameCount.cs index 20678927..3d5725f4 100644 --- a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldHaveSameCount.cs +++ b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldHaveSameCount.cs @@ -1,31 +1,11 @@ using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; using System.Linq; namespace FluentAssertions.Analyzers; -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class CollectionShouldHaveSameCountAnalyzer : CollectionAnalyzer +public static class CollectionShouldHaveSameCount { - public const string DiagnosticId = Constants.Tips.Collections.CollectionShouldHaveSameCount; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().HaveSameCount() instead."; - - protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - protected override IEnumerable Visitors - { - get - { - yield return new ShouldHaveCountOtherCollectionCountSyntaxVisitor(); - } - } - public class ShouldHaveCountOtherCollectionCountSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor { public ShouldHaveCountOtherCollectionCountSyntaxVisitor() : base(MemberValidator.Should, new MemberValidator("HaveCount", HasArgumentInvokingCountMethod)) @@ -43,15 +23,4 @@ private static bool HasArgumentInvokingCountMethod(SeparatedSyntaxList FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldHaveSameCountAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties) - { - return GetNewExpression(expression, NodeReplacement.RenameAndRemoveInvocationOfMethodOnFirstArgument("HaveCount", "HaveSameCount")); - } -} +} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldIntersectWith.cs b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldIntersectWith.cs index 7eb4c8cf..89bb00ad 100644 --- a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldIntersectWith.cs +++ b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldIntersectWith.cs @@ -1,48 +1,11 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; +namespace FluentAssertions.Analyzers; -namespace FluentAssertions.Analyzers; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class CollectionShouldIntersectWithAnalyzer : CollectionAnalyzer +public static class CollectionShouldIntersectWith { - public const string DiagnosticId = Constants.Tips.Collections.CollectionShouldIntersectWith; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().IntersectWith() instead."; - - protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - protected override IEnumerable Visitors - { - get - { - yield return new IntersectShouldNotBeEmptySyntaxVisitor(); - } - } - public class IntersectShouldNotBeEmptySyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor { public IntersectShouldNotBeEmptySyntaxVisitor() : base(MemberValidator.HasArguments("Intersect"), MemberValidator.Should, new MemberValidator("NotBeEmpty")) { } } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(CollectionShouldIntersectWithCodeFix)), Shared] -public class CollectionShouldIntersectWithCodeFix : FluentAssertionsCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldIntersectWithAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties) - { - var remove = NodeReplacement.RemoveAndExtractArguments("Intersect"); - var newExpression = GetNewExpression(expression, remove); - - return GetNewExpression(newExpression, NodeReplacement.RenameAndPrependArguments("NotBeEmpty", "IntersectWith", remove.Arguments)); - } -} +} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldNotBeEmpty.cs b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldNotBeEmpty.cs index 40a22d95..ccddc98b 100644 --- a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldNotBeEmpty.cs +++ b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldNotBeEmpty.cs @@ -1,47 +1,11 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; +namespace FluentAssertions.Analyzers; -namespace FluentAssertions.Analyzers; - - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class CollectionShouldNotBeEmptyAnalyzer : CollectionAnalyzer +public static class CollectionShouldNotBeEmpty { - public const string DiagnosticId = Constants.Tips.Collections.CollectionsShouldNotBeEmpty; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().NotBeEmpty() instead."; - - protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - - protected override IEnumerable Visitors - { - get - { - yield return new AnyShouldBeTrueSyntaxVisitor(); - } - } - public class AnyShouldBeTrueSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor { public AnyShouldBeTrueSyntaxVisitor() : base(MemberValidator.MethodNotContainingLambda("Any"), MemberValidator.Should, new MemberValidator("BeTrue")) { } } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(CollectionShouldNotBeEmptyCodeFix)), Shared] -public class CollectionShouldNotBeEmptyCodeFix : FluentAssertionsCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldNotBeEmptyAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties) - { - return GetNewExpression(expression, NodeReplacement.Remove("Any"), NodeReplacement.Rename("BeTrue", "NotBeEmpty")); - } -} +} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldNotBeNullOrEmpty.cs b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldNotBeNullOrEmpty.cs index 55f383d8..9c760916 100644 --- a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldNotBeNullOrEmpty.cs +++ b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldNotBeNullOrEmpty.cs @@ -10,7 +10,7 @@ namespace FluentAssertions.Analyzers; [DiagnosticAnalyzer(LanguageNames.CSharp)] -public class CollectionShouldNotBeNullOrEmptyAnalyzer : CollectionAnalyzer +public class CollectionShouldNotBeNullOrEmptyAnalyzer : CollectionBaseAnalyzer { public const string DiagnosticId = Constants.Tips.Collections.CollectionShouldNotBeNullOrEmpty; public const string Category = Constants.Tips.Category; diff --git a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldNotContainItem.cs b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldNotContainItem.cs index 2b60b3fb..d30be01d 100644 --- a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldNotContainItem.cs +++ b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldNotContainItem.cs @@ -1,48 +1,11 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; +namespace FluentAssertions.Analyzers; -namespace FluentAssertions.Analyzers; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class CollectionShouldNotContainItemAnalyzer : CollectionAnalyzer +public static class CollectionShouldNotContainItem { - public const string DiagnosticId = Constants.Tips.Collections.CollectionShouldNotContainItem; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().NotContain() instead."; - - protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - protected override IEnumerable Visitors - { - get - { - yield return new ContainsShouldBeFalseSyntaxVisitor(); - } - } - public class ContainsShouldBeFalseSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor { public ContainsShouldBeFalseSyntaxVisitor() : base(new MemberValidator("Contains"), MemberValidator.Should, new MemberValidator("BeFalse")) { } } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(CollectionShouldNotContainItemCodeFix)), Shared] -public class CollectionShouldNotContainItemCodeFix : FluentAssertionsCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldNotContainItemAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties) - { - var remove = NodeReplacement.RemoveAndExtractArguments("Contains"); - var newExpression = GetNewExpression(expression, remove); - - return GetNewExpression(newExpression, NodeReplacement.RenameAndPrependArguments("BeFalse", "NotContain", remove.Arguments)); - } -} +} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldNotContainNulls.cs b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldNotContainNulls.cs index 904dd6db..52488cea 100644 --- a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldNotContainNulls.cs +++ b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldNotContainNulls.cs @@ -1,48 +1,11 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; +namespace FluentAssertions.Analyzers; -namespace FluentAssertions.Analyzers; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class CollectionShouldNotContainNullsAnalyzer : CollectionAnalyzer +public static class CollectionShouldNotContainNulls { - public const string DiagnosticId = Constants.Tips.Collections.CollectionShouldNotContainNulls; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should()### instead."; - - protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - protected override IEnumerable Visitors - { - get - { - yield return new SelectShouldNotContainNullsSyntaxVisitor(); - } - } - public class SelectShouldNotContainNullsSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor { public SelectShouldNotContainNullsSyntaxVisitor() : base(MemberValidator.MethodContainingLambda("Select"), MemberValidator.Should, new MemberValidator("NotContainNulls")) { } } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(CollectionShouldNotContainNullsCodeFix)), Shared] -public class CollectionShouldNotContainNullsCodeFix : FluentAssertionsCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldNotContainNullsAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties) - { - var remove = NodeReplacement.RemoveAndExtractArguments("Select"); - var newExpression = GetNewExpression(expression, remove); - - return GetNewExpression(newExpression, NodeReplacement.PrependArguments("NotContainNulls", remove.Arguments)); - } -} +} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldNotContainProperty.cs b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldNotContainProperty.cs index 387c8621..0008e98a 100644 --- a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldNotContainProperty.cs +++ b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldNotContainProperty.cs @@ -1,35 +1,10 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; +namespace FluentAssertions.Analyzers; -namespace FluentAssertions.Analyzers; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class CollectionShouldNotContainPropertyAnalyzer : CollectionAnalyzer +public static class CollectionShouldNotContainProperty { - public const string DiagnosticId = Constants.Tips.Collections.CollectionShouldNotContainProperty; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().NotContain() instead."; - - protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - protected override IEnumerable Visitors - { - get - { - yield return new AnyShouldBeFalseSyntaxVisitor(); - yield return new WhereShouldBeEmptySyntaxVisitor(); - // TODO: yield return new ShouldOnlyContainNotSyntaxVisitor(); - } - } - - public class AnyShouldBeFalseSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor + public class AnyLambdaShouldBeFalseSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor { - public AnyShouldBeFalseSyntaxVisitor() : base(MemberValidator.MethodContainingLambda("Any"), MemberValidator.Should, new MemberValidator("BeFalse")) + public AnyLambdaShouldBeFalseSyntaxVisitor() : base(MemberValidator.MethodContainingLambda("Any"), MemberValidator.Should, new MemberValidator("BeFalse")) { } } @@ -47,35 +22,4 @@ public ShouldOnlyContainSyntaxVisitor() : base(MemberValidator.Should, MemberVal { } } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(CollectionShouldNotContainPropertyCodeFix)), Shared] -public class CollectionShouldNotContainPropertyCodeFix : FluentAssertionsCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldNotContainPropertyAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties) - { - if (properties.VisitorName == nameof(CollectionShouldNotContainPropertyAnalyzer.AnyShouldBeFalseSyntaxVisitor)) - { - var remove = NodeReplacement.RemoveAndExtractArguments("Any"); - var newExpression = GetNewExpression(expression, remove); - - return GetNewExpression(newExpression, NodeReplacement.RenameAndPrependArguments("BeFalse", "NotContain", remove.Arguments)); - } - else if (properties.VisitorName == nameof(CollectionShouldNotContainPropertyAnalyzer.WhereShouldBeEmptySyntaxVisitor)) - { - var remove = NodeReplacement.RemoveAndExtractArguments("Where"); - var newExpression = GetNewExpression(expression, remove); - - return GetNewExpression(newExpression, NodeReplacement.RenameAndPrependArguments("BeEmpty", "NotContain", remove.Arguments)); - } - /* - else if (properties.VisitorName == nameof(CollectionShouldNotContainPropertyAnalyzer.ShouldOnlyContainNotSyntaxVisitor)) - { - return GetNewExpression(expression, NodeReplacement.RenameAndNegateLambda("OnlyContain", "NotContain")); - } - */ - throw new System.InvalidOperationException($"Invalid visitor name - {properties.VisitorName}"); - } -} +} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldNotHaveCount.cs b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldNotHaveCount.cs index b9cb29de..c5d39a47 100644 --- a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldNotHaveCount.cs +++ b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldNotHaveCount.cs @@ -1,45 +1,11 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; +namespace FluentAssertions.Analyzers; -namespace FluentAssertions.Analyzers; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class CollectionShouldNotHaveCountAnalyzer : CollectionAnalyzer +public static class CollectionShouldNotHaveCount { - public const string DiagnosticId = Constants.Tips.Collections.CollectionShouldNotHaveCount; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().NotHaveCount() instead."; - - protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - protected override IEnumerable Visitors - { - get - { - yield return new CountShouldNotBeSyntaxVisitor(); - } - } - public class CountShouldNotBeSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor { public CountShouldNotBeSyntaxVisitor() : base(MemberValidator.HasNoArguments("Count"), MemberValidator.Should, MemberValidator.ArgumentIsIdentifierOrLiteral("NotBe")) { } } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(CollectionShouldNotHaveCountCodeFix)), Shared] -public class CollectionShouldNotHaveCountCodeFix : FluentAssertionsCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldNotHaveCountAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties) - { - return GetNewExpression(expression, NodeReplacement.Remove("Count"), NodeReplacement.Rename("NotBe", "NotHaveCount")); - } -} +} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldNotHaveSameCount.cs b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldNotHaveSameCount.cs index 6a89b3b4..267d2c05 100644 --- a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldNotHaveSameCount.cs +++ b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldNotHaveSameCount.cs @@ -1,31 +1,11 @@ using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; using System.Linq; namespace FluentAssertions.Analyzers; -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class CollectionShouldNotHaveSameCountAnalyzer : CollectionAnalyzer +public static class CollectionShouldNotHaveSameCount { - public const string DiagnosticId = Constants.Tips.Collections.CollectionShouldNotHaveSameCount; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().NotHaveSameCount() instead."; - - protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - protected override IEnumerable Visitors - { - get - { - yield return new CountShouldNotBeOtherCollectionCountSyntaxVisitor(); - } - } - public class CountShouldNotBeOtherCollectionCountSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor { public CountShouldNotBeOtherCollectionCountSyntaxVisitor() : base(MemberValidator.HasNoArguments("Count"), MemberValidator.Should, new MemberValidator("NotBe", HasArgumentInvokingCountMethod)) @@ -43,18 +23,4 @@ private static bool HasArgumentInvokingCountMethod(SeparatedSyntaxList FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldNotHaveSameCountAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties) - { - return GetNewExpression(expression, - NodeReplacement.Remove("Count"), - NodeReplacement.RenameAndRemoveInvocationOfMethodOnFirstArgument("NotBe", "NotHaveSameCount") - ); - } -} +} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldNotIntersectWith.cs b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldNotIntersectWith.cs index 421f6079..8deaa5be 100644 --- a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldNotIntersectWith.cs +++ b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldNotIntersectWith.cs @@ -1,47 +1,11 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; +namespace FluentAssertions.Analyzers; -namespace FluentAssertions.Analyzers; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class CollectionShouldNotIntersectWithAnalyzer : CollectionAnalyzer +public static class CollectionShouldNotIntersectWith { - public const string DiagnosticId = Constants.Tips.Collections.CollectionShouldNotIntersectWith; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().NotIntersectWith() instead."; - - protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - protected override IEnumerable Visitors - { - get - { - yield return new IntersectShouldBeEmptySyntaxVisitor(); - } - } public class IntersectShouldBeEmptySyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor { public IntersectShouldBeEmptySyntaxVisitor() : base(MemberValidator.HasArguments("Intersect"), MemberValidator.Should, new MemberValidator("BeEmpty")) { } } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(CollectionShouldNotIntersectWithCodeFix)), Shared] -public class CollectionShouldNotIntersectWithCodeFix : FluentAssertionsCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldNotIntersectWithAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties) - { - var remove = NodeReplacement.RemoveAndExtractArguments("Intersect"); - var newExpression = GetNewExpression(expression, remove); - - return GetNewExpression(newExpression, NodeReplacement.RenameAndPrependArguments("BeEmpty", "NotIntersectWith", remove.Arguments)); - } -} +} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldOnlyContainProperty.cs b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldOnlyContainProperty.cs index 948447d9..2e7cab9e 100644 --- a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldOnlyContainProperty.cs +++ b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldOnlyContainProperty.cs @@ -1,49 +1,11 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; +namespace FluentAssertions.Analyzers; -namespace FluentAssertions.Analyzers; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class CollectionShouldOnlyContainPropertyAnalyzer : CollectionAnalyzer +public static class CollectionShouldOnlyContainProperty { - public const string DiagnosticId = Constants.Tips.Collections.CollectionShouldOnlyContainProperty; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().OnlyContain() instead."; - - protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - - protected override IEnumerable Visitors - { - get - { - yield return new AllShouldBeTrueSyntaxVisitor(); - } - } - public class AllShouldBeTrueSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor { public AllShouldBeTrueSyntaxVisitor() : base(MemberValidator.MethodContainingLambda("All"), MemberValidator.Should, new MemberValidator("BeTrue")) { } } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(CollectionShouldOnlyContainPropertyCodeFix)), Shared] -public class CollectionShouldOnlyContainPropertyCodeFix : FluentAssertionsCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldOnlyContainPropertyAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties) - { - var remove = NodeReplacement.RemoveAndExtractArguments("All"); - var newExpression = GetNewExpression(expression, remove); - - return GetNewExpression(newExpression, NodeReplacement.RenameAndPrependArguments("BeTrue", "OnlyContain", remove.Arguments)); - } -} +} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldOnlyHaveUniqueItems.cs b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldOnlyHaveUniqueItems.cs index ef4f0bc6..67f08be7 100644 --- a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldOnlyHaveUniqueItems.cs +++ b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldOnlyHaveUniqueItems.cs @@ -1,32 +1,11 @@ using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; using System.Linq; namespace FluentAssertions.Analyzers; -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class CollectionShouldOnlyHaveUniqueItemsAnalyzer : CollectionAnalyzer +public static class CollectionShouldOnlyHaveUniqueItems { - public const string DiagnosticId = Constants.Tips.Collections.CollectionShouldOnlyHaveUniqueItems; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().OnlyHaveUniqueItems() instead."; - - protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - - protected override IEnumerable Visitors - { - get - { - yield return new ShouldHaveSameCountThisCollectionDistinctSyntaxVisitor(); - } - } - public class ShouldHaveSameCountThisCollectionDistinctSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor { public ShouldHaveSameCountThisCollectionDistinctSyntaxVisitor() : base(MemberValidator.Should, new MemberValidator("HaveSameCount", ArgumentInvokesDistinctMethod)) @@ -47,15 +26,4 @@ private static bool ArgumentInvokesDistinctMethod(SeparatedSyntaxList FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldOnlyHaveUniqueItemsAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties) - { - return GetNewExpression(expression, NodeReplacement.RenameAndRemoveFirstArgument("HaveSameCount", "OnlyHaveUniqueItems")); - } -} +} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldOnlyHaveUniqueItemsByComparer.cs b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldOnlyHaveUniqueItemsByComparer.cs index 7a7b3ea9..1ce54468 100644 --- a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldOnlyHaveUniqueItemsByComparer.cs +++ b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionShouldOnlyHaveUniqueItemsByComparer.cs @@ -1,49 +1,11 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; +namespace FluentAssertions.Analyzers; -namespace FluentAssertions.Analyzers; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class CollectionShouldOnlyHaveUniqueItemsByComparerAnalyzer : CollectionAnalyzer +public static class CollectionShouldOnlyHaveUniqueItemsByComparer { - public const string DiagnosticId = Constants.Tips.Collections.CollectionShouldOnlyHaveUniqueItemsByComparer; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().OnlyHaveUniqueItems() instead."; - - protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - - protected override IEnumerable Visitors - { - get - { - yield return new SelectShouldOnlyHaveUniqueItemsSyntaxVisitor(); - } - } - public class SelectShouldOnlyHaveUniqueItemsSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor { public SelectShouldOnlyHaveUniqueItemsSyntaxVisitor() : base(MemberValidator.MethodContainingLambda("Select"), MemberValidator.Should, new MemberValidator("OnlyHaveUniqueItems")) { } } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(CollectionShouldOnlyHaveUniqueItemsByComparerCodeFix)), Shared] -public class CollectionShouldOnlyHaveUniqueItemsByComparerCodeFix : FluentAssertionsCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldOnlyHaveUniqueItemsByComparerAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties) - { - var remove = NodeReplacement.RemoveAndExtractArguments("Select"); - var newExpression = GetNewExpression(expression, remove); - - return GetNewExpression(newExpression, NodeReplacement.PrependArguments("OnlyHaveUniqueItems", remove.Arguments)); - } -} +} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Utilities/HelpLinks.cs b/src/FluentAssertions.Analyzers/Utilities/HelpLinks.cs index d928ca10..f9fdfb2e 100644 --- a/src/FluentAssertions.Analyzers/Utilities/HelpLinks.cs +++ b/src/FluentAssertions.Analyzers/Utilities/HelpLinks.cs @@ -12,43 +12,43 @@ static HelpLinks() { TypesHelpLinks = new Dictionary { - [typeof(CollectionShouldNotBeEmptyAnalyzer.AnyShouldBeTrueSyntaxVisitor)] = GetHelpLink("Collections-1"), - [typeof(CollectionShouldBeEmptyAnalyzer.AnyShouldBeFalseSyntaxVisitor)] = GetHelpLink("Collections-2"), - [typeof(CollectionShouldContainPropertyAnalyzer.AnyShouldBeTrueSyntaxVisitor)] = GetHelpLink("Collections-3"), - [typeof(CollectionShouldNotContainPropertyAnalyzer.AnyShouldBeFalseSyntaxVisitor)] = GetHelpLink("Collections-4"), - [typeof(CollectionShouldOnlyContainPropertyAnalyzer.AllShouldBeTrueSyntaxVisitor)] = GetHelpLink("Collections-5"), - [typeof(CollectionShouldContainItemAnalyzer.ContainsShouldBeTrueSyntaxVisitor)] = GetHelpLink("Collections-6"), - [typeof(CollectionShouldNotContainItemAnalyzer.ContainsShouldBeFalseSyntaxVisitor)] = GetHelpLink("Collections-7"), + [typeof(CollectionShouldNotBeEmpty.AnyShouldBeTrueSyntaxVisitor)] = GetHelpLink("Collections-1"), + [typeof(CollectionShouldBeEmpty.AnyShouldBeFalseSyntaxVisitor)] = GetHelpLink("Collections-2"), + [typeof(CollectionShouldContainProperty.AnyWithLambdaShouldBeTrueSyntaxVisitor)] = GetHelpLink("Collections-3"), + [typeof(CollectionShouldNotContainProperty.AnyLambdaShouldBeFalseSyntaxVisitor)] = GetHelpLink("Collections-4"), + [typeof(CollectionShouldOnlyContainProperty.AllShouldBeTrueSyntaxVisitor)] = GetHelpLink("Collections-5"), + [typeof(CollectionShouldContainItem.ContainsShouldBeTrueSyntaxVisitor)] = GetHelpLink("Collections-6"), + [typeof(CollectionShouldNotContainItem.ContainsShouldBeFalseSyntaxVisitor)] = GetHelpLink("Collections-7"), // missing Collections-8 - [typeof(CollectionShouldHaveCountAnalyzer.CountShouldBeSyntaxVisitor)] = GetHelpLink("Collections-9"), - [typeof(CollectionShouldHaveCountGreaterThanAnalyzer.CountShouldBeGreaterThanSyntaxVisitor)] = GetHelpLink("Collections-10"), - [typeof(CollectionShouldHaveCountGreaterOrEqualToAnalyzer.CountShouldBeGreaterOrEqualToSyntaxVisitor)] = GetHelpLink("Collections-11"), - [typeof(CollectionShouldHaveCountLessThanAnalyzer.CountShouldBeLessThanSyntaxVisitor)] = GetHelpLink("Collections-12"), - [typeof(CollectionShouldHaveCountLessOrEqualToAnalyzer.CountShouldBeLessOrEqualToSyntaxVisitor)] = GetHelpLink("Collections-13"), - [typeof(CollectionShouldNotHaveCountAnalyzer.CountShouldNotBeSyntaxVisitor)] = GetHelpLink("Collections-14"), - [typeof(CollectionShouldContainSingleAnalyzer.ShouldHaveCount1SyntaxVisitor)] = GetHelpLink("Collections-15"), - [typeof(CollectionShouldHaveCountAnalyzer.CountShouldBe1SyntaxVisitor)] = GetHelpLink("Collections-15"), - [typeof(CollectionShouldBeEmptyAnalyzer.ShouldHaveCount0SyntaxVisitor)] = GetHelpLink("Collections-16"), - [typeof(CollectionShouldHaveCountAnalyzer.CountShouldBe0SyntaxVisitor)] = GetHelpLink("Collections-16"), // hmmm - [typeof(CollectionShouldHaveSameCountAnalyzer.ShouldHaveCountOtherCollectionCountSyntaxVisitor)] = GetHelpLink("Collections-17"), - [typeof(CollectionShouldNotHaveSameCountAnalyzer.CountShouldNotBeOtherCollectionCountSyntaxVisitor)] = GetHelpLink("Collections-18"), - [typeof(CollectionShouldContainPropertyAnalyzer.WhereShouldNotBeEmptySyntaxVisitor)] = GetHelpLink("Collections-19"), - [typeof(CollectionShouldNotContainPropertyAnalyzer.WhereShouldBeEmptySyntaxVisitor)] = GetHelpLink("Collections-20"), - [typeof(CollectionShouldContainSingleAnalyzer.WhereShouldHaveCount1SyntaxVisitor)] = GetHelpLink("Collections-21"), - [typeof(CollectionShouldNotContainPropertyAnalyzer.ShouldOnlyContainSyntaxVisitor)] = GetHelpLink("Collections-22"), + [typeof(CollectionShouldHaveCount.CountShouldBeSyntaxVisitor)] = GetHelpLink("Collections-9"), + [typeof(CollectionShouldHaveCountGreaterThan.CountShouldBeGreaterThanSyntaxVisitor)] = GetHelpLink("Collections-10"), + [typeof(CollectionShouldHaveCountGreaterOrEqualTo.CountShouldBeGreaterOrEqualToSyntaxVisitor)] = GetHelpLink("Collections-11"), + [typeof(CollectionShouldHaveCountLessThan.CountShouldBeLessThanSyntaxVisitor)] = GetHelpLink("Collections-12"), + [typeof(CollectionShouldHaveCountLessOrEqualTo.CountShouldBeLessOrEqualToSyntaxVisitor)] = GetHelpLink("Collections-13"), + [typeof(CollectionShouldNotHaveCount.CountShouldNotBeSyntaxVisitor)] = GetHelpLink("Collections-14"), + [typeof(CollectionShouldContainSingle.ShouldHaveCount1SyntaxVisitor)] = GetHelpLink("Collections-15"), + [typeof(CollectionShouldHaveCount.CountShouldBe1SyntaxVisitor)] = GetHelpLink("Collections-15"), + [typeof(CollectionShouldBeEmpty.ShouldHaveCount0SyntaxVisitor)] = GetHelpLink("Collections-16"), + [typeof(CollectionShouldHaveCount.CountShouldBe0SyntaxVisitor)] = GetHelpLink("Collections-16"), // hmmm + [typeof(CollectionShouldHaveSameCount.ShouldHaveCountOtherCollectionCountSyntaxVisitor)] = GetHelpLink("Collections-17"), + [typeof(CollectionShouldNotHaveSameCount.CountShouldNotBeOtherCollectionCountSyntaxVisitor)] = GetHelpLink("Collections-18"), + [typeof(CollectionShouldContainProperty.WhereShouldNotBeEmptySyntaxVisitor)] = GetHelpLink("Collections-19"), + [typeof(CollectionShouldNotContainProperty.WhereShouldBeEmptySyntaxVisitor)] = GetHelpLink("Collections-20"), + [typeof(CollectionShouldContainSingle.WhereShouldHaveCount1SyntaxVisitor)] = GetHelpLink("Collections-21"), + [typeof(CollectionShouldNotContainProperty.ShouldOnlyContainSyntaxVisitor)] = GetHelpLink("Collections-22"), [typeof(CollectionShouldNotBeNullOrEmptyAnalyzer.ShouldNotBeNullAndNotBeEmptySyntaxVisitor)] = GetHelpLink("Collections-23"), [typeof(CollectionShouldNotBeNullOrEmptyAnalyzer.ShouldNotBeEmptyAndNotBeNullSyntaxVisitor)] = GetHelpLink("Collections-23"), [typeof(CollectionShouldHaveElementAtAnalyzer.ElementAtIndexShouldBeSyntaxVisitor)] = GetHelpLink("Collections-24"), [typeof(CollectionShouldHaveElementAtAnalyzer.IndexerShouldBeSyntaxVisitor)] = GetHelpLink("Collections-25"), [typeof(CollectionShouldHaveElementAtAnalyzer.SkipFirstShouldBeSyntaxVisitor)] = GetHelpLink("Collections-26"), - [typeof(CollectionShouldBeInAscendingOrderAnalyzer.OrderByShouldEqualSyntaxVisitor)] = GetHelpLink("Collections-27"), - [typeof(CollectionShouldBeInDescendingOrderAnalyzer.OrderByDescendingShouldEqualSyntaxVisitor)] = GetHelpLink("Collections-28"), - [typeof(CollectionShouldEqualOtherCollectionByComparerAnalyzer.SelectShouldEqualOtherCollectionSelectSyntaxVisitor)] = GetHelpLink("Collections-29"), - [typeof(CollectionShouldNotIntersectWithAnalyzer.IntersectShouldBeEmptySyntaxVisitor)] = GetHelpLink("Collections-30"), - [typeof(CollectionShouldIntersectWithAnalyzer.IntersectShouldNotBeEmptySyntaxVisitor)] = GetHelpLink("Collections-31"), - [typeof(CollectionShouldNotContainNullsAnalyzer.SelectShouldNotContainNullsSyntaxVisitor)] = GetHelpLink("Collections-32"), - [typeof(CollectionShouldOnlyHaveUniqueItemsAnalyzer.ShouldHaveSameCountThisCollectionDistinctSyntaxVisitor)] = GetHelpLink("Collections-33"), - [typeof(CollectionShouldOnlyHaveUniqueItemsByComparerAnalyzer.SelectShouldOnlyHaveUniqueItemsSyntaxVisitor)] = GetHelpLink("Collections-34"), + [typeof(CollectionShouldBeInAscendingOrder.OrderByShouldEqualSyntaxVisitor)] = GetHelpLink("Collections-27"), + [typeof(CollectionShouldBeInDescendingOrder.OrderByDescendingShouldEqualSyntaxVisitor)] = GetHelpLink("Collections-28"), + [typeof(CollectionShouldEqualOtherCollectionByComparer.SelectShouldEqualOtherCollectionSelectSyntaxVisitor)] = GetHelpLink("Collections-29"), + [typeof(CollectionShouldNotIntersectWith.IntersectShouldBeEmptySyntaxVisitor)] = GetHelpLink("Collections-30"), + [typeof(CollectionShouldIntersectWith.IntersectShouldNotBeEmptySyntaxVisitor)] = GetHelpLink("Collections-31"), + [typeof(CollectionShouldNotContainNulls.SelectShouldNotContainNullsSyntaxVisitor)] = GetHelpLink("Collections-32"), + [typeof(CollectionShouldOnlyHaveUniqueItems.ShouldHaveSameCountThisCollectionDistinctSyntaxVisitor)] = GetHelpLink("Collections-33"), + [typeof(CollectionShouldOnlyHaveUniqueItemsByComparer.SelectShouldOnlyHaveUniqueItemsSyntaxVisitor)] = GetHelpLink("Collections-34"), [typeof(NumericShouldBePositiveAnalyzer.NumericShouldBeBeGreaterThan0SyntaxVisitor)] = GetHelpLink("Comparable-and-Numerics-1"), [typeof(NumericShouldBeNegativeAnalyzer.NumericShouldBeBeLessThan0SyntaxVisitor)] = GetHelpLink("Comparable-and-Numerics-2"),