Skip to content

Commit 0af0204

Browse files
committed
* Change severity level of "UnnecessarySingleValuePassedToAttribute" rule from warning to information
* Move diagnostic "MethodWithoutAttributeMustHaveNoParameters" to its own analyzer and also take [ArgumentsSource] attribute into consideration * Suppress analyzer errors for incorrect BenchmarkDotNet usages in tests * Adjust wording of "ClassWithGenericTypeArgumentsAttributeMustBeGenericRule" diagnostic and move trigger location to the attribute level
1 parent f8005fd commit 0af0204

27 files changed

+509
-253
lines changed

src/BenchmarkDotNet.Analyzers/AnalyzerReleases.Unshipped.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ BDN1206 | Usage | Error | BDN1206_Attributes_GeneralParameterAttributes_P
2929
BDN1207 | Usage | Error | BDN1207_Attributes_GeneralParameterAttributes_PropertyMustHavePublicSetter
3030
BDN1300 | Usage | Error | BDN1300_Attributes_ParamsAttribute_MustHaveValues
3131
BDN1301 | Usage | Error | BDN1301_Attributes_ParamsAttribute_MustHaveMatchingValueType
32-
BDN1302 | Usage | Warning | BDN1302_Attributes_ParamsAttribute_UnnecessarySingleValuePassedToAttribute
32+
BDN1302 | Usage | Info | BDN1302_Attributes_ParamsAttribute_UnnecessarySingleValuePassedToAttribute
3333
BDN1303 | Usage | Error | BDN1303_Attributes_ParamsAllValuesAttribute_NotAllowedOnFlagsEnumPropertyOrFieldType
3434
BDN1304 | Usage | Error | BDN1304_Attributes_ParamsAllValues_PropertyOrFieldTypeMustBeEnumOrBool
35-
BDN1400 | Usage | Error | BDN1400_Attributes_ArgumentsAttribute_RequiresBenchmarkAttribute
36-
BDN1401 | Usage | Error | BDN1401_Attributes_ArgumentsAttribute_MethodWithoutAttributeMustHaveNoParameters
37-
BDN1402 | Usage | Error | BDN1402_Attributes_ArgumentsAttribute_MustHaveMatchingValueCount
38-
BDN1403 | Usage | Error | BDN1403_Attributes_ArgumentsAttribute_MustHaveMatchingValueType
35+
BDN1400 | Usage | Error | BDN1400_Attributes_GeneralArgumentAttributes_MethodWithoutAttributeMustHaveNoParameters
36+
BDN1500 | Usage | Error | BDN1500_Attributes_ArgumentsAttribute_RequiresBenchmarkAttribute
37+
BDN1501 | Usage | Error | BDN1501_Attributes_ArgumentsAttribute_MustHaveMatchingValueCount
38+
BDN1502 | Usage | Error | BDN1502_Attributes_ArgumentsAttribute_MustHaveMatchingValueType

src/BenchmarkDotNet.Analyzers/Attributes/ArgumentsAttributeAnalyzer.cs

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,6 @@ public class ArgumentsAttributeAnalyzer : DiagnosticAnalyzer
1919
DiagnosticSeverity.Error,
2020
isEnabledByDefault: true);
2121

22-
internal static readonly DiagnosticDescriptor MethodWithoutAttributeMustHaveNoParametersRule = new DiagnosticDescriptor(DiagnosticIds.Attributes_ArgumentsAttribute_MethodWithoutAttributeMustHaveNoParameters,
23-
AnalyzerHelper.GetResourceString(nameof(BenchmarkDotNetAnalyzerResources.Attributes_ArgumentsAttribute_MethodWithoutAttributeMustHaveNoParameters_Title)),
24-
AnalyzerHelper.GetResourceString(nameof(BenchmarkDotNetAnalyzerResources.Attributes_ArgumentsAttribute_MethodWithoutAttributeMustHaveNoParameters_MessageFormat)),
25-
"Usage",
26-
DiagnosticSeverity.Error,
27-
isEnabledByDefault: true,
28-
description: BenchmarkDotNetAnalyzerResources.Attributes_ArgumentsAttribute_MethodWithoutAttributeMustHaveNoParameters_Description);
29-
3022
internal static readonly DiagnosticDescriptor MustHaveMatchingValueCountRule = new DiagnosticDescriptor(DiagnosticIds.Attributes_ArgumentsAttribute_MustHaveMatchingValueCount,
3123
AnalyzerHelper.GetResourceString(nameof(BenchmarkDotNetAnalyzerResources.Attributes_ArgumentsAttribute_MustHaveMatchingValueCount_Title)),
3224
AnalyzerHelper.GetResourceString(nameof(BenchmarkDotNetAnalyzerResources.Attributes_ArgumentsAttribute_MustHaveMatchingValueCount_MessageFormat)),
@@ -46,7 +38,6 @@ public class ArgumentsAttributeAnalyzer : DiagnosticAnalyzer
4638
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics =>
4739
[
4840
RequiresBenchmarkAttributeRule,
49-
MethodWithoutAttributeMustHaveNoParametersRule,
5041
MustHaveMatchingValueCountRule,
5142
MustHaveMatchingValueTypeRule
5243
];
@@ -77,7 +68,9 @@ private static void AnalyzeMethodDeclaration(SyntaxNodeAnalysisContext context)
7768
}
7869

7970
var argumentsAttributeTypeSymbol = context.Compilation.GetTypeByMetadataName("BenchmarkDotNet.Attributes.ArgumentsAttribute");
80-
if (argumentsAttributeTypeSymbol == null)
71+
var argumentsSourceAttributeTypeSymbol = context.Compilation.GetTypeByMetadataName("BenchmarkDotNet.Attributes.ArgumentsSourceAttribute");
72+
73+
if (argumentsAttributeTypeSymbol == null || argumentsSourceAttributeTypeSymbol == null)
8174
{
8275
return;
8376
}
@@ -87,11 +80,6 @@ private static void AnalyzeMethodDeclaration(SyntaxNodeAnalysisContext context)
8780
var argumentsAttributes = AnalyzerHelper.GetAttributes(argumentsAttributeTypeSymbol, methodDeclarationSyntax.AttributeLists, context.SemanticModel);
8881
if (argumentsAttributes.Length == 0)
8982
{
90-
if (hasBenchmarkAttribute && methodDeclarationSyntax.ParameterList.Parameters.Count > 0)
91-
{
92-
context.ReportDiagnostic(Diagnostic.Create(MethodWithoutAttributeMustHaveNoParametersRule, Location.Create(context.FilterTree, methodDeclarationSyntax.ParameterList.Parameters.Span), methodDeclarationSyntax.Identifier.ToString()));
93-
}
94-
9583
return;
9684
}
9785

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
namespace BenchmarkDotNet.Analyzers.Attributes
2+
{
3+
using Microsoft.CodeAnalysis.CSharp;
4+
using Microsoft.CodeAnalysis.CSharp.Syntax;
5+
using Microsoft.CodeAnalysis;
6+
using Microsoft.CodeAnalysis.Diagnostics;
7+
8+
using System.Collections.Immutable;
9+
10+
[DiagnosticAnalyzer(LanguageNames.CSharp)]
11+
public class GeneralArgumentAttributesAnalyzer : DiagnosticAnalyzer
12+
{
13+
internal static readonly DiagnosticDescriptor MethodWithoutAttributeMustHaveNoParametersRule = new DiagnosticDescriptor(DiagnosticIds.Attributes_GeneralArgumentAttributes_MethodWithoutAttributeMustHaveNoParameters,
14+
AnalyzerHelper.GetResourceString(nameof(BenchmarkDotNetAnalyzerResources.Attributes_GeneralArgumentAttributes_MethodWithoutAttributeMustHaveNoParameters_Title)),
15+
AnalyzerHelper.GetResourceString(nameof(BenchmarkDotNetAnalyzerResources.Attributes_GeneralArgumentAttributes_MethodWithoutAttributeMustHaveNoParameters_MessageFormat)),
16+
"Usage",
17+
DiagnosticSeverity.Error,
18+
isEnabledByDefault: true,
19+
description: BenchmarkDotNetAnalyzerResources.Attributes_GeneralArgumentAttributes_MethodWithoutAttributeMustHaveNoParameters_Description);
20+
21+
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics =>
22+
[
23+
MethodWithoutAttributeMustHaveNoParametersRule,
24+
];
25+
26+
public override void Initialize(AnalysisContext analysisContext)
27+
{
28+
analysisContext.EnableConcurrentExecution();
29+
analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
30+
31+
analysisContext.RegisterCompilationStartAction(ctx =>
32+
{
33+
// Only run if BenchmarkDotNet.Annotations is referenced
34+
var benchmarkAttributeTypeSymbol = AnalyzerHelper.GetBenchmarkAttributeTypeSymbol(ctx.Compilation);
35+
if (benchmarkAttributeTypeSymbol == null)
36+
{
37+
return;
38+
}
39+
40+
ctx.RegisterSyntaxNodeAction(AnalyzeMethodDeclaration, SyntaxKind.MethodDeclaration);
41+
});
42+
}
43+
44+
private static void AnalyzeMethodDeclaration(SyntaxNodeAnalysisContext context)
45+
{
46+
if (context.Node is not MethodDeclarationSyntax methodDeclarationSyntax)
47+
{
48+
return;
49+
}
50+
51+
var argumentsAttributeTypeSymbol = context.Compilation.GetTypeByMetadataName("BenchmarkDotNet.Attributes.ArgumentsAttribute");
52+
var argumentsSourceAttributeTypeSymbol = context.Compilation.GetTypeByMetadataName("BenchmarkDotNet.Attributes.ArgumentsSourceAttribute");
53+
54+
if (argumentsAttributeTypeSymbol == null || argumentsSourceAttributeTypeSymbol == null)
55+
{
56+
return;
57+
}
58+
59+
var hasBenchmarkAttribute = AnalyzerHelper.AttributeListsContainAttribute(AnalyzerHelper.GetBenchmarkAttributeTypeSymbol(context.Compilation), methodDeclarationSyntax.AttributeLists, context.SemanticModel);
60+
var hasArgumentsSourceAttribute = AnalyzerHelper.AttributeListsContainAttribute(argumentsSourceAttributeTypeSymbol, methodDeclarationSyntax.AttributeLists, context.SemanticModel);
61+
62+
var argumentsAttributes = AnalyzerHelper.GetAttributes(argumentsAttributeTypeSymbol, methodDeclarationSyntax.AttributeLists, context.SemanticModel);
63+
if (argumentsAttributes.Length == 0)
64+
{
65+
if (hasBenchmarkAttribute && !hasArgumentsSourceAttribute && methodDeclarationSyntax.ParameterList.Parameters.Count > 0)
66+
{
67+
context.ReportDiagnostic(Diagnostic.Create(MethodWithoutAttributeMustHaveNoParametersRule, Location.Create(context.FilterTree, methodDeclarationSyntax.ParameterList.Parameters.Span), methodDeclarationSyntax.Identifier.ToString()));
68+
}
69+
}
70+
}
71+
}
72+
}

src/BenchmarkDotNet.Analyzers/Attributes/GeneralParameterAttributesAnalyzer.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,6 @@ private static void AnalyzeFieldOrPropertySymbol(SyntaxNodeAnalysisContext conte
254254
{
255255
context.ReportDiagnostic(Diagnostic.Create(NotValidOnConstantFieldRule,
256256
fieldConstModifierLocation,
257-
fieldOrPropertyIdentifier,
258257
attributeSyntax.Name.ToString()));
259258

260259
return;

src/BenchmarkDotNet.Analyzers/Attributes/ParamsAttributeAnalyzer.cs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,15 @@ public class ParamsAttributeAnalyzer : DiagnosticAnalyzer
3030
AnalyzerHelper.GetResourceString(nameof(BenchmarkDotNetAnalyzerResources.Attributes_ParamsAttribute_UnnecessarySingleValuePassedToAttribute_Title)),
3131
AnalyzerHelper.GetResourceString(nameof(BenchmarkDotNetAnalyzerResources.Attributes_ParamsAttribute_UnnecessarySingleValuePassedToAttribute_MessageFormat)),
3232
"Usage",
33-
DiagnosticSeverity.Warning,
33+
DiagnosticSeverity.Info,
3434
isEnabledByDefault: true);
3535

36-
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(
37-
MustHaveValuesRule,
38-
MustHaveMatchingValueTypeRule,
39-
UnnecessarySingleValuePassedToAttributeRule
40-
);
36+
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics =>
37+
[
38+
MustHaveValuesRule,
39+
MustHaveMatchingValueTypeRule,
40+
UnnecessarySingleValuePassedToAttributeRule
41+
];
4142

4243
public override void Initialize(AnalysisContext analysisContext)
4344
{

src/BenchmarkDotNet.Analyzers/BenchmarkDotNetAnalyzerResources.Designer.cs

Lines changed: 32 additions & 31 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)