/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/Core/Rebuild/CompilationFactory.cs
213 строк
9 KB
AlekseyTs
Standardize references to the UTF-8 term in code and comments/documentation (#62074)
27 июн 2022, 19:22
Не верифицирован
27 июн 2022, 19:22
eb7b204
Код
Авторство
О чём код?
// 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. using System; using System.Collections.Immutable; using System.IO; using System.Linq; using System.Reflection.Metadata; using System.Reflection.PortableExecutable; using System.Threading; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Emit; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Text; namespace Microsoft.CodeAnalysis.Rebuild { public abstract class CompilationFactory { public string AssemblyFileName { get; } public CompilationOptionsReader OptionsReader { get; } public ParseOptions ParseOptions => CommonParseOptions; public CompilationOptions CompilationOptions => CommonCompilationOptions; protected abstract ParseOptions CommonParseOptions { get; } protected abstract CompilationOptions CommonCompilationOptions { get; } protected CompilationFactory(string assemblyFileName, CompilationOptionsReader optionsReader) { AssemblyFileName = assemblyFileName; OptionsReader = optionsReader; } public static CompilationFactory Create(string assemblyFileName, CompilationOptionsReader optionsReader) => optionsReader.GetLanguageName() switch { LanguageNames.CSharp => CSharpCompilationFactory.Create(assemblyFileName, optionsReader), LanguageNames.VisualBasic => VisualBasicCompilationFactory.Create(assemblyFileName, optionsReader), var language => throw new InvalidDataException($"{assemblyFileName} has unsupported language {language}") }; public abstract SyntaxTree CreateSyntaxTree(string filePath, SourceText sourceText); public Compilation CreateCompilation(IRebuildArtifactResolver resolver) { var tuple = OptionsReader.ResolveArtifacts(resolver, CreateSyntaxTree); return CreateCompilation(tuple.SyntaxTrees, tuple.MetadataReferences); } public abstract Compilation CreateCompilation( ImmutableArray<SyntaxTree> syntaxTrees, ImmutableArray<MetadataReference> metadataReferences); public EmitResult Emit( Stream rebuildPeStream, Stream? rebuildPdbStream, IRebuildArtifactResolver rebuildArtifactResolver, CancellationToken cancellationToken) => Emit( rebuildPeStream, rebuildPdbStream, CreateCompilation(rebuildArtifactResolver), cancellationToken); public EmitResult Emit( Stream rebuildPeStream, Stream? rebuildPdbStream, ImmutableArray<SyntaxTree> syntaxTrees, ImmutableArray<MetadataReference> metadataReferences, CancellationToken cancellationToken) => Emit( rebuildPeStream, rebuildPdbStream, CreateCompilation(syntaxTrees, metadataReferences), cancellationToken); public EmitResult Emit( Stream rebuildPeStream, Stream? rebuildPdbStream, Compilation rebuildCompilation, CancellationToken cancellationToken) { var embeddedTexts = rebuildCompilation.SyntaxTrees .Select(st => (path: st.FilePath, text: st.GetText())) .Where(pair => pair.text.CanBeEmbedded) .Select(pair => EmbeddedText.FromSource(pair.path, pair.text)) .ToImmutableArray(); return Emit( rebuildPeStream, rebuildPdbStream, rebuildCompilation, embeddedTexts, cancellationToken); } public unsafe EmitResult Emit( Stream rebuildPeStream, Stream? rebuildPdbStream, Compilation rebuildCompilation, ImmutableArray<EmbeddedText> embeddedTexts, CancellationToken cancellationToken) { var peHeader = OptionsReader.PeReader.PEHeaders.PEHeader!; var win32Resources = OptionsReader.PeReader.GetSectionData(peHeader.ResourceTableDirectory.RelativeVirtualAddress); using var win32ResourceStream = win32Resources.Pointer != null ? new UnmanagedMemoryStream(win32Resources.Pointer, win32Resources.Length) : null; var sourceLink = OptionsReader.GetSourceLinkUtf8(); var debugEntryPoint = getDebugEntryPoint(); string? pdbFilePath; DebugInformationFormat debugInformationFormat; if (OptionsReader.HasEmbeddedPdb) { if (rebuildPdbStream is object) { throw new ArgumentException(RebuildResources.PDB_stream_must_be_null_because_the_compilation_has_an_embedded_PDB, nameof(rebuildPdbStream)); } debugInformationFormat = DebugInformationFormat.Embedded; pdbFilePath = null; } else { if (rebuildPdbStream is null) { throw new ArgumentException(RebuildResources.A_non_null_PDB_stream_must_be_provided_because_the_compilation_does_not_have_an_embedded_PDB, nameof(rebuildPdbStream)); } debugInformationFormat = DebugInformationFormat.PortablePdb; var codeViewEntry = OptionsReader.PeReader.ReadDebugDirectory().Single(entry => entry.Type == DebugDirectoryEntryType.CodeView); var codeView = OptionsReader.PeReader.ReadCodeViewDebugDirectoryData(codeViewEntry); pdbFilePath = codeView.Path ?? throw new InvalidOperationException(RebuildResources.Could_not_get_PDB_file_path); } var rebuildData = new RebuildData( OptionsReader.GetMetadataCompilationOptionsBlobReader(), getNonSourceFileDocumentNames(OptionsReader.PdbReader, OptionsReader.GetSourceFileCount())); var emitResult = rebuildCompilation.Emit( peStream: rebuildPeStream, pdbStream: rebuildPdbStream, xmlDocumentationStream: null, win32Resources: win32ResourceStream, manifestResources: OptionsReader.GetManifestResources(), options: new EmitOptions( debugInformationFormat: debugInformationFormat, pdbFilePath: pdbFilePath, highEntropyVirtualAddressSpace: (peHeader.DllCharacteristics & DllCharacteristics.HighEntropyVirtualAddressSpace) != 0, subsystemVersion: SubsystemVersion.Create(peHeader.MajorSubsystemVersion, peHeader.MinorSubsystemVersion)), debugEntryPoint: debugEntryPoint, metadataPEStream: null, rebuildData: rebuildData, sourceLinkStream: sourceLink != null ? new MemoryStream(sourceLink) : null, embeddedTexts: embeddedTexts, cancellationToken: cancellationToken); return emitResult; static ImmutableArray<string> getNonSourceFileDocumentNames(MetadataReader pdbReader, int sourceFileCount) { var count = pdbReader.Documents.Count - sourceFileCount; var builder = ArrayBuilder<string>.GetInstance(count); foreach (var documentHandle in pdbReader.Documents.Skip(sourceFileCount)) { var document = pdbReader.GetDocument(documentHandle); var name = pdbReader.GetString(document.Name); builder.Add(name); } return builder.ToImmutableAndFree(); } IMethodSymbol? getDebugEntryPoint() { if (OptionsReader.GetMainMethodInfo() is (string mainTypeName, string mainMethodName)) { var typeSymbol = rebuildCompilation.GetTypeByMetadataName(mainTypeName); if (typeSymbol is object) { var methodSymbols = typeSymbol .GetMembers(mainMethodName) .OfType<IMethodSymbol>(); return methodSymbols.FirstOrDefault(); } } return null; } } protected static (OptimizationLevel OptimizationLevel, bool DebugPlus) GetOptimizationLevel(string? value) { if (value is null) { return OptimizationLevelFacts.DefaultValues; } if (!OptimizationLevelFacts.TryParsePdbSerializedString(value, out OptimizationLevel optimizationLevel, out bool debugPlus)) { throw new InvalidOperationException(); } return (optimizationLevel, debugPlus); } protected static Platform GetPlatform(string? platform) => platform is null ? Platform.AnyCpu : (Platform)Enum.Parse(typeof(Platform), platform); } }