C# keywords are prohibited for benchmark names, print nice error message, fixes #849
This commit is contained in:
Родитель
935ead0dd0
Коммит
20a0110e06
|
@ -1,8 +1,11 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using BenchmarkDotNet.Extensions;
|
||||
using BenchmarkDotNet.Running;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
|
||||
namespace BenchmarkDotNet.Validators
|
||||
{
|
||||
|
@ -12,6 +15,8 @@ namespace BenchmarkDotNet.Validators
|
|||
|
||||
public static readonly IValidator Default = new CompilationValidator();
|
||||
|
||||
private static readonly ImmutableHashSet<string> CsharpKeywords = GetCsharpKeywords().ToImmutableHashSet();
|
||||
|
||||
private CompilationValidator() { }
|
||||
|
||||
public bool TreatsWarningsAsErrors => true;
|
||||
|
@ -29,7 +34,7 @@ namespace BenchmarkDotNet.Validators
|
|||
.Select(benchmark
|
||||
=> new ValidationError(
|
||||
true,
|
||||
$"Benchmarked method `{benchmark.Descriptor.WorkloadMethod.Name}` contains illegal character(s). Please use `[<Benchmark(Description = \"Custom name\")>]` to set custom display name.",
|
||||
$"Benchmarked method `{benchmark.Descriptor.WorkloadMethod.Name}` contains illegal character(s) or uses C# keyword. Please use `[<Benchmark(Description = \"Custom name\")>]` to set custom display name.",
|
||||
benchmark
|
||||
));
|
||||
|
||||
|
@ -54,23 +59,32 @@ namespace BenchmarkDotNet.Validators
|
|||
.Select(benchmark
|
||||
=> new ValidationError(
|
||||
true,
|
||||
$"Benchmarked method `{benchmark.Descriptor.WorkloadMethod.DeclaringType.Name}.{benchmark.Descriptor.WorkloadMethod.Name}` is static. Please use instance methods only for benchmarks.",
|
||||
$"Benchmarked method `{benchmark.Descriptor.WorkloadMethod.Name}` is static. Please use instance methods only for benchmarks.",
|
||||
benchmark
|
||||
));
|
||||
|
||||
private static bool IsValidCSharpIdentifier(string identifier) // F# allows to use whitespaces as names #479
|
||||
=> !string.IsNullOrEmpty(identifier)
|
||||
&& (char.IsLetter(identifier[0]) || identifier[0] == Underscore) // An identifier must start with a letter or an underscore
|
||||
&& identifier
|
||||
.Skip(1)
|
||||
.All(character => char.IsLetterOrDigit(character) || character == Underscore);
|
||||
&& identifier.Skip(1).All(character => char.IsLetterOrDigit(character) || character == Underscore)
|
||||
&& !CsharpKeywords.Contains(identifier);
|
||||
|
||||
private static bool IsUsingNameUsedInternallyByOurTemplate(string identifier)
|
||||
=> identifier == "__Overhead";
|
||||
|
||||
private static bool HasPrivateGenericArguments(Type type) => type.GetGenericArguments().Any(a => !(a.IsPublic
|
||||
|| a.IsNestedPublic));
|
||||
|
||||
private static bool HasPrivateGenericArguments(Type type) => type.GetGenericArguments().Any(a => !(a.IsPublic || a.IsNestedPublic));
|
||||
|
||||
// source: https://stackoverflow.com/a/19562316
|
||||
private static IEnumerable<string> GetCsharpKeywords()
|
||||
{
|
||||
var memberInfos = typeof(SyntaxKind).GetMembers(BindingFlags.Public | BindingFlags.Static);
|
||||
|
||||
return from memberInfo in memberInfos
|
||||
where memberInfo.Name.EndsWith("Keyword")
|
||||
orderby memberInfo.Name
|
||||
select memberInfo.Name.Substring(startIndex: 0, length: memberInfo.Name.IndexOf("Keyword")).ToLower();
|
||||
}
|
||||
|
||||
private class BenchmarkMethodEqualityComparer : IEqualityComparer<BenchmarkCase>
|
||||
{
|
||||
internal static readonly IEqualityComparer<BenchmarkCase> Instance = new BenchmarkMethodEqualityComparer();
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using BenchmarkDotNet.Configs;
|
||||
using BenchmarkDotNet.Jobs;
|
||||
|
@ -33,7 +32,30 @@ namespace BenchmarkDotNet.Tests.Validators
|
|||
|
||||
Assert.Contains(errors,
|
||||
s => s.Equals(
|
||||
"Benchmarked method `Has Some Whitespaces` contains illegal character(s). Please use `[<Benchmark(Description = \"Custom name\")>]` to set custom display name."));
|
||||
"Benchmarked method `Has Some Whitespaces` contains illegal character(s) or uses C# keyword. Please use `[<Benchmark(Description = \"Custom name\")>]` to set custom display name."));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BenchmarkedMethodNameMustNotUseCsharpKeywords()
|
||||
{
|
||||
Delegate method = BuildDummyMethod<int>("typeof");
|
||||
|
||||
var parameters = new ValidationParameters(
|
||||
new[]
|
||||
{
|
||||
BenchmarkCase.Create(
|
||||
new Descriptor(
|
||||
typeof(CompilationValidatorTests),
|
||||
method.Method),
|
||||
Job.Dry,
|
||||
null)
|
||||
}, new ManualConfig());
|
||||
|
||||
var errors = CompilationValidator.Default.Validate(parameters).Select(e => e.Message);
|
||||
|
||||
Assert.Contains(errors,
|
||||
s => s.Equals(
|
||||
"Benchmarked method `typeof` contains illegal character(s) or uses C# keyword. Please use `[<Benchmark(Description = \"Custom name\")>]` to set custom display name."));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
@ -115,6 +137,4 @@ namespace BenchmarkDotNet.Tests.Validators
|
|||
{
|
||||
internal class InternalNestedClass { }
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче