Skip to content

Commit

Permalink
{EnumerableAnalyzer} - even more assertions
Browse files Browse the repository at this point in the history
  • Loading branch information
Meir017 committed Oct 13, 2017
1 parent c5c91fe commit cc6dc0d
Show file tree
Hide file tree
Showing 12 changed files with 141 additions and 183 deletions.
41 changes: 0 additions & 41 deletions FluentAssertions.BestPractices.sln

This file was deleted.

3 changes: 1 addition & 2 deletions build.cake
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,7 @@ Task("Default")
.IsDependentOn("Update-Version")
.IsDependentOn("Build")
.IsDependentOn("Run-Unit-Tests")
.IsDependentOn("Pack")
.IsDependentOn("Publish-NuGet");
.IsDependentOn("Pack");

//////////////////////////////////////////////////////////////////////
// EXECUTION
Expand Down
38 changes: 23 additions & 15 deletions src/FluentAssertions.BestPractices.Tests/Tips/CollectionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -259,14 +259,18 @@ public class CollectionTests

[AssertionDataTestMethod]
[AssertionDiagnostic("actual.Should().NotBeNull().And.NotBeEmpty({0});")]
[NotImplemented]
[AssertionDiagnostic("actual.Should().NotBeEmpty().And.NotBeNull({0});")]
[Implemented]
public void CollectionShouldNotBeNullOrEmpty_TestAnalyzer(string assertion) => VerifyCSharpDiagnostic<CollectionShouldNotBeNullOrEmptyAnalyzer>(assertion);

[AssertionDataTestMethod]
[AssertionCodeFix(
oldAssertion: "actual.Should().NotBeNull({0}).And.NotBeEmpty({0});",
newAssertion: "actual.Should().NotBeNullOrEmpty({0});")]
[NotImplemented]
oldAssertion: "actual.Should().NotBeNull().And.NotBeEmpty({0});",
newAssertion: "actual.Should().NotBeNullOrEmpty({0});")]
[AssertionCodeFix(
oldAssertion: "actual.Should().NotBeEmpty().And.NotBeNull({0});",
newAssertion: "actual.Should().NotBeNullOrEmpty({0});")]
[Implemented]
public void CollectionShouldNotBeNullOrEmpty_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFix<CollectionShouldNotBeNullOrEmptyCodeFix, CollectionShouldNotBeNullOrEmptyAnalyzer>(oldAssertion, newAssertion);

[AssertionDataTestMethod]
Expand Down Expand Up @@ -326,15 +330,15 @@ public class CollectionTests
public void CollectionShouldBeInDescendingOrder_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFix<CollectionShouldBeInDescendingOrderCodeFix, CollectionShouldBeInDescendingOrderAnalyzer>(oldAssertion, newAssertion);

[AssertionDataTestMethod]
[AssertionDiagnostic("actual.Select(e1 => e1.SomeProperty).Should().Equal(expected.Select(e2 => e2.SomeProperty){0});")]
[NotImplemented]
[AssertionDiagnostic("actual.Select(e1 => e1.BooleanProperty).Should().Equal(expected.Select(e2 => e2.BooleanProperty){0});")]
[Implemented]
public void CollectionShouldEqualOtherCollectionByComparer_TestAnalyzer(string assertion) => VerifyCSharpDiagnostic<CollectionShouldEqualOtherCollectionByComparerAnalyzer>(assertion);

[AssertionDataTestMethod]
[AssertionCodeFix(
oldAssertion: "actual.Select(e1 => e1.SomeProperty).Should().Equal(expected.Select(e2 => e2.SomeProperty){0});",
newAssertion: "actual.Should().Equal(expected, (e1, e2) => e1.SomeProperty == e2.SomeProperty{0});")]
[NotImplemented]
oldAssertion: "actual.Select(e1 => e1.BooleanProperty).Should().Equal(expected.Select(e2 => e2.BooleanProperty){0});",
newAssertion: "actual.Should().Equal(expected, (e1, e2) => e1.BooleanProperty == e2.BooleanProperty{0});")]
[Implemented]
public void CollectionShouldEqualOtherCollectionByComparer_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFix<CollectionShouldEqualOtherCollectionByComparerCodeFix, CollectionShouldEqualOtherCollectionByComparerAnalyzer>(oldAssertion, newAssertion);

[AssertionDataTestMethod]
Expand All @@ -344,8 +348,8 @@ public class CollectionTests

[AssertionDataTestMethod]
[AssertionCodeFix(
oldAssertion: "actual.Intersect(expected).Should().BeEmpty({0});",
newAssertion: "actual.Should().NotIntersectWith(expected{0});")]
oldAssertion: "actual.Intersect(expected).Should().BeEmpty({0});",
newAssertion: "actual.Should().NotIntersectWith(expected{0});")]
[Implemented]
public void CollectionShouldNotIntersectWith_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFix<CollectionShouldNotIntersectWithCodeFix, CollectionShouldNotIntersectWithAnalyzer>(oldAssertion, newAssertion);

Expand Down Expand Up @@ -376,37 +380,41 @@ public class CollectionTests

[AssertionDataTestMethod]
[AssertionDiagnostic("actual.Should().HaveSameCount(actual.Distinct(){0});")]
[NotImplemented]
[Implemented]
public void CollectionShouldOnlyHaveUniqueItems_TestAnalyzer(string assertion) => VerifyCSharpDiagnostic<CollectionShouldOnlyHaveUniqueItemsAnalyzer>(assertion);

[AssertionDataTestMethod]
[AssertionCodeFix(
oldAssertion: "actual.Should().HaveSameCount(actual.Distinct(){0});",
newAssertion: "actual.Should().OnlyHaveUniqueItems({0});")]
[NotImplemented]
[Implemented]
public void CollectionShouldOnlyHaveUniqueItems_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFix<CollectionShouldOnlyHaveUniqueItemsCodeFix, CollectionShouldOnlyHaveUniqueItemsAnalyzer>(oldAssertion, newAssertion);

[AssertionDataTestMethod]
[AssertionDiagnostic("actual.Select(x => x.BooleanProperty).Should().OnlyHaveUniqueItems({0});")]
[NotImplemented]
[Implemented]
public void CollectionShouldOnlyHaveUniqueItemsByComparer_TestAnalyzer(string assertion) => VerifyCSharpDiagnostic<CollectionShouldOnlyHaveUniqueItemsByComparerAnalyzer>(assertion);

[AssertionDataTestMethod]
[AssertionCodeFix(
oldAssertion: "actual.Select(x => x.BooleanProperty).Should().OnlyHaveUniqueItems({0});",
newAssertion: "actual.Should().OnlyHaveUniqueItems(x => x.BooleanProperty{0});")]
[NotImplemented]
[Implemented]
[Ignore("Will be available in Fluent Assertions 5.0")]
public void CollectionShouldOnlyHaveUniqueItemsByComparer_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFix<CollectionShouldOnlyHaveUniqueItemsByComparerCodeFix, CollectionShouldOnlyHaveUniqueItemsByComparerAnalyzer>(oldAssertion, newAssertion);

[AssertionDataTestMethod]
[AssertionDiagnostic("actual.FirstOrDefault().Should().BeNull({0});")]
[NotImplemented]
[Ignore("What Should Happen?")]
public void CollectionShouldHaveElementAt0Null_TestAnalyzer(string assertion) => VerifyCSharpDiagnostic<CollectionShouldHaveElementAt0NullAnalyzer>(assertion);

[AssertionDataTestMethod]
[AssertionCodeFix(
oldAssertion: "actual.FirstOrDefault().Should().BeNull({0});",
newAssertion: "actual.Should().HaveElementAt(0, null{0});")]
[NotImplemented]
[Ignore("What Should Happen?")]
public void CollectionShouldHaveElementAt0Null_TestCodeFix(string oldAssertion, string newAssertion) => VerifyCSharpFix<CollectionShouldHaveElementAt0NullCodeFix, CollectionShouldHaveElementAt0NullAnalyzer>(oldAssertion, newAssertion);

private void VerifyCSharpDiagnostic<TDiagnosticAnalyzer>(string sourceAssersion) where TDiagnosticAnalyzer : Microsoft.CodeAnalysis.Diagnostics.DiagnosticAnalyzer, new()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<metadata>
<id>FluentAssertions.BestPractices</id>
<title>Fluent Assertions Best Practice</title>
<version>0.2.1</version>
<version>0.3.0</version>
<owners>Meir Blachman</owners>
<authors>Meir Blachman</authors>
<summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using System.Collections.Generic;
Expand All @@ -14,32 +15,62 @@ public class CollectionShouldEqualOtherCollectionByComparerAnalyzer : FluentAsse
public const string DiagnosticId = Constants.Tips.Collections.CollectionShouldEqualOtherCollectionByComparer;
public const string Category = Constants.Tips.Category;

public const string Message = "Use {0} .Should() followed by ### instead.";
public const string Message = "Use {0} .Should() followed by .Equal() instead.";

protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true);

protected override Diagnostic AnalyzeExpressionStatement(ExpressionStatementSyntax statement)
protected override IEnumerable<(FluentAssertionsCSharpSyntaxVisitor, BecauseArgumentsSyntaxVisitor)> Visitors
{
return null;
var visitor = new CollectionShouldEqualOtherCollectionByComparerSyntaxVisitor();
statement.Accept(visitor);
get
{
yield return (new SelectShouldEqualOtherCollectionSelectSyntaxVisitor(), new BecauseArgumentsSyntaxVisitor("Equal", 1));
}
}

private class SelectShouldEqualOtherCollectionSelectSyntaxVisitor : FluentAssertionsWithArgumentsCSharpSyntaxVisitor
{
private ExpressionSyntax _lambdaArgument;
private string _otherVariable;

if (visitor.IsValid)
protected override bool AreArgumentsValid()
{
var properties = new Dictionary<string, string>
if (Arguments.TryGetValue(("Select", 0), out var selectArgument) && selectArgument is SimpleLambdaExpressionSyntax select
&& Arguments.TryGetValue(("Equal", 0), out var expectedArgument) && expectedArgument is InvocationExpressionSyntax expected)
{
[Constants.DiagnosticProperties.VariableName] = visitor.VariableName,
[Constants.DiagnosticProperties.Title] = Title
}.ToImmutableDictionary();
throw new System.NotImplementedException();
var visitor = new SelectSyntaxVisitor();
expected.Accept(visitor);

if (visitor.IsValid)
{
_otherVariable = visitor.VariableName;
_lambdaArgument = SyntaxFactory.ParenthesizedLambdaExpression(
parameterList: SyntaxFactory.ParameterList().AddParameters(select.Parameter, visitor.Lambda.Parameter),
body: SyntaxFactory.BinaryExpression(SyntaxKind.EqualsExpression,
left: (ExpressionSyntax)select.Body,
right: (ExpressionSyntax)visitor.Lambda.Body)
).NormalizeWhitespace();
return true;
}
}
return false;
}

public SelectShouldEqualOtherCollectionSelectSyntaxVisitor() : base("Select", "Should", "Equal")
{
}

return Diagnostic.Create(
descriptor: Rule,
location: statement.Expression.GetLocation(),
properties: properties,
messageArgs: visitor.VariableName);
public override ImmutableDictionary<string, string> ToDiagnosticProperties() => base.ToDiagnosticProperties()
.Add(Constants.DiagnosticProperties.LambdaString, _lambdaArgument.ToFullString())
.Add(Constants.DiagnosticProperties.ArgumentString, _otherVariable);


private class SelectSyntaxVisitor : FluentAssertionsWithLambdaArgumentCSharpSyntaxVisitor
{
protected override string MethodContainingLambda => "Select";
public SelectSyntaxVisitor() : base("Select")
{
}
}
return null;
}
}

Expand All @@ -49,16 +80,6 @@ public class CollectionShouldEqualOtherCollectionByComparerCodeFix : FluentAsser
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldEqualOtherCollectionByComparerAnalyzer.DiagnosticId);

protected override StatementSyntax GetNewStatement(FluentAssertionsDiagnosticProperties properties)
{
throw new System.NotImplementedException();
}
}

public class CollectionShouldEqualOtherCollectionByComparerSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor
{
public CollectionShouldEqualOtherCollectionByComparerSyntaxVisitor() : base("###")
{
throw new System.NotImplementedException();
}
=> SyntaxFactory.ParseStatement($"{properties.VariableName}.Should().Equal({properties.ArgumentString}, {properties.CombineWithBecauseArgumentsString(properties.LambdaString)});");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public class CollectionShouldHaveElementAtAnalyzer : FluentAssertionsAnalyzer

private class ElementAtIndexShouldBeSyntaxVisitor : FluentAssertionsWithArgumentsCSharpSyntaxVisitor
{
protected override bool AreArgumentsValid =>
protected override bool AreArgumentsValid() =>
Arguments.TryGetValue(("ElementAt", 0), out ExpressionSyntax index) && (index is LiteralExpressionSyntax || index is IdentifierNameSyntax)
&& Arguments.TryGetValue(("Be", 0), out ExpressionSyntax expectedItem) && (expectedItem is LiteralExpressionSyntax || expectedItem is IdentifierNameSyntax);

Expand All @@ -45,7 +45,7 @@ public override ImmutableDictionary<string, string> ToDiagnosticProperties()
}
private class IndexerShouldBeSyntaxVisitor : FluentAssertionsWithArgumentsCSharpSyntaxVisitor
{
protected override bool AreArgumentsValid =>
protected override bool AreArgumentsValid() =>
Arguments.TryGetValue(("[]", 0), out ExpressionSyntax index) && (index is LiteralExpressionSyntax || index is IdentifierNameSyntax)
&& Arguments.TryGetValue(("Be", 0), out ExpressionSyntax expectedItem) && (expectedItem is LiteralExpressionSyntax || expectedItem is IdentifierNameSyntax);

Expand All @@ -60,7 +60,7 @@ public override ImmutableDictionary<string, string> ToDiagnosticProperties()

private class SkipFirstShouldBeSyntaxVisitor : FluentAssertionsWithArgumentsCSharpSyntaxVisitor
{
protected override bool AreArgumentsValid =>
protected override bool AreArgumentsValid() =>
Arguments.TryGetValue(("Skip", 0), out ExpressionSyntax index) && (index is LiteralExpressionSyntax || index is IdentifierNameSyntax)
&& Arguments.TryGetValue(("Be", 0), out ExpressionSyntax expectedItem) && (expectedItem is LiteralExpressionSyntax || expectedItem is IdentifierNameSyntax);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using System.Collections.Generic;
Expand All @@ -18,28 +19,26 @@ public class CollectionShouldNotBeNullOrEmptyAnalyzer : FluentAssertionsAnalyzer

protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true);

protected override Diagnostic AnalyzeExpressionStatement(ExpressionStatementSyntax statement)
protected override IEnumerable<(FluentAssertionsCSharpSyntaxVisitor, BecauseArgumentsSyntaxVisitor)> Visitors
{
return null;
var visitor = new CollectionShouldNotBeNullOrEmptySyntaxVisitor();
statement.Accept(visitor);

if (visitor.IsValid)
get
{
var properties = new Dictionary<string, string>
{
[Constants.DiagnosticProperties.VariableName] = visitor.VariableName,
[Constants.DiagnosticProperties.Title] = Title
}.ToImmutableDictionary();
throw new System.NotImplementedException();
yield return (new ShouldNotBeNullAndNotBeEmptySyntaxVisitor(), new BecauseArgumentsSyntaxVisitor("NotBeEmpty", 0));
yield return (new ShouldNotBeEmptyAndNotBeNullSyntaxVisitor(), new BecauseArgumentsSyntaxVisitor("NotBeNull", 0));
}
}

return Diagnostic.Create(
descriptor: Rule,
location: statement.Expression.GetLocation(),
properties: properties,
messageArgs: visitor.VariableName);
private class ShouldNotBeNullAndNotBeEmptySyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor
{
public ShouldNotBeNullAndNotBeEmptySyntaxVisitor() : base("Should", "NotBeNull", "And", "NotBeEmpty")
{
}
}
private class ShouldNotBeEmptyAndNotBeNullSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor
{
public ShouldNotBeEmptyAndNotBeNullSyntaxVisitor() : base("Should", "NotBeEmpty", "And", "NotBeNull")
{
}
return null;
}
}

Expand All @@ -49,16 +48,6 @@ public class CollectionShouldNotBeNullOrEmptyCodeFix : FluentAssertionsCodeFixPr
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldNotBeNullOrEmptyAnalyzer.DiagnosticId);

protected override StatementSyntax GetNewStatement(FluentAssertionsDiagnosticProperties properties)
{
throw new System.NotImplementedException();
}
}

public class CollectionShouldNotBeNullOrEmptySyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor
{
public CollectionShouldNotBeNullOrEmptySyntaxVisitor() : base("###")
{
throw new System.NotImplementedException();
}
=> SyntaxFactory.ParseStatement($"{properties.VariableName}.Should().NotBeNullOrEmpty({properties.BecauseArgumentsString});");
}
}
Loading

0 comments on commit cc6dc0d

Please sign in to comment.