Example #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;

            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 synthesizedDelegates = moduleBeingBuilt.GetSynthesizedDelegates();
            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,
                synthesizedDelegates,
                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,
                synthesizedDelegates,
                sourceAssembly,
                sourceContext,
                compilation.SourceAssembly,
                otherContext,
                mappedSynthesizedMembers);

            return(matcherWithAllSynthesizedMembers.MapBaselineToCompilation(
                       previousGeneration,
                       compilation,
                       moduleBeingBuilt,
                       mappedSynthesizedMembers));
        }
Example #2
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);
        }
Example #3
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 EmitContext((PEModuleBuilder)previousGeneration.PEModuleBuilder, null, new DiagnosticBag()),
                compilation.SourceAssembly,
                new EmitContext((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,
                       eventMapAdded: previousGeneration.EventMapAdded,
                       propertyMapAdded: previousGeneration.PropertyMapAdded,
                       methodImplsAdded: previousGeneration.MethodImplsAdded,
                       tableEntriesAdded: previousGeneration.TableEntriesAdded,
                       blobStreamLengthAdded: previousGeneration.BlobStreamLengthAdded,
                       stringStreamLengthAdded: previousGeneration.StringStreamLengthAdded,
                       userStringStreamLengthAdded: previousGeneration.UserStringStreamLengthAdded,
                       guidStreamLengthAdded: previousGeneration.GuidStreamLengthAdded,
                       anonymousTypeMap: anonymousTypeMap,
                       localsForMethodsAddedOrChanged: locals,
                       localNames: previousGeneration.LocalNames));
        }