/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/Test/Core/Compilation/CompilationDifference.cs
186 строк
8 KB
Tomáš Matoušek
EnC: Fix symbol mapping of delegates with indexed name (#79837)
21 авг 2025, 02:02
Не верифицирован
21 авг 2025, 02:02
4ecc7b3
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #nullable disable using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Runtime.CompilerServices; using System.Xml.Linq; using Microsoft.CodeAnalysis.CodeGen; using Microsoft.CodeAnalysis.Collections; using Microsoft.CodeAnalysis.Emit; using Microsoft.CodeAnalysis.Symbols; using Microsoft.DiaSymReader.Tools; using Microsoft.Metadata.Tools; using Roslyn.Test.Utilities; using Roslyn.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.Test.Utilities { public sealed class CompilationDifference { public readonly ImmutableArray<byte> MetadataDelta; public readonly ImmutableArray<byte> ILDelta; public readonly ImmutableArray<byte> PdbDelta; internal readonly CompilationTestData TestData; public readonly EmitDifferenceResult EmitResult; internal CompilationDifference( ImmutableArray<byte> metadata, ImmutableArray<byte> il, ImmutableArray<byte> pdb, CompilationTestData testData, EmitDifferenceResult result) { MetadataDelta = metadata; ILDelta = il; PdbDelta = pdb; TestData = testData; EmitResult = result; } public EmitBaseline NextGeneration { get { return EmitResult.Baseline; } } internal PinnedMetadata GetMetadata() { return new PinnedMetadata(MetadataDelta); } public void VerifyIL( string expectedIL, [CallerLineNumber] int callerLine = 0, [CallerFilePath] string callerPath = null) { using var readerProvider = MetadataReaderProvider.FromMetadataImage(MetadataDelta); string actualIL = ILValidation.DumpEncDeltaMethodBodies(ILDelta, [readerProvider.GetMetadataReader()]); AssertEx.AssertEqualToleratingWhitespaceDifferences(expectedIL, actualIL, escapeQuotes: false, expectedValueSourcePath: callerPath, expectedValueSourceLine: callerLine); } public void VerifyLocalSignature( string qualifiedMethodName, string expectedSignature, [CallerLineNumber] int callerLine = 0, [CallerFilePath] string callerPath = null) { var ilBuilder = TestData.GetMethodData(qualifiedMethodName).ILBuilder; string actualSignature = ILBuilderVisualizer.LocalSignatureToString(ilBuilder, ToLocalInfo); AssertEx.AssertEqualToleratingWhitespaceDifferences(expectedSignature, actualSignature, escapeQuotes: true, expectedValueSourcePath: callerPath, expectedValueSourceLine: callerLine); } internal void VerifyIL( string qualifiedMethodName, string expectedIL, Func<Cci.ILocalDefinition, ILVisualizer.LocalInfo> mapLocal = null, MethodDefinitionHandle methodToken = default, [CallerFilePath] string callerPath = null, [CallerLineNumber] int callerLine = 0) { var ilBuilder = TestData.GetMethodData(qualifiedMethodName).ILBuilder; Dictionary<int, string> sequencePointMarkers = null; if (!methodToken.IsNil) { string actualPdb = PdbToXmlConverter.DeltaPdbToXml(new ImmutableMemoryStream(PdbDelta), new[] { MetadataTokens.GetToken(methodToken) }); sequencePointMarkers = ILValidation.GetSequencePointMarkers(XElement.Parse(actualPdb)); Assert.True(sequencePointMarkers.Count > 0, $"No sequence points found in:{Environment.NewLine}{actualPdb}"); } string actualIL = ILBuilderVisualizer.ILBuilderToString(ilBuilder, mapLocal ?? ToLocalInfo, sequencePointMarkers); AssertEx.AssertEqualToleratingWhitespaceDifferences(expectedIL, actualIL, escapeQuotes: false, expectedValueSourcePath: callerPath, expectedValueSourceLine: callerLine); } internal string GetMethodIL(string qualifiedMethodName) { return ILBuilderVisualizer.ILBuilderToString(this.TestData.GetMethodData(qualifiedMethodName).ILBuilder, ToLocalInfo); } private static ILVisualizer.LocalInfo ToLocalInfo(Cci.ILocalDefinition local) { var signature = local.Signature; if (signature == null) { return new ILVisualizer.LocalInfo(local.Name, local.Type, local.IsPinned, local.IsReference); } else { // Decode simple types only. var typeName = (signature.Length == 1) ? GetTypeName((SignatureTypeCode)signature[0]) : null; return new ILVisualizer.LocalInfo(null, typeName ?? "[unchanged]", false, false); } } private static string GetTypeName(SignatureTypeCode typeCode) { switch (typeCode) { case SignatureTypeCode.Boolean: return "[bool]"; case SignatureTypeCode.Int32: return "[int]"; case SignatureTypeCode.String: return "[string]"; case SignatureTypeCode.Object: return "[object]"; default: return null; } } public void VerifySynthesizedMembers(params string[] expectedSynthesizedTypesAndMemberCounts) => VerifySynthesizedMembers(EmitResult.Baseline.SynthesizedMembers, displayTypeKind: false, expectedSynthesizedTypesAndMemberCounts); internal static void VerifySynthesizedMembers(IReadOnlyDictionary<ISymbolInternal, ImmutableArray<ISymbolInternal>> actualMembers, bool displayTypeKind, params string[] expected) { // Synthesized namespaces are not interesting. Explode them and display types contained in them as separate fully qualified names in the list. var actual = new List<string>(); foreach (var (container, members) in actualMembers) { if (container is INamespaceSymbolInternal ns) { actual.AddRange(members .Where(m => m is not INamespaceSymbolInternal) .Select(m => m.GetISymbol().ToDisplayString(SymbolDisplayFormat.TestFormat))); } } foreach (var (container, members) in actualMembers) { if (container is not INamespaceSymbolInternal) { actual.Add( $"{(displayTypeKind && container is INamedTypeSymbolInternal type ? (type.TypeKind == TypeKind.Struct ? "struct " : "class ") : "")}{container}: " + $"{{{string.Join(", ", members.Select(v => v.Name))}}}"); } } AssertEx.SetEqual(expected, actual, itemSeparator: ",\r\n", itemInspector: s => $"\"{s}\""); } internal static void VerifySynthesizedSymbols(IEnumerable<ISymbolInternal> actualSymbols, params string[] expected) { AssertEx.SetEqual(expected, actualSymbols.Select(v => v.GetISymbol().ToDisplayString(SymbolDisplayFormat.TestFormat)), itemSeparator: ",\r\n", itemInspector: s => $"\"{s}\""); } public void VerifySynthesizedFields(string typeName, params string[] expectedSynthesizedTypesAndMemberCounts) { var actual = EmitResult.Baseline.SynthesizedMembers.Single(e => e.Key.ToString() == typeName).Value.Where(s => s.Kind == SymbolKind.Field).Select(s => (IFieldSymbol)s.GetISymbol()).Select(f => f.Name + ": " + f.Type); AssertEx.SetEqual(expectedSynthesizedTypesAndMemberCounts, actual, itemSeparator: "\r\n"); } public void VerifyUpdatedMethods(params string[] expectedMethodTokens) { AssertEx.Equal( expectedMethodTokens, EmitResult.UpdatedMethods.Select(methodHandle => $"0x{MetadataTokens.GetToken(methodHandle):X8}")); } } }