示例#1
0
        public PEDeltaAssemblyBuilder(
            SourceAssemblySymbol sourceAssembly,
            string outputName,
            OutputKind outputKind,
            ModulePropertiesForSerialization serializationProperties,
            IEnumerable <ResourceDescription> manifestResources,
            Func <AssemblySymbol, AssemblyIdentity> assemblySymbolMapper,
            EmitBaseline previousGeneration,
            IEnumerable <SemanticEdit> edits)
            : base(sourceAssembly, outputName, outputKind, serializationProperties, manifestResources, assemblySymbolMapper, additionalTypes: ImmutableArray <NamedTypeSymbol> .Empty, metadataOnly: false)
        {
            var context          = new EmitContext(this, null, new DiagnosticBag());
            var module           = previousGeneration.OriginalMetadata;
            var compilation      = sourceAssembly.DeclaringCompilation;
            var metadataAssembly = compilation.GetBoundReferenceManager().CreatePEAssemblyForAssemblyMetadata(AssemblyMetadata.Create(module), MetadataImportOptions.All);
            var metadataDecoder  = new Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE.MetadataDecoder(metadataAssembly.PrimaryModule);

            previousGeneration = EnsureInitialized(previousGeneration, metadataDecoder);

            var matchToMetadata = new CSharpSymbolMatcher(previousGeneration.AnonymousTypeMap, sourceAssembly, context, metadataAssembly);

            CSharpSymbolMatcher matchToPrevious = null;

            if (previousGeneration.Ordinal > 0)
            {
                var previousAssembly = ((CSharpCompilation)previousGeneration.Compilation).SourceAssembly;
                var previousContext  = new EmitContext((PEModuleBuilder)previousGeneration.PEModuleBuilder, null, new DiagnosticBag());
                matchToPrevious = new CSharpSymbolMatcher(previousGeneration.AnonymousTypeMap, sourceAssembly, context, previousAssembly, previousContext);
            }

            this.previousDefinitions = new CSharpDefinitionMap(previousGeneration.OriginalMetadata.Module, edits, metadataDecoder, matchToMetadata, matchToPrevious);
            this.previousGeneration  = previousGeneration;
            this.changes             = new SymbolChanges(this.previousDefinitions, edits);
        }
        public PEDeltaAssemblyBuilder(
            SourceAssemblySymbol sourceAssembly,
            EmitOptions emitOptions,
            OutputKind outputKind,
            Cci.ModulePropertiesForSerialization serializationProperties,
            IEnumerable <ResourceDescription> manifestResources,
            EmitBaseline previousGeneration,
            IEnumerable <SemanticEdit> edits,
            Func <ISymbol, bool> isAddedSymbol)
            : base(sourceAssembly, emitOptions, outputKind, serializationProperties, manifestResources, additionalTypes: ImmutableArray <NamedTypeSymbol> .Empty)
        {
            var initialBaseline = previousGeneration.InitialBaseline;
            var context         = new EmitContext(this, null, new DiagnosticBag(), metadataOnly: false, includePrivateMembers: true);

            // Hydrate symbols from initial metadata. Once we do so it is important to reuse these symbols across all generations,
            // in order for the symbol matcher to be able to use reference equality once it maps symbols to initial metadata.
            var metadataSymbols  = GetOrCreateMetadataSymbols(initialBaseline, sourceAssembly.DeclaringCompilation);
            var metadataDecoder  = (MetadataDecoder)metadataSymbols.MetadataDecoder;
            var metadataAssembly = (PEAssemblySymbol)metadataDecoder.ModuleSymbol.ContainingAssembly;

            var matchToMetadata = new CSharpSymbolMatcher(metadataSymbols.AnonymousTypes, metadataSymbols.SynthesizedDelegates, sourceAssembly, context, metadataAssembly);

            CSharpSymbolMatcher?matchToPrevious = null;

            if (previousGeneration.Ordinal > 0)
            {
                RoslynDebug.AssertNotNull(previousGeneration.Compilation);
                RoslynDebug.AssertNotNull(previousGeneration.PEModuleBuilder);

                var previousAssembly = ((CSharpCompilation)previousGeneration.Compilation).SourceAssembly;
                var previousContext  = new EmitContext((PEModuleBuilder)previousGeneration.PEModuleBuilder, null, new DiagnosticBag(), metadataOnly: false, includePrivateMembers: true);

                matchToPrevious = new CSharpSymbolMatcher(
                    previousGeneration.AnonymousTypeMap,
                    previousGeneration.SynthesizedDelegates,
                    sourceAssembly: sourceAssembly,
                    sourceContext: context,
                    otherAssembly: previousAssembly,
                    otherContext: previousContext,
                    otherSynthesizedMembersOpt: previousGeneration.SynthesizedMembers);
            }

            _previousDefinitions = new CSharpDefinitionMap(edits, metadataDecoder, matchToMetadata, matchToPrevious);
            _previousGeneration  = previousGeneration;
            _changes             = new CSharpSymbolChanges(_previousDefinitions, edits, isAddedSymbol);

            // Workaround for https://github.com/dotnet/roslyn/issues/3192.
            // When compiling state machine we stash types of awaiters and state-machine hoisted variables,
            // so that next generation can look variables up and reuse their slots if possible.
            //
            // When we are about to allocate a slot for a lifted variable while compiling the next generation
            // we map its type to the previous generation and then check the slot types that we stashed earlier.
            // If the variable type matches we reuse it. In order to compare the previous variable type with the current one
            // both need to be completely lowered (translated). Standard translation only goes one level deep.
            // Generic arguments are not translated until they are needed by metadata writer.
            //
            // In order to get the fully lowered form we run the type symbols of stashed variables through a deep translator
            // that translates the symbol recursively.
            _deepTranslator = new CSharpSymbolMatcher.DeepTranslator(sourceAssembly.GetSpecialType(SpecialType.System_Object));
        }
示例#3
0
 public CSharpDefinitionMap(
     IEnumerable <SemanticEdit> edits,
     MetadataDecoder metadataDecoder,
     CSharpSymbolMatcher mapToMetadata,
     CSharpSymbolMatcher mapToPrevious)
     : base(edits, mapToMetadata, mapToPrevious)
 {
     Debug.Assert(metadataDecoder != null);
     _metadataDecoder = metadataDecoder;
 }
示例#4
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));
        }
 public CSharpDefinitionMap(
     IEnumerable <SemanticEdit> edits,
     MetadataDecoder metadataDecoder,
     CSharpSymbolMatcher mapToMetadata,
     CSharpSymbolMatcher?mapToPrevious)
     : base(edits)
 {
     _metadataDecoder = metadataDecoder;
     _mapToMetadata   = mapToMetadata;
     _mapToPrevious   = mapToPrevious ?? mapToMetadata;
 }
示例#6
0
        public CSharpDefinitionMap(
            PEModule module,
            IEnumerable <SemanticEdit> edits,
            MetadataDecoder metadataDecoder,
            CSharpSymbolMatcher mapToMetadata,
            CSharpSymbolMatcher mapToPrevious)
            : base(module, edits)
        {
            Debug.Assert(mapToMetadata != null);
            Debug.Assert(metadataDecoder != null);

            this.mapToMetadata   = mapToMetadata;
            this.mapToPrevious   = mapToPrevious ?? mapToMetadata;
            this.metadataDecoder = metadataDecoder;
        }
示例#7
0
 private static EncLocalInfo MapLocalInfo(
     CSharpSymbolMatcher map,
     EncLocalInfo localInfo)
 {
     Debug.Assert(!localInfo.IsDefault);
     if (localInfo.Type == null)
     {
         Debug.Assert(localInfo.Signature != null);
         return(localInfo);
     }
     else
     {
         var type = map.MapReference(localInfo.Type);
         Debug.Assert(type != null);
         return(new EncLocalInfo(localInfo.Offset, type, localInfo.Constraints, localInfo.SynthesizedKind, localInfo.Signature));
     }
 }
        public PEDeltaAssemblyBuilder(
            SourceAssemblySymbol sourceAssembly,
            EmitOptions emitOptions,
            OutputKind outputKind,
            ModulePropertiesForSerialization serializationProperties,
            IEnumerable <ResourceDescription> manifestResources,
            EmitBaseline previousGeneration,
            IEnumerable <SemanticEdit> edits,
            Func <ISymbol, bool> isAddedSymbol)
            : base(sourceAssembly, emitOptions, outputKind, serializationProperties, manifestResources, assemblySymbolMapper: null, additionalTypes: ImmutableArray <NamedTypeSymbol> .Empty)
        {
            var initialBaseline  = previousGeneration.InitialBaseline;
            var context          = new EmitContext(this, null, new DiagnosticBag());
            var module           = previousGeneration.OriginalMetadata;
            var compilation      = sourceAssembly.DeclaringCompilation;
            var metadataAssembly = compilation.GetBoundReferenceManager().CreatePEAssemblyForAssemblyMetadata(AssemblyMetadata.Create(module), MetadataImportOptions.All);
            var metadataDecoder  = new Symbols.Metadata.PE.MetadataDecoder(metadataAssembly.PrimaryModule);

            if (initialBaseline.LazyOriginalMetadataAnonymousTypeMap == null)
            {
                initialBaseline.LazyOriginalMetadataAnonymousTypeMap = GetAnonymousTypeMapFromMetadata(module.MetadataReader, metadataDecoder);
            }

            var matchToMetadata = new CSharpSymbolMatcher(initialBaseline.LazyOriginalMetadataAnonymousTypeMap, sourceAssembly, context, metadataAssembly);

            CSharpSymbolMatcher matchToPrevious = null;

            if (previousGeneration.Ordinal > 0)
            {
                var previousAssembly = ((CSharpCompilation)previousGeneration.Compilation).SourceAssembly;
                var previousContext  = new EmitContext((PEModuleBuilder)previousGeneration.PEModuleBuilder, null, new DiagnosticBag());

                matchToPrevious = new CSharpSymbolMatcher(
                    previousGeneration.AnonymousTypeMap,
                    sourceAssembly: sourceAssembly,
                    sourceContext: context,
                    otherAssembly: previousAssembly,
                    otherContext: previousContext,
                    otherSynthesizedMembersOpt: previousGeneration.SynthesizedMembers);
            }

            _previousDefinitions = new CSharpDefinitionMap(previousGeneration.OriginalMetadata.Module, edits, metadataDecoder, matchToMetadata, matchToPrevious);
            _previousGeneration  = previousGeneration;
            _changes             = new SymbolChanges(_previousDefinitions, edits, isAddedSymbol);
        }
示例#9
0
        private static IReadOnlyDictionary <K, V> MapDefinitions <K, V>(
            CSharpSymbolMatcher map,
            IReadOnlyDictionary <K, V> items)
            where K : Cci.IDefinition
        {
            var result = new Dictionary <K, V>();

            foreach (var pair in items)
            {
                var key = (K)map.MapDefinition(pair.Key);
                // Result may be null if the definition was deleted, or if the definition
                // was synthesized (e.g.: an iterator type) and the method that generated
                // the synthesized definition was unchanged and not recompiled.
                if (key != null)
                {
                    result.Add(key, pair.Value);
                }
            }
            return(result);
        }
示例#10
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 CSharpSymbolMatcher(
                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));
        }