/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/Test/Core/PDB/DeterministicBuildCompilationTestHelpers.cs
187 строк
8 KB
Tomáš Matoušek
[EnC] Use default encoding stored in the PDB for creating committed document SourceText (#81912)
26 янв 2026, 20:56
Не верифицирован
26 янв 2026, 20:56
049aa52
Код
Авторство
О чём код?
// 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; using System.Reflection.Metadata; using System.Security.Cryptography; using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Debugging; using Microsoft.CodeAnalysis.Emit; using Microsoft.CodeAnalysis.Test.Utilities; using Xunit; namespace Roslyn.Test.Utilities.PDB { internal static partial class DeterministicBuildCompilationTestHelpers { public static void VerifyPdbOption<T>(this ImmutableDictionary<string, string> pdbOptions, string pdbName, T expectedValue, Func<T, bool> isDefault = null, Func<T, string> toString = null) { bool expectedIsDefault = (isDefault != null) ? isDefault(expectedValue) : EqualityComparer<T>.Default.Equals(expectedValue, default); var expectedValueString = expectedIsDefault ? null : (toString != null) ? toString(expectedValue) : expectedValue.ToString(); pdbOptions.TryGetValue(pdbName, out var actualValueString); Assert.Equal(expectedValueString, actualValueString); } public static IEnumerable<EmitOptions> GetEmitOptions() { var emitOptions = new EmitOptions( debugInformationFormat: DebugInformationFormat.Embedded, pdbChecksumAlgorithm: HashAlgorithmName.SHA256, defaultSourceFileEncoding: Encoding.UTF32); yield return emitOptions; yield return emitOptions.WithDefaultSourceFileEncoding(Encoding.ASCII); yield return emitOptions.WithDefaultSourceFileEncoding(null).WithFallbackSourceFileEncoding(Encoding.Unicode); yield return emitOptions.WithFallbackSourceFileEncoding(Encoding.Unicode).WithDefaultSourceFileEncoding(Encoding.ASCII); } internal static void AssertCommonOptions(EmitOptions emitOptions, CompilationOptions compilationOptions, Compilation compilation, ImmutableDictionary<string, string> pdbOptions) { pdbOptions.VerifyPdbOption("version", 2); pdbOptions.VerifyPdbOption("fallback-encoding", emitOptions.FallbackSourceFileEncoding, toString: v => v.WebName); pdbOptions.VerifyPdbOption("default-encoding", emitOptions.DefaultSourceFileEncoding, toString: v => v.WebName); int portabilityPolicy = 0; if (compilationOptions.AssemblyIdentityComparer is DesktopAssemblyIdentityComparer identityComparer) { portabilityPolicy |= identityComparer.PortabilityPolicy.SuppressSilverlightLibraryAssembliesPortability ? 0b1 : 0; portabilityPolicy |= identityComparer.PortabilityPolicy.SuppressSilverlightPlatformAssembliesPortability ? 0b10 : 0; } pdbOptions.VerifyPdbOption("portability-policy", portabilityPolicy); var compilerVersion = typeof(Compilation).Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion; Assert.Equal(compilerVersion.ToString(), pdbOptions["compiler-version"]); var runtimeVersion = typeof(object).Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion; Assert.Equal(runtimeVersion, pdbOptions[CompilationOptionNames.RuntimeVersion]); pdbOptions.VerifyPdbOption( "optimization", (compilationOptions.OptimizationLevel, compilationOptions.DebugPlusMode), toString: v => v.OptimizationLevel.ToPdbSerializedString(v.DebugPlusMode)); Assert.Equal(compilation.Language, pdbOptions["language"]); } public static void VerifyReferenceInfo(TestMetadataReferenceInfo[] references, TargetFramework targetFramework, BlobReader metadataReferenceReader) { var frameworkReferences = TargetFrameworkUtil.GetReferences(targetFramework); var count = 0; while (metadataReferenceReader.RemainingBytes > 0) { var info = ParseMetadataReferenceInfo(ref metadataReferenceReader); if (frameworkReferences.Any(x => x.GetModuleVersionId() == info.Mvid)) { count++; continue; } var testReference = references.Single(x => x.MetadataReferenceInfo.Mvid == info.Mvid); testReference.MetadataReferenceInfo.AssertEqual(info); count++; } Assert.Equal(references.Length + frameworkReferences.Length, count); } public static BlobReader GetSingleBlob(Guid infoGuid, MetadataReader pdbReader) { return (from cdiHandle in pdbReader.GetCustomDebugInformation(EntityHandle.ModuleDefinition) let cdi = pdbReader.GetCustomDebugInformation(cdiHandle) where pdbReader.GetGuid(cdi.Kind) == infoGuid select pdbReader.GetBlobReader(cdi.Value)).Single(); } public static MetadataReferenceInfo ParseMetadataReferenceInfo(ref BlobReader blobReader) { // Order of information // File name (null terminated string): A.exe // Extern Alias (null terminated string): a1,a2,a3 // EmbedInteropTypes/MetadataImageKind (byte) // COFF header Timestamp field (4 byte int) // COFF header SizeOfImage field (4 byte int) // MVID (Guid, 24 bytes) var terminatorIndex = blobReader.IndexOf(0); Assert.NotEqual(-1, terminatorIndex); var name = blobReader.ReadUTF8(terminatorIndex); // Skip the null terminator blobReader.ReadByte(); terminatorIndex = blobReader.IndexOf(0); Assert.NotEqual(-1, terminatorIndex); var externAliases = blobReader.ReadUTF8(terminatorIndex); blobReader.ReadByte(); var embedInteropTypesAndKind = blobReader.ReadByte(); var embedInteropTypes = (embedInteropTypesAndKind & 0b10) == 0b10; var kind = (embedInteropTypesAndKind & 0b1) == 0b1 ? MetadataImageKind.Assembly : MetadataImageKind.Module; var timestamp = blobReader.ReadInt32(); var imageSize = blobReader.ReadInt32(); var mvid = blobReader.ReadGuid(); return new MetadataReferenceInfo( timestamp, imageSize, name, mvid, string.IsNullOrEmpty(externAliases) ? ImmutableArray<string>.Empty : externAliases.Split(',').ToImmutableArray(), kind, embedInteropTypes); } public static ImmutableDictionary<string, string> ParseCompilationOptions(BlobReader blobReader) { // Compiler flag bytes are UTF-8 null-terminated key-value pairs string key = null; Dictionary<string, string> kvp = new Dictionary<string, string>(); for (; ; ) { var nullIndex = blobReader.IndexOf(0); if (nullIndex == -1) { break; } var value = blobReader.ReadUTF8(nullIndex); // Skip the null terminator blobReader.ReadByte(); if (key is null) { key = value; } else { kvp[key] = value; key = null; } } Assert.Null(key); Assert.Equal(0, blobReader.RemainingBytes); return kvp.ToImmutableDictionary(); } } }