From b94d586990ea4a5a64eb5fad9574689ff593690a Mon Sep 17 00:00:00 2001 From: Meir Blachman Date: Sun, 10 Dec 2023 07:33:52 +0200 Subject: [PATCH] consolidate CollectionShouldNotContainProperty into collection analyzer --- .../Tips/CollectionTests.cs | 4 +- .../Tips/Collections/CollectionAnalyzer.cs | 27 +++++++- .../CollectionShouldNotContainProperty.cs | 66 ++----------------- .../Utilities/HelpLinks.cs | 6 +- 4 files changed, 36 insertions(+), 67 deletions(-) diff --git a/src/FluentAssertions.Analyzers.Tests/Tips/CollectionTests.cs b/src/FluentAssertions.Analyzers.Tests/Tips/CollectionTests.cs index 4b756ab9..795b3bb8 100644 --- a/src/FluentAssertions.Analyzers.Tests/Tips/CollectionTests.cs +++ b/src/FluentAssertions.Analyzers.Tests/Tips/CollectionTests.cs @@ -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,7 +135,7 @@ 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});")] diff --git a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionAnalyzer.cs b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionAnalyzer.cs index dd5ae60a..9c2d5ed9 100644 --- a/src/FluentAssertions.Analyzers/Tips/Collections/CollectionAnalyzer.cs +++ b/src/FluentAssertions.Analyzers/Tips/Collections/CollectionAnalyzer.cs @@ -71,7 +71,10 @@ protected override IEnumerable Visitors yield return new CollectionShouldNotContainNulls.SelectShouldNotContainNullsSyntaxVisitor(); - // TODO: Add support for CollectionShouldNotContainPropertyAnalyzer + 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(); @@ -187,6 +190,28 @@ protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression 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): 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/Utilities/HelpLinks.cs b/src/FluentAssertions.Analyzers/Utilities/HelpLinks.cs index d002554d..61e6e031 100644 --- a/src/FluentAssertions.Analyzers/Utilities/HelpLinks.cs +++ b/src/FluentAssertions.Analyzers/Utilities/HelpLinks.cs @@ -15,7 +15,7 @@ static HelpLinks() [typeof(CollectionShouldNotBeEmpty.AnyShouldBeTrueSyntaxVisitor)] = GetHelpLink("Collections-1"), [typeof(CollectionShouldBeEmpty.AnyShouldBeFalseSyntaxVisitor)] = GetHelpLink("Collections-2"), [typeof(CollectionShouldContainProperty.AnyWithLambdaShouldBeTrueSyntaxVisitor)] = GetHelpLink("Collections-3"), - [typeof(CollectionShouldNotContainPropertyAnalyzer.AnyShouldBeFalseSyntaxVisitor)] = GetHelpLink("Collections-4"), + [typeof(CollectionShouldNotContainProperty.AnyLambdaShouldBeFalseSyntaxVisitor)] = GetHelpLink("Collections-4"), [typeof(CollectionShouldOnlyContainProperty.AllShouldBeTrueSyntaxVisitor)] = GetHelpLink("Collections-5"), [typeof(CollectionShouldContainItem.ContainsShouldBeTrueSyntaxVisitor)] = GetHelpLink("Collections-6"), [typeof(CollectionShouldNotContainItem.ContainsShouldBeFalseSyntaxVisitor)] = GetHelpLink("Collections-7"), @@ -33,9 +33,9 @@ static HelpLinks() [typeof(CollectionShouldHaveSameCount.ShouldHaveCountOtherCollectionCountSyntaxVisitor)] = GetHelpLink("Collections-17"), [typeof(CollectionShouldNotHaveSameCount.CountShouldNotBeOtherCollectionCountSyntaxVisitor)] = GetHelpLink("Collections-18"), [typeof(CollectionShouldContainProperty.WhereShouldNotBeEmptySyntaxVisitor)] = GetHelpLink("Collections-19"), - [typeof(CollectionShouldNotContainPropertyAnalyzer.WhereShouldBeEmptySyntaxVisitor)] = GetHelpLink("Collections-20"), + [typeof(CollectionShouldNotContainProperty.WhereShouldBeEmptySyntaxVisitor)] = GetHelpLink("Collections-20"), [typeof(CollectionShouldContainSingle.WhereShouldHaveCount1SyntaxVisitor)] = GetHelpLink("Collections-21"), - [typeof(CollectionShouldNotContainPropertyAnalyzer.ShouldOnlyContainSyntaxVisitor)] = GetHelpLink("Collections-22"), + [typeof(CollectionShouldNotContainProperty.ShouldOnlyContainSyntaxVisitor)] = GetHelpLink("Collections-22"), [typeof(CollectionShouldNotBeNullOrEmptyAnalyzer.ShouldNotBeNullAndNotBeEmptySyntaxVisitor)] = GetHelpLink("Collections-23"), [typeof(CollectionShouldNotBeNullOrEmptyAnalyzer.ShouldNotBeEmptyAndNotBeNullSyntaxVisitor)] = GetHelpLink("Collections-23"), [typeof(CollectionShouldHaveElementAtAnalyzer.ElementAtIndexShouldBeSyntaxVisitor)] = GetHelpLink("Collections-24"),