using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Threading; using Microsoft.Cci; using Microsoft.CodeAnalysis.Emit; using Microsoft.CodeAnalysis.Symbols; using Microsoft.DiaSymReader; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CodeGen; internal sealed class CompilationTestData { internal readonly struct MethodData(ILBuilder ilBuilder, IMethodSymbolInternal method) { public readonly ILBuilder ILBuilder = ilBuilder; public readonly IMethodSymbolInternal Method = method; } public readonly ConcurrentDictionary Methods = new ConcurrentDictionary(); public CommonPEModuleBuilder? Module; public Func? SymWriterFactory; private ImmutableDictionary? _lazyMethodsByName; private static readonly SymbolDisplayFormat _testDataKeyFormat = new SymbolDisplayFormat(SymbolDisplayCompilerInternalOptions.UseMetadataMethodNames | SymbolDisplayCompilerInternalOptions.IncludeContainingFileForFileTypes, SymbolDisplayGlobalNamespaceStyle.OmittedAsContaining, SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces, SymbolDisplayGenericsOptions.IncludeTypeParameters | SymbolDisplayGenericsOptions.IncludeVariance, SymbolDisplayMemberOptions.IncludeExplicitInterface | SymbolDisplayMemberOptions.IncludeParameters | SymbolDisplayMemberOptions.IncludeContainingType, SymbolDisplayParameterOptions.IncludeExtensionThis | SymbolDisplayParameterOptions.IncludeParamsRefOut | SymbolDisplayParameterOptions.IncludeType, SymbolDisplayDelegateStyle.NameOnly, SymbolDisplayExtensionMethodStyle.Default, SymbolDisplayPropertyStyle.NameOnly, SymbolDisplayLocalOptions.None, SymbolDisplayKindOptions.None, SymbolDisplayMiscellaneousOptions.UseSpecialTypes | SymbolDisplayMiscellaneousOptions.EscapeKeywordIdentifiers | SymbolDisplayMiscellaneousOptions.UseAsterisksInMultiDimensionalArrays | SymbolDisplayMiscellaneousOptions.UseErrorTypeSymbolName | SymbolDisplayMiscellaneousOptions.ExpandValueTuple); private static readonly SymbolDisplayFormat _testDataOperatorKeyFormat = new SymbolDisplayFormat(_testDataKeyFormat.CompilerInternalOptions, _testDataKeyFormat.GlobalNamespaceStyle, _testDataKeyFormat.TypeQualificationStyle, _testDataKeyFormat.GenericsOptions, _testDataKeyFormat.MemberOptions | SymbolDisplayMemberOptions.IncludeType, _testDataKeyFormat.ParameterOptions, _testDataKeyFormat.DelegateStyle, _testDataKeyFormat.ExtensionMethodStyle, _testDataKeyFormat.PropertyStyle, _testDataKeyFormat.LocalOptions, _testDataKeyFormat.KindOptions, _testDataKeyFormat.MiscellaneousOptions); public MetadataWriter? MetadataWriter { get; private set; } public void SetMetadataWriter(MetadataWriter writer) { MetadataWriter = writer; } public void SetMethodILBuilder(IMethodSymbolInternal method, ILBuilder builder) { Methods.Add(method, new MethodData(builder, method)); } public ILBuilder GetIL(Func predicate) { return Methods.Single>((KeyValuePair p) => predicate(p.Key)).Value.ILBuilder; } public ImmutableDictionary GetMethodsByName() { if (_lazyMethodsByName == null) { Dictionary dictionary = new Dictionary(); foreach (KeyValuePair method in Methods) { string methodName = GetMethodName(method.Key); if (dictionary.ContainsKey(methodName)) { dictionary[methodName] = default(MethodData); } else { dictionary.Add(methodName, method.Value); } } ImmutableDictionary value = dictionary.Where((KeyValuePair p) => p.Value.Method != null).ToImmutableDictionary(); Interlocked.CompareExchange(ref _lazyMethodsByName, value, null); } return _lazyMethodsByName; } private static string GetMethodName(IMethodSymbolInternal methodSymbol) { IMethodSymbol obj = (IMethodSymbol)methodSymbol.GetISymbol(); SymbolDisplayFormat format = ((obj.MethodKind == MethodKind.UserDefinedOperator) ? _testDataOperatorKeyFormat : _testDataKeyFormat); return obj.ToDisplayString(format); } }