Skip to content

Commit

Permalink
add deep inheritance chain for tests analyzer
Browse files Browse the repository at this point in the history
  • Loading branch information
fakefeik committed Aug 22, 2024
1 parent 74d8162 commit a892388
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 0 deletions.
1 change: 1 addition & 0 deletions NUnit.Analyzers/Constants/AnalyzerIdentifiers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ internal static class AnalyzerIdentifiers
{
internal const string TestFieldIsNotReadonly = "NU0001";
internal const string TestUsesSetupAttributes = "NU0002";
internal const string TestDeepInheritanceChain = "NU0003";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using System.Collections.Immutable;
using System.Linq;

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;

using SkbKontur.NUnit.Analyzers.Constants;
using SkbKontur.NUnit.Analyzers.Extensions;

namespace SkbKontur.NUnit.Analyzers.TestDeepInheritanceChain
{
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class TestDeepInheritanceChainAnalyzer : DiagnosticAnalyzer
{
public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
context.EnableConcurrentExecution();
context.RegisterSymbolAction(AnalyzeType, SymbolKind.NamedType);
}

private static void AnalyzeType(SymbolAnalysisContext context)
{
var typeSymbol = (INamedTypeSymbol)context.Symbol;

var hasTests = typeSymbol
.GetMembers()
.OfType<IMethodSymbol>()
.Any(x => x.MethodKind == MethodKind.Ordinary && x.IsTestRelatedMethod(context.Compilation));

if (!hasTests)
return;

var testBase = typeSymbol.BaseType?.BaseType;
if (testBase != null && !knownRoots.Any(r => testBase.IsType(r, context.Compilation)))
context.ReportDiagnostic(Diagnostic.Create(testDeepInheritanceChain, typeSymbol.Locations[0]));
}

public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics =>
ImmutableArray.Create(testDeepInheritanceChain);

private static readonly DiagnosticDescriptor testDeepInheritanceChain = new DiagnosticDescriptor(
AnalyzerIdentifiers.TestDeepInheritanceChain,

Check warning on line 43 in NUnit.Analyzers/TestDeepInheritanceChain/TestDeepInheritanceChainAnalyzer.cs

View workflow job for this annotation

GitHub Actions / test

Enable analyzer release tracking for the analyzer project containing rule 'NU0003' (https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md)

Check warning on line 43 in NUnit.Analyzers/TestDeepInheritanceChain/TestDeepInheritanceChainAnalyzer.cs

View workflow job for this annotation

GitHub Actions / test

Enable analyzer release tracking for the analyzer project containing rule 'NU0003' (https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md)

Check warning on line 43 in NUnit.Analyzers/TestDeepInheritanceChain/TestDeepInheritanceChainAnalyzer.cs

View workflow job for this annotation

GitHub Actions / test

Enable analyzer release tracking for the analyzer project containing rule 'NU0003' (https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md)

Check warning on line 43 in NUnit.Analyzers/TestDeepInheritanceChain/TestDeepInheritanceChainAnalyzer.cs

View workflow job for this annotation

GitHub Actions / test

Enable analyzer release tracking for the analyzer project containing rule 'NU0003' (https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md)
TestDeepInheritanceChainConstants.TestDeepInheritanceChainTitle,
TestDeepInheritanceChainConstants.TestDeepInheritanceChainMessage,
Categories.ParallelExecution,
DiagnosticSeverity.Warning,
true,
TestDeepInheritanceChainConstants.TestDeepInheritanceChainDescription,
TestDeepInheritanceChainConstants.TestDeepInheritanceChainUri
);

private static readonly string[] knownRoots =
{
"System.Object",
"SkbKontur.NUnit.Middlewares.SimpleTestBase",
"SkbKontur.NUnit.Middlewares.SimpleSuiteBase",
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace SkbKontur.NUnit.Analyzers.TestDeepInheritanceChain
{
internal static class TestDeepInheritanceChainConstants
{
internal const string TestDeepInheritanceChainTitle = "Test base inheritance chain is too deep";
internal const string TestDeepInheritanceChainMessage = "Test base inheritance chain is too deep";
internal const string TestDeepInheritanceChainDescription = "Test fixture class should have only one base class for clarity.";
internal const string TestDeepInheritanceChainUri = "https://en.wikipedia.org/wiki/Composition_over_inheritance";
}
}

0 comments on commit a892388

Please sign in to comment.