Skip to content

Commit

Permalink
add support for arrays in collection analyzers
Browse files Browse the repository at this point in the history
  • Loading branch information
Meir017 committed Aug 15, 2023
1 parent 51e7c7e commit 919d4ae
Show file tree
Hide file tree
Showing 11 changed files with 38 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,17 @@ namespace FluentAssertions.Analyzers
{
public abstract class CollectionAnalyzer : FluentAssertionsAnalyzer
{
protected override bool ShouldAnalyzeVariableType(INamedTypeSymbol type, SemanticModel semanticModel)
protected override bool ShouldAnalyzeVariableNamedType(INamedTypeSymbol type, SemanticModel semanticModel)
{
return type.SpecialType != SpecialType.System_String
&& type.IsTypeOrConstructedFromTypeOrImplementsType(SpecialType.System_Collections_Generic_IEnumerable_T);
}

override protected bool ShouldAnalyzeVariableType(ITypeSymbol type, SemanticModel semanticModel)
{
return type.SpecialType != SpecialType.System_String
&& type.IsTypeOrConstructedFromTypeOrImplementsType(SpecialType.System_Collections_Generic_IEnumerable_T);
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ protected override IEnumerable<FluentAssertionsCSharpSyntaxVisitor> Visitors
}
}

protected override bool ShouldAnalyzeVariableType(INamedTypeSymbol type, SemanticModel semanticModel)
protected override bool ShouldAnalyzeVariableNamedType(INamedTypeSymbol type, SemanticModel semanticModel)
{
if (!type.IsTypeOrConstructedFromTypeOrImplementsType(SpecialType.System_Collections_Generic_IEnumerable_T))
{
return false;
}

return base.ShouldAnalyzeVariableType(type, semanticModel);
return base.ShouldAnalyzeVariableNamedType(type, semanticModel);
}

public class WhereShouldHaveCount1SyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ protected override IEnumerable<FluentAssertionsCSharpSyntaxVisitor> Visitors
}
}

protected override bool ShouldAnalyzeVariableType(INamedTypeSymbol type, SemanticModel semanticModel)
protected override bool ShouldAnalyzeVariableNamedType(INamedTypeSymbol type, SemanticModel semanticModel)
{
var iReadOnlyDictionaryType = semanticModel.GetIReadOnlyDictionaryType();
var iDictionaryType = semanticModel.GetGenericIDictionaryType();
Expand All @@ -38,7 +38,7 @@ protected override bool ShouldAnalyzeVariableType(INamedTypeSymbol type, Semanti
return false;
}

return base.ShouldAnalyzeVariableType(type, semanticModel);
return base.ShouldAnalyzeVariableNamedType(type, semanticModel);
}

public class ElementAtIndexShouldBeSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace FluentAssertions.Analyzers
{
public abstract class DictionaryAnalyzer : FluentAssertionsAnalyzer
{
protected override bool ShouldAnalyzeVariableType(INamedTypeSymbol type, SemanticModel semanticModel)
protected override bool ShouldAnalyzeVariableNamedType(INamedTypeSymbol type, SemanticModel semanticModel)
{
var iDictionaryType = semanticModel.GetGenericIDictionaryType();
return type.IsTypeOrConstructedFromTypeOrImplementsType(iDictionaryType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace FluentAssertions.Analyzers
{
public abstract class ExceptionAnalyzer : FluentAssertionsAnalyzer
{
protected override bool ShouldAnalyzeVariableType(INamedTypeSymbol type, SemanticModel semanticModel)
protected override bool ShouldAnalyzeVariableNamedType(INamedTypeSymbol type, SemanticModel semanticModel)
{
var actionType = semanticModel.GetActionType();
return type.IsTypeOrConstructedFromTypeOrImplementsType(actionType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ namespace FluentAssertions.Analyzers
{
public abstract class NumericAnalyzer : FluentAssertionsAnalyzer
{
protected override bool ShouldAnalyzeVariableType(INamedTypeSymbol type, SemanticModel semanticModel) => true;
protected override bool ShouldAnalyzeVariableNamedType(INamedTypeSymbol type, SemanticModel semanticModel) => true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ protected override IEnumerable<FluentAssertionsCSharpSyntaxVisitor> Visitors
}

private static readonly string[] ValidaTypeNames = { "double", "decimal", "float" };
protected override bool ShouldAnalyzeVariableType(INamedTypeSymbol type, SemanticModel semanticModel)
protected override bool ShouldAnalyzeVariableNamedType(INamedTypeSymbol type, SemanticModel semanticModel)
=> ValidaTypeNames.Contains(type.ToDisplayString(), StringComparer.OrdinalIgnoreCase);

public class MathAbsShouldBeLessOrEqualToSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ namespace FluentAssertions.Analyzers
{
public abstract class StringAnalyzer : FluentAssertionsAnalyzer
{
protected override bool ShouldAnalyzeVariableType(INamedTypeSymbol type, SemanticModel semanticModel) => type.SpecialType == SpecialType.System_String;
protected override bool ShouldAnalyzeVariableNamedType(INamedTypeSymbol type, SemanticModel semanticModel) => type.SpecialType == SpecialType.System_String;
}
}
2 changes: 1 addition & 1 deletion src/FluentAssertions.Analyzers/Tips/Xunit/XunitBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public abstract class XunitAnalyzer : TestingLibraryAnalyzerBase
protected override string TestingLibraryModule => "xunit.assert";
protected override string TestingLibraryAssertionType => "Assert";

protected override bool ShouldAnalyzeVariableType(INamedTypeSymbol type, SemanticModel semanticModel) => type.Name == "Assert";
protected override bool ShouldAnalyzeVariableNamedType(INamedTypeSymbol type, SemanticModel semanticModel) => type.Name == "Assert";
}

public abstract class XunitCodeFixProvider : TestingLibraryCodeFixBase
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,18 @@ private void AnalyzeExpressionStatementSyntax(SyntaxNodeAnalysisContext context)
}
}

protected virtual bool ShouldAnalyzeVariableType(INamedTypeSymbol type, SemanticModel semanticModel) => true;
protected virtual bool ShouldAnalyzeVariableNamedType(INamedTypeSymbol type, SemanticModel semanticModel) => true;
protected virtual bool ShouldAnalyzeVariableType(ITypeSymbol type, SemanticModel semanticModel) => true;

private bool ShouldAnalyzeVariableTypeCore(ITypeSymbol type, SemanticModel semanticModel)
{
if (type is INamedTypeSymbol namedType)
{
return ShouldAnalyzeVariableNamedType(namedType, semanticModel);
}

return ShouldAnalyzeVariableType(type, semanticModel);
}

protected virtual Diagnostic AnalyzeExpression(ExpressionSyntax expression, SemanticModel semanticModel)
{
Expand All @@ -53,8 +64,7 @@ protected virtual Diagnostic AnalyzeExpression(ExpressionSyntax expression, Sema

if (variableNameExtractor.VariableIdentifierName == null) return null;
var typeInfo = semanticModel.GetTypeInfo(variableNameExtractor.VariableIdentifierName);
if (!(typeInfo.Type is INamedTypeSymbol namedType)) return null;
if (!ShouldAnalyzeVariableType(namedType, semanticModel)) return null;
if (!ShouldAnalyzeVariableTypeCore(typeInfo.Type, semanticModel)) return null;

foreach (var visitor in Visitors)
{
Expand Down Expand Up @@ -104,7 +114,7 @@ public abstract class TestingLibraryAnalyzerBase : FluentAssertionsAnalyzer
protected abstract string TestingLibraryModule { get; }
protected abstract string TestingLibraryAssertionType { get; }

protected override bool ShouldAnalyzeVariableType(INamedTypeSymbol type, SemanticModel semanticModel)
protected override bool ShouldAnalyzeVariableNamedType(INamedTypeSymbol type, SemanticModel semanticModel)
=> type.Name == TestingLibraryAssertionType && type.ContainingModule.Name == TestingLibraryModule + ".dll";
}
}
6 changes: 6 additions & 0 deletions src/FluentAssertions.Analyzers/Utilities/TypesExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,11 @@ public static bool IsTypeOrConstructedFromTypeOrImplementsType(this INamedTypeSy
return abstractType.Equals(other, SymbolEqualityComparer.Default)
|| abstractType.AllInterfaces.Any(@interface => @interface.OriginalDefinition.Equals(other, SymbolEqualityComparer.Default));
}

public static bool IsTypeOrConstructedFromTypeOrImplementsType(this ITypeSymbol type, SpecialType specialType)
{
return type.SpecialType == specialType
|| type.AllInterfaces.Any(@interface => @interface.OriginalDefinition.SpecialType == specialType);
}
}
}

0 comments on commit 919d4ae

Please sign in to comment.