/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/CSharp/Test/WinRT/Metadata/WinMdDumpTest.cs
482 строки
18 KB
Jason Malinowski
Switch code that was using Assert.True/False as a replacement for .Fail
21 апр 2026, 23:28
21 апр 2026, 23:28
3bf59ba
Код
Авторство
О чём код?
// 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.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Metadata; using System.Text; using Basic.Reference.Assemblies; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Roslyn.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Symbols.Metadata { public class WinMdDumpTest : CSharpTestBase { private readonly MetadataReference _windowsRef = MetadataReference.CreateFromImage(TestResources.WinRt.Windows.AsImmutableOrNull()); private readonly MetadataReference _systemRuntimeRef = MetadataReference.CreateFromImage(Net461.Resources.SystemRuntime.AsImmutableOrNull()); private readonly MetadataReference _systemObjectModelRef = MetadataReference.CreateFromImage(Net461.Resources.SystemObjectModel.AsImmutableOrNull()); private readonly MetadataReference _windowsRuntimeUIXamlRef = MetadataReference.CreateFromImage(TestResources.NetFX.WinRt.SystemRuntimeWindowsRuntimeUIXaml.AsImmutableOrNull()); private readonly MetadataReference _interopServicesWindowsRuntimeRef = MetadataReference.CreateFromImage(Net461.Resources.SystemRuntimeInteropServicesWindowsRuntime.AsImmutableOrNull()); private void AppendMembers(StringBuilder result, NamespaceOrTypeSymbol container, string indent) { string memberIndent; if (container is NamedTypeSymbol) { memberIndent = indent + " "; result.Append(indent); result.AppendLine("{"); AppendCustomAttributes(result, container, indent, inBlock: true); if (container.GetAttributes().Length > 0) { result.AppendLine(); } } else { memberIndent = indent; } foreach (var member in container.GetMembers().OrderBy(m => m.Name, System.StringComparer.InvariantCulture)) { switch (member.Kind) { case SymbolKind.NamedType: var namedType = (PENamedTypeSymbol)member; result.Append(memberIndent); result.Append(".class "); MetadataSignatureHelper.AppendTypeAttributes(result, namedType.Flags); result.Append(' '); result.Append(member); if ((object)namedType.BaseType() != null) { result.AppendLine(); result.Append(memberIndent); result.Append(" extends "); result.Append(namedType.BaseType()); } if (namedType.Interfaces().Length > 0) { result.AppendLine(); result.Append(memberIndent); result.Append(" implements "); result.Append(string.Join(", ", namedType.Interfaces())); } result.AppendLine(); AppendMembers(result, namedType, memberIndent); break; case SymbolKind.Namespace: var ns = member as PENamespaceSymbol; if ((object)ns != null) { AppendMembers(result, ns, indent); } break; case SymbolKind.Method: var method = member as PEMethodSymbol; if ((object)method != null && method.AssociatedSymbol == null) { result.Append(memberIndent); result.Append(".method "); AppendMethod(result, method, memberIndent); AppendCustomAttributes(result, member, memberIndent, inBlock: false); } break; case SymbolKind.Field: var field = (PEFieldSymbol)member; result.Append(memberIndent); result.Append(".field "); MetadataSignatureHelper.AppendFieldAttributes(result, field.Flags); result.Append(' '); result.Append(field.TypeWithAnnotations); result.Append(' '); result.Append(member.Name); result.AppendLine(); AppendCustomAttributes(result, member, memberIndent, inBlock: false); break; case SymbolKind.Property: var property = (PEPropertySymbol)member; string propertyName; result.Append(memberIndent); result.Append(".property "); PropertyAttributes propertyAttrs; ((PEModuleSymbol)container.ContainingModule).Module.GetPropertyDefPropsOrThrow(property.Handle, out propertyName, out propertyAttrs); if (MetadataSignatureHelper.AppendPropertyAttributes(result, propertyAttrs)) { result.Append(' '); } result.Append(property.TypeWithAnnotations); result.Append(' '); result.Append(property.Name); result.AppendLine(); result.Append(memberIndent); result.AppendLine("{"); AppendCustomAttributes(result, member, memberIndent, inBlock: true); if (property.GetMethod != null) { result.Append(memberIndent); result.Append(" .get "); AppendMethod(result, (PEMethodSymbol)property.GetMethod, memberIndent); } if (property.SetMethod != null) { result.Append(memberIndent); result.Append(" .set "); AppendMethod(result, (PEMethodSymbol)property.SetMethod, memberIndent); } result.Append(memberIndent); result.AppendLine("}"); break; case SymbolKind.Event: var evnt = (PEEventSymbol)member; result.Append(memberIndent); result.Append(".event "); string eventName; EventAttributes eventAttrs; EntityHandle type; ((PEModuleSymbol)container.ContainingModule).Module.GetEventDefPropsOrThrow(evnt.Handle, out eventName, out eventAttrs, out type); if (MetadataSignatureHelper.AppendEventAttributes(result, eventAttrs)) { result.Append(' '); } result.Append(evnt.TypeWithAnnotations); result.Append(' '); result.Append(evnt.Name); result.AppendLine(); result.Append(memberIndent); result.Append('{'); result.AppendLine(); AppendCustomAttributes(result, member, memberIndent, inBlock: true); if (evnt.RemoveMethod != null) { result.Append(memberIndent); result.Append(" .removeon "); AppendMethod(result, (PEMethodSymbol)evnt.RemoveMethod, memberIndent); } if (evnt.AddMethod != null) { result.Append(memberIndent); result.Append(" .addon "); AppendMethod(result, (PEMethodSymbol)evnt.AddMethod, memberIndent); } result.Append(memberIndent); result.AppendLine("}"); break; } } if (container is NamedTypeSymbol) { result.Append(indent); result.AppendLine("}"); } } private static void AppendCustomAttributes(StringBuilder result, Symbol symbol, string indent, bool inBlock) { var attributes = symbol.GetAttributes(); if (attributes.Length == 0) { return; } if (!inBlock) { result.Append(indent); result.AppendLine("{"); } string memberIndent = indent + " "; foreach (var attribute in attributes) { result.Append(memberIndent); result.Append(".custom "); if (attribute.AttributeConstructor == null) { result.Append("[Missing: "); result.Append(attribute.AttributeClass); result.Append(']'); } else { AppendMethod(result, (PEMethodSymbol)attribute.AttributeConstructor, indent: null, includeTypeName: true); } result.Append(" = ("); int i = 0; foreach (var arg in attribute.ConstructorArguments) { if (i > 0) { result.Append(", "); } AppendConstant(result, arg); i++; } foreach (var arg in attribute.NamedArguments) { if (i > 0) { result.Append(", "); } result.Append(arg.Key); result.Append(" = "); AppendConstant(result, arg.Value); i++; } result.Append(')'); result.AppendLine(); } if (!inBlock) { result.Append(indent); result.AppendLine("}"); } } private static void AppendConstant(StringBuilder result, TypedConstant constant) { switch (constant.Kind) { case TypedConstantKind.Array: result.Append('{'); int i = 0; foreach (var item in constant.Values) { if (i > 0) { result.Append(", "); } AppendConstant(result, item); } result.Append('}'); break; case TypedConstantKind.Type: result.Append("typeof("); result.Append(constant.Value); result.Append(')'); break; case TypedConstantKind.Enum: case TypedConstantKind.Primitive: var value = constant.Value; if (value.GetType() == typeof(string)) { result.Append('"'); result.Append(value); result.Append('"'); } else if (value.GetType() == typeof(bool)) { result.Append(value.ToString().ToLower()); } else { result.Append(value); } break; default: throw ExceptionUtilities.UnexpectedValue(constant.Kind); } } private static void AppendMethod(StringBuilder result, PEMethodSymbol method, string indent, bool includeTypeName = false) { MetadataSignatureHelper.AppendMethodAttributes(result, method.Flags); result.Append(' '); AppendSignatureType(result, method.ReturnType, RefKind.None); result.Append(' '); if (includeTypeName) { result.Append(method.ContainingType); result.Append("::"); } result.Append(method.Name); result.Append('('); bool hasParameterAttributes = false; int i = 0; foreach (PEParameterSymbol parameter in method.Parameters) { if (i > 0) { result.Append(", "); } if (parameter.GetAttributes().Length > 0) { hasParameterAttributes = true; } if (MetadataSignatureHelper.AppendParameterAttributes(result, parameter.Flags, all: true)) { result.Append(' '); } AppendSignatureType(result, parameter.Type, parameter.RefKind); result.Append(' '); result.Append(parameter.Name); i++; } result.Append(") "); MetadataSignatureHelper.AppendMethodImplAttributes(result, method.ImplementationAttributes); if (indent != null) { result.AppendLine(); if (hasParameterAttributes) { result.Append(indent); result.AppendLine("{"); string memberIndent = indent + " "; i = 1; foreach (PEParameterSymbol parameter in method.Parameters) { if (parameter.GetAttributes().Length > 0) { result.Append(memberIndent); result.AppendFormat(".param [{0}]", i); result.AppendLine(); AppendCustomAttributes(result, parameter, indent, inBlock: true); } i++; } result.Append(indent); result.AppendLine("}"); } } } private static void AppendSignatureType(StringBuilder result, TypeSymbol type, RefKind refKind) { result.Append(type); if (refKind != RefKind.None) { result.Append('&'); } } private void AppendAssemblyRefs(StringBuilder result, PEAssemblySymbol assembly) { foreach (var a in assembly.PrimaryModule.GetReferencedAssemblies()) { result.Append(".assembly extern "); result.AppendLine(a.GetDisplayName(fullKey: true)); } } private string Dump(MetadataReference winmd, MetadataReference[] additionalRefs = null) { IEnumerable<MetadataReference> references = new[] { MscorlibRef_v4_0_30316_17626, _systemRuntimeRef, _systemObjectModelRef, _windowsRuntimeUIXamlRef, _interopServicesWindowsRuntimeRef, winmd }; if (additionalRefs != null) { references = references.Concat(additionalRefs); } var comp = CreateEmptyCompilation("", references, options: TestOptions.ReleaseDll.WithMetadataImportOptions(MetadataImportOptions.All)); var writer = new StringBuilder(); AppendAssemblyRefs(writer, (PEAssemblySymbol)comp.GetReferencedAssemblySymbol(winmd)); AppendMembers(writer, comp.GetReferencedAssemblySymbol(winmd).GlobalNamespace, ""); return writer.ToString(); } private void AssertDumpsEqual(string expected, string actual) { if (expected != actual) { string fileExpected = Path.Combine(Path.GetTempPath(), "roslyn_winmd_dump.expected.txt"); string fileActual = Path.Combine(Path.GetTempPath(), "roslyn_winmd_dump.actual.txt"); File.WriteAllText(fileExpected, expected); File.WriteAllText(fileActual, actual); Assert.Fail("Dump is different. To investigate compare files:\r\n\"" + fileExpected + "\" \"" + fileActual + "\""); } } [Fact] public void DumpWindowsWinMD() { var expected = Encoding.UTF8.GetString(TestResources.WinRt.Windows_dump); var actual = Dump(_windowsRef); AssertDumpsEqual(expected, actual); } [Fact] public void DumpWinMDPrefixing() { var winmd = MetadataReference.CreateFromImage(TestResources.WinRt.WinMDPrefixing.AsImmutableOrNull()); var actual = Dump(winmd, new[] { _windowsRef }); var expected = Encoding.UTF8.GetString(TestResources.WinRt.WinMDPrefixing_dump); AssertDumpsEqual(expected, actual); } } }