Пример #1
0
        /// <summary>
        /// Return a version of the baseline with all definitions mapped to this compilation.
        /// Definitions from the initial generation, from metadata, are not mapped since
        /// the initial generation is always included as metadata. That is, the symbols from
        /// types, methods, ... in the TypesAdded, MethodsAdded, ... collections are replaced
        /// by the corresponding symbols from the current compilation.
        /// </summary>
        private static EmitBaseline MapToCompilation(
            CSharpCompilation compilation,
            PEDeltaAssemblyBuilder moduleBeingBuilt)
        {
            var previousGeneration = moduleBeingBuilt.PreviousGeneration;
            Debug.Assert(previousGeneration.Compilation != compilation);

            if (previousGeneration.Ordinal == 0)
            {
                // Initial generation, nothing to map. (Since the initial generation
                // is always loaded from metadata in the context of the current
                // compilation, there's no separate mapping step.)
                return previousGeneration;
            }

            var currentSynthesizedMembers = moduleBeingBuilt.GetSynthesizedMembers();

            // Mapping from previous compilation to the current.
            var anonymousTypeMap = moduleBeingBuilt.GetAnonymousTypeMap();
            var sourceAssembly = ((CSharpCompilation)previousGeneration.Compilation).SourceAssembly;
            var sourceContext = new EmitContext((PEModuleBuilder)previousGeneration.PEModuleBuilder, null, new DiagnosticBag());
            var otherContext = new EmitContext(moduleBeingBuilt, null, new DiagnosticBag());

            var matcher = new CSharpSymbolMatcher(
                anonymousTypeMap,
                sourceAssembly,
                sourceContext,
                compilation.SourceAssembly,
                otherContext,
                currentSynthesizedMembers);

            var mappedSynthesizedMembers = matcher.MapSynthesizedMembers(previousGeneration.SynthesizedMembers, currentSynthesizedMembers);

            // TODO: can we reuse some data from the previos matcher?
            var matcherWithAllSynthesizedMembers = new CSharpSymbolMatcher(
                anonymousTypeMap,
                sourceAssembly,
                sourceContext,
                compilation.SourceAssembly,
                otherContext,
                mappedSynthesizedMembers);

            return matcherWithAllSynthesizedMembers.MapBaselineToCompilation(
                previousGeneration,
                compilation,
                moduleBeingBuilt,
                mappedSynthesizedMembers);
        }
Пример #2
0
        internal static EmitDifferenceResult EmitDifference(
            CSharpCompilation compilation,
            EmitBaseline baseline,
            IEnumerable<SemanticEdit> edits,
            Func<ISymbol, bool> isAddedSymbol,
            Stream metadataStream,
            Stream ilStream,
            Stream pdbStream,
            ICollection<MethodDefinitionHandle> updatedMethods,
            CompilationTestData testData,
            CancellationToken cancellationToken)
        {
            Guid moduleVersionId;
            try
            {
                moduleVersionId = baseline.OriginalMetadata.GetModuleVersionId();
            }
            catch (BadImageFormatException)
            {
                // TODO:
                // return MakeEmitResult(success: false, diagnostics: ..., baseline: null);
                throw;
            }

            var diagnostics = DiagnosticBag.GetInstance();

            var emitOptions = EmitOptions.Default;
            string runtimeMDVersion = compilation.GetRuntimeMetadataVersion(emitOptions, diagnostics);
            var serializationProperties = compilation.ConstructModuleSerializationProperties(emitOptions, runtimeMDVersion, moduleVersionId);
            var manifestResources = SpecializedCollections.EmptyEnumerable<ResourceDescription>();

            var moduleBeingBuilt = new PEDeltaAssemblyBuilder(
                compilation.SourceAssembly,
                emitOptions: emitOptions,
                outputKind: compilation.Options.OutputKind,
                serializationProperties: serializationProperties,
                manifestResources: manifestResources,
                previousGeneration: baseline,
                edits: edits,
                isAddedSymbol: isAddedSymbol);

            if (testData != null)
            {
                moduleBeingBuilt.SetMethodTestData(testData.Methods);
                testData.Module = moduleBeingBuilt;
            }

            var definitionMap = moduleBeingBuilt.PreviousDefinitions;
            var changes = moduleBeingBuilt.Changes;

            EmitBaseline newBaseline = null;

            if (compilation.Compile(
                moduleBeingBuilt,
                win32Resources: null,
                xmlDocStream: null,
                emittingPdb: true,
                diagnostics: diagnostics,
                filterOpt: changes.RequiresCompilation,
                cancellationToken: cancellationToken))
            {
                // Map the definitions from the previous compilation to the current compilation.
                // This must be done after compiling above since synthesized definitions
                // (generated when compiling method bodies) may be required.
                var mappedBaseline = MapToCompilation(compilation, moduleBeingBuilt);

                newBaseline = compilation.SerializeToDeltaStreams(
                    moduleBeingBuilt,
                    mappedBaseline, 
                    definitionMap,
                    changes,
                    metadataStream,
                    ilStream,
                    pdbStream,
                    updatedMethods,
                    diagnostics,
                    testData?.SymWriterFactory,
                    cancellationToken);
            }

            return new EmitDifferenceResult(
                success: newBaseline != null,
                diagnostics: diagnostics.ToReadOnlyAndFree(),
                baseline: newBaseline);
        }
Пример #3
0
        internal static EmitDifferenceResult EmitDifference(
            CSharpCompilation compilation,
            EmitBaseline baseline,
            IEnumerable <SemanticEdit> edits,
            Func <ISymbol, bool> isAddedSymbol,
            Stream metadataStream,
            Stream ilStream,
            Stream pdbStream,
            CompilationTestData?testData,
            CancellationToken cancellationToken)
        {
            var diagnostics = DiagnosticBag.GetInstance();

            var emitOptions             = EmitOptions.Default.WithDebugInformationFormat(baseline.HasPortablePdb ? DebugInformationFormat.PortablePdb : DebugInformationFormat.Pdb);
            var runtimeMDVersion        = compilation.GetRuntimeMetadataVersion(emitOptions, diagnostics);
            var serializationProperties = compilation.ConstructModuleSerializationProperties(emitOptions, runtimeMDVersion, baseline.ModuleVersionId);
            var manifestResources       = SpecializedCollections.EmptyEnumerable <ResourceDescription>();

            var updatedMethods = ArrayBuilder <MethodDefinitionHandle> .GetInstance();

            var updatedTypes = ArrayBuilder <TypeDefinitionHandle> .GetInstance();

            PEDeltaAssemblyBuilder moduleBeingBuilt;

            try
            {
                moduleBeingBuilt = new PEDeltaAssemblyBuilder(
                    compilation.SourceAssembly,
                    emitOptions: emitOptions,
                    outputKind: compilation.Options.OutputKind,
                    serializationProperties: serializationProperties,
                    manifestResources: manifestResources,
                    previousGeneration: baseline,
                    edits: edits,
                    isAddedSymbol: isAddedSymbol);
            }
            catch (NotSupportedException e)
            {
                // TODO: https://github.com/dotnet/roslyn/issues/9004
                diagnostics.Add(ErrorCode.ERR_ModuleEmitFailure, NoLocation.Singleton, compilation.AssemblyName, e.Message);
                return(new EmitDifferenceResult(success: false, diagnostics: diagnostics.ToReadOnlyAndFree(), baseline: null, updatedMethods: updatedMethods.ToImmutableAndFree(), updatedTypes: updatedTypes.ToImmutableAndFree()));
            }

            if (testData != null)
            {
                moduleBeingBuilt.SetMethodTestData(testData.Methods);
                testData.Module = moduleBeingBuilt;
            }

            var definitionMap = moduleBeingBuilt.PreviousDefinitions;
            var changes       = moduleBeingBuilt.Changes;

            EmitBaseline?newBaseline = null;

            if (compilation.Compile(
                    moduleBeingBuilt,
                    emittingPdb: true,
                    diagnostics: diagnostics,
                    filterOpt: s => changes.RequiresCompilation(s.GetISymbol()),
                    cancellationToken: cancellationToken))
            {
                // Map the definitions from the previous compilation to the current compilation.
                // This must be done after compiling above since synthesized definitions
                // (generated when compiling method bodies) may be required.
                var mappedBaseline = MapToCompilation(compilation, moduleBeingBuilt);

                newBaseline = compilation.SerializeToDeltaStreams(
                    moduleBeingBuilt,
                    mappedBaseline,
                    definitionMap,
                    changes,
                    metadataStream,
                    ilStream,
                    pdbStream,
                    updatedMethods,
                    updatedTypes,
                    diagnostics,
                    testData?.SymWriterFactory,
                    emitOptions.PdbFilePath,
                    cancellationToken);
            }

            return(new EmitDifferenceResult(
                       success: newBaseline != null,
                       diagnostics: diagnostics.ToReadOnlyAndFree(),
                       baseline: newBaseline,
                       updatedMethods: updatedMethods.ToImmutableAndFree(),
                       updatedTypes: updatedTypes.ToImmutableAndFree()));
        }
Пример #4
0
        internal static EmitDifferenceResult EmitDifference(
            CSharpCompilation compilation,
            EmitBaseline baseline,
            IEnumerable<SemanticEdit> edits,
            Func<ISymbol, bool> isAddedSymbol,
            Stream metadataStream,
            Stream ilStream,
            Stream pdbStream,
            ICollection<MethodDefinitionHandle> updatedMethods,
            CompilationTestData testData,
            CancellationToken cancellationToken)
        {
            Guid moduleVersionId;
            try
            {
                moduleVersionId = baseline.OriginalMetadata.GetModuleVersionId();
            }
            catch (BadImageFormatException)
            {
                // TODO:
                // return MakeEmitResult(success: false, diagnostics: ..., baseline: null);
                throw;
            }

            var pdbName = FileNameUtilities.ChangeExtension(compilation.SourceModule.Name, "pdb");
            var diagnostics = DiagnosticBag.GetInstance();

            var emitOptions = EmitOptions.Default;
            string runtimeMDVersion = compilation.GetRuntimeMetadataVersion(emitOptions, diagnostics);
            var serializationProperties = compilation.ConstructModuleSerializationProperties(emitOptions, runtimeMDVersion, moduleVersionId);
            var manifestResources = SpecializedCollections.EmptyEnumerable<ResourceDescription>();

            var moduleBeingBuilt = new PEDeltaAssemblyBuilder(
                compilation.SourceAssembly,
                emitOptions: emitOptions,
                outputKind: compilation.Options.OutputKind,
                serializationProperties: serializationProperties,
                manifestResources: manifestResources,
                previousGeneration: baseline,
                edits: edits,
                isAddedSymbol: isAddedSymbol);

            if (testData != null)
            {
                moduleBeingBuilt.SetMethodTestData(testData.Methods);
                testData.Module = moduleBeingBuilt;
            }

            baseline = moduleBeingBuilt.PreviousGeneration;

            var definitionMap = moduleBeingBuilt.PreviousDefinitions;
            var changes = moduleBeingBuilt.Changes;

            if (compilation.Compile(
                moduleBeingBuilt,
                win32Resources: null,
                xmlDocStream: null,
                generateDebugInfo: true,
                diagnostics: diagnostics,
                filterOpt: changes.RequiresCompilation,
                cancellationToken: cancellationToken))
            {
                // Map the definitions from the previous compilation to the current compilation.
                // This must be done after compiling above since synthesized definitions
                // (generated when compiling method bodies) may be required.
                baseline = MapToCompilation(compilation, moduleBeingBuilt);

                using (var pdbWriter = new Cci.PdbWriter(pdbName, pdbStream, (testData != null) ? testData.SymWriterFactory : null))
                {
                    var context = new EmitContext(moduleBeingBuilt, null, diagnostics);
                    var encId = Guid.NewGuid();

                    try
                    {
                        var writer = new DeltaMetadataWriter(
                            context,
                            compilation.MessageProvider,
                            baseline,
                            encId,
                            definitionMap,
                            changes,
                            cancellationToken);

                        Cci.MetadataSizes metadataSizes;
                        writer.WriteMetadataAndIL(pdbWriter, metadataStream, ilStream, out metadataSizes);
                        writer.GetMethodTokens(updatedMethods);

                        bool hasErrors = diagnostics.HasAnyErrors();

                        return new EmitDifferenceResult(
                            success: !hasErrors,
                            diagnostics: diagnostics.ToReadOnlyAndFree(),
                            baseline: hasErrors ? null : writer.GetDelta(baseline, compilation, encId, metadataSizes));
                    }
                    catch (Cci.PdbWritingException e)
                    {
                        diagnostics.Add(ErrorCode.FTL_DebugEmitFailure, Location.None, e.Message);
                    }
                    catch (PermissionSetFileReadException e)
                    {
                        diagnostics.Add(ErrorCode.ERR_PermissionSetAttributeFileReadError, Location.None, e.FileName, e.PropertyName, e.Message);
                    }
                }
            }

            return new EmitDifferenceResult(success: false, diagnostics: diagnostics.ToReadOnlyAndFree(), baseline: null);
        }
Пример #5
0
        internal static EmitDifferenceResult EmitDifference(
            CSharpCompilation compilation,
            EmitBaseline baseline,
            IEnumerable <SemanticEdit> edits,
            Stream metadataStream,
            Stream ilStream,
            Stream pdbStream,
            ICollection <uint> updatedMethodTokens,
            CompilationTestData testData,
            CancellationToken cancellationToken)
        {
            Guid moduleVersionId;

            try
            {
                moduleVersionId = baseline.OriginalMetadata.GetModuleVersionId();
            }
            catch (BadImageFormatException)
            {
                // return MakeEmitResult(success: false, diagnostics: ..., baseline: null);
                throw;
            }

            var pdbName = PathUtilities.ChangeExtension(compilation.SourceModule.Name, "pdb");

            using (var pdbWriter = new Cci.PdbWriter(pdbName, new ComStreamWrapper(pdbStream)))
            {
                var    diagnostics             = DiagnosticBag.GetInstance();
                string runtimeMDVersion        = compilation.GetRuntimeMetadataVersion(diagnostics);
                var    serializationProperties = compilation.ConstructModuleSerializationProperties(runtimeMDVersion, moduleVersionId);
                var    manifestResources       = SpecializedCollections.EmptyEnumerable <ResourceDescription>();

                var moduleBeingBuilt = new PEDeltaAssemblyBuilder(
                    compilation.SourceAssembly,
                    outputName: null,
                    outputKind: compilation.Options.OutputKind,
                    serializationProperties: serializationProperties,
                    manifestResources: manifestResources,
                    assemblySymbolMapper: null,
                    previousGeneration: baseline,
                    edits: edits);

                if (testData != null)
                {
                    moduleBeingBuilt.SetMethodTestData(testData.Methods);
                    testData.Module = moduleBeingBuilt;
                }

                baseline = moduleBeingBuilt.PreviousGeneration;

                var definitionMap = moduleBeingBuilt.PreviousDefinitions;
                var changes       = moduleBeingBuilt.Changes;

                if (compilation.Compile(
                        moduleBeingBuilt,
                        outputName: null,
                        manifestResources: manifestResources,
                        win32Resources: null,
                        xmlDocStream: null,
                        cancellationToken: cancellationToken,
                        metadataOnly: false,
                        generateDebugInfo: true,
                        diagnostics: diagnostics,
                        filter: changes.HasChanged,
                        hasDeclarationErrors: false))
                {
                    var context = new Context((Cci.IModule)moduleBeingBuilt, null, diagnostics);

                    // Map the definitions from the previous compilation to the current compilation.
                    // This must be done after compiling above since synthesized definitions
                    // (generated when compiling method bodies) may be required.
                    baseline = MapToCompilation(compilation, moduleBeingBuilt);

                    var encId  = Guid.NewGuid();
                    var writer = new DeltaPeWriter(
                        context,
                        compilation.MessageProvider,
                        pdbWriter,
                        baseline,
                        encId,
                        definitionMap,
                        changes,
                        cancellationToken);
                    writer.WriteMetadataAndIL(metadataStream, ilStream);
                    writer.GetMethodTokens(updatedMethodTokens);

                    return(new EmitDifferenceResult(
                               success: true,
                               diagnostics: diagnostics.ToReadOnlyAndFree(),
                               baseline: writer.GetDelta(baseline, compilation, encId)));
                }

                return(new EmitDifferenceResult(success: false, diagnostics: diagnostics.ToReadOnlyAndFree(), baseline: null));
            }
        }
Пример #6
0
        /// <summary>
        /// Return a version of the baseline with all definitions mapped to this compilation.
        /// Definitions from the initial generation, from metadata, are not mapped since
        /// the initial generation is always included as metadata. That is, the symbols from
        /// types, methods, ... in the TypesAdded, MethodsAdded, ... collections are replaced
        /// by the corresponding symbols from the current compilation.
        /// </summary>
        private static EmitBaseline MapToCompilation(
            CSharpCompilation compilation,
            PEDeltaAssemblyBuilder moduleBeingBuilt)
        {
            var previousGeneration = moduleBeingBuilt.PreviousGeneration;

            Debug.Assert(previousGeneration.Compilation != compilation);

            if (previousGeneration.Ordinal == 0)
            {
                // Initial generation, nothing to map. (Since the initial generation
                // is always loaded from metadata in the context of the current
                // compilation, there's no separate mapping step.)
                return(previousGeneration);
            }

            var map = new SymbolMatcher(
                moduleBeingBuilt.GetAnonymousTypeMap(),
                ((CSharpCompilation)previousGeneration.Compilation).SourceAssembly,
                new Context((PEModuleBuilder)previousGeneration.PEModuleBuilder, null, new DiagnosticBag()),
                compilation.SourceAssembly,
                new Context((Cci.IModule)moduleBeingBuilt, null, new DiagnosticBag()));

            // Map all definitions to this compilation.
            var typesAdded      = MapDefinitions(map, previousGeneration.TypesAdded);
            var eventsAdded     = MapDefinitions(map, previousGeneration.EventsAdded);
            var fieldsAdded     = MapDefinitions(map, previousGeneration.FieldsAdded);
            var methodsAdded    = MapDefinitions(map, previousGeneration.MethodsAdded);
            var propertiesAdded = MapDefinitions(map, previousGeneration.PropertiesAdded);

            // Map anonymous types to this compilation.
            var anonymousTypeMap = new Dictionary <AnonymousTypeKey, AnonymousTypeValue>();

            foreach (var pair in previousGeneration.AnonymousTypeMap)
            {
                var key   = pair.Key;
                var value = pair.Value;
                var type  = (Cci.ITypeDefinition)map.MapDefinition(value.Type);
                Debug.Assert(type != null);
                anonymousTypeMap.Add(key, new AnonymousTypeValue(value.Name, value.UniqueIndex, type));
            }

            // Map locals (specifically, local types) to this compilation.
            var locals = new Dictionary <uint, ImmutableArray <EncLocalInfo> >();

            foreach (var pair in previousGeneration.LocalsForMethodsAddedOrChanged)
            {
                locals.Add(pair.Key, pair.Value.SelectAsArray((l, m) => MapLocalInfo(m, l), map));
            }

            return(previousGeneration.With(
                       compilation,
                       moduleBeingBuilt,
                       previousGeneration.Ordinal,
                       previousGeneration.EncId,
                       typesAdded,
                       eventsAdded,
                       fieldsAdded,
                       methodsAdded,
                       propertiesAdded,
                       previousGeneration.EventMapAdded,
                       previousGeneration.PropertyMapAdded,
                       previousGeneration.TableEntriesAdded,
                       blobStreamLengthAdded: previousGeneration.BlobStreamLengthAdded,
                       stringStreamLengthAdded: previousGeneration.StringStreamLengthAdded,
                       userStringStreamLengthAdded: previousGeneration.UserStringStreamLengthAdded,
                       guidStreamLengthAdded: previousGeneration.GuidStreamLengthAdded,
                       anonymousTypeMap: anonymousTypeMap,
                       localsForMethodsAddedOrChanged: locals,
                       localNames: previousGeneration.LocalNames));
        }
Пример #7
0
        internal static EmitDifferenceResult EmitDifference(
            CSharpCompilation compilation,
            EmitBaseline baseline,
            IEnumerable <SemanticEdit> edits,
            Func <ISymbol, bool> isAddedSymbol,
            Stream metadataStream,
            Stream ilStream,
            Stream pdbStream,
            ICollection <MethodDefinitionHandle> updatedMethods,
            CompilationTestData testData,
            CancellationToken cancellationToken)
        {
            Guid moduleVersionId;

            try
            {
                moduleVersionId = baseline.OriginalMetadata.GetModuleVersionId();
            }
            catch (BadImageFormatException)
            {
                // TODO:
                // return MakeEmitResult(success: false, diagnostics: ..., baseline: null);
                throw;
            }

            var pdbName     = FileNameUtilities.ChangeExtension(compilation.SourceModule.Name, "pdb");
            var diagnostics = DiagnosticBag.GetInstance();

            var    emitOptions             = EmitOptions.Default;
            string runtimeMDVersion        = compilation.GetRuntimeMetadataVersion(emitOptions, diagnostics);
            var    serializationProperties = compilation.ConstructModuleSerializationProperties(emitOptions, runtimeMDVersion, moduleVersionId);
            var    manifestResources       = SpecializedCollections.EmptyEnumerable <ResourceDescription>();

            var moduleBeingBuilt = new PEDeltaAssemblyBuilder(
                compilation.SourceAssembly,
                emitOptions: emitOptions,
                outputKind: compilation.Options.OutputKind,
                serializationProperties: serializationProperties,
                manifestResources: manifestResources,
                previousGeneration: baseline,
                edits: edits,
                isAddedSymbol: isAddedSymbol);

            if (testData != null)
            {
                moduleBeingBuilt.SetMethodTestData(testData.Methods);
                testData.Module = moduleBeingBuilt;
            }

            baseline = moduleBeingBuilt.PreviousGeneration;

            var definitionMap = moduleBeingBuilt.PreviousDefinitions;
            var changes       = moduleBeingBuilt.Changes;

            if (compilation.Compile(
                    moduleBeingBuilt,
                    win32Resources: null,
                    xmlDocStream: null,
                    generateDebugInfo: true,
                    diagnostics: diagnostics,
                    filterOpt: changes.RequiresCompilation,
                    cancellationToken: cancellationToken))
            {
                // Map the definitions from the previous compilation to the current compilation.
                // This must be done after compiling above since synthesized definitions
                // (generated when compiling method bodies) may be required.
                baseline = MapToCompilation(compilation, moduleBeingBuilt);

                var pdbOutputInfo = new Cci.PdbOutputInfo(pdbName, pdbStream);
                using (var pdbWriter = new Cci.PdbWriter(pdbOutputInfo, (testData != null) ? testData.SymWriterFactory : null))
                {
                    var context = new EmitContext(moduleBeingBuilt, null, diagnostics);
                    var encId   = Guid.NewGuid();

                    try
                    {
                        var writer = new DeltaMetadataWriter(
                            context,
                            compilation.MessageProvider,
                            baseline,
                            encId,
                            definitionMap,
                            changes,
                            cancellationToken);

                        Cci.MetadataSizes metadataSizes;
                        writer.WriteMetadataAndIL(pdbWriter, metadataStream, ilStream, out metadataSizes);
                        writer.GetMethodTokens(updatedMethods);

                        bool hasErrors = diagnostics.HasAnyErrors();

                        return(new EmitDifferenceResult(
                                   success: !hasErrors,
                                   diagnostics: diagnostics.ToReadOnlyAndFree(),
                                   baseline: hasErrors ? null : writer.GetDelta(baseline, compilation, encId, metadataSizes)));
                    }
                    catch (Cci.PdbWritingException e)
                    {
                        diagnostics.Add(ErrorCode.FTL_DebugEmitFailure, Location.None, e.Message);
                    }
                    catch (PermissionSetFileReadException e)
                    {
                        diagnostics.Add(ErrorCode.ERR_PermissionSetAttributeFileReadError, Location.None, e.FileName, e.PropertyName, e.Message);
                    }
                }
            }

            return(new EmitDifferenceResult(success: false, diagnostics: diagnostics.ToReadOnlyAndFree(), baseline: null));
        }
Пример #8
0
        /// <summary>
        /// Return a version of the baseline with all definitions mapped to this compilation.
        /// Definitions from the initial generation, from metadata, are not mapped since
        /// the initial generation is always included as metadata. That is, the symbols from
        /// types, methods, ... in the TypesAdded, MethodsAdded, ... collections are replaced
        /// by the corresponding symbols from the current compilation.
        /// </summary>
        private static EmitBaseline MapToCompilation(
            CSharpCompilation compilation,
            PEDeltaAssemblyBuilder moduleBeingBuilt
            )
        {
            var previousGeneration = moduleBeingBuilt.PreviousGeneration;

            RoslynDebug.Assert(previousGeneration.Compilation != compilation);

            if (previousGeneration.Ordinal == 0)
            {
                // Initial generation, nothing to map. (Since the initial generation
                // is always loaded from metadata in the context of the current
                // compilation, there's no separate mapping step.)
                return(previousGeneration);
            }

            RoslynDebug.AssertNotNull(previousGeneration.Compilation);
            RoslynDebug.AssertNotNull(previousGeneration.PEModuleBuilder);

            var currentSynthesizedMembers = moduleBeingBuilt.GetAllSynthesizedMembers();

            // Mapping from previous compilation to the current.
            var anonymousTypeMap = moduleBeingBuilt.GetAnonymousTypeMap();
            var sourceAssembly   = ((CSharpCompilation)previousGeneration.Compilation).SourceAssembly;
            var sourceContext    = new EmitContext(
                (PEModuleBuilder)previousGeneration.PEModuleBuilder,
                null,
                new DiagnosticBag(),
                metadataOnly: false,
                includePrivateMembers: true
                );
            var otherContext = new EmitContext(
                moduleBeingBuilt,
                null,
                new DiagnosticBag(),
                metadataOnly: false,
                includePrivateMembers: true
                );

            var matcher = new CSharpSymbolMatcher(
                anonymousTypeMap,
                sourceAssembly,
                sourceContext,
                compilation.SourceAssembly,
                otherContext,
                currentSynthesizedMembers
                );

            var mappedSynthesizedMembers = matcher.MapSynthesizedMembers(
                previousGeneration.SynthesizedMembers,
                currentSynthesizedMembers
                );

            // TODO: can we reuse some data from the previous matcher?
            var matcherWithAllSynthesizedMembers = new CSharpSymbolMatcher(
                anonymousTypeMap,
                sourceAssembly,
                sourceContext,
                compilation.SourceAssembly,
                otherContext,
                mappedSynthesizedMembers
                );

            return(matcherWithAllSynthesizedMembers.MapBaselineToCompilation(
                       previousGeneration,
                       compilation,
                       moduleBeingBuilt,
                       mappedSynthesizedMembers
                       ));
        }
Пример #9
0
        internal static EmitDifferenceResult EmitDifference(
            CSharpCompilation compilation,
            EmitBaseline baseline,
            IEnumerable <SemanticEdit> edits,
            Func <ISymbol, bool> isAddedSymbol,
            Stream metadataStream,
            Stream ilStream,
            Stream pdbStream,
            ICollection <MethodDefinitionHandle> updatedMethods,
            CompilationTestData testData,
            CancellationToken cancellationToken)
        {
            Guid moduleVersionId;

            try
            {
                moduleVersionId = baseline.OriginalMetadata.GetModuleVersionId();
            }
            catch (BadImageFormatException)
            {
                // TODO:
                // return MakeEmitResult(success: false, diagnostics: ..., baseline: null);
                throw;
            }

            var diagnostics = DiagnosticBag.GetInstance();

            var    emitOptions             = EmitOptions.Default;
            string runtimeMDVersion        = compilation.GetRuntimeMetadataVersion(emitOptions, diagnostics);
            var    serializationProperties = compilation.ConstructModuleSerializationProperties(emitOptions, runtimeMDVersion, moduleVersionId);
            var    manifestResources       = SpecializedCollections.EmptyEnumerable <ResourceDescription>();

            var moduleBeingBuilt = new PEDeltaAssemblyBuilder(
                compilation.SourceAssembly,
                emitOptions: emitOptions,
                outputKind: compilation.Options.OutputKind,
                serializationProperties: serializationProperties,
                manifestResources: manifestResources,
                previousGeneration: baseline,
                edits: edits,
                isAddedSymbol: isAddedSymbol);

            if (testData != null)
            {
                moduleBeingBuilt.SetMethodTestData(testData.Methods);
                testData.Module = moduleBeingBuilt;
            }

            var definitionMap = moduleBeingBuilt.PreviousDefinitions;
            var changes       = moduleBeingBuilt.Changes;

            EmitBaseline newBaseline = null;

            if (compilation.Compile(
                    moduleBeingBuilt,
                    win32Resources: null,
                    xmlDocStream: null,
                    generateDebugInfo: true,
                    diagnostics: diagnostics,
                    filterOpt: changes.RequiresCompilation,
                    cancellationToken: cancellationToken))
            {
                // Map the definitions from the previous compilation to the current compilation.
                // This must be done after compiling above since synthesized definitions
                // (generated when compiling method bodies) may be required.
                var mappedBaseline = MapToCompilation(compilation, moduleBeingBuilt);

                newBaseline = compilation.SerializeToDeltaStreams(
                    moduleBeingBuilt,
                    mappedBaseline,
                    definitionMap,
                    changes,
                    metadataStream,
                    ilStream,
                    pdbStream,
                    updatedMethods,
                    diagnostics,
                    testData?.SymWriterFactory,
                    cancellationToken);
            }

            return(new EmitDifferenceResult(
                       success: newBaseline != null,
                       diagnostics: diagnostics.ToReadOnlyAndFree(),
                       baseline: newBaseline));
        }