private static IReadOnlyDictionary <K, V> MapDefinitions <K, V>( SymbolMatcher 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); }
/// <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)); }