-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added a suppressor when CA1812 fires on NUnit Test classes. (#569)
* Added a suppressor when CA1812 fires on NUnit Test classes. * Run test in Release mode This prevents the Dump of documentation templates.
- Loading branch information
1 parent
35fe3df
commit 522ffbe
Showing
19 changed files
with
341 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
# NUnit3003 | ||
|
||
## Class is a NUnit TestFixture and called by reflection | ||
|
||
| Topic | Value | ||
| :-- | :-- | ||
| Id | NUnit3003 | ||
| Severity | Info | ||
| Enabled | True | ||
| Category | Suppressor | ||
| Code | [AvoidUninstantiatedInternalClassesSuppressor](https://github.com/nunit/nunit.analyzers/blob/master/src/nunit.analyzers/DiagnosticSuppressors/AvoidUninstantiatedInternalClassesSuppressor.cs) | ||
|
||
## Description | ||
|
||
Class is a NUnit TestFixture and called by reflection | ||
|
||
## Motivation | ||
|
||
The default roslyn analyzer has rule [CA1812](https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1812) | ||
which warns about internal classes not being used. | ||
That analyzer doesn't know about NUnit test classes. | ||
This suppressor catches the error, verifies the class is an NUnit TestFixture and if so suppresses the error. | ||
|
||
<!-- start generated config severity --> | ||
## Configure severity | ||
|
||
The rule has no severity, but can be disabled. | ||
|
||
### Via ruleset file | ||
|
||
To disable the rule for a project, you need to add a | ||
[ruleset file](https://github.com/nunit/nunit.analyzers/blob/master/src/nunit.analyzers/DiagnosticSuppressors/NUnit.Analyzers.Suppressions.ruleset) | ||
|
||
```xml | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<RuleSet Name="NUnit.Analyzer Suppressions" Description="DiagnosticSuppression Rules" ToolsVersion="12.0"> | ||
<Rules AnalyzerId="DiagnosticSuppressors" RuleNamespace="NUnit.NUnitAnalyzers"> | ||
<Rule Id="NUnit3001" Action="Info" /> <!-- Possible Null Reference --> | ||
<Rule Id="NUnit3002" Action="Info" /> <!-- NonNullableField/Property is Uninitialized --> | ||
<Rule Id="NUnit3003" Action="Info" /> <!-- Avoid Uninstantiated Internal Classes --> | ||
</Rules> | ||
</RuleSet> | ||
``` | ||
|
||
and add it to the project like: | ||
|
||
```xml | ||
<PropertyGroup> | ||
<CodeAnalysisRuleSet>NUnit.Analyzers.Suppressions.ruleset</CodeAnalysisRuleSet> | ||
</PropertyGroup> | ||
``` | ||
|
||
For more info about rulesets see [MSDN](https://learn.microsoft.com/en-us/visualstudio/code-quality/using-rule-sets-to-group-code-analysis-rules?view=vs-2022). | ||
|
||
### Via .editorconfig file | ||
|
||
This is currently not working. Waiting for [Roslyn](https://github.com/dotnet/roslyn/issues/49727) | ||
|
||
```ini | ||
# NUnit3003: Class is a NUnit TestFixture and called by reflection | ||
dotnet_diagnostic.NUnit3003.severity = none | ||
``` | ||
<!-- end generated config severity --> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
using System; | ||
using System.Collections.Immutable; | ||
using System.Linq; | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.Diagnostics; | ||
|
||
namespace NUnit.Analyzers.Tests | ||
{ | ||
[DiagnosticAnalyzer(LanguageNames.CSharp)] | ||
#pragma warning disable RS1036 // Specify analyzer banned API enforcement setting | ||
internal sealed class DefaultEnabledAnalyzer : DiagnosticAnalyzer | ||
#pragma warning restore RS1036 // Specify analyzer banned API enforcement setting | ||
{ | ||
private readonly DiagnosticAnalyzer inner; | ||
|
||
internal DefaultEnabledAnalyzer(DiagnosticAnalyzer inner) | ||
{ | ||
this.inner = inner; | ||
this.SupportedDiagnostics = EnabledDiagnostics(inner.SupportedDiagnostics); | ||
|
||
static ImmutableArray<DiagnosticDescriptor> EnabledDiagnostics(ImmutableArray<DiagnosticDescriptor> source) | ||
{ | ||
var builder = ImmutableArray.CreateBuilder<DiagnosticDescriptor>(source.Length); | ||
foreach (var diagnostic in source) | ||
{ | ||
builder.Add( | ||
new DiagnosticDescriptor( | ||
diagnostic.Id, | ||
diagnostic.Title, | ||
diagnostic.MessageFormat, | ||
diagnostic.Category, | ||
diagnostic.DefaultSeverity, | ||
isEnabledByDefault: true, | ||
diagnostic.Description, | ||
diagnostic.HelpLinkUri, | ||
diagnostic.CustomTags?.ToArray() ?? Array.Empty<string>())); | ||
} | ||
|
||
return builder.MoveToImmutable(); | ||
} | ||
} | ||
|
||
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } | ||
|
||
#pragma warning disable RS1025, RS1026 | ||
public override void Initialize(AnalysisContext context) => this.inner.Initialize(context); | ||
#pragma warning restore RS1025, RS1026 | ||
} | ||
} |
89 changes: 89 additions & 0 deletions
89
...nalyzers.tests/DiagnosticSuppressors/AvoidUninstantiatedInternalClassesSuppressorTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
using System; | ||
using System.IO; | ||
using System.Reflection; | ||
using System.Threading.Tasks; | ||
using Microsoft.CodeAnalysis.Diagnostics; | ||
using NUnit.Analyzers.DiagnosticSuppressors; | ||
using NUnit.Framework; | ||
|
||
namespace NUnit.Analyzers.Tests.DiagnosticSuppressors | ||
{ | ||
internal class AvoidUninstantiatedInternalClassesSuppressorTests | ||
{ | ||
private const string CalculatorClass = @" | ||
internal sealed class Calculator | ||
{ | ||
private readonly Calculation _calculation; | ||
public Calculator(Calculation calculation) => _calculation = calculation; | ||
public int Calculate(int op1, int op2) | ||
{ | ||
return _calculation == Calculation.Add ? op1 + op2 : op1 - op2; | ||
} | ||
public enum Calculation | ||
{ | ||
Add, | ||
Subtract, | ||
} | ||
} | ||
"; | ||
|
||
private const string CalculatorTest = @" | ||
internal sealed class CalculatorTests | ||
{ | ||
[Test] | ||
public void TestAdd() | ||
{ | ||
var instance = new Calculator(Calculator.Calculation.Add); | ||
var result = instance.Calculate(3, 4); | ||
Assert.That(result, Is.EqualTo(7)); | ||
} | ||
[Test] | ||
public void TestSubtract() | ||
{ | ||
var instance = new Calculator(Calculator.Calculation.Subtract); | ||
var result = instance.Calculate(3, 4); | ||
Assert.That(result, Is.EqualTo(-1)); | ||
} | ||
} | ||
"; | ||
|
||
private static readonly DiagnosticSuppressor suppressor = new AvoidUninstantiatedInternalClassesSuppressor(); | ||
private DiagnosticAnalyzer analyzer; | ||
|
||
[OneTimeSetUp] | ||
public void OneTimeSetUp() | ||
{ | ||
// Find the NetAnalyzers assembly (note version should match the one referenced) | ||
string netAnalyzersPath = Path.Combine(PathHelper.GetNuGetPackageDirectory(), | ||
"microsoft.codeanalysis.netanalyzers/7.0.3/analyzers/dotnet/cs/Microsoft.CodeAnalysis.CSharp.NetAnalyzers.dll"); | ||
Assembly netAnalyzerAssembly = Assembly.LoadFrom(netAnalyzersPath); | ||
Type analyzerType = netAnalyzerAssembly.GetType("Microsoft.CodeQuality.CSharp.Analyzers.Maintainability.CSharpAvoidUninstantiatedInternalClasses", true)!; | ||
this.analyzer = (DiagnosticAnalyzer)Activator.CreateInstance(analyzerType)!; | ||
|
||
this.analyzer = new DefaultEnabledAnalyzer(this.analyzer); | ||
} | ||
|
||
[Test] | ||
public async Task NonTestClass() | ||
{ | ||
var testCode = TestUtility.WrapClassInNamespaceAndAddUsing(CalculatorClass); | ||
|
||
await TestHelpers.NotSuppressed(this.analyzer, suppressor, testCode).ConfigureAwait(true); | ||
} | ||
|
||
[Test] | ||
public async Task TestClass() | ||
{ | ||
var testCode = TestUtility.WrapClassInNamespaceAndAddUsing($@" | ||
{CalculatorClass} | ||
{CalculatorTest} | ||
"); | ||
|
||
await TestHelpers.Suppressed(this.analyzer, suppressor, testCode).ConfigureAwait(true); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
using System; | ||
using System.IO; | ||
|
||
namespace NUnit.Analyzers.Tests | ||
{ | ||
internal static class PathHelper | ||
{ | ||
public static string GetNuGetPackageDirectory() | ||
{ | ||
return Environment.GetEnvironmentVariable("NUGET_PACKAGES") ?? | ||
Path.Combine(GetHomeDirectory(), ".nuget/packages"); | ||
} | ||
|
||
public static string GetHomeDirectory() | ||
{ | ||
return Environment.GetEnvironmentVariable("HOME") ?? // Linux | ||
Environment.GetEnvironmentVariable("USERPROFILE") ?? // Windows | ||
throw new NotSupportedException("Cannot determine home directory"); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.