Skip to content

Commit 6b77c83

Browse files
authored
chore: Enable nullable annotation for validators (#2902)
* chore: enable nullable for validators * chore: fix code based on review comment * chore: fix code based on review comment
1 parent 1f8e8db commit 6b77c83

10 files changed

+55
-33
lines changed

src/BenchmarkDotNet/Validators/BaselineValidator.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
using System.Collections.Generic;
1+
using BenchmarkDotNet.Jobs;
2+
using BenchmarkDotNet.Order;
3+
using System.Collections.Generic;
24
using System.Collections.Immutable;
35
using System.Linq;
4-
using BenchmarkDotNet.Jobs;
6+
7+
#nullable enable
58

69
namespace BenchmarkDotNet.Validators
710
{
@@ -16,14 +19,14 @@ private BaselineValidator() { }
1619
public IEnumerable<ValidationError> Validate(ValidationParameters input)
1720
{
1821
var allBenchmarks = input.Benchmarks.ToImmutableArray();
19-
var orderProvider = input.Config.Orderer;
22+
var orderProvider = input.Config.Orderer ?? DefaultOrderer.Instance;
2023

2124
var benchmarkLogicalGroups = allBenchmarks
2225
.Select(benchmark => orderProvider.GetLogicalGroupKey(allBenchmarks, benchmark))
2326
.ToArray();
2427

2528
var logicalGroups = benchmarkLogicalGroups.Distinct().ToArray();
26-
foreach (string logicalGroup in logicalGroups)
29+
foreach (string? logicalGroup in logicalGroups)
2730
{
2831
var benchmarks = allBenchmarks.Where((benchmark, index) => benchmarkLogicalGroups[index] == logicalGroup).ToArray();
2932
int methodBaselineCount = benchmarks.Select(b => b.Descriptor).Distinct().Count(it => it.Baseline);
@@ -38,7 +41,7 @@ public IEnumerable<ValidationError> Validate(ValidationParameters input)
3841
}
3942
}
4043

41-
private ValidationError CreateError(string subject, string property, string groupName, string className, string actual) =>
44+
private ValidationError CreateError(string subject, string property, string? groupName, string className, string actual) =>
4245
new ValidationError(
4346
TreatsWarningsAsErrors,
4447
$"Only 1 {subject} in a group can have \"{property}\" applied to it, group {groupName} in class {className} has {actual}");

src/BenchmarkDotNet/Validators/CompilationValidator.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
using Microsoft.CodeAnalysis.CSharp;
1010
using BenchmarkDotNet.Attributes;
1111

12+
#nullable enable
13+
1214
namespace BenchmarkDotNet.Validators
1315
{
1416
public class CompilationValidator : IValidator
@@ -133,7 +135,7 @@ private class BenchmarkMethodEqualityComparer : IEqualityComparer<BenchmarkCase>
133135
{
134136
internal static readonly IEqualityComparer<BenchmarkCase> Instance = new BenchmarkMethodEqualityComparer();
135137

136-
public bool Equals(BenchmarkCase x, BenchmarkCase y)
138+
public bool Equals(BenchmarkCase? x, BenchmarkCase? y)
137139
{
138140
if (x == null && y == null) return true;
139141
if (x == null || y == null) return false;

src/BenchmarkDotNet/Validators/ConfigValidator.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
using BenchmarkDotNet.Extensions;
77
using BenchmarkDotNet.Loggers;
88

9+
#nullable enable
10+
911
namespace BenchmarkDotNet.Validators
1012
{
1113
public class ConfigValidator : IValidator
@@ -38,7 +40,7 @@ public IEnumerable<ValidationError> Validate(ValidationParameters validationPara
3840
yield return pathValidation;
3941
}
4042

41-
private static ValidationError ValidateArtifactsPath(string artifactsPath)
43+
private static ValidationError? ValidateArtifactsPath(string artifactsPath)
4244
{
4345
if (artifactsPath == null) // null is OK, default path will be used
4446
return null;

src/BenchmarkDotNet/Validators/DeferredExecutionValidator.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
using System.Threading.Tasks;
66
using BenchmarkDotNet.Extensions;
77

8+
#nullable enable
9+
810
namespace BenchmarkDotNet.Validators
911
{
1012
public class DeferredExecutionValidator : IValidator
@@ -29,7 +31,7 @@ public IEnumerable<ValidationError> Validate(ValidationParameters validationPara
2931
private bool IsDeferredExecution(Type returnType)
3032
{
3133
if (returnType.IsByRef && !returnType.IsGenericType)
32-
return IsDeferredExecution(returnType.GetElementType());
34+
return IsDeferredExecution(returnType.GetElementType()!);
3335

3436
if (returnType.IsGenericType && (returnType.GetGenericTypeDefinition() == typeof(Task<>) || returnType.GetGenericTypeDefinition() == typeof(ValueTask<>)))
3537
return IsDeferredExecution(returnType.GetGenericArguments().Single());

src/BenchmarkDotNet/Validators/DotNetSdkValidator.cs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,13 @@
66
using System.Collections.Generic;
77
using System.ComponentModel;
88
using System.Diagnostics;
9+
using System.Diagnostics.CodeAnalysis;
910
using System.IO;
1011
using System.Linq;
1112
using System.Runtime.InteropServices;
1213

14+
#nullable enable
15+
1316
namespace BenchmarkDotNet.Validators
1417
{
1518
internal static class DotNetSdkValidator
@@ -26,15 +29,15 @@ public static IEnumerable<ValidationError> ValidateCoreSdks(string? customDotNet
2629
var requiredSdkVersion = benchmark.GetRuntime().RuntimeMoniker.GetRuntimeVersion();
2730
if (!GetInstalledDotNetSdks(customDotNetCliPath).Any(sdk => sdk >= requiredSdkVersion))
2831
{
29-
yield return new ValidationError(true, $"The required .NET Core SDK version {requiredSdkVersion} or higher for runtime moniker {benchmark.Job.Environment.Runtime.RuntimeMoniker} is not installed.", benchmark);
32+
yield return new ValidationError(true, $"The required .NET Core SDK version {requiredSdkVersion} or higher for runtime moniker {benchmark.Job.Environment.Runtime!.RuntimeMoniker} is not installed.", benchmark);
3033
}
3134
}
3235

3336
public static IEnumerable<ValidationError> ValidateFrameworkSdks(BenchmarkCase benchmark)
3437
{
3538
var targetRuntime = benchmark.Job.Environment.HasValue(EnvironmentMode.RuntimeCharacteristic)
36-
? benchmark.Job.Environment.Runtime
37-
: ClrRuntime.GetTargetOrCurrentVersion(benchmark.Descriptor.WorkloadMethod.DeclaringType.Assembly);
39+
? benchmark.Job.Environment.Runtime!
40+
: ClrRuntime.GetTargetOrCurrentVersion(benchmark.Descriptor.WorkloadMethod.DeclaringType!.Assembly);
3841
var requiredSdkVersion = targetRuntime.RuntimeMoniker.GetRuntimeVersion();
3942

4043
var installedVersionString = cachedFrameworkSdks.Value.FirstOrDefault();
@@ -44,7 +47,7 @@ public static IEnumerable<ValidationError> ValidateFrameworkSdks(BenchmarkCase b
4447
}
4548
}
4649

47-
public static bool IsCliPathInvalid(string customDotNetCliPath, BenchmarkCase benchmarkCase, out ValidationError? validationError)
50+
public static bool IsCliPathInvalid(string? customDotNetCliPath, BenchmarkCase benchmarkCase, [NotNullWhen(true)] out ValidationError? validationError)
4851
{
4952
validationError = null;
5053

@@ -71,7 +74,7 @@ public static bool IsCliPathInvalid(string customDotNetCliPath, BenchmarkCase be
7174

7275
private static IEnumerable<Version> GetInstalledDotNetSdks(string? customDotNetCliPath)
7376
{
74-
string dotnetExecutable = string.IsNullOrEmpty(customDotNetCliPath) ? "dotnet" : customDotNetCliPath;
77+
string dotnetExecutable = string.IsNullOrEmpty(customDotNetCliPath) ? "dotnet" : customDotNetCliPath!;
7578
var startInfo = new ProcessStartInfo(dotnetExecutable, "--list-sdks")
7679
{
7780
RedirectStandardOutput = true,
@@ -146,13 +149,13 @@ private static void Get45PlusFromRegistry(List<string> versions)
146149

147150
if (ndpKey.GetValue("Version") != null)
148151
{
149-
versions.Add(ndpKey.GetValue("Version").ToString());
152+
versions.Add(ndpKey.GetValue("Version")!.ToString()!);
150153
}
151154
else
152155
{
153156
if (ndpKey.GetValue("Release") != null)
154157
{
155-
versions.Add(CheckFor45PlusVersion((int)ndpKey.GetValue("Release")));
158+
versions.Add(CheckFor45PlusVersion((int)ndpKey.GetValue("Release")!));
156159
}
157160
}
158161
}

src/BenchmarkDotNet/Validators/ExecutionValidatorBase.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Diagnostics.CodeAnalysis;
34
using System.Linq;
45
using System.Reflection;
56
using System.Threading.Tasks;
@@ -8,6 +9,8 @@
89
using BenchmarkDotNet.Helpers;
910
using BenchmarkDotNet.Running;
1011

12+
#nullable enable
13+
1114
namespace BenchmarkDotNet.Validators
1215
{
1316
public abstract class ExecutionValidatorBase : IValidator
@@ -53,11 +56,11 @@ public IEnumerable<ValidationError> Validate(ValidationParameters validationPara
5356
return errors;
5457
}
5558

56-
private bool TryCreateBenchmarkTypeInstance(Type type, List<ValidationError> errors, out object? instance)
59+
private bool TryCreateBenchmarkTypeInstance(Type type, List<ValidationError> errors, [NotNullWhen(true)] out object? instance)
5760
{
5861
try
5962
{
60-
instance = Activator.CreateInstance(type);
63+
instance = Activator.CreateInstance(type)!;
6164

6265
return true;
6366
}
@@ -124,7 +127,7 @@ private bool TryToCallGlobalMethod<T>(object benchmarkTypeInstance, List<Validat
124127

125128
private string GetAttributeName(Type type) => type.Name.Replace("Attribute", string.Empty);
126129

127-
private void TryToGetTaskResult(object result)
130+
private void TryToGetTaskResult(object? result)
128131
{
129132
if (result == null)
130133
{
@@ -241,7 +244,7 @@ private bool TryToSetParamsProperties(object benchmarkTypeInstance, List<Validat
241244
protected static string GetDisplayExceptionMessage(Exception ex)
242245
{
243246
if (ex is TargetInvocationException targetInvocationException)
244-
ex = targetInvocationException.InnerException;
247+
ex = targetInvocationException.InnerException!;
245248

246249
return ex?.Message ?? "Unknown error";
247250
}

src/BenchmarkDotNet/Validators/ParamsAllValuesValidator.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Diagnostics.CodeAnalysis;
34
using System.Linq;
45
using System.Reflection;
56
using BenchmarkDotNet.Attributes;
67
using BenchmarkDotNet.Extensions;
78

9+
#nullable enable
10+
811
namespace BenchmarkDotNet.Validators
912
{
1013
public class ParamsAllValuesValidator : IValidator
@@ -24,7 +27,7 @@ public IEnumerable<ValidationError> Validate(ValidationParameters input) =>
2427
.SelectMany(type => type.GetTypeMembersWithGivenAttribute<ParamsAllValuesAttribute>(ReflectionFlags))
2528
.Distinct()
2629
.Select(member => GetErrorOrDefault(member.ParameterType))
27-
.Where(error => error != null);
30+
.WhereNotNull();
2831

2932
private bool IsBool(Type paramType) => paramType == typeof(bool);
3033
private bool IsEnum(Type paramType) => paramType.GetTypeInfo().IsEnum;
@@ -33,17 +36,17 @@ private bool IsFlagsEnum(Type paramType)
3336
var typeInfo = paramType.GetTypeInfo();
3437
return typeInfo.IsEnum && typeInfo.IsDefined(typeof(FlagsAttribute));
3538
}
36-
private bool IsNullable(Type paramType, out Type underlyingType)
39+
private bool IsNullable(Type paramType, [NotNullWhen(true)] out Type? underlyingType)
3740
{
3841
underlyingType = Nullable.GetUnderlyingType(paramType);
3942
return underlyingType != null;
4043
}
4144

42-
private ValidationError GetErrorOrDefault(Type parameterType)
45+
private ValidationError? GetErrorOrDefault(Type parameterType)
4346
{
4447
switch (parameterType)
4548
{
46-
case Type t when IsNullable(t, out Type underType):
49+
case Type t when IsNullable(t, out var underType):
4750
return GetErrorOrDefault(underType);
4851

4952
case Type t when IsFlagsEnum(t):

src/BenchmarkDotNet/Validators/ReturnValueValidator.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
using BenchmarkDotNet.Running;
1111
using BenchmarkDotNet.Toolchains.InProcess.NoEmit;
1212

13+
#nullable enable
14+
1315
namespace BenchmarkDotNet.Validators
1416
{
1517
public class ReturnValueValidator : ExecutionValidatorBase
@@ -32,7 +34,7 @@ protected override void ExecuteBenchmarks(object benchmarkTypeInstance, IEnumera
3234
try
3335
{
3436
InProcessNoEmitRunner.FillMembers(benchmarkTypeInstance, benchmark);
35-
var result = benchmark.Descriptor.WorkloadMethod.Invoke(benchmarkTypeInstance, null);
37+
var result = benchmark.Descriptor.WorkloadMethod.Invoke(benchmarkTypeInstance, null)!;
3638

3739
if (benchmark.Descriptor.WorkloadMethod.ReturnType != typeof(void))
3840
results.Add((benchmark, result));
@@ -64,7 +66,7 @@ private class ParameterInstancesEqualityComparer : IEqualityComparer<ParameterIn
6466
{
6567
public static ParameterInstancesEqualityComparer Instance { get; } = new ParameterInstancesEqualityComparer();
6668

67-
public bool Equals(ParameterInstances x, ParameterInstances y)
69+
public bool Equals(ParameterInstances? x, ParameterInstances? y)
6870
{
6971
if (ReferenceEquals(x, y))
7072
return true;
@@ -98,7 +100,7 @@ private class InDepthEqualityComparer : IEqualityComparer
98100
public static InDepthEqualityComparer Instance { get; } = new InDepthEqualityComparer();
99101

100102
[SuppressMessage("ReSharper", "MemberHidesStaticFromOuterClass")]
101-
public new bool Equals(object x, object y)
103+
public new bool Equals(object? x, object? y)
102104
{
103105
if (ReferenceEquals(x, y) || object.Equals(x, y))
104106
return true;
@@ -137,7 +139,7 @@ private bool CompareStructural(object x, object y)
137139

138140
return false;
139141

140-
Array ToStructuralEquatable(object obj)
142+
Array? ToStructuralEquatable(object obj)
141143
{
142144
switch (obj)
143145
{

src/BenchmarkDotNet/Validators/ValidationError.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
using BenchmarkDotNet.Running;
33
using JetBrains.Annotations;
44

5+
#nullable enable
6+
57
namespace BenchmarkDotNet.Validators
68
{
79
public class ValidationError : IEquatable<ValidationError>
@@ -43,6 +45,6 @@ public override bool Equals(object? obj)
4345

4446
public static bool operator ==(ValidationError left, ValidationError right) => Equals(left, right);
4547

46-
public static bool operator !=(ValidationError left, ValidationError right) => !Equals(left, right);
48+
public static bool operator !=(ValidationError? left, ValidationError? right) => !Equals(left, right);
4749
}
4850
}

src/BenchmarkDotNet/Validators/ValidationParameters.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,16 @@ public class ValidationParameters
1010
{
1111
public IReadOnlyList<BenchmarkCase> Benchmarks { get; }
1212

13-
public ImmutableConfig? Config { get; }
13+
public ImmutableConfig Config { get; }
1414

15-
public ValidationParameters(IReadOnlyList<BenchmarkCase> benchmarks, ImmutableConfig? config)
15+
public ValidationParameters(IReadOnlyList<BenchmarkCase> benchmarks, ImmutableConfig config)
1616
{
1717
Benchmarks = benchmarks;
1818
Config = config;
1919
}
2020

21-
// to have backward compatibility for people who implemented IValidator(Benchmark[] benchmarks)
22-
public static implicit operator ValidationParameters(BenchmarkCase[] benchmarksCase) => new ValidationParameters(benchmarksCase, null);
23-
public static implicit operator ValidationParameters(BenchmarkRunInfo benchmarkRunInfo) => new ValidationParameters(benchmarkRunInfo.BenchmarksCases, null);
21+
// Note: Following implicit operators are expected to be used for test projects.
22+
public static implicit operator ValidationParameters(BenchmarkCase[] benchmarksCase) => new ValidationParameters(benchmarksCase, DefaultConfig.Instance.CreateImmutableConfig());
23+
public static implicit operator ValidationParameters(BenchmarkRunInfo benchmarkRunInfo) => new ValidationParameters(benchmarkRunInfo.BenchmarksCases, benchmarkRunInfo.Config);
2424
}
2525
}

0 commit comments

Comments
 (0)