Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/BenchmarkDotNet.Analyzers/AnalyzerReleases.Unshipped.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,10 @@
Rule ID | Category | Severity | Notes
---------|----------|----------|--------------------
BDN1305 | Usage | Error | [ParamsSource] cannot reference write-only property


### Removed Rules

Rule ID | Category | Severity | Notes
---------|----------|----------|--------------------
BDN1100 | Usage | Error | Rule removed as GenericTypeArguments now supports abstract classes

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -135,15 +135,9 @@
<data name="General_BenchmarkClass_ClassMustBeNonStatic_Description" xml:space="preserve">
<value>A benchmark class must be an instance class</value>
</data>
<data name="General_BenchmarkClass_ClassWithGenericTypeArgumentsAttributeMustBeNonAbstract_Description" xml:space="preserve">
<value>A benchmark class annotated with a [GenericTypeArguments] attribute must be non-abstract</value>
</data>
<data name="General_BenchmarkClass_ClassMustBeNonStatic_MessageFormat" xml:space="preserve">
<value>Benchmark class '{0}' cannot be static</value>
</data>
<data name="General_BenchmarkClass_ClassWithGenericTypeArgumentsAttributeMustBeNonAbstract_MessageFormat" xml:space="preserve">
<value>Attribute [GenericTypeArguments] can only be applied to a non-abstract class</value>
</data>
<data name="BenchmarkRunner_Run_GenericTypeArgumentClassMustBeAnnotatedWithAGenericTypeArgumentsAttribute_MessageFormat" xml:space="preserve">
<value>Referenced generic benchmark class '{0}' has no [GenericTypeArguments] attribute(s)</value>
</data>
Expand All @@ -153,9 +147,6 @@
<data name="General_BenchmarkClass_ClassMustBeNonStatic_Title" xml:space="preserve">
<value>Benchmark classes must be non-static</value>
</data>
<data name="General_BenchmarkClass_ClassWithGenericTypeArgumentsAttributeMustBeNonAbstract_Title" xml:space="preserve">
<value>Benchmark classes annotated with the [GenericTypeArguments] attribute must be non-abstract</value>
</data>
<data name="BenchmarkRunner_Run_GenericTypeArgumentClassMustBeAnnotatedWithAGenericTypeArgumentsAttribute_Title" xml:space="preserve">
<value>Generic benchmark classes must be annotated with at least one [GenericTypeArguments] attribute</value>
</data>
Expand Down
1 change: 0 additions & 1 deletion src/BenchmarkDotNet.Analyzers/DiagnosticIds.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ public static class DiagnosticIds
public const string BenchmarkRunner_Run_TypeArgumentClassMustBeUnsealed = "BDN1002";
public const string BenchmarkRunner_Run_TypeArgumentClassMustBeNonAbstract = "BDN1003";
public const string BenchmarkRunner_Run_GenericTypeArgumentClassMustBeAnnotatedWithAGenericTypeArgumentsAttribute = "BDN1004";
public const string General_BenchmarkClass_ClassWithGenericTypeArgumentsAttributeMustBeNonAbstract = "BDN1100";
public const string General_BenchmarkClass_ClassWithGenericTypeArgumentsAttributeMustBeGeneric = "BDN1101";
public const string General_BenchmarkClass_GenericTypeArgumentsAttributeMustHaveMatchingTypeParameterCount = "BDN1102";
public const string General_BenchmarkClass_MethodMustBePublic = "BDN1103";
Expand Down
15 changes: 0 additions & 15 deletions src/BenchmarkDotNet.Analyzers/General/BenchmarkClassAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,6 @@ namespace BenchmarkDotNet.Analyzers.General;
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class BenchmarkClassAnalyzer : DiagnosticAnalyzer
{
internal static readonly DiagnosticDescriptor ClassWithGenericTypeArgumentsAttributeMustBeNonAbstractRule = new(
DiagnosticIds.General_BenchmarkClass_ClassWithGenericTypeArgumentsAttributeMustBeNonAbstract,
AnalyzerHelper.GetResourceString(nameof(BenchmarkDotNetAnalyzerResources.General_BenchmarkClass_ClassWithGenericTypeArgumentsAttributeMustBeNonAbstract_Title)),
AnalyzerHelper.GetResourceString(nameof(BenchmarkDotNetAnalyzerResources.General_BenchmarkClass_ClassWithGenericTypeArgumentsAttributeMustBeNonAbstract_MessageFormat)),
"Usage",
DiagnosticSeverity.Error,
isEnabledByDefault: true,
description: AnalyzerHelper.GetResourceString(nameof(BenchmarkDotNetAnalyzerResources.General_BenchmarkClass_ClassWithGenericTypeArgumentsAttributeMustBeNonAbstract_Description)));

internal static readonly DiagnosticDescriptor ClassWithGenericTypeArgumentsAttributeMustBeGenericRule = new(
DiagnosticIds.General_BenchmarkClass_ClassWithGenericTypeArgumentsAttributeMustBeGeneric,
AnalyzerHelper.GetResourceString(nameof(BenchmarkDotNetAnalyzerResources.General_BenchmarkClass_ClassWithGenericTypeArgumentsAttributeMustBeGeneric_Title)),
Expand Down Expand Up @@ -92,7 +83,6 @@ public class BenchmarkClassAnalyzer : DiagnosticAnalyzer

public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => new DiagnosticDescriptor[]
{
ClassWithGenericTypeArgumentsAttributeMustBeNonAbstractRule,
ClassWithGenericTypeArgumentsAttributeMustBeGenericRule,
GenericTypeArgumentsAttributeMustHaveMatchingTypeParameterCountRule,
MethodMustBePublicRule,
Expand Down Expand Up @@ -149,11 +139,6 @@ private static void AnalyzeClassDeclaration(SyntaxNodeAnalysisContext context)
{
foreach (var genericTypeArgumentsAttribute in genericTypeArgumentsAttributes)
{
if (classAbstractModifier.HasValue)
{
context.ReportDiagnostic(Diagnostic.Create(ClassWithGenericTypeArgumentsAttributeMustBeNonAbstractRule, genericTypeArgumentsAttribute.GetLocation()));
}

if (classDeclarationSyntax.TypeParameterList == null || classDeclarationSyntax.TypeParameterList.Parameters.Count == 0)
{
context.ReportDiagnostic(Diagnostic.Create(ClassWithGenericTypeArgumentsAttributeMustBeGenericRule, genericTypeArgumentsAttribute.GetLocation()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,46 +35,6 @@ public void BenchmarkMethod()
}
}

public class ClassWithGenericTypeArgumentsAttributeMustBeNonAbstract : AnalyzerTestFixture<BenchmarkClassAnalyzer>
{
public ClassWithGenericTypeArgumentsAttributeMustBeNonAbstract() : base(BenchmarkClassAnalyzer.ClassWithGenericTypeArgumentsAttributeMustBeNonAbstractRule) { }

[Theory, CombinatorialData]
public async Task Abstract_class_annotated_with_at_least_one_generictypearguments_attribute_should_trigger_diagnostic(
[CombinatorialRange(1, 2)] int genericTypeArgumentsAttributeUsageCount,
[CombinatorialMemberData(nameof(BenchmarkAttributeUsagesEnumerableLocal))] string benchmarkAttributeUsage)
{
const string benchmarkClassName = "BenchmarkClass";

var genericTypeArgumentsAttributeUsages = Enumerable.Repeat("[{{|#{0}:GenericTypeArguments(typeof(int))|}}]", genericTypeArgumentsAttributeUsageCount).Select((a, i) => string.Format(a, i));

var testCode = /* lang=c#-test */ $$"""
using BenchmarkDotNet.Attributes;

{{string.Join("\n", genericTypeArgumentsAttributeUsages)}}
public abstract class {{benchmarkClassName}}<TParameter>
{
{{benchmarkAttributeUsage}}
public void BenchmarkMethod()
{

}
}
""";

TestCode = testCode;

for (var i = 0; i < genericTypeArgumentsAttributeUsageCount; i++)
{
AddExpectedDiagnostic(i);
}

await RunAsync();
}

public static IEnumerable<string> BenchmarkAttributeUsagesEnumerableLocal => BenchmarkAttributeUsagesEnumerable;
}

public class ClassWithGenericTypeArgumentsAttributeMustBeGeneric : AnalyzerTestFixture<BenchmarkClassAnalyzer>
{
public ClassWithGenericTypeArgumentsAttributeMustBeGeneric() : base(BenchmarkClassAnalyzer.ClassWithGenericTypeArgumentsAttributeMustBeGenericRule) { }
Expand Down