diff --git a/src/BenchmarkDotNet/Validators/BaselineValidator.cs b/src/BenchmarkDotNet/Validators/BaselineValidator.cs index 2bb8fea85c..33e6417350 100644 --- a/src/BenchmarkDotNet/Validators/BaselineValidator.cs +++ b/src/BenchmarkDotNet/Validators/BaselineValidator.cs @@ -1,7 +1,10 @@ -using System.Collections.Generic; +using BenchmarkDotNet.Jobs; +using BenchmarkDotNet.Order; +using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; -using BenchmarkDotNet.Jobs; + +#nullable enable namespace BenchmarkDotNet.Validators { @@ -16,14 +19,14 @@ private BaselineValidator() { } public IEnumerable Validate(ValidationParameters input) { var allBenchmarks = input.Benchmarks.ToImmutableArray(); - var orderProvider = input.Config.Orderer; + var orderProvider = input.Config.Orderer ?? DefaultOrderer.Instance; var benchmarkLogicalGroups = allBenchmarks .Select(benchmark => orderProvider.GetLogicalGroupKey(allBenchmarks, benchmark)) .ToArray(); var logicalGroups = benchmarkLogicalGroups.Distinct().ToArray(); - foreach (string logicalGroup in logicalGroups) + foreach (string? logicalGroup in logicalGroups) { var benchmarks = allBenchmarks.Where((benchmark, index) => benchmarkLogicalGroups[index] == logicalGroup).ToArray(); int methodBaselineCount = benchmarks.Select(b => b.Descriptor).Distinct().Count(it => it.Baseline); @@ -38,7 +41,7 @@ public IEnumerable Validate(ValidationParameters input) } } - private ValidationError CreateError(string subject, string property, string groupName, string className, string actual) => + private ValidationError CreateError(string subject, string property, string? groupName, string className, string actual) => new ValidationError( TreatsWarningsAsErrors, $"Only 1 {subject} in a group can have \"{property}\" applied to it, group {groupName} in class {className} has {actual}"); diff --git a/src/BenchmarkDotNet/Validators/CompilationValidator.cs b/src/BenchmarkDotNet/Validators/CompilationValidator.cs index b0bb87681d..3af42404fa 100644 --- a/src/BenchmarkDotNet/Validators/CompilationValidator.cs +++ b/src/BenchmarkDotNet/Validators/CompilationValidator.cs @@ -9,6 +9,8 @@ using Microsoft.CodeAnalysis.CSharp; using BenchmarkDotNet.Attributes; +#nullable enable + namespace BenchmarkDotNet.Validators { public class CompilationValidator : IValidator @@ -121,7 +123,7 @@ private class BenchmarkMethodEqualityComparer : IEqualityComparer { internal static readonly IEqualityComparer Instance = new BenchmarkMethodEqualityComparer(); - public bool Equals(BenchmarkCase x, BenchmarkCase y) + public bool Equals(BenchmarkCase? x, BenchmarkCase? y) { if (x == null && y == null) return true; if (x == null || y == null) return false; diff --git a/src/BenchmarkDotNet/Validators/ConfigValidator.cs b/src/BenchmarkDotNet/Validators/ConfigValidator.cs index 514b32cccc..3b73ae72d4 100644 --- a/src/BenchmarkDotNet/Validators/ConfigValidator.cs +++ b/src/BenchmarkDotNet/Validators/ConfigValidator.cs @@ -6,6 +6,8 @@ using BenchmarkDotNet.Extensions; using BenchmarkDotNet.Loggers; +#nullable enable + namespace BenchmarkDotNet.Validators { public class ConfigValidator : IValidator @@ -38,7 +40,7 @@ public IEnumerable Validate(ValidationParameters validationPara yield return pathValidation; } - private static ValidationError ValidateArtifactsPath(string artifactsPath) + private static ValidationError? ValidateArtifactsPath(string artifactsPath) { if (artifactsPath == null) // null is OK, default path will be used return null; diff --git a/src/BenchmarkDotNet/Validators/DeferredExecutionValidator.cs b/src/BenchmarkDotNet/Validators/DeferredExecutionValidator.cs index d0bda6ed28..fe0ccaa701 100644 --- a/src/BenchmarkDotNet/Validators/DeferredExecutionValidator.cs +++ b/src/BenchmarkDotNet/Validators/DeferredExecutionValidator.cs @@ -5,6 +5,8 @@ using System.Threading.Tasks; using BenchmarkDotNet.Extensions; +#nullable enable + namespace BenchmarkDotNet.Validators { public class DeferredExecutionValidator : IValidator @@ -29,7 +31,7 @@ public IEnumerable Validate(ValidationParameters validationPara private bool IsDeferredExecution(Type returnType) { if (returnType.IsByRef && !returnType.IsGenericType) - return IsDeferredExecution(returnType.GetElementType()); + return IsDeferredExecution(returnType.GetElementType()!); if (returnType.IsGenericType && (returnType.GetGenericTypeDefinition() == typeof(Task<>) || returnType.GetGenericTypeDefinition() == typeof(ValueTask<>))) return IsDeferredExecution(returnType.GetGenericArguments().Single()); diff --git a/src/BenchmarkDotNet/Validators/DotNetSdkValidator.cs b/src/BenchmarkDotNet/Validators/DotNetSdkValidator.cs index 5b84a12b12..8f16547944 100644 --- a/src/BenchmarkDotNet/Validators/DotNetSdkValidator.cs +++ b/src/BenchmarkDotNet/Validators/DotNetSdkValidator.cs @@ -6,10 +6,13 @@ using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Runtime.InteropServices; +#nullable enable + namespace BenchmarkDotNet.Validators { internal static class DotNetSdkValidator @@ -26,15 +29,15 @@ public static IEnumerable ValidateCoreSdks(string? customDotNet var requiredSdkVersion = benchmark.GetRuntime().RuntimeMoniker.GetRuntimeVersion(); if (!GetInstalledDotNetSdks(customDotNetCliPath).Any(sdk => sdk >= requiredSdkVersion)) { - 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); + 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); } } public static IEnumerable ValidateFrameworkSdks(BenchmarkCase benchmark) { var targetRuntime = benchmark.Job.Environment.HasValue(EnvironmentMode.RuntimeCharacteristic) - ? benchmark.Job.Environment.Runtime - : ClrRuntime.GetTargetOrCurrentVersion(benchmark.Descriptor.WorkloadMethod.DeclaringType.Assembly); + ? benchmark.Job.Environment.Runtime! + : ClrRuntime.GetTargetOrCurrentVersion(benchmark.Descriptor.WorkloadMethod.DeclaringType!.Assembly); var requiredSdkVersion = targetRuntime.RuntimeMoniker.GetRuntimeVersion(); var installedVersionString = cachedFrameworkSdks.Value.FirstOrDefault(); @@ -44,7 +47,7 @@ public static IEnumerable ValidateFrameworkSdks(BenchmarkCase b } } - public static bool IsCliPathInvalid(string customDotNetCliPath, BenchmarkCase benchmarkCase, out ValidationError? validationError) + public static bool IsCliPathInvalid(string? customDotNetCliPath, BenchmarkCase benchmarkCase, [NotNullWhen(true)] out ValidationError? validationError) { validationError = null; @@ -71,7 +74,7 @@ public static bool IsCliPathInvalid(string customDotNetCliPath, BenchmarkCase be private static IEnumerable GetInstalledDotNetSdks(string? customDotNetCliPath) { - string dotnetExecutable = string.IsNullOrEmpty(customDotNetCliPath) ? "dotnet" : customDotNetCliPath; + string dotnetExecutable = string.IsNullOrEmpty(customDotNetCliPath) ? "dotnet" : customDotNetCliPath!; var startInfo = new ProcessStartInfo(dotnetExecutable, "--list-sdks") { RedirectStandardOutput = true, @@ -146,13 +149,13 @@ private static void Get45PlusFromRegistry(List versions) if (ndpKey.GetValue("Version") != null) { - versions.Add(ndpKey.GetValue("Version").ToString()); + versions.Add(ndpKey.GetValue("Version")!.ToString()!); } else { if (ndpKey.GetValue("Release") != null) { - versions.Add(CheckFor45PlusVersion((int)ndpKey.GetValue("Release"))); + versions.Add(CheckFor45PlusVersion((int)ndpKey.GetValue("Release")!)); } } } diff --git a/src/BenchmarkDotNet/Validators/ExecutionValidatorBase.cs b/src/BenchmarkDotNet/Validators/ExecutionValidatorBase.cs index bb94aec254..b393d2849a 100644 --- a/src/BenchmarkDotNet/Validators/ExecutionValidatorBase.cs +++ b/src/BenchmarkDotNet/Validators/ExecutionValidatorBase.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Threading.Tasks; @@ -8,6 +9,8 @@ using BenchmarkDotNet.Helpers; using BenchmarkDotNet.Running; +#nullable enable + namespace BenchmarkDotNet.Validators { public abstract class ExecutionValidatorBase : IValidator @@ -53,11 +56,11 @@ public IEnumerable Validate(ValidationParameters validationPara return errors; } - private bool TryCreateBenchmarkTypeInstance(Type type, List errors, out object? instance) + private bool TryCreateBenchmarkTypeInstance(Type type, List errors, [NotNullWhen(true)] out object? instance) { try { - instance = Activator.CreateInstance(type); + instance = Activator.CreateInstance(type)!; return true; } @@ -124,7 +127,7 @@ private bool TryToCallGlobalMethod(object benchmarkTypeInstance, List type.Name.Replace("Attribute", string.Empty); - private void TryToGetTaskResult(object result) + private void TryToGetTaskResult(object? result) { if (result == null) { @@ -241,7 +244,7 @@ private bool TryToSetParamsProperties(object benchmarkTypeInstance, List Validate(ValidationParameters input) => .SelectMany(type => type.GetTypeMembersWithGivenAttribute(ReflectionFlags)) .Distinct() .Select(member => GetErrorOrDefault(member.ParameterType)) - .Where(error => error != null); + .WhereNotNull(); private bool IsBool(Type paramType) => paramType == typeof(bool); private bool IsEnum(Type paramType) => paramType.GetTypeInfo().IsEnum; @@ -33,17 +36,17 @@ private bool IsFlagsEnum(Type paramType) var typeInfo = paramType.GetTypeInfo(); return typeInfo.IsEnum && typeInfo.IsDefined(typeof(FlagsAttribute)); } - private bool IsNullable(Type paramType, out Type underlyingType) + private bool IsNullable(Type paramType, [NotNullWhen(true)] out Type? underlyingType) { underlyingType = Nullable.GetUnderlyingType(paramType); return underlyingType != null; } - private ValidationError GetErrorOrDefault(Type parameterType) + private ValidationError? GetErrorOrDefault(Type parameterType) { switch (parameterType) { - case Type t when IsNullable(t, out Type underType): + case Type t when IsNullable(t, out var underType): return GetErrorOrDefault(underType); case Type t when IsFlagsEnum(t): diff --git a/src/BenchmarkDotNet/Validators/ReturnValueValidator.cs b/src/BenchmarkDotNet/Validators/ReturnValueValidator.cs index f4b5b7b63d..75c44d04db 100644 --- a/src/BenchmarkDotNet/Validators/ReturnValueValidator.cs +++ b/src/BenchmarkDotNet/Validators/ReturnValueValidator.cs @@ -10,6 +10,8 @@ using BenchmarkDotNet.Running; using BenchmarkDotNet.Toolchains.InProcess.NoEmit; +#nullable enable + namespace BenchmarkDotNet.Validators { public class ReturnValueValidator : ExecutionValidatorBase @@ -32,7 +34,7 @@ protected override void ExecuteBenchmarks(object benchmarkTypeInstance, IEnumera try { InProcessNoEmitRunner.FillMembers(benchmarkTypeInstance, benchmark); - var result = benchmark.Descriptor.WorkloadMethod.Invoke(benchmarkTypeInstance, null); + var result = benchmark.Descriptor.WorkloadMethod.Invoke(benchmarkTypeInstance, null)!; if (benchmark.Descriptor.WorkloadMethod.ReturnType != typeof(void)) results.Add((benchmark, result)); @@ -64,7 +66,7 @@ private class ParameterInstancesEqualityComparer : IEqualityComparer @@ -43,6 +45,6 @@ public override bool Equals(object? obj) public static bool operator ==(ValidationError left, ValidationError right) => Equals(left, right); - public static bool operator !=(ValidationError left, ValidationError right) => !Equals(left, right); + public static bool operator !=(ValidationError? left, ValidationError? right) => !Equals(left, right); } } \ No newline at end of file diff --git a/src/BenchmarkDotNet/Validators/ValidationParameters.cs b/src/BenchmarkDotNet/Validators/ValidationParameters.cs index 83c5803d05..3fed1a85a6 100644 --- a/src/BenchmarkDotNet/Validators/ValidationParameters.cs +++ b/src/BenchmarkDotNet/Validators/ValidationParameters.cs @@ -10,16 +10,16 @@ public class ValidationParameters { public IReadOnlyList Benchmarks { get; } - public ImmutableConfig? Config { get; } + public ImmutableConfig Config { get; } - public ValidationParameters(IReadOnlyList benchmarks, ImmutableConfig? config) + public ValidationParameters(IReadOnlyList benchmarks, ImmutableConfig config) { Benchmarks = benchmarks; Config = config; } - // to have backward compatibility for people who implemented IValidator(Benchmark[] benchmarks) - public static implicit operator ValidationParameters(BenchmarkCase[] benchmarksCase) => new ValidationParameters(benchmarksCase, null); - public static implicit operator ValidationParameters(BenchmarkRunInfo benchmarkRunInfo) => new ValidationParameters(benchmarkRunInfo.BenchmarksCases, null); + // Note: Following implicit operators are expected to be used for test projects. + public static implicit operator ValidationParameters(BenchmarkCase[] benchmarksCase) => new ValidationParameters(benchmarksCase, DefaultConfig.Instance.CreateImmutableConfig()); + public static implicit operator ValidationParameters(BenchmarkRunInfo benchmarkRunInfo) => new ValidationParameters(benchmarkRunInfo.BenchmarksCases, benchmarkRunInfo.Config); } } \ No newline at end of file