diff --git a/src/BenchmarkDotNet/Characteristics/CharacteristicPresenter.cs b/src/BenchmarkDotNet/Characteristics/CharacteristicPresenter.cs index b013ac6597..31200d4141 100644 --- a/src/BenchmarkDotNet/Characteristics/CharacteristicPresenter.cs +++ b/src/BenchmarkDotNet/Characteristics/CharacteristicPresenter.cs @@ -83,7 +83,7 @@ public override string ToPresentation(object? characteristicValue, Characteristi { // TODO: DO NOT hardcode Characteristic suffix string id = characteristic.Id; - string type = characteristic.DeclaringType.FullName!; + string type = characteristic.DeclaringType.GetCorrectCSharpTypeName(); string value = SourceCodeHelper.ToSourceCode(characteristicValue); return $"{type}.{id}Characteristic[job] = {value}"; } diff --git a/src/BenchmarkDotNet/Code/CodeGenerator.cs b/src/BenchmarkDotNet/Code/CodeGenerator.cs index 480bc4c598..80dcbce27b 100644 --- a/src/BenchmarkDotNet/Code/CodeGenerator.cs +++ b/src/BenchmarkDotNet/Code/CodeGenerator.cs @@ -49,11 +49,11 @@ internal static string Generate(BuildPartition buildPartition) .Replace("$IterationSetupMethodName$", provider.IterationSetupMethodName) .Replace("$IterationCleanupMethodName$", provider.IterationCleanupMethodName) .Replace("$JobSetDefinition$", GetJobsSetDefinition(benchmark)) - .Replace("$ParamsInitializer$", GetParamsInitializer(benchmark)) .Replace("$ParamsContent$", GetParamsContent(benchmark)) .Replace("$ArgumentsDefinition$", GetArgumentsDefinition(benchmark)) .Replace("$DeclareArgumentFields$", GetDeclareArgumentFields(benchmark)) - .Replace("$InitializeArgumentFields$", GetInitializeArgumentFields(benchmark)).Replace("$LoadArguments$", GetLoadArguments(benchmark)) + .Replace("$InitializeArgumentFields$", GetInitializeArgumentFields(benchmark)) + .Replace("$LoadArguments$", GetLoadArguments(benchmark)) .Replace("$PassArguments$", passArguments) .Replace("$EngineFactoryType$", GetEngineFactoryTypeName(benchmark)) .Replace("$MeasureExtraStats$", buildInfo.Config.HasExtraStatsDiagnoser() ? "true" : "false") @@ -159,13 +159,6 @@ private static DeclarationsProvider GetDeclarationsProvider(Descriptor descripto return new SyncDeclarationsProvider(descriptor); } - private static string GetParamsInitializer(BenchmarkCase benchmarkCase) - => string.Join( - ", ", - benchmarkCase.Parameters.Items - .Where(parameter => !parameter.IsArgument && !parameter.IsStatic) - .Select(parameter => $"{parameter.Name} = default")); - // internal for tests internal static string GetParamsContent(BenchmarkCase benchmarkCase) @@ -173,7 +166,7 @@ internal static string GetParamsContent(BenchmarkCase benchmarkCase) string.Empty, benchmarkCase.Parameters.Items .Where(parameter => !parameter.IsArgument) - .Select(parameter => $"{(parameter.IsStatic ? "" : "instance.")}{parameter.Name} = {parameter.ToSourceCode()};")); + .Select(parameter => $"{(parameter.IsStatic ? benchmarkCase.Descriptor.Type.GetCorrectCSharpTypeName() : "base")}.{parameter.Name} = {parameter.ToSourceCode()};")); private static string GetArgumentsDefinition(BenchmarkCase benchmarkCase) => string.Join( @@ -191,13 +184,13 @@ private static string GetInitializeArgumentFields(BenchmarkCase benchmarkCase) => string.Join( Environment.NewLine, benchmarkCase.Descriptor.WorkloadMethod.GetParameters() - .Select((parameter, index) => $"__argField{index} = {benchmarkCase.Parameters.GetArgument(parameter.Name).ToSourceCode()};")); // we init the fields in ctor to provoke all possible allocations and overhead of other type + .Select((parameter, index) => $"this.__argField{index} = {benchmarkCase.Parameters.GetArgument(parameter.Name).ToSourceCode()};")); // we init the fields in ctor to provoke all possible allocations and overhead of other type private static string GetLoadArguments(BenchmarkCase benchmarkCase) => string.Join( Environment.NewLine, benchmarkCase.Descriptor.WorkloadMethod.GetParameters() - .Select((parameter, index) => $"{(parameter.ParameterType.IsByRef ? "ref" : string.Empty)} {parameter.ParameterType.GetCorrectCSharpTypeName()} arg{index} = {(parameter.ParameterType.IsByRef ? "ref" : string.Empty)} __argField{index};")); + .Select((parameter, index) => $"{(parameter.ParameterType.IsByRef ? "ref" : string.Empty)} {parameter.ParameterType.GetCorrectCSharpTypeName()} arg{index} = {(parameter.ParameterType.IsByRef ? "ref" : string.Empty)} this.__argField{index};")); private static string GetPassArguments(BenchmarkCase benchmarkCase) => string.Join( diff --git a/src/BenchmarkDotNet/Code/DeclarationsProvider.cs b/src/BenchmarkDotNet/Code/DeclarationsProvider.cs index 0c9a8dce46..9581b709d1 100644 --- a/src/BenchmarkDotNet/Code/DeclarationsProvider.cs +++ b/src/BenchmarkDotNet/Code/DeclarationsProvider.cs @@ -26,7 +26,10 @@ internal abstract class DeclarationsProvider public string IterationCleanupMethodName => Descriptor.IterationCleanupMethod?.Name ?? EmptyAction; - public virtual string GetWorkloadMethodCall(string passArguments) => $"{Descriptor.WorkloadMethod.Name}({passArguments})"; + public abstract string GetWorkloadMethodCall(string passArguments); + + protected static string GetMethodPrefix(MethodInfo method) + => method.IsStatic ? method.DeclaringType.GetCorrectCSharpTypeName() : "base"; private string GetMethodName(MethodInfo method) { @@ -41,22 +44,22 @@ private string GetMethodName(MethodInfo method) (method.ReturnType.GetGenericTypeDefinition() == typeof(Task<>) || method.ReturnType.GetGenericTypeDefinition() == typeof(ValueTask<>)))) { - return $"() => BenchmarkDotNet.Helpers.AwaitHelper.GetResult({method.Name}())"; + return $"() => global::BenchmarkDotNet.Helpers.AwaitHelper.GetResult({GetMethodPrefix(Descriptor.WorkloadMethod)}.{method.Name}())"; } - return method.Name; + return $"{GetMethodPrefix(Descriptor.WorkloadMethod)}.{method.Name}"; } } - internal class SyncDeclarationsProvider : DeclarationsProvider + internal class SyncDeclarationsProvider(Descriptor descriptor) : DeclarationsProvider(descriptor) { - public SyncDeclarationsProvider(Descriptor descriptor) : base(descriptor) { } + public override string GetWorkloadMethodCall(string passArguments) + => $"{GetMethodPrefix(Descriptor.WorkloadMethod)}.{Descriptor.WorkloadMethod.Name}({passArguments})"; } - internal class AsyncDeclarationsProvider : DeclarationsProvider + internal class AsyncDeclarationsProvider(Descriptor descriptor) : DeclarationsProvider(descriptor) { - public AsyncDeclarationsProvider(Descriptor descriptor) : base(descriptor) { } - - public override string GetWorkloadMethodCall(string passArguments) => $"BenchmarkDotNet.Helpers.AwaitHelper.GetResult({Descriptor.WorkloadMethod.Name}({passArguments}))"; + public override string GetWorkloadMethodCall(string passArguments) + => $"global::BenchmarkDotNet.Helpers.AwaitHelper.GetResult({GetMethodPrefix(Descriptor.WorkloadMethod)}.{Descriptor.WorkloadMethod.Name}({passArguments}))"; } } \ No newline at end of file diff --git a/src/BenchmarkDotNet/Extensions/ReflectionExtensions.cs b/src/BenchmarkDotNet/Extensions/ReflectionExtensions.cs index 5708ba7a38..8e67a28e8c 100644 --- a/src/BenchmarkDotNet/Extensions/ReflectionExtensions.cs +++ b/src/BenchmarkDotNet/Extensions/ReflectionExtensions.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using System.Security.Cryptography.X509Certificates; using BenchmarkDotNet.Attributes; namespace BenchmarkDotNet.Extensions @@ -36,7 +37,7 @@ public static bool IsInitOnly(this PropertyInfo propertyInfo) /// /// returns type name which can be used in generated C# code /// - internal static string GetCorrectCSharpTypeName(this Type type, bool includeNamespace = true, bool includeGenericArgumentsNamespace = true) + internal static string GetCorrectCSharpTypeName(this Type type, bool includeNamespace = true, bool includeGenericArgumentsNamespace = true, bool prefixWithGlobal = true) { while (!(type.IsPublic || type.IsNestedPublic) && type.BaseType != null) type = type.BaseType; @@ -49,16 +50,23 @@ internal static string GetCorrectCSharpTypeName(this Type type, bool includeName return "void"; if (type == typeof(void*)) return "void*"; + string prefix = ""; + if (!string.IsNullOrEmpty(type.Namespace) && includeNamespace) + { prefix += type.Namespace + "."; + if (prefixWithGlobal) + prefix = $"global::{prefix}"; + } + if (type.GetTypeInfo().IsGenericParameter) return type.Name; if (type.IsArray) { - var typeName = GetCorrectCSharpTypeName(type.GetElementType()); + var typeName = GetCorrectCSharpTypeName(type.GetElementType(), includeNamespace, includeGenericArgumentsNamespace, prefixWithGlobal); var parts = typeName.Split(['['], count: 2); string repr = parts[0] + '[' + new string(',', type.GetArrayRank() - 1) + ']'; @@ -68,11 +76,11 @@ internal static string GetCorrectCSharpTypeName(this Type type, bool includeName return repr; } - return prefix + string.Join(".", GetNestedTypeNames(type, includeGenericArgumentsNamespace).Reverse()); + return prefix + string.Join(".", GetNestedTypeNames(type, includeGenericArgumentsNamespace, prefixWithGlobal).Reverse()); } // from most nested to least - private static IEnumerable GetNestedTypeNames(Type type, bool includeGenericArgumentsNamespace) + private static IEnumerable GetNestedTypeNames(Type type, bool includeGenericArgumentsNamespace, bool prefixWithGlobal) { var allTypeParameters = new Stack(type.GetGenericArguments()); @@ -92,7 +100,7 @@ private static IEnumerable GetNestedTypeNames(Type type, bool includeGen .Select(_ => allTypeParameters.Pop()) .Reverse(); - var args = string.Join(", ", typeParameters.Select(T => GetCorrectCSharpTypeName(T, includeGenericArgumentsNamespace, includeGenericArgumentsNamespace))); + var args = string.Join(", ", typeParameters.Select(T => GetCorrectCSharpTypeName(T, includeGenericArgumentsNamespace, includeGenericArgumentsNamespace, prefixWithGlobal))); name = $"{mainName}<{args}>"; } diff --git a/src/BenchmarkDotNet/Helpers/FolderNameHelper.cs b/src/BenchmarkDotNet/Helpers/FolderNameHelper.cs index 4625f9c03d..4ef503d7a7 100644 --- a/src/BenchmarkDotNet/Helpers/FolderNameHelper.cs +++ b/src/BenchmarkDotNet/Helpers/FolderNameHelper.cs @@ -44,7 +44,7 @@ public static string ToFolderName(object? value) // we can't simply use type.FullName, because for generics it's too long // example: typeof(List).FullName => "System.Collections.Generic.List`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]" public static string ToFolderName(Type type, bool includeNamespace = true, bool includeGenericArgumentsNamespace = false) - => Escape(new StringBuilder(type.GetCorrectCSharpTypeName(includeNamespace, includeGenericArgumentsNamespace))); + => Escape(new StringBuilder(type.GetCorrectCSharpTypeName(includeNamespace, includeGenericArgumentsNamespace, prefixWithGlobal: false))); private static string Escape(StringBuilder builder) { diff --git a/src/BenchmarkDotNet/Parameters/SmartParamBuilder.cs b/src/BenchmarkDotNet/Parameters/SmartParamBuilder.cs index adc9789ef8..89e5c38368 100644 --- a/src/BenchmarkDotNet/Parameters/SmartParamBuilder.cs +++ b/src/BenchmarkDotNet/Parameters/SmartParamBuilder.cs @@ -125,7 +125,7 @@ public string ToSourceCode() else { // If the source member is non-static, we mustn't include the type name, as this would be a compiler error when accessing a non-static source member in the base class of this generated type. - methodCall = source.Name; + methodCall = $"base.{source.Name}"; } // we do something like enumerable.ElementAt(sourceIndex)[argumentIndex]; @@ -157,12 +157,12 @@ public string ToSourceCode() { string cast = $"({parameterType.GetCorrectCSharpTypeName()})"; // it's an object so we need to cast it to the right type - string instancePrefix = method.IsStatic ? source.DeclaringType.GetCorrectCSharpTypeName() : "instance"; + string callPrefix = method.IsStatic ? source.DeclaringType.GetCorrectCSharpTypeName() : "base"; string callPostfix = source is PropertyInfo ? string.Empty : "()"; // we so something like enumerable.ElementAt(index); - return $"{cast}BenchmarkDotNet.Parameters.ParameterExtractor.GetParameter({instancePrefix}.{source.Name}{callPostfix}, {index});"; + return $"{cast}BenchmarkDotNet.Parameters.ParameterExtractor.GetParameter({callPrefix}.{source.Name}{callPostfix}, {index});"; } } diff --git a/src/BenchmarkDotNet/Running/BenchmarkRunnerClean.cs b/src/BenchmarkDotNet/Running/BenchmarkRunnerClean.cs index 69ef36d8be..3f7c7aad1d 100644 --- a/src/BenchmarkDotNet/Running/BenchmarkRunnerClean.cs +++ b/src/BenchmarkDotNet/Running/BenchmarkRunnerClean.cs @@ -137,7 +137,7 @@ internal static Summary[] Run(BenchmarkRunInfo[] benchmarkRunInfos) var benchmarkWithHighestIdForGivenType = benchmarkRunInfo.BenchmarksCases.Last(); if (benchmarkToBuildResult[benchmarkWithHighestIdForGivenType].Id.Value <= idToResume) { - compositeLogger.WriteLineInfo($"Skipping {benchmarkRunInfo.BenchmarksCases.Length} benchmark(s) defined by {benchmarkRunInfo.Type.GetCorrectCSharpTypeName()}."); + compositeLogger.WriteLineInfo($"Skipping {benchmarkRunInfo.BenchmarksCases.Length} benchmark(s) defined by {benchmarkRunInfo.Type.GetCorrectCSharpTypeName(prefixWithGlobal: false)}."); continue; } } diff --git a/src/BenchmarkDotNet/Running/Descriptor.cs b/src/BenchmarkDotNet/Running/Descriptor.cs index 4ff74fced7..87df323646 100644 --- a/src/BenchmarkDotNet/Running/Descriptor.cs +++ b/src/BenchmarkDotNet/Running/Descriptor.cs @@ -71,7 +71,7 @@ public Descriptor( public bool HasCategory(string category) => Categories.Any(c => c.EqualsWithIgnoreCase(category)); - public string GetFilterName() => $"{Type.GetCorrectCSharpTypeName(includeGenericArgumentsNamespace: false)}.{WorkloadMethod.Name}"; + public string GetFilterName() => $"{Type.GetCorrectCSharpTypeName(includeGenericArgumentsNamespace: false, prefixWithGlobal: false)}.{WorkloadMethod.Name}"; public bool Equals(Descriptor? other) => GetFilterName().Equals(other?.GetFilterName()); diff --git a/src/BenchmarkDotNet/Templates/BenchmarkProgram.txt b/src/BenchmarkDotNet/Templates/BenchmarkProgram.txt index fa830ecd09..6aa252670c 100644 --- a/src/BenchmarkDotNet/Templates/BenchmarkProgram.txt +++ b/src/BenchmarkDotNet/Templates/BenchmarkProgram.txt @@ -5,13 +5,28 @@ $AdditionalLogic$ // this file must not be importing any namespaces // we should use full names everywhere to avoid any potential naming conflicts, example: #1007, #778 +#if !NET7_0_OR_GREATER +namespace System.Diagnostics.CodeAnalysis +{ + /// + /// Specifies that this constructor sets all required members for the current type, + /// and callers do not need to set any required members themselves. + /// + [global::System.AttributeUsage(global::System.AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)] + [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] + internal sealed class SetsRequiredMembersAttribute : global::System.Attribute + { + } +} +#endif + // the namespace name must be in sync with WindowsDisassembler.BuildArguments namespace BenchmarkDotNet.Autogenerated { public class UniqueProgramName // we need different name than typical "Program" to avoid problems with referencing "Program" types from benchmarked code, #691 { $ExtraAttribute$ - public static System.Int32 Main(System.String[] args) + public static global::System.Int32 Main(global::System.String[] args) { // this method MUST NOT have any dependencies to BenchmarkDotNet and any other external dlls! (CoreRT is exception from this rule) // otherwise if LINQPad's shadow copy is enabled, we will not register for AssemblyLoading event @@ -22,17 +37,17 @@ namespace BenchmarkDotNet.Autogenerated return AfterAssemblyLoadingAttached(args); } - private static System.Int32 AfterAssemblyLoadingAttached(System.String[] args) + private static global::System.Int32 AfterAssemblyLoadingAttached(global::System.String[] args) { - BenchmarkDotNet.Engines.IHost host; // this variable name is used by CodeGenerator.GetCoreRtSwitch, do NOT change it - if (BenchmarkDotNet.Engines.AnonymousPipesHost.TryGetFileHandles(args, out System.String writeHandle, out System.String readHandle)) - host = new BenchmarkDotNet.Engines.AnonymousPipesHost(writeHandle, readHandle); + global::BenchmarkDotNet.Engines.IHost host; // this variable name is used by CodeGenerator.GetCoreRtSwitch, do NOT change it + if (global::BenchmarkDotNet.Engines.AnonymousPipesHost.TryGetFileHandles(args, out global::System.String writeHandle, out global::System.String readHandle)) + host = new global::BenchmarkDotNet.Engines.AnonymousPipesHost(writeHandle, readHandle); else - host = new BenchmarkDotNet.Engines.NoAcknowledgementConsoleHost(); + host = new global::BenchmarkDotNet.Engines.NoAcknowledgementConsoleHost(); // the first thing to do is to let diagnosers hook in before anything happens // so all jit-related diagnosers can catch first jit compilation! - BenchmarkDotNet.Engines.HostExtensions.BeforeAnythingElse(host); + global::BenchmarkDotNet.Engines.HostExtensions.BeforeAnythingElse(host); try { @@ -41,10 +56,10 @@ namespace BenchmarkDotNet.Autogenerated // we have some jitting diagnosers and we want them to catch all the informations!! // this variable name is used by CodeGenerator.GetCoreRtSwitch, do NOT change it - System.String benchmarkName = System.Linq.Enumerable.FirstOrDefault(System.Linq.Enumerable.Skip(System.Linq.Enumerable.SkipWhile(args, arg => arg != "--benchmarkName"), 1)) ?? "not provided"; - BenchmarkDotNet.Diagnosers.RunMode diagnoserRunMode = (BenchmarkDotNet.Diagnosers.RunMode) System.Int32.Parse(System.Linq.Enumerable.FirstOrDefault(System.Linq.Enumerable.Skip(System.Linq.Enumerable.SkipWhile(args, arg => arg != "--diagnoserRunMode"), 1)) ?? "0"); - System.Int32 id = args.Length > 0 - ? System.Int32.Parse(args[args.Length - 1]) // this variable name is used by CodeGenerator.GetCoreRtSwitch, do NOT change it + global::System.String benchmarkName = global::System.Linq.Enumerable.FirstOrDefault(global::System.Linq.Enumerable.Skip(global::System.Linq.Enumerable.SkipWhile(args, arg => arg != "--benchmarkName"), 1)) ?? "not provided"; + global::BenchmarkDotNet.Diagnosers.RunMode diagnoserRunMode = (global::BenchmarkDotNet.Diagnosers.RunMode) global::System.Int32.Parse(global::System.Linq.Enumerable.FirstOrDefault(global::System.Linq.Enumerable.Skip(global::System.Linq.Enumerable.SkipWhile(args, arg => arg != "--diagnoserRunMode"), 1)) ?? "0"); + global::System.Int32 id = args.Length > 0 + ? global::System.Int32.Parse(args[args.Length - 1]) // this variable name is used by CodeGenerator.GetCoreRtSwitch, do NOT change it : 0; // used when re-using generated exe without BDN (typically to repro a bug) if (args.Length == 0) @@ -54,12 +69,12 @@ namespace BenchmarkDotNet.Autogenerated #if NATIVEAOT $NativeAotSwitch$ #else - System.Type type = typeof(BenchmarkDotNet.Autogenerated.UniqueProgramName).Assembly.GetType($"BenchmarkDotNet.Autogenerated.Runnable_{id}"); - type.GetMethod("Run", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static).Invoke(null, new System.Object[] { host, benchmarkName, diagnoserRunMode }); + global::System.Type type = typeof(global::BenchmarkDotNet.Autogenerated.UniqueProgramName).Assembly.GetType($"BenchmarkDotNet.Autogenerated.Runnable_{id}"); + type.GetMethod("Run", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.Static).Invoke(null, new global::System.Object[] { host, benchmarkName, diagnoserRunMode }); #endif return 0; } - catch (System.Exception oom) when (oom is System.OutOfMemoryException || oom is System.Reflection.TargetInvocationException reflection && reflection.InnerException is System.OutOfMemoryException) + catch (global::System.Exception oom) when (oom is global::System.OutOfMemoryException || oom is global::System.Reflection.TargetInvocationException reflection && reflection.InnerException is global::System.OutOfMemoryException) { host.WriteLine(); host.WriteLine("OutOfMemoryException!"); @@ -71,7 +86,7 @@ namespace BenchmarkDotNet.Autogenerated return -1; } - catch(System.Exception ex) + catch(global::System.Exception ex) { host.WriteLine(); host.WriteLine(ex.ToString()); @@ -79,7 +94,7 @@ namespace BenchmarkDotNet.Autogenerated } finally { - BenchmarkDotNet.Engines.HostExtensions.AfterAll(host); + global::BenchmarkDotNet.Engines.HostExtensions.AfterAll(host); host.Dispose(); } @@ -87,34 +102,34 @@ namespace BenchmarkDotNet.Autogenerated } #if NETFRAMEWORK - internal class DirtyAssemblyResolveHelper : System.IDisposable + internal class DirtyAssemblyResolveHelper : global::System.IDisposable { - internal DirtyAssemblyResolveHelper() => System.AppDomain.CurrentDomain.AssemblyResolve += HelpTheFrameworkToResolveTheAssembly; + internal DirtyAssemblyResolveHelper() => global::System.AppDomain.CurrentDomain.AssemblyResolve += HelpTheFrameworkToResolveTheAssembly; - public void Dispose() => System.AppDomain.CurrentDomain.AssemblyResolve -= HelpTheFrameworkToResolveTheAssembly; + public void Dispose() => global::System.AppDomain.CurrentDomain.AssemblyResolve -= HelpTheFrameworkToResolveTheAssembly; /// /// according to https://msdn.microsoft.com/en-us/library/ff527268(v=vs.110).aspx /// "the handler is invoked whenever the runtime fails to bind to an assembly by name." /// /// not null when we find it manually, null when can't help - private System.Reflection.Assembly HelpTheFrameworkToResolveTheAssembly(System.Object sender, System.ResolveEventArgs args) + private global::System.Reflection.Assembly HelpTheFrameworkToResolveTheAssembly(global::System.Object sender, global::System.ResolveEventArgs args) { #if SHADOWCOPY // used for LINQPad - const System.String shadowCopyFolderPath = @"$ShadowCopyFolderPath$"; + const global::System.String shadowCopyFolderPath = @"$ShadowCopyFolderPath$"; - System.String guessedPath = System.IO.Path.Combine(shadowCopyFolderPath, $"{new System.Reflection.AssemblyName(args.Name).Name}.dll"); + global::System.String guessedPath = global::System.IO.Path.Combine(shadowCopyFolderPath, $"{new global::System.Reflection.AssemblyName(args.Name).Name}.dll"); - return System.IO.File.Exists(guessedPath) ? System.Reflection.Assembly.LoadFrom(guessedPath) : null; + return global::System.IO.File.Exists(guessedPath) ? global::System.Reflection.Assembly.LoadFrom(guessedPath) : null; #else - System.Reflection.AssemblyName fullName = new System.Reflection.AssemblyName(args.Name); - System.String simpleName = fullName.Name; + global::System.Reflection.AssemblyName fullName = new global::System.Reflection.AssemblyName(args.Name); + global::System.String simpleName = fullName.Name; - System.String guessedPath = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, $"{simpleName}.dll"); + global::System.String guessedPath = global::System.IO.Path.Combine(global::System.AppDomain.CurrentDomain.BaseDirectory, $"{simpleName}.dll"); - if (!System.IO.File.Exists(guessedPath)) + if (!global::System.IO.File.Exists(guessedPath)) { - System.Console.WriteLine($"// Wrong assembly binding redirects for {args.Name}."); + global::System.Console.WriteLine($"// Wrong assembly binding redirects for {args.Name}."); return null; // we can't help, and we also don't call Assembly.Load which if fails comes back here, creates endless loop and causes StackOverflow } @@ -122,9 +137,9 @@ namespace BenchmarkDotNet.Autogenerated // so we just load it and ignore the version mismatch // we warn the user about that, in case some Super User want to be aware of that - System.Console.WriteLine($"// Wrong assembly binding redirects for {simpleName}, loading it from disk anyway."); + global::System.Console.WriteLine($"// Wrong assembly binding redirects for {simpleName}, loading it from disk anyway."); - return System.Reflection.Assembly.LoadFrom(guessedPath); + return global::System.Reflection.Assembly.LoadFrom(guessedPath); #endif // SHADOWCOPY } } diff --git a/src/BenchmarkDotNet/Templates/BenchmarkType.txt b/src/BenchmarkDotNet/Templates/BenchmarkType.txt index 5cf2fcb4aa..d5a7db5f00 100644 --- a/src/BenchmarkDotNet/Templates/BenchmarkType.txt +++ b/src/BenchmarkDotNet/Templates/BenchmarkType.txt @@ -1,42 +1,41 @@ - // the type name must be in sync with WindowsDisassembler.BuildArguments - public unsafe sealed class Runnable_$ID$ : global::$WorkloadTypeName$ + // Type name must be in sync with DisassemblyDiagnoser.BuildClrMdArgs. + public unsafe sealed class Runnable_$ID$ : $WorkloadTypeName$ { - public static void Run(BenchmarkDotNet.Engines.IHost host, System.String benchmarkName, BenchmarkDotNet.Diagnosers.RunMode diagnoserRunMode) + public static void Run(global::BenchmarkDotNet.Engines.IHost host, global::System.String benchmarkName, global::BenchmarkDotNet.Diagnosers.RunMode diagnoserRunMode) { - BenchmarkDotNet.Autogenerated.Runnable_$ID$ instance = new BenchmarkDotNet.Autogenerated.Runnable_$ID$ { $ParamsInitializer$ }; // do NOT change name "instance" (used in SmartParamameter) - $ParamsContent$ + global::BenchmarkDotNet.Autogenerated.Runnable_$ID$ instance = new global::BenchmarkDotNet.Autogenerated.Runnable_$ID$(); host.WriteLine(); - foreach (System.String infoLine in BenchmarkDotNet.Environments.BenchmarkEnvironmentInfo.GetCurrent().ToFormattedString()) + foreach (global::System.String infoLine in global::BenchmarkDotNet.Environments.BenchmarkEnvironmentInfo.GetCurrent().ToFormattedString()) { host.WriteLine($"// {infoLine}"); } - BenchmarkDotNet.Jobs.Job job = new BenchmarkDotNet.Jobs.Job(); // use full name to avoid naming conflicts, #778 + global::BenchmarkDotNet.Jobs.Job job = new global::BenchmarkDotNet.Jobs.Job(); // use full name to avoid naming conflicts, #778 $JobSetDefinition$; job.Freeze(); host.WriteLine($"// Job: {job.DisplayInfo}"); host.WriteLine(); - System.Collections.Generic.IEnumerable errors = BenchmarkDotNet.Validators.BenchmarkProcessValidator.Validate(job, instance); - if (BenchmarkDotNet.Validators.ValidationErrorReporter.ReportIfAny(errors, host)) + global::System.Collections.Generic.IEnumerable errors = global::BenchmarkDotNet.Validators.BenchmarkProcessValidator.Validate(job, instance); + if (global::BenchmarkDotNet.Validators.ValidationErrorReporter.ReportIfAny(errors, host)) return; - BenchmarkDotNet.Diagnosers.CompositeInProcessDiagnoserHandler compositeInProcessDiagnoserHandler = new BenchmarkDotNet.Diagnosers.CompositeInProcessDiagnoserHandler( - new BenchmarkDotNet.Diagnosers.InProcessDiagnoserRouter[] { + global::BenchmarkDotNet.Diagnosers.CompositeInProcessDiagnoserHandler compositeInProcessDiagnoserHandler = new global::BenchmarkDotNet.Diagnosers.CompositeInProcessDiagnoserHandler( + new global::BenchmarkDotNet.Diagnosers.InProcessDiagnoserRouter[] { $InProcessDiagnoserRouters$ }, host, diagnoserRunMode, - new BenchmarkDotNet.Diagnosers.InProcessDiagnoserActionArgs(instance) + new global::BenchmarkDotNet.Diagnosers.InProcessDiagnoserActionArgs(instance) ); - if (diagnoserRunMode == BenchmarkDotNet.Diagnosers.RunMode.SeparateLogic) + if (diagnoserRunMode == global::BenchmarkDotNet.Diagnosers.RunMode.SeparateLogic) { - compositeInProcessDiagnoserHandler.Handle(BenchmarkDotNet.Engines.BenchmarkSignal.SeparateLogic); + compositeInProcessDiagnoserHandler.Handle(global::BenchmarkDotNet.Engines.BenchmarkSignal.SeparateLogic); return; } - compositeInProcessDiagnoserHandler.Handle(BenchmarkDotNet.Engines.BenchmarkSignal.BeforeEngine); + compositeInProcessDiagnoserHandler.Handle(global::BenchmarkDotNet.Engines.BenchmarkSignal.BeforeEngine); - BenchmarkDotNet.Engines.EngineParameters engineParameters = new BenchmarkDotNet.Engines.EngineParameters() + global::BenchmarkDotNet.Engines.EngineParameters engineParameters = new global::BenchmarkDotNet.Engines.EngineParameters() { Host = host, WorkloadActionUnroll = instance.WorkloadActionUnroll, @@ -54,79 +53,81 @@ InProcessDiagnoserHandler = compositeInProcessDiagnoserHandler }; - using (BenchmarkDotNet.Engines.IEngine engine = new $EngineFactoryType$().CreateReadyToRun(engineParameters)) + using (global::BenchmarkDotNet.Engines.IEngine engine = new $EngineFactoryType$().CreateReadyToRun(engineParameters)) { - BenchmarkDotNet.Engines.RunResults results = engine.Run(); + global::BenchmarkDotNet.Engines.RunResults results = engine.Run(); host.ReportResults(results); // printing costs memory, do this after runs instance.__TrickTheJIT__(); // compile the method for disassembler, but without actual run of the benchmark ;) } - compositeInProcessDiagnoserHandler.Handle(BenchmarkDotNet.Engines.BenchmarkSignal.AfterEngine); + compositeInProcessDiagnoserHandler.Handle(global::BenchmarkDotNet.Engines.BenchmarkSignal.AfterEngine); } + [global::System.Diagnostics.CodeAnalysis.SetsRequiredMembers] public Runnable_$ID$() { - globalSetupAction = $GlobalSetupMethodName$; - globalCleanupAction = $GlobalCleanupMethodName$; - iterationSetupAction = $IterationSetupMethodName$; - iterationCleanupAction = $IterationCleanupMethodName$; + this.globalSetupAction = $GlobalSetupMethodName$; + this.globalCleanupAction = $GlobalCleanupMethodName$; + this.iterationSetupAction = $IterationSetupMethodName$; + this.iterationCleanupAction = $IterationCleanupMethodName$; $InitializeArgumentFields$ + $ParamsContent$ } - private System.Action globalSetupAction; - private System.Action globalCleanupAction; - private System.Action iterationSetupAction; - private System.Action iterationCleanupAction; + private global::System.Action globalSetupAction; + private global::System.Action globalCleanupAction; + private global::System.Action iterationSetupAction; + private global::System.Action iterationCleanupAction; $DeclareArgumentFields$ // this method is used only for the disassembly diagnoser purposes // the goal is to get this and the benchmarked method jitted, but without executing the benchmarked method itself - public System.Int32 NotEleven; - [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoOptimization | System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] + public global::System.Int32 NotEleven; + [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.NoOptimization | global::System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] public void __TrickTheJIT__() { - NotEleven = new System.Random(123).Next(0, 10); + this.NotEleven = new global::System.Random(123).Next(0, 10); $DisassemblerEntryMethodName$(); } - [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoOptimization | System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] + [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.NoOptimization | global::System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] public void $DisassemblerEntryMethodName$() { - if (NotEleven == 11) + if (this.NotEleven == 11) { $LoadArguments$ $WorkloadMethodCall$; } } - [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] - private void __Overhead($ArgumentsDefinition$) // __ is to avoid possible name conflict + [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] + private void __Overhead($ArgumentsDefinition$) { } - [System.Runtime.CompilerServices.MethodImpl(BenchmarkDotNet.Portability.CodeGenHelper.AggressiveOptimizationOption)] - private void OverheadActionUnroll(System.Int64 invokeCount) + [global::System.Runtime.CompilerServices.MethodImpl(global::BenchmarkDotNet.Portability.CodeGenHelper.AggressiveOptimizationOption)] + private void OverheadActionUnroll(global::System.Int64 invokeCount) { $LoadArguments$ while (--invokeCount >= 0) { - __Overhead($PassArguments$);@Unroll@ + this.__Overhead($PassArguments$);@Unroll@ } } - [System.Runtime.CompilerServices.MethodImpl(BenchmarkDotNet.Portability.CodeGenHelper.AggressiveOptimizationOption)] - private void OverheadActionNoUnroll(System.Int64 invokeCount) + [global::System.Runtime.CompilerServices.MethodImpl(global::BenchmarkDotNet.Portability.CodeGenHelper.AggressiveOptimizationOption)] + private void OverheadActionNoUnroll(global::System.Int64 invokeCount) { $LoadArguments$ while (--invokeCount >= 0) { - __Overhead($PassArguments$); + this.__Overhead($PassArguments$); } } - [System.Runtime.CompilerServices.MethodImpl(BenchmarkDotNet.Portability.CodeGenHelper.AggressiveOptimizationOption)] - private void WorkloadActionUnroll(System.Int64 invokeCount) + [global::System.Runtime.CompilerServices.MethodImpl(global::BenchmarkDotNet.Portability.CodeGenHelper.AggressiveOptimizationOption)] + private void WorkloadActionUnroll(global::System.Int64 invokeCount) { $LoadArguments$ while (--invokeCount >= 0) @@ -135,8 +136,8 @@ } } - [System.Runtime.CompilerServices.MethodImpl(BenchmarkDotNet.Portability.CodeGenHelper.AggressiveOptimizationOption)] - private void WorkloadActionNoUnroll(System.Int64 invokeCount) + [global::System.Runtime.CompilerServices.MethodImpl(global::BenchmarkDotNet.Portability.CodeGenHelper.AggressiveOptimizationOption)] + private void WorkloadActionNoUnroll(global::System.Int64 invokeCount) { $LoadArguments$ while (--invokeCount >= 0) diff --git a/src/BenchmarkDotNet/Validators/CompilationValidator.cs b/src/BenchmarkDotNet/Validators/CompilationValidator.cs index 5b788ccb63..3275c74431 100644 --- a/src/BenchmarkDotNet/Validators/CompilationValidator.cs +++ b/src/BenchmarkDotNet/Validators/CompilationValidator.cs @@ -25,7 +25,6 @@ private CompilationValidator() { } public IEnumerable Validate(ValidationParameters validationParameters) => ValidateCSharpNaming(validationParameters.Benchmarks) - .Union(ValidateNamingConflicts(validationParameters.Benchmarks)) .Union(ValidateClassModifiers((validationParameters.Benchmarks)) .Union(ValidateAccessModifiers(validationParameters.Benchmarks)) .Union(ValidateBindingModifiers(validationParameters.Benchmarks)) @@ -71,16 +70,6 @@ private static IEnumerable ValidateCSharpNaming(IEnumerable ValidateNamingConflicts(IEnumerable benchmarks) - => benchmarks - .Select(benchmark => benchmark.Descriptor.Type) - .Distinct() - .Where(type => type.GetAllMethods().Any(method => IsUsingNameUsedInternallyByOurTemplate(method.Name))) - .Select(benchmark - => new ValidationError( - true, - "Using \"__Overhead\" for method name is prohibited. We are using it internally in our templates. Please rename your method")); - private static IEnumerable ValidateAccessModifiers(IEnumerable benchmarks) => benchmarks.Where(x => x.Descriptor.Type.IsGenericType && HasPrivateGenericArguments(x.Descriptor.Type)) @@ -113,9 +102,6 @@ private static bool IsValidCSharpIdentifier(string identifier) // F# allows to u && 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)); // source: https://stackoverflow.com/a/19562316 diff --git a/tests/BenchmarkDotNet.IntegrationTests/ConflictingNamesTests.cs b/tests/BenchmarkDotNet.IntegrationTests/ConflictingNamesTests.cs new file mode 100644 index 0000000000..8cc604bac7 --- /dev/null +++ b/tests/BenchmarkDotNet.IntegrationTests/ConflictingNamesTests.cs @@ -0,0 +1,43 @@ +using BenchmarkDotNet.Attributes; +using Xunit; +using Xunit.Abstractions; + +namespace BenchmarkDotNet.IntegrationTests; + +public class ConflictingNamesTests(ITestOutputHelper output) : BenchmarkTestExecutor(output) +{ + [Fact] + public void BenchmarkMethodsCanUseTemplateNames() => CanExecute(); + + public class WithNamesUsedByTemplate + { + [Params(1)] + public int OverheadActionUnroll { get; set; } + + [Benchmark] + [Arguments(2)] + public void System(int OverheadActionNoUnroll) + { + + } + + [Benchmark] + public void BenchmarkDotNet() + { + + } + + [Benchmark] + public void __Overhead() + { + + } + + [Benchmark] + [Arguments(3)] + public void WorkloadActionUnroll(int WorkloadActionNoUnroll) + { + + } + } +} \ No newline at end of file diff --git a/tests/BenchmarkDotNet.IntegrationTests/InProcess.EmitTests/NaiveRunnableEmitDiff.cs b/tests/BenchmarkDotNet.IntegrationTests/InProcess.EmitTests/NaiveRunnableEmitDiff.cs index 75438fc0ce..ea0ea4a6e2 100644 --- a/tests/BenchmarkDotNet.IntegrationTests/InProcess.EmitTests/NaiveRunnableEmitDiff.cs +++ b/tests/BenchmarkDotNet.IntegrationTests/InProcess.EmitTests/NaiveRunnableEmitDiff.cs @@ -13,7 +13,8 @@ public class NaiveRunnableEmitDiff private static readonly HashSet IgnoredTypeNames = new HashSet() { "BenchmarkDotNet.Autogenerated.UniqueProgramName", - "BenchmarkDotNet.Autogenerated.DirtyAssemblyResolveHelper" // not required to be used in the InProcess toolchains (it's already used in the host process) + "BenchmarkDotNet.Autogenerated.DirtyAssemblyResolveHelper", // not required to be used in the InProcess toolchains (it's already used in the host process) + "System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute", // Conditionally added in runtimes older than .Net 7. }; private static readonly HashSet IgnoredAttributeTypeNames = new HashSet() diff --git a/tests/BenchmarkDotNet.Tests/ReflectionTests.cs b/tests/BenchmarkDotNet.Tests/ReflectionTests.cs index 0d1ea69673..d8e138cc24 100644 --- a/tests/BenchmarkDotNet.Tests/ReflectionTests.cs +++ b/tests/BenchmarkDotNet.Tests/ReflectionTests.cs @@ -14,18 +14,18 @@ public class ReflectionTests [Fact] public void GetCorrectCSharpTypeNameReturnsCSharpFriendlyTypeName() { - CheckCorrectTypeName("System.Int32", typeof(int)); - CheckCorrectTypeName("System.Int32[]", typeof(int[])); - CheckCorrectTypeName("System.Int32[][]", typeof(int[][])); - CheckCorrectTypeName("System.Int32[,]", typeof(int[,])); - CheckCorrectTypeName("System.Tuple[]", typeof(Tuple[])); - CheckCorrectTypeName("System.ValueTuple[]", typeof(ValueTuple[])); + CheckCorrectTypeName("global::System.Int32", typeof(int)); + CheckCorrectTypeName("global::System.Int32[]", typeof(int[])); + CheckCorrectTypeName("global::System.Int32[][]", typeof(int[][])); + CheckCorrectTypeName("global::System.Int32[,]", typeof(int[,])); + CheckCorrectTypeName("global::System.Tuple[]", typeof(Tuple[])); + CheckCorrectTypeName("global::System.ValueTuple[]", typeof(ValueTuple[])); CheckCorrectTypeName("void", typeof(void)); CheckCorrectTypeName("void*", typeof(void*)); - CheckCorrectTypeName("System.IEquatable", typeof(IEquatable<>)); - CheckCorrectTypeName("System.Type", typeof(Type)); + CheckCorrectTypeName("global::System.IEquatable", typeof(IEquatable<>)); + CheckCorrectTypeName("global::System.Type", typeof(Type)); // ReSharper disable once PossibleMistakenCallToGetType.2 - CheckCorrectTypeName("System.Reflection.TypeInfo", typeof(string).GetType()); // typeof(string).GetType() == System.RuntimeType which is not public + CheckCorrectTypeName("global::System.Reflection.TypeInfo", typeof(string).GetType()); // typeof(string).GetType() == System.RuntimeType which is not public } [Fact] @@ -33,7 +33,7 @@ public void GetCorrectCSharpTypeNameSupportsGenericTypesPassedByReference() { var byRefGenericType = typeof(GenericByRef).GetMethod(nameof(GenericByRef.TheMethod)).GetParameters().Single().ParameterType; - CheckCorrectTypeName("System.ValueTuple", byRefGenericType); + CheckCorrectTypeName("global::System.ValueTuple", byRefGenericType); } public class GenericByRef @@ -44,32 +44,32 @@ public void TheMethod(ref (int, short) _) { } [Fact] public void GetCorrectCSharpTypeNameSupportsNestedTypes() { - CheckCorrectTypeName("BenchmarkDotNet.Tests.ReflectionTests.Nested", typeof(Nested)); + CheckCorrectTypeName("global::BenchmarkDotNet.Tests.ReflectionTests.Nested", typeof(Nested)); - CheckCorrectTypeName("BenchmarkDotNet.Tests.ReflectionTests.NestedNonGeneric1.NestedNonGeneric2", + CheckCorrectTypeName("global::BenchmarkDotNet.Tests.ReflectionTests.NestedNonGeneric1.NestedNonGeneric2", typeof(NestedNonGeneric1.NestedNonGeneric2)); - CheckCorrectTypeName("BenchmarkDotNet.Tests.ReflectionTests.NestedNonGeneric1.NestedGeneric2", + CheckCorrectTypeName("global::BenchmarkDotNet.Tests.ReflectionTests.NestedNonGeneric1.NestedGeneric2", typeof(NestedNonGeneric1.NestedGeneric2)); - CheckCorrectTypeName("BenchmarkDotNet.Tests.ReflectionTests.NestedNonGeneric1.NestedGeneric2.NestedNonGeneric3", + CheckCorrectTypeName("global::BenchmarkDotNet.Tests.ReflectionTests.NestedNonGeneric1.NestedGeneric2.NestedNonGeneric3", typeof(NestedNonGeneric1.NestedGeneric2.NestedNonGeneric3)); - CheckCorrectTypeName("BenchmarkDotNet.Tests.ReflectionTests.NestedGeneric1", + CheckCorrectTypeName("global::BenchmarkDotNet.Tests.ReflectionTests.NestedGeneric1", typeof(NestedGeneric1)); - CheckCorrectTypeName("BenchmarkDotNet.Tests.ReflectionTests.NestedGeneric1.NonGeneric2", + CheckCorrectTypeName("global::BenchmarkDotNet.Tests.ReflectionTests.NestedGeneric1.NonGeneric2", typeof(NestedGeneric1.NonGeneric2)); - CheckCorrectTypeName("BenchmarkDotNet.Tests.ReflectionTests.NestedGeneric1.NonGeneric2.Generic3", + CheckCorrectTypeName("global::BenchmarkDotNet.Tests.ReflectionTests.NestedGeneric1.NonGeneric2.Generic3", typeof(NestedGeneric1.NonGeneric2.Generic3)); - CheckCorrectTypeName("BenchmarkDotNet.Tests.ReflectionTests.NestedGeneric1.NonGeneric2.Generic3.NonGeneric4", + CheckCorrectTypeName("global::BenchmarkDotNet.Tests.ReflectionTests.NestedGeneric1.NonGeneric2.Generic3.NonGeneric4", typeof(NestedGeneric1.NonGeneric2.Generic3.NonGeneric4)); - CheckCorrectTypeName("BenchmarkDotNet.Tests.ReflectionTests.NestedGeneric1.NonGeneric2.Generic3.Generic4", + CheckCorrectTypeName("global::BenchmarkDotNet.Tests.ReflectionTests.NestedGeneric1.NonGeneric2.Generic3.Generic4", typeof(NestedGeneric1.NonGeneric2.Generic3.Generic4)); - CheckCorrectTypeName("BenchmarkDotNet.Tests.ReflectionTests.NestedGeneric1", + CheckCorrectTypeName("global::BenchmarkDotNet.Tests.ReflectionTests.NestedGeneric1", typeof(NestedGeneric1<,>)); - CheckCorrectTypeName("BenchmarkDotNet.Tests.ReflectionTests.NestedGeneric1.NonGeneric2.Generic3.NonGeneric4", + CheckCorrectTypeName("global::BenchmarkDotNet.Tests.ReflectionTests.NestedGeneric1.NonGeneric2.Generic3.NonGeneric4", typeof(NestedGeneric1<,>.NonGeneric2.Generic3<,,>.NonGeneric4)); - CheckCorrectTypeName("BenchmarkDotNet.Tests.ReflectionTests.NestedGeneric1.NonGeneric2.Generic3.Generic4", + CheckCorrectTypeName("global::BenchmarkDotNet.Tests.ReflectionTests.NestedGeneric1.NonGeneric2.Generic3.Generic4", typeof(NestedGeneric1<,>.NonGeneric2.Generic3<,,>.Generic4<,>)); } @@ -78,7 +78,7 @@ public void GetCorrectCSharpTypeNameSupportsNestedTypesPassedByReference() { var byRefNestedType = typeof(Nested).GetMethod(nameof(Nested.TheMethod)).GetParameters().Single().ParameterType; - CheckCorrectTypeName("BenchmarkDotNet.Tests.ReflectionTests.Nested", byRefNestedType); + CheckCorrectTypeName("global::BenchmarkDotNet.Tests.ReflectionTests.Nested", byRefNestedType); } public class Nested diff --git a/tests/BenchmarkDotNet.Tests/SourceCodeHelperTests.cs b/tests/BenchmarkDotNet.Tests/SourceCodeHelperTests.cs index 6e8e504a60..b8126cbef8 100644 --- a/tests/BenchmarkDotNet.Tests/SourceCodeHelperTests.cs +++ b/tests/BenchmarkDotNet.Tests/SourceCodeHelperTests.cs @@ -23,7 +23,7 @@ public class SourceCodeHelperTests [InlineData('\\', "'\\\\'")] [InlineData(0.123f, "0.123f")] [InlineData(0.123d, "0.123d")] - [InlineData(BindingFlags.Public, "(System.Reflection.BindingFlags)(16)")] + [InlineData(BindingFlags.Public, "(global::System.Reflection.BindingFlags)(16)")] public void ToSourceCodeSimpleTest(object? original, string expected) { string actual = SourceCodeHelper.ToSourceCode(original);