1447 lines
51 KiB
C#
1447 lines
51 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Collections.Immutable;
|
|
using System.Linq;
|
|
using System.Reflection.Metadata;
|
|
using System.Reflection.Metadata.Ecma335;
|
|
using System.Threading;
|
|
using Microsoft.Cci;
|
|
using Microsoft.CodeAnalysis.Emit.EditAndContinue;
|
|
using Microsoft.CodeAnalysis.PooledObjects;
|
|
using Microsoft.CodeAnalysis.Symbols;
|
|
using Roslyn.Utilities;
|
|
|
|
namespace Microsoft.CodeAnalysis.Emit;
|
|
|
|
internal sealed class DeltaMetadataWriter : MetadataWriter
|
|
{
|
|
private abstract class DefinitionIndexBase<T> where T : notnull
|
|
{
|
|
protected readonly Dictionary<T, int> added;
|
|
|
|
protected readonly List<T> rows;
|
|
|
|
private readonly int _firstRowId;
|
|
|
|
private bool _frozen;
|
|
|
|
public int FirstRowId => _firstRowId;
|
|
|
|
public int NextRowId => added.Count + _firstRowId;
|
|
|
|
public bool IsFrozen => _frozen;
|
|
|
|
public DefinitionIndexBase(int lastRowId, IEqualityComparer<T>? comparer = null)
|
|
{
|
|
added = new Dictionary<T, int>(comparer);
|
|
rows = new List<T>();
|
|
_firstRowId = lastRowId + 1;
|
|
}
|
|
|
|
public abstract bool TryGetRowId(T item, out int rowId);
|
|
|
|
public int GetRowId(T item)
|
|
{
|
|
TryGetRowId(item, out var rowId);
|
|
return rowId;
|
|
}
|
|
|
|
public bool Contains(T item)
|
|
{
|
|
int rowId;
|
|
return TryGetRowId(item, out rowId);
|
|
}
|
|
|
|
public IReadOnlyDictionary<T, int> GetAdded()
|
|
{
|
|
Freeze();
|
|
return added;
|
|
}
|
|
|
|
public IReadOnlyList<T> GetRows()
|
|
{
|
|
Freeze();
|
|
return rows;
|
|
}
|
|
|
|
protected virtual void OnFrozen()
|
|
{
|
|
}
|
|
|
|
private void Freeze()
|
|
{
|
|
if (!_frozen)
|
|
{
|
|
_frozen = true;
|
|
OnFrozen();
|
|
}
|
|
}
|
|
}
|
|
|
|
private sealed class DefinitionIndex<T> : DefinitionIndexBase<T> where T : class, IDefinition
|
|
{
|
|
public delegate bool TryGetExistingIndex(T item, out int index);
|
|
|
|
private readonly TryGetExistingIndex _tryGetExistingIndex;
|
|
|
|
private readonly Dictionary<int, T> _map;
|
|
|
|
public DefinitionIndex(TryGetExistingIndex tryGetExistingIndex, int lastRowId)
|
|
: base(lastRowId, (IEqualityComparer<T>?)Roslyn.Utilities.ReferenceEqualityComparer.Instance)
|
|
{
|
|
_tryGetExistingIndex = tryGetExistingIndex;
|
|
_map = new Dictionary<int, T>();
|
|
}
|
|
|
|
public override bool TryGetRowId(T item, out int index)
|
|
{
|
|
if (added.TryGetValue(item, out index))
|
|
{
|
|
return true;
|
|
}
|
|
if (_tryGetExistingIndex(item, out index))
|
|
{
|
|
_map[index] = item;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public T GetDefinition(int rowId)
|
|
{
|
|
return _map[rowId];
|
|
}
|
|
|
|
public void Add(T item)
|
|
{
|
|
int nextRowId = base.NextRowId;
|
|
added.Add(item, nextRowId);
|
|
_map[nextRowId] = item;
|
|
rows.Add(item);
|
|
}
|
|
|
|
public void AddUpdated(T item)
|
|
{
|
|
rows.Add(item);
|
|
}
|
|
|
|
public bool IsAddedNotChanged(T item)
|
|
{
|
|
return added.ContainsKey(item);
|
|
}
|
|
|
|
protected override void OnFrozen()
|
|
{
|
|
rows.Sort((T x, T y) => GetRowId(x).CompareTo(GetRowId(y)));
|
|
}
|
|
}
|
|
|
|
private sealed class GenericParameterIndex : DefinitionIndexBase<IGenericParameter>
|
|
{
|
|
public GenericParameterIndex(int lastRowId)
|
|
: base(lastRowId, (IEqualityComparer<IGenericParameter>?)Roslyn.Utilities.ReferenceEqualityComparer.Instance)
|
|
{
|
|
}
|
|
|
|
public override bool TryGetRowId(IGenericParameter item, out int index)
|
|
{
|
|
return added.TryGetValue(item, out index);
|
|
}
|
|
|
|
public void Add(IGenericParameter item)
|
|
{
|
|
int nextRowId = base.NextRowId;
|
|
added.Add(item, nextRowId);
|
|
rows.Add(item);
|
|
}
|
|
}
|
|
|
|
private sealed class EventOrPropertyMapIndex : DefinitionIndexBase<int>
|
|
{
|
|
public delegate bool TryGetExistingIndex(int item, out int index);
|
|
|
|
private readonly TryGetExistingIndex _tryGetExistingIndex;
|
|
|
|
public EventOrPropertyMapIndex(TryGetExistingIndex tryGetExistingIndex, int lastRowId)
|
|
: base(lastRowId, (IEqualityComparer<int>?)null)
|
|
{
|
|
_tryGetExistingIndex = tryGetExistingIndex;
|
|
}
|
|
|
|
public override bool TryGetRowId(int item, out int index)
|
|
{
|
|
if (added.TryGetValue(item, out index))
|
|
{
|
|
return true;
|
|
}
|
|
if (_tryGetExistingIndex(item, out index))
|
|
{
|
|
return true;
|
|
}
|
|
index = 0;
|
|
return false;
|
|
}
|
|
|
|
public void Add(int item)
|
|
{
|
|
int nextRowId = base.NextRowId;
|
|
added.Add(item, nextRowId);
|
|
rows.Add(item);
|
|
}
|
|
}
|
|
|
|
private sealed class MethodImplIndex : DefinitionIndexBase<MethodImplKey>
|
|
{
|
|
private readonly DeltaMetadataWriter _writer;
|
|
|
|
public MethodImplIndex(DeltaMetadataWriter writer, int lastRowId)
|
|
: base(lastRowId, (IEqualityComparer<MethodImplKey>?)null)
|
|
{
|
|
_writer = writer;
|
|
}
|
|
|
|
public override bool TryGetRowId(MethodImplKey item, out int index)
|
|
{
|
|
if (added.TryGetValue(item, out index))
|
|
{
|
|
return true;
|
|
}
|
|
if (_writer.TryGetExistingMethodImplIndex(item, out index))
|
|
{
|
|
return true;
|
|
}
|
|
index = 0;
|
|
return false;
|
|
}
|
|
|
|
public void Add(MethodImplKey item)
|
|
{
|
|
int nextRowId = base.NextRowId;
|
|
added.Add(item, nextRowId);
|
|
rows.Add(item);
|
|
}
|
|
}
|
|
|
|
private sealed class DeltaReferenceIndexer : ReferenceIndexer
|
|
{
|
|
private readonly SymbolChanges _changes;
|
|
|
|
private readonly IReadOnlyDictionary<ITypeDefinition, ImmutableArray<DeletedMethodDefinition>> _deletedTypeMembers;
|
|
|
|
public DeltaReferenceIndexer(DeltaMetadataWriter writer)
|
|
: base(writer)
|
|
{
|
|
_changes = writer._changes;
|
|
_deletedTypeMembers = writer._deletedTypeMembers;
|
|
}
|
|
|
|
public override void Visit(CommonPEModuleBuilder module)
|
|
{
|
|
Visit(module.GetTopLevelTypeDefinitions(metadataWriter.Context));
|
|
}
|
|
|
|
public override void Visit(IEventDefinition eventDefinition)
|
|
{
|
|
base.Visit(eventDefinition);
|
|
}
|
|
|
|
public override void Visit(IFieldDefinition fieldDefinition)
|
|
{
|
|
base.Visit(fieldDefinition);
|
|
}
|
|
|
|
public override void Visit(ILocalDefinition localDefinition)
|
|
{
|
|
if (localDefinition.Signature == null)
|
|
{
|
|
base.Visit(localDefinition);
|
|
}
|
|
}
|
|
|
|
public override void Visit(IMethodDefinition method)
|
|
{
|
|
base.Visit(method);
|
|
}
|
|
|
|
public override void Visit(Microsoft.Cci.MethodImplementation methodImplementation)
|
|
{
|
|
IMethodDefinition def = (IMethodDefinition)methodImplementation.ImplementingMethod.AsDefinition(Context);
|
|
if (_changes.GetChange(def) == SymbolChange.Added)
|
|
{
|
|
base.Visit(methodImplementation);
|
|
}
|
|
}
|
|
|
|
public override void Visit(INamespaceTypeDefinition namespaceTypeDefinition)
|
|
{
|
|
base.Visit(namespaceTypeDefinition);
|
|
}
|
|
|
|
public override void Visit(INestedTypeDefinition nestedTypeDefinition)
|
|
{
|
|
base.Visit(nestedTypeDefinition);
|
|
}
|
|
|
|
public override void Visit(IPropertyDefinition propertyDefinition)
|
|
{
|
|
base.Visit(propertyDefinition);
|
|
}
|
|
|
|
public override void Visit(ITypeDefinition typeDefinition)
|
|
{
|
|
if (ShouldVisit(typeDefinition))
|
|
{
|
|
base.Visit(typeDefinition);
|
|
if (_deletedTypeMembers.TryGetValue(typeDefinition, out ImmutableArray<DeletedMethodDefinition> value))
|
|
{
|
|
Visit(value);
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void Visit(ITypeDefinitionMember typeMember)
|
|
{
|
|
if (ShouldVisit(typeMember))
|
|
{
|
|
base.Visit(typeMember);
|
|
}
|
|
}
|
|
|
|
private bool ShouldVisit(IDefinition def)
|
|
{
|
|
if (!(def is DeletedMethodDefinition))
|
|
{
|
|
return _changes.GetChange(def) != SymbolChange.None;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
private readonly EmitBaseline _previousGeneration;
|
|
|
|
private readonly Guid _encId;
|
|
|
|
private readonly DefinitionMap _definitionMap;
|
|
|
|
private readonly SymbolChanges _changes;
|
|
|
|
private readonly List<ITypeDefinition> _changedTypeDefs;
|
|
|
|
private readonly Dictionary<ITypeDefinition, DeletedTypeDefinition> _typesUsedByDeletedMembers;
|
|
|
|
private readonly Dictionary<ITypeDefinition, ImmutableArray<DeletedMethodDefinition>> _deletedTypeMembers;
|
|
|
|
private readonly DefinitionIndex<ITypeDefinition> _typeDefs;
|
|
|
|
private readonly DefinitionIndex<IEventDefinition> _eventDefs;
|
|
|
|
private readonly DefinitionIndex<IFieldDefinition> _fieldDefs;
|
|
|
|
private readonly DefinitionIndex<IMethodDefinition> _methodDefs;
|
|
|
|
private readonly DefinitionIndex<IPropertyDefinition> _propertyDefs;
|
|
|
|
private readonly DefinitionIndex<IParameterDefinition> _parameterDefs;
|
|
|
|
private readonly Dictionary<IParameterDefinition, IMethodDefinition> _parameterDefList;
|
|
|
|
private readonly GenericParameterIndex _genericParameters;
|
|
|
|
private readonly EventOrPropertyMapIndex _eventMap;
|
|
|
|
private readonly EventOrPropertyMapIndex _propertyMap;
|
|
|
|
private readonly MethodImplIndex _methodImpls;
|
|
|
|
private readonly Dictionary<EntityHandle, int> _customAttributeParentCounts;
|
|
|
|
private readonly Dictionary<EntityHandle, ImmutableArray<int>> _customAttributesAdded;
|
|
|
|
private readonly Dictionary<IParameterDefinition, int> _existingParameterDefs;
|
|
|
|
private readonly Dictionary<MethodDefinitionHandle, int> _firstParamRowMap;
|
|
|
|
private readonly HeapOrReferenceIndex<AssemblyIdentity> _assemblyRefIndex;
|
|
|
|
private readonly HeapOrReferenceIndex<string> _moduleRefIndex;
|
|
|
|
private readonly InstanceAndStructuralReferenceIndex<ITypeMemberReference> _memberRefIndex;
|
|
|
|
private readonly InstanceAndStructuralReferenceIndex<IGenericMethodInstanceReference> _methodSpecIndex;
|
|
|
|
private readonly TypeReferenceIndex _typeRefIndex;
|
|
|
|
private readonly InstanceAndStructuralReferenceIndex<ITypeReference> _typeSpecIndex;
|
|
|
|
private readonly HeapOrReferenceIndex<BlobHandle> _standAloneSignatureIndex;
|
|
|
|
private readonly Dictionary<IMethodDefinition, AddedOrChangedMethodInfo> _addedOrChangedMethods;
|
|
|
|
protected override ushort Generation => (ushort)(_previousGeneration.Ordinal + 1);
|
|
|
|
protected override Guid EncId => _encId;
|
|
|
|
protected override Guid EncBaseId => _previousGeneration.EncId;
|
|
|
|
protected override int GreatestMethodDefIndex => _methodDefs.NextRowId;
|
|
|
|
public DeltaMetadataWriter(EmitContext context, CommonMessageProvider messageProvider, EmitBaseline previousGeneration, Guid encId, DefinitionMap definitionMap, SymbolChanges changes, CancellationToken cancellationToken)
|
|
: base(MakeTablesBuilder(previousGeneration), (context.Module.DebugInformationFormat == DebugInformationFormat.PortablePdb) ? new MetadataBuilder() : null, null, context, messageProvider, metadataOnly: false, deterministic: false, emitTestCoverageData: false, cancellationToken)
|
|
{
|
|
_previousGeneration = previousGeneration;
|
|
_encId = encId;
|
|
_definitionMap = definitionMap;
|
|
_changes = changes;
|
|
ImmutableArray<int> tableSizes = previousGeneration.TableSizes;
|
|
_changedTypeDefs = new List<ITypeDefinition>();
|
|
_typesUsedByDeletedMembers = new Dictionary<ITypeDefinition, DeletedTypeDefinition>(Roslyn.Utilities.ReferenceEqualityComparer.Instance);
|
|
_deletedTypeMembers = new Dictionary<ITypeDefinition, ImmutableArray<DeletedMethodDefinition>>(Roslyn.Utilities.ReferenceEqualityComparer.Instance);
|
|
_typeDefs = new DefinitionIndex<ITypeDefinition>(TryGetExistingTypeDefIndex, tableSizes[2]);
|
|
_eventDefs = new DefinitionIndex<IEventDefinition>(TryGetExistingEventDefIndex, tableSizes[20]);
|
|
_fieldDefs = new DefinitionIndex<IFieldDefinition>(TryGetExistingFieldDefIndex, tableSizes[4]);
|
|
_methodDefs = new DefinitionIndex<IMethodDefinition>(TryGetExistingMethodDefIndex, tableSizes[6]);
|
|
_propertyDefs = new DefinitionIndex<IPropertyDefinition>(TryGetExistingPropertyDefIndex, tableSizes[23]);
|
|
_parameterDefs = new DefinitionIndex<IParameterDefinition>(TryGetExistingParameterDefIndex, tableSizes[8]);
|
|
_parameterDefList = new Dictionary<IParameterDefinition, IMethodDefinition>(SymbolEquivalentEqualityComparer.Instance);
|
|
_genericParameters = new GenericParameterIndex(tableSizes[42]);
|
|
_eventMap = new EventOrPropertyMapIndex(TryGetExistingEventMapIndex, tableSizes[18]);
|
|
_propertyMap = new EventOrPropertyMapIndex(TryGetExistingPropertyMapIndex, tableSizes[21]);
|
|
_methodImpls = new MethodImplIndex(this, tableSizes[25]);
|
|
_customAttributeParentCounts = new Dictionary<EntityHandle, int>();
|
|
_customAttributesAdded = new Dictionary<EntityHandle, ImmutableArray<int>>();
|
|
_firstParamRowMap = new Dictionary<MethodDefinitionHandle, int>();
|
|
_existingParameterDefs = new Dictionary<IParameterDefinition, int>(Roslyn.Utilities.ReferenceEqualityComparer.Instance);
|
|
_assemblyRefIndex = new HeapOrReferenceIndex<AssemblyIdentity>(this, tableSizes[35]);
|
|
_moduleRefIndex = new HeapOrReferenceIndex<string>(this, tableSizes[26]);
|
|
_memberRefIndex = new InstanceAndStructuralReferenceIndex<ITypeMemberReference>(this, new MemberRefComparer(this), tableSizes[10]);
|
|
_methodSpecIndex = new InstanceAndStructuralReferenceIndex<IGenericMethodInstanceReference>(this, new MethodSpecComparer(this), tableSizes[43]);
|
|
_typeRefIndex = new TypeReferenceIndex(this, tableSizes[1]);
|
|
_typeSpecIndex = new InstanceAndStructuralReferenceIndex<ITypeReference>(this, new TypeSpecComparer(this), tableSizes[27]);
|
|
_standAloneSignatureIndex = new HeapOrReferenceIndex<BlobHandle>(this, tableSizes[17]);
|
|
_addedOrChangedMethods = new Dictionary<IMethodDefinition, AddedOrChangedMethodInfo>(SymbolEquivalentEqualityComparer.Instance);
|
|
}
|
|
|
|
private static MetadataBuilder MakeTablesBuilder(EmitBaseline previousGeneration)
|
|
{
|
|
return new MetadataBuilder(previousGeneration.UserStringStreamLength, previousGeneration.StringStreamLength, previousGeneration.BlobStreamLength, previousGeneration.GuidStreamLength);
|
|
}
|
|
|
|
private ImmutableArray<int> GetDeltaTableSizes(ImmutableArray<int> rowCounts)
|
|
{
|
|
int[] array = new int[MetadataTokens.TableCount];
|
|
rowCounts.CopyTo(array);
|
|
array[1] = _typeRefIndex.Rows.Count;
|
|
array[2] = _typeDefs.GetAdded().Count;
|
|
array[4] = _fieldDefs.GetAdded().Count;
|
|
array[6] = _methodDefs.GetAdded().Count;
|
|
array[8] = _parameterDefs.GetAdded().Count;
|
|
array[10] = _memberRefIndex.Rows.Count;
|
|
array[17] = _standAloneSignatureIndex.Rows.Count;
|
|
array[18] = _eventMap.GetAdded().Count;
|
|
array[20] = _eventDefs.GetAdded().Count;
|
|
array[21] = _propertyMap.GetAdded().Count;
|
|
array[23] = _propertyDefs.GetAdded().Count;
|
|
array[25] = _methodImpls.GetAdded().Count;
|
|
array[26] = _moduleRefIndex.Rows.Count;
|
|
array[27] = _typeSpecIndex.Rows.Count;
|
|
array[35] = _assemblyRefIndex.Rows.Count;
|
|
array[42] = _genericParameters.GetAdded().Count;
|
|
array[43] = _methodSpecIndex.Rows.Count;
|
|
return ImmutableArray.Create(array);
|
|
}
|
|
|
|
internal EmitBaseline GetDelta(Compilation compilation, Guid encId, MetadataSizes metadataSizes)
|
|
{
|
|
Dictionary<int, AddedOrChangedMethodInfo> dictionary = new Dictionary<int, AddedOrChangedMethodInfo>();
|
|
foreach (KeyValuePair<IMethodDefinition, AddedOrChangedMethodInfo> addedOrChangedMethod in _addedOrChangedMethods)
|
|
{
|
|
dictionary.Add(MetadataTokens.GetRowNumber(GetMethodDefinitionHandle(addedOrChangedMethod.Key)), addedOrChangedMethod.Value);
|
|
}
|
|
ImmutableArray<int> tableEntriesAdded = _previousGeneration.TableEntriesAdded;
|
|
ImmutableArray<int> deltaTableSizes = GetDeltaTableSizes(metadataSizes.RowCounts);
|
|
int[] array = new int[MetadataTokens.TableCount];
|
|
for (int i = 0; i < array.Length; i++)
|
|
{
|
|
array[i] = tableEntriesAdded[i] + deltaTableSizes[i];
|
|
}
|
|
ImmutableDictionary<ISymbolInternal, ImmutableArray<ISymbolInternal>> synthesizedMembers = (ImmutableDictionary<ISymbolInternal, ImmutableArray<ISymbolInternal>>)((_previousGeneration.Ordinal == 0) ? ((IDictionary)module.GetAllSynthesizedMembers()) : ((IDictionary)_previousGeneration.SynthesizedMembers));
|
|
ImmutableDictionary<ISymbolInternal, ImmutableArray<ISymbolInternal>> deletedMembers = ((_previousGeneration.Ordinal == 0) ? module.EncSymbolChanges.GetAllDeletedMembers() : _previousGeneration.DeletedMembers);
|
|
int num = _previousGeneration.Ordinal + 1;
|
|
IReadOnlyDictionary<ITypeDefinition, int> added = _typeDefs.GetAdded();
|
|
Dictionary<IDefinition, int> dictionary2 = CreateDictionary(_previousGeneration.GenerationOrdinals, SymbolEquivalentEqualityComparer.Instance);
|
|
foreach (var (typeDefinition2, _) in added)
|
|
{
|
|
if (_changes.IsReplaced(typeDefinition2))
|
|
{
|
|
dictionary2[typeDefinition2] = num;
|
|
}
|
|
}
|
|
return _previousGeneration.With(compilation, module, num, encId, dictionary2, AddRange(_previousGeneration.TypesAdded, added, SymbolEquivalentEqualityComparer.Instance), AddRange(_previousGeneration.EventsAdded, _eventDefs.GetAdded(), SymbolEquivalentEqualityComparer.Instance), AddRange(_previousGeneration.FieldsAdded, _fieldDefs.GetAdded(), SymbolEquivalentEqualityComparer.Instance), AddRange(_previousGeneration.MethodsAdded, _methodDefs.GetAdded(), SymbolEquivalentEqualityComparer.Instance), AddRange(_previousGeneration.FirstParamRowMap, _firstParamRowMap), AddRange(_previousGeneration.PropertiesAdded, _propertyDefs.GetAdded(), SymbolEquivalentEqualityComparer.Instance), AddRange(_previousGeneration.EventMapAdded, _eventMap.GetAdded()), AddRange(_previousGeneration.PropertyMapAdded, _propertyMap.GetAdded()), AddRange(_previousGeneration.MethodImplsAdded, _methodImpls.GetAdded()), AddRange(_previousGeneration.CustomAttributesAdded, _customAttributesAdded), ImmutableArray.Create(array), metadataSizes.GetAlignedHeapSize(HeapIndex.Blob) + _previousGeneration.BlobStreamLengthAdded, metadataSizes.HeapSizes[1] + _previousGeneration.StringStreamLengthAdded, metadataSizes.GetAlignedHeapSize(HeapIndex.UserString) + _previousGeneration.UserStringStreamLengthAdded, metadataSizes.HeapSizes[3], ((IPEDeltaAssemblyBuilder)module).GetSynthesizedTypes(), synthesizedMembers, deletedMembers, AddRange(_previousGeneration.AddedOrChangedMethods, dictionary), _previousGeneration.DebugInformationProvider, _previousGeneration.LocalSignatureProvider);
|
|
}
|
|
|
|
private static Dictionary<K, V> CreateDictionary<K, V>(IReadOnlyDictionary<K, V> dictionary, IEqualityComparer<K>? comparer) where K : notnull
|
|
{
|
|
Dictionary<K, V> dictionary2 = new Dictionary<K, V>(comparer);
|
|
foreach (KeyValuePair<K, V> item in dictionary)
|
|
{
|
|
dictionary2.Add(item.Key, item.Value);
|
|
}
|
|
return dictionary2;
|
|
}
|
|
|
|
private static IReadOnlyDictionary<K, V> AddRange<K, V>(IReadOnlyDictionary<K, V> previous, IReadOnlyDictionary<K, V> current, IEqualityComparer<K>? comparer = null) where K : notnull
|
|
{
|
|
if (previous.Count == 0)
|
|
{
|
|
return current;
|
|
}
|
|
if (current.Count == 0)
|
|
{
|
|
return previous;
|
|
}
|
|
Dictionary<K, V> dictionary = CreateDictionary(previous, comparer);
|
|
foreach (KeyValuePair<K, V> item in current)
|
|
{
|
|
dictionary[item.Key] = item.Value;
|
|
}
|
|
return dictionary;
|
|
}
|
|
|
|
public void GetUpdatedMethodTokens(ArrayBuilder<MethodDefinitionHandle> methods)
|
|
{
|
|
foreach (IMethodDefinition row in _methodDefs.GetRows())
|
|
{
|
|
if (!_methodDefs.IsAddedNotChanged(row))
|
|
{
|
|
IMethodBody body = row.GetBody(Context);
|
|
if (body != null && body.SequencePoints.Length > 0)
|
|
{
|
|
methods.Add(MetadataTokens.MethodDefinitionHandle(_methodDefs.GetRowId(row)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void GetChangedTypeTokens(ArrayBuilder<TypeDefinitionHandle> types)
|
|
{
|
|
foreach (ITypeDefinition changedTypeDef in _changedTypeDefs)
|
|
{
|
|
types.Add(GetTypeDefinitionHandle(changedTypeDef));
|
|
}
|
|
}
|
|
|
|
protected override EventDefinitionHandle GetEventDefinitionHandle(IEventDefinition def)
|
|
{
|
|
return MetadataTokens.EventDefinitionHandle(_eventDefs.GetRowId(def));
|
|
}
|
|
|
|
protected override IReadOnlyList<IEventDefinition> GetEventDefs()
|
|
{
|
|
return _eventDefs.GetRows();
|
|
}
|
|
|
|
protected override FieldDefinitionHandle GetFieldDefinitionHandle(IFieldDefinition def)
|
|
{
|
|
return MetadataTokens.FieldDefinitionHandle(_fieldDefs.GetRowId(def));
|
|
}
|
|
|
|
protected override IReadOnlyList<IFieldDefinition> GetFieldDefs()
|
|
{
|
|
return _fieldDefs.GetRows();
|
|
}
|
|
|
|
protected override bool TryGetTypeDefinitionHandle(ITypeDefinition def, out TypeDefinitionHandle handle)
|
|
{
|
|
int rowId;
|
|
bool result = _typeDefs.TryGetRowId(def, out rowId);
|
|
handle = MetadataTokens.TypeDefinitionHandle(rowId);
|
|
return result;
|
|
}
|
|
|
|
protected override TypeDefinitionHandle GetTypeDefinitionHandle(ITypeDefinition def)
|
|
{
|
|
return MetadataTokens.TypeDefinitionHandle(_typeDefs.GetRowId(def));
|
|
}
|
|
|
|
protected override ITypeDefinition GetTypeDef(TypeDefinitionHandle handle)
|
|
{
|
|
return _typeDefs.GetDefinition(MetadataTokens.GetRowNumber(handle));
|
|
}
|
|
|
|
protected override IReadOnlyList<ITypeDefinition> GetTypeDefs()
|
|
{
|
|
return _typeDefs.GetRows();
|
|
}
|
|
|
|
protected override bool TryGetMethodDefinitionHandle(IMethodDefinition def, out MethodDefinitionHandle handle)
|
|
{
|
|
int rowId;
|
|
bool result = _methodDefs.TryGetRowId(def, out rowId);
|
|
handle = MetadataTokens.MethodDefinitionHandle(rowId);
|
|
return result;
|
|
}
|
|
|
|
protected override MethodDefinitionHandle GetMethodDefinitionHandle(IMethodDefinition def)
|
|
{
|
|
return MetadataTokens.MethodDefinitionHandle(_methodDefs.GetRowId(def));
|
|
}
|
|
|
|
protected override IMethodDefinition GetMethodDef(MethodDefinitionHandle index)
|
|
{
|
|
return _methodDefs.GetDefinition(MetadataTokens.GetRowNumber(index));
|
|
}
|
|
|
|
protected override IReadOnlyList<IMethodDefinition> GetMethodDefs()
|
|
{
|
|
return _methodDefs.GetRows();
|
|
}
|
|
|
|
protected override PropertyDefinitionHandle GetPropertyDefIndex(IPropertyDefinition def)
|
|
{
|
|
return MetadataTokens.PropertyDefinitionHandle(_propertyDefs.GetRowId(def));
|
|
}
|
|
|
|
protected override IReadOnlyList<IPropertyDefinition> GetPropertyDefs()
|
|
{
|
|
return _propertyDefs.GetRows();
|
|
}
|
|
|
|
protected override ParameterHandle GetParameterHandle(IParameterDefinition def)
|
|
{
|
|
return MetadataTokens.ParameterHandle(_parameterDefs.GetRowId(def));
|
|
}
|
|
|
|
protected override IReadOnlyList<IParameterDefinition> GetParameterDefs()
|
|
{
|
|
return _parameterDefs.GetRows();
|
|
}
|
|
|
|
protected override IReadOnlyList<IGenericParameter> GetGenericParameters()
|
|
{
|
|
return _genericParameters.GetRows();
|
|
}
|
|
|
|
protected override FieldDefinitionHandle GetFirstFieldDefinitionHandle(INamedTypeDefinition typeDef)
|
|
{
|
|
return default(FieldDefinitionHandle);
|
|
}
|
|
|
|
protected override MethodDefinitionHandle GetFirstMethodDefinitionHandle(INamedTypeDefinition typeDef)
|
|
{
|
|
return default(MethodDefinitionHandle);
|
|
}
|
|
|
|
protected override ParameterHandle GetFirstParameterHandle(IMethodDefinition methodDef)
|
|
{
|
|
return default(ParameterHandle);
|
|
}
|
|
|
|
protected override AssemblyReferenceHandle GetOrAddAssemblyReferenceHandle(IAssemblyReference reference)
|
|
{
|
|
AssemblyIdentity assemblyIdentity = reference.Identity;
|
|
Version assemblyVersionPattern = reference.AssemblyVersionPattern;
|
|
if ((object)assemblyVersionPattern != null)
|
|
{
|
|
assemblyIdentity = _previousGeneration.InitialBaseline.LazyMetadataSymbols.AssemblyReferenceIdentityMap[assemblyIdentity.WithVersion(assemblyVersionPattern)];
|
|
}
|
|
return MetadataTokens.AssemblyReferenceHandle(_assemblyRefIndex.GetOrAdd(assemblyIdentity));
|
|
}
|
|
|
|
protected override IReadOnlyList<AssemblyIdentity> GetAssemblyRefs()
|
|
{
|
|
return _assemblyRefIndex.Rows;
|
|
}
|
|
|
|
protected override ModuleReferenceHandle GetOrAddModuleReferenceHandle(string reference)
|
|
{
|
|
return MetadataTokens.ModuleReferenceHandle(_moduleRefIndex.GetOrAdd(reference));
|
|
}
|
|
|
|
protected override IReadOnlyList<string> GetModuleRefs()
|
|
{
|
|
return _moduleRefIndex.Rows;
|
|
}
|
|
|
|
protected override MemberReferenceHandle GetOrAddMemberReferenceHandle(ITypeMemberReference reference)
|
|
{
|
|
return MetadataTokens.MemberReferenceHandle(_memberRefIndex.GetOrAdd(reference));
|
|
}
|
|
|
|
protected override IReadOnlyList<ITypeMemberReference> GetMemberRefs()
|
|
{
|
|
return _memberRefIndex.Rows;
|
|
}
|
|
|
|
protected override MethodSpecificationHandle GetOrAddMethodSpecificationHandle(IGenericMethodInstanceReference reference)
|
|
{
|
|
return MetadataTokens.MethodSpecificationHandle(_methodSpecIndex.GetOrAdd(reference));
|
|
}
|
|
|
|
protected override IReadOnlyList<IGenericMethodInstanceReference> GetMethodSpecs()
|
|
{
|
|
return _methodSpecIndex.Rows;
|
|
}
|
|
|
|
protected override bool TryGetTypeReferenceHandle(ITypeReference reference, out TypeReferenceHandle handle)
|
|
{
|
|
int index;
|
|
bool result = _typeRefIndex.TryGetValue(reference, out index);
|
|
handle = MetadataTokens.TypeReferenceHandle(index);
|
|
return result;
|
|
}
|
|
|
|
protected override TypeReferenceHandle GetOrAddTypeReferenceHandle(ITypeReference reference)
|
|
{
|
|
return MetadataTokens.TypeReferenceHandle(_typeRefIndex.GetOrAdd(reference));
|
|
}
|
|
|
|
protected override IReadOnlyList<ITypeReference> GetTypeRefs()
|
|
{
|
|
return _typeRefIndex.Rows;
|
|
}
|
|
|
|
protected override TypeSpecificationHandle GetOrAddTypeSpecificationHandle(ITypeReference reference)
|
|
{
|
|
return MetadataTokens.TypeSpecificationHandle(_typeSpecIndex.GetOrAdd(reference));
|
|
}
|
|
|
|
protected override IReadOnlyList<ITypeReference> GetTypeSpecs()
|
|
{
|
|
return _typeSpecIndex.Rows;
|
|
}
|
|
|
|
protected override StandaloneSignatureHandle GetOrAddStandaloneSignatureHandle(BlobHandle blobIndex)
|
|
{
|
|
return MetadataTokens.StandaloneSignatureHandle(_standAloneSignatureIndex.GetOrAdd(blobIndex));
|
|
}
|
|
|
|
protected override IReadOnlyList<BlobHandle> GetStandaloneSignatureBlobHandles()
|
|
{
|
|
return _standAloneSignatureIndex.Rows;
|
|
}
|
|
|
|
protected override void OnIndicesCreated()
|
|
{
|
|
((IPEDeltaAssemblyBuilder)module).OnCreatedIndices(Context.Diagnostics);
|
|
}
|
|
|
|
protected override void CreateIndicesForNonTypeMembers(ITypeDefinition typeDef)
|
|
{
|
|
SymbolChange change = _changes.GetChange(typeDef);
|
|
switch (change)
|
|
{
|
|
case SymbolChange.Added:
|
|
{
|
|
_typeDefs.Add(typeDef);
|
|
_changedTypeDefs.Add(typeDef);
|
|
IEnumerable<IGenericTypeParameter> consolidatedTypeParameters = GetConsolidatedTypeParameters(typeDef);
|
|
if (consolidatedTypeParameters == null)
|
|
{
|
|
break;
|
|
}
|
|
foreach (IGenericTypeParameter item4 in consolidatedTypeParameters)
|
|
{
|
|
_genericParameters.Add(item4);
|
|
}
|
|
break;
|
|
}
|
|
case SymbolChange.Updated:
|
|
_typeDefs.AddUpdated(typeDef);
|
|
_changedTypeDefs.Add(typeDef);
|
|
break;
|
|
case SymbolChange.ContainsChanges:
|
|
_changedTypeDefs.Add(typeDef);
|
|
break;
|
|
case SymbolChange.None:
|
|
return;
|
|
default:
|
|
throw ExceptionUtilities.UnexpectedValue(change);
|
|
}
|
|
int rowId = _typeDefs.GetRowId(typeDef);
|
|
foreach (IEventDefinition @event in typeDef.GetEvents(Context))
|
|
{
|
|
if (!_eventMap.Contains(rowId))
|
|
{
|
|
_eventMap.Add(rowId);
|
|
}
|
|
SymbolChange changeForPossibleReAddedMember = _changes.GetChangeForPossibleReAddedMember(@event, DefinitionExistsInAnyPreviousGeneration);
|
|
AddDefIfNecessary(_eventDefs, @event, changeForPossibleReAddedMember);
|
|
}
|
|
foreach (IFieldDefinition field in typeDef.GetFields(Context))
|
|
{
|
|
SymbolChange changeForPossibleReAddedMember2 = _changes.GetChangeForPossibleReAddedMember(field, DefinitionExistsInAnyPreviousGeneration);
|
|
AddDefIfNecessary(_fieldDefs, field, changeForPossibleReAddedMember2);
|
|
}
|
|
foreach (IMethodDefinition method in typeDef.GetMethods(Context))
|
|
{
|
|
SymbolChange changeForPossibleReAddedMember3 = _changes.GetChangeForPossibleReAddedMember(method, DefinitionExistsInAnyPreviousGeneration);
|
|
AddDefIfNecessary(_methodDefs, method, changeForPossibleReAddedMember3);
|
|
CreateIndicesForMethod(method, changeForPossibleReAddedMember3);
|
|
}
|
|
ImmutableArray<ISymbolInternal> deletedMethods = _changes.GetDeletedMethods(typeDef);
|
|
if (deletedMethods.Length > 0)
|
|
{
|
|
ImmutableArray<DeletedMethodDefinition> value = deletedMethods.SelectAsArray((ISymbolInternal m, (ITypeDefinition typeDef, Dictionary<ITypeDefinition, DeletedTypeDefinition> _typesUsedByDeletedMembers) args) => new DeletedMethodDefinition((IMethodDefinition)m.GetCciAdapter(), args.typeDef, args._typesUsedByDeletedMembers), (typeDef, _typesUsedByDeletedMembers));
|
|
ImmutableArray<DeletedMethodDefinition>.Enumerator enumerator5 = value.GetEnumerator();
|
|
while (enumerator5.MoveNext())
|
|
{
|
|
DeletedMethodDefinition current5 = enumerator5.Current;
|
|
_methodDefs.AddUpdated(current5);
|
|
CreateIndicesForMethod(current5, SymbolChange.Updated);
|
|
}
|
|
_deletedTypeMembers.Add(typeDef, value);
|
|
}
|
|
foreach (IPropertyDefinition property in typeDef.GetProperties(Context))
|
|
{
|
|
if (!_propertyMap.Contains(rowId))
|
|
{
|
|
_propertyMap.Add(rowId);
|
|
}
|
|
SymbolChange changeForPossibleReAddedMember4 = _changes.GetChangeForPossibleReAddedMember(property, DefinitionExistsInAnyPreviousGeneration);
|
|
AddDefIfNecessary(_propertyDefs, property, changeForPossibleReAddedMember4);
|
|
}
|
|
ArrayBuilder<int> instance = ArrayBuilder<int>.GetInstance();
|
|
foreach (Microsoft.Cci.MethodImplementation explicitImplementationOverride in typeDef.GetExplicitImplementationOverrides(Context))
|
|
{
|
|
IMethodDefinition item = (IMethodDefinition)explicitImplementationOverride.ImplementingMethod.AsDefinition(Context);
|
|
int rowId2 = _methodDefs.GetRowId(item);
|
|
MethodImplKey item2 = new MethodImplKey(rowId2, 1);
|
|
if (!_methodImpls.Contains(item2))
|
|
{
|
|
instance.Add(rowId2);
|
|
methodImplList.Add(explicitImplementationOverride);
|
|
}
|
|
}
|
|
ArrayBuilder<int>.Enumerator enumerator8 = instance.GetEnumerator();
|
|
while (enumerator8.MoveNext())
|
|
{
|
|
int current8 = enumerator8.Current;
|
|
int num = 1;
|
|
MethodImplKey item3;
|
|
while (true)
|
|
{
|
|
item3 = new MethodImplKey(current8, num);
|
|
if (!_methodImpls.Contains(item3))
|
|
{
|
|
break;
|
|
}
|
|
num++;
|
|
}
|
|
_methodImpls.Add(item3);
|
|
}
|
|
instance.Free();
|
|
}
|
|
|
|
private bool DefinitionExistsInAnyPreviousGeneration(ITypeDefinitionMember item)
|
|
{
|
|
int index;
|
|
if (!(item is IMethodDefinition item2))
|
|
{
|
|
if (!(item is IPropertyDefinition item3))
|
|
{
|
|
if (!(item is IFieldDefinition item4))
|
|
{
|
|
if (item is IEventDefinition item5)
|
|
{
|
|
return TryGetExistingEventDefIndex(item5, out index);
|
|
}
|
|
return false;
|
|
}
|
|
return TryGetExistingFieldDefIndex(item4, out index);
|
|
}
|
|
return TryGetExistingPropertyDefIndex(item3, out index);
|
|
}
|
|
return TryGetExistingMethodDefIndex(item2, out index);
|
|
}
|
|
|
|
private void CreateIndicesForMethod(IMethodDefinition methodDef, SymbolChange methodChange)
|
|
{
|
|
switch (methodChange)
|
|
{
|
|
case SymbolChange.Added:
|
|
{
|
|
_firstParamRowMap.Add(GetMethodDefinitionHandle(methodDef), _parameterDefs.NextRowId);
|
|
ImmutableArray<IParameterDefinition>.Enumerator enumerator = GetParametersToEmit(methodDef).GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
IParameterDefinition current = enumerator.Current;
|
|
_parameterDefs.Add(current);
|
|
_parameterDefList.Add(current, methodDef);
|
|
}
|
|
break;
|
|
}
|
|
case SymbolChange.Updated:
|
|
{
|
|
MethodDefinitionHandle methodDefinitionHandle = GetMethodDefinitionHandle(methodDef);
|
|
if (_previousGeneration.OriginalMetadata.MetadataReader.GetTableRowCount(TableIndex.MethodDef) >= MetadataTokens.GetRowNumber(methodDefinitionHandle))
|
|
{
|
|
EmitParametersFromOriginalMetadata(methodDef, methodDefinitionHandle);
|
|
}
|
|
else
|
|
{
|
|
EmitParametersFromDelta(methodDef, methodDefinitionHandle);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (methodChange != SymbolChange.Added || methodDef.GenericParameterCount <= 0)
|
|
{
|
|
return;
|
|
}
|
|
foreach (IGenericMethodParameter genericParameter in methodDef.GenericParameters)
|
|
{
|
|
_genericParameters.Add(genericParameter);
|
|
}
|
|
}
|
|
|
|
private void EmitParametersFromOriginalMetadata(IMethodDefinition methodDef, MethodDefinitionHandle handle)
|
|
{
|
|
ParameterHandleCollection parameters = _previousGeneration.OriginalMetadata.MetadataReader.GetMethodDefinition(handle).GetParameters();
|
|
ImmutableArray<IParameterDefinition> parametersToEmit = GetParametersToEmit(methodDef);
|
|
int num = 0;
|
|
foreach (ParameterHandle item in parameters)
|
|
{
|
|
IParameterDefinition parameterDefinition = parametersToEmit[num];
|
|
_parameterDefs.AddUpdated(parameterDefinition);
|
|
_existingParameterDefs.Add(parameterDefinition, MetadataTokens.GetRowNumber(item));
|
|
_parameterDefList.Add(parameterDefinition, methodDef);
|
|
num++;
|
|
}
|
|
}
|
|
|
|
private void EmitParametersFromDelta(IMethodDefinition methodDef, MethodDefinitionHandle handle)
|
|
{
|
|
_previousGeneration.FirstParamRowMap.TryGetValue(handle, out var value);
|
|
ImmutableArray<IParameterDefinition>.Enumerator enumerator = GetParametersToEmit(methodDef).GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
IParameterDefinition current = enumerator.Current;
|
|
_parameterDefs.AddUpdated(current);
|
|
_existingParameterDefs.Add(current, value++);
|
|
_parameterDefList.Add(current, methodDef);
|
|
}
|
|
}
|
|
|
|
private bool AddDefIfNecessary<T>(DefinitionIndex<T> defIndex, T def, SymbolChange change) where T : class, IDefinition
|
|
{
|
|
switch (change)
|
|
{
|
|
case SymbolChange.Added:
|
|
defIndex.Add(def);
|
|
return true;
|
|
case SymbolChange.Updated:
|
|
defIndex.AddUpdated(def);
|
|
return false;
|
|
case SymbolChange.ContainsChanges:
|
|
return false;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
protected override ReferenceIndexer CreateReferenceVisitor()
|
|
{
|
|
return new DeltaReferenceIndexer(this);
|
|
}
|
|
|
|
protected override void ReportReferencesToAddedSymbols()
|
|
{
|
|
foreach (ITypeReference typeRef in GetTypeRefs())
|
|
{
|
|
ReportReferencesToAddedSymbol(typeRef.GetInternalSymbol());
|
|
}
|
|
foreach (ITypeMemberReference memberRef in GetMemberRefs())
|
|
{
|
|
ReportReferencesToAddedSymbol(memberRef.GetInternalSymbol());
|
|
}
|
|
}
|
|
|
|
private void ReportReferencesToAddedSymbol(ISymbolInternal? symbol)
|
|
{
|
|
if (symbol != null && _changes.IsAdded(symbol.GetISymbol()))
|
|
{
|
|
Context.Diagnostics.Add(messageProvider.CreateDiagnostic(messageProvider.ERR_EncReferenceToAddedMember, MetadataWriter.GetSymbolLocation(symbol), symbol.Name, symbol.ContainingAssembly.Name));
|
|
}
|
|
}
|
|
|
|
protected override StandaloneSignatureHandle SerializeLocalVariablesSignature(IMethodBody body)
|
|
{
|
|
ImmutableArray<ILocalDefinition> localVariables = body.LocalVariables;
|
|
ArrayBuilder<EncLocalInfo> instance = ArrayBuilder<EncLocalInfo>.GetInstance();
|
|
StandaloneSignatureHandle result;
|
|
if (localVariables.Length > 0)
|
|
{
|
|
PooledBlobBuilder instance2 = PooledBlobBuilder.GetInstance();
|
|
LocalVariablesEncoder localVariablesEncoder = new BlobEncoder(instance2).LocalVariableSignature(localVariables.Length);
|
|
ImmutableArray<ILocalDefinition>.Enumerator enumerator = localVariables.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
ILocalDefinition current = enumerator.Current;
|
|
byte[] array = current.Signature;
|
|
if (array == null)
|
|
{
|
|
int count = instance2.Count;
|
|
SerializeLocalVariableType(localVariablesEncoder.AddVariable(), current);
|
|
array = instance2.ToArray(count, instance2.Count - count);
|
|
}
|
|
else
|
|
{
|
|
instance2.WriteBytes(array);
|
|
}
|
|
instance.Add(CreateEncLocalInfo(current, array));
|
|
}
|
|
BlobHandle orAddBlob = metadata.GetOrAddBlob(instance2);
|
|
result = GetOrAddStandaloneSignatureHandle(orAddBlob);
|
|
instance2.Free();
|
|
}
|
|
else
|
|
{
|
|
result = default(StandaloneSignatureHandle);
|
|
}
|
|
AddedOrChangedMethodInfo value = new AddedOrChangedMethodInfo(body.MethodId, instance.ToImmutable(), body.LambdaDebugInfo, body.ClosureDebugInfo, body.StateMachineTypeName, body.StateMachineHoistedLocalSlots, body.StateMachineAwaiterSlots, body.StateMachineStatesDebugInfo);
|
|
_addedOrChangedMethods.Add(body.MethodDefinition, value);
|
|
instance.Free();
|
|
return result;
|
|
}
|
|
|
|
private EncLocalInfo CreateEncLocalInfo(ILocalDefinition localDef, byte[] signature)
|
|
{
|
|
if (localDef.SlotInfo.Id.IsNone)
|
|
{
|
|
return new EncLocalInfo(signature);
|
|
}
|
|
ITypeReference typeReference = localDef.Type;
|
|
if (typeReference.GetInternalSymbol() is ITypeSymbolInternal type)
|
|
{
|
|
typeReference = Context.Module.EncTranslateType(type, Context.Diagnostics);
|
|
}
|
|
return new EncLocalInfo(localDef.SlotInfo, typeReference, localDef.Constraints, signature);
|
|
}
|
|
|
|
protected override int AddCustomAttributesToTable(EntityHandle parentHandle, IEnumerable<ICustomAttribute> attributes)
|
|
{
|
|
int num = base.AddCustomAttributesToTable(parentHandle, attributes);
|
|
_customAttributeParentCounts.Add(parentHandle, num);
|
|
return num;
|
|
}
|
|
|
|
public override void PopulateEncTables(ImmutableArray<int> typeSystemRowCounts)
|
|
{
|
|
PopulateEncLogTableRows(typeSystemRowCounts, out List<int> customAttributeEncMapRows, out List<int> paramEncMapRows);
|
|
PopulateEncMapTableRows(typeSystemRowCounts, customAttributeEncMapRows, paramEncMapRows);
|
|
}
|
|
|
|
private void PopulateEncLogTableRows(ImmutableArray<int> rowCounts, out List<int> customAttributeEncMapRows, out List<int> paramEncMapRows)
|
|
{
|
|
ImmutableArray<int> tableSizes = _previousGeneration.TableSizes;
|
|
ImmutableArray<int> deltaTableSizes = GetDeltaTableSizes(rowCounts);
|
|
PopulateEncLogTableRows(TableIndex.AssemblyRef, tableSizes, deltaTableSizes);
|
|
PopulateEncLogTableRows(TableIndex.ModuleRef, tableSizes, deltaTableSizes);
|
|
PopulateEncLogTableRows(TableIndex.MemberRef, tableSizes, deltaTableSizes);
|
|
PopulateEncLogTableRows(TableIndex.MethodSpec, tableSizes, deltaTableSizes);
|
|
PopulateEncLogTableRows(TableIndex.TypeRef, tableSizes, deltaTableSizes);
|
|
PopulateEncLogTableRows(TableIndex.TypeSpec, tableSizes, deltaTableSizes);
|
|
PopulateEncLogTableRows(TableIndex.StandAloneSig, tableSizes, deltaTableSizes);
|
|
PopulateEncLogTableRows(_typeDefs, TableIndex.TypeDef);
|
|
PopulateEncLogTableRows(TableIndex.EventMap, tableSizes, deltaTableSizes);
|
|
PopulateEncLogTableRows(TableIndex.PropertyMap, tableSizes, deltaTableSizes);
|
|
PopulateEncLogTableEventsOrProperties(_eventDefs, TableIndex.Event, EditAndContinueOperation.AddEvent, _eventMap, TableIndex.EventMap);
|
|
PopulateEncLogTableFieldsOrMethods(_fieldDefs, TableIndex.Field, EditAndContinueOperation.AddField);
|
|
PopulateEncLogTableFieldsOrMethods(_methodDefs, TableIndex.MethodDef, EditAndContinueOperation.AddMethod);
|
|
PopulateEncLogTableEventsOrProperties(_propertyDefs, TableIndex.Property, EditAndContinueOperation.AddProperty, _propertyMap, TableIndex.PropertyMap);
|
|
PopulateEncLogTableParameters(out paramEncMapRows);
|
|
PopulateEncLogTableRows(TableIndex.Constant, tableSizes, deltaTableSizes);
|
|
PopulateEncLogTableCustomAttributes(out customAttributeEncMapRows);
|
|
PopulateEncLogTableRows(TableIndex.DeclSecurity, tableSizes, deltaTableSizes);
|
|
PopulateEncLogTableRows(TableIndex.ClassLayout, tableSizes, deltaTableSizes);
|
|
PopulateEncLogTableRows(TableIndex.FieldLayout, tableSizes, deltaTableSizes);
|
|
PopulateEncLogTableRows(TableIndex.MethodSemantics, tableSizes, deltaTableSizes);
|
|
PopulateEncLogTableRows(TableIndex.MethodImpl, tableSizes, deltaTableSizes);
|
|
PopulateEncLogTableRows(TableIndex.ImplMap, tableSizes, deltaTableSizes);
|
|
PopulateEncLogTableRows(TableIndex.FieldRva, tableSizes, deltaTableSizes);
|
|
PopulateEncLogTableRows(TableIndex.NestedClass, tableSizes, deltaTableSizes);
|
|
PopulateEncLogTableRows(TableIndex.GenericParam, tableSizes, deltaTableSizes);
|
|
PopulateEncLogTableRows(TableIndex.InterfaceImpl, tableSizes, deltaTableSizes);
|
|
PopulateEncLogTableRows(TableIndex.GenericParamConstraint, tableSizes, deltaTableSizes);
|
|
}
|
|
|
|
private void PopulateEncLogTableEventsOrProperties<T>(DefinitionIndex<T> index, TableIndex table, EditAndContinueOperation addCode, EventOrPropertyMapIndex map, TableIndex mapTable) where T : class, ITypeDefinitionMember
|
|
{
|
|
foreach (T row in index.GetRows())
|
|
{
|
|
if (index.IsAddedNotChanged(row))
|
|
{
|
|
int rowNumber = MetadataTokens.GetRowNumber(GetTypeDefinitionHandle(row.ContainingTypeDefinition));
|
|
int rowId = map.GetRowId(rowNumber);
|
|
metadata.AddEncLogEntry(MetadataTokens.Handle(mapTable, rowId), addCode);
|
|
}
|
|
metadata.AddEncLogEntry(MetadataTokens.Handle(table, index.GetRowId(row)), EditAndContinueOperation.Default);
|
|
}
|
|
}
|
|
|
|
private void PopulateEncLogTableFieldsOrMethods<T>(DefinitionIndex<T> index, TableIndex tableIndex, EditAndContinueOperation addCode) where T : class, ITypeDefinitionMember
|
|
{
|
|
foreach (T row in index.GetRows())
|
|
{
|
|
if (index.IsAddedNotChanged(row))
|
|
{
|
|
metadata.AddEncLogEntry(GetTypeDefinitionHandle(row.ContainingTypeDefinition), addCode);
|
|
}
|
|
metadata.AddEncLogEntry(MetadataTokens.Handle(tableIndex, index.GetRowId(row)), EditAndContinueOperation.Default);
|
|
}
|
|
}
|
|
|
|
private void PopulateEncLogTableParameters(out List<int> paramEncMapRows)
|
|
{
|
|
paramEncMapRows = new List<int>();
|
|
int firstRowId = _parameterDefs.FirstRowId;
|
|
int num = 0;
|
|
foreach (IParameterDefinition parameterDef in GetParameterDefs())
|
|
{
|
|
IMethodDefinition item = _parameterDefList[parameterDef];
|
|
if (_methodDefs.IsAddedNotChanged(item))
|
|
{
|
|
paramEncMapRows.Add(firstRowId + num);
|
|
metadata.AddEncLogEntry(MetadataTokens.MethodDefinitionHandle(_methodDefs.GetRowId(item)), EditAndContinueOperation.AddParameter);
|
|
metadata.AddEncLogEntry(MetadataTokens.ParameterHandle(firstRowId + num), EditAndContinueOperation.Default);
|
|
num++;
|
|
}
|
|
else
|
|
{
|
|
ParameterHandle parameterHandle = GetParameterHandle(parameterDef);
|
|
paramEncMapRows.Add(MetadataTokens.GetRowNumber(parameterHandle));
|
|
metadata.AddEncLogEntry(parameterHandle, EditAndContinueOperation.Default);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void PopulateEncLogTableCustomAttributes(out List<int> customAttributeEncMapRows)
|
|
{
|
|
customAttributeEncMapRows = new List<int>();
|
|
List<(int parentRowId, HandleKind kind)> deletedAttributeRows = new List<(int, HandleKind)>();
|
|
Dictionary<EntityHandle, ArrayBuilder<int>> customAttributesAdded = new Dictionary<EntityHandle, ArrayBuilder<int>>();
|
|
int num = _previousGeneration.OriginalMetadata.MetadataReader.GetTableRowCount(TableIndex.CustomAttribute);
|
|
if (_previousGeneration.CustomAttributesAdded.Count > 0)
|
|
{
|
|
num = _previousGeneration.CustomAttributesAdded.SelectMany((KeyValuePair<EntityHandle, ImmutableArray<int>> s) => s.Value).Max();
|
|
}
|
|
EntityHandle key;
|
|
foreach (KeyValuePair<EntityHandle, int> item in _customAttributeParentCounts.OrderBy((KeyValuePair<EntityHandle, int> kvp) => CodedIndex.HasCustomAttribute(kvp.Key)))
|
|
{
|
|
KeyValuePairUtil.Deconstruct(item, out key, out var value);
|
|
EntityHandle entityHandle = key;
|
|
int num2 = value;
|
|
int num3 = 0;
|
|
foreach (CustomAttributeHandle customAttribute in _previousGeneration.OriginalMetadata.MetadataReader.GetCustomAttributes(entityHandle))
|
|
{
|
|
int rowNumber = MetadataTokens.GetRowNumber(customAttribute);
|
|
AddLogEntryOrDelete(rowNumber, entityHandle, num3 < num2, customAttributeEncMapRows);
|
|
num3++;
|
|
}
|
|
if (_previousGeneration.CustomAttributesAdded.TryGetValue(entityHandle, out var value2))
|
|
{
|
|
ImmutableArray<int>.Enumerator enumerator3 = value2.GetEnumerator();
|
|
while (enumerator3.MoveNext())
|
|
{
|
|
int current = enumerator3.Current;
|
|
TrackCustomAttributeAdded(current, entityHandle);
|
|
AddLogEntryOrDelete(current, entityHandle, num3 < num2, customAttributeEncMapRows);
|
|
num3++;
|
|
}
|
|
}
|
|
for (int num4 = num3; num4 < num2; num4++)
|
|
{
|
|
num++;
|
|
TrackCustomAttributeAdded(num, entityHandle);
|
|
AddEncLogEntry(num, customAttributeEncMapRows);
|
|
}
|
|
}
|
|
foreach (KeyValuePair<EntityHandle, ArrayBuilder<int>> item2 in customAttributesAdded)
|
|
{
|
|
KeyValuePairUtil.Deconstruct(item2, out key, out var value3);
|
|
EntityHandle key2 = key;
|
|
ArrayBuilder<int> arrayBuilder = value3;
|
|
_customAttributesAdded.Add(key2, arrayBuilder.ToImmutableAndFree());
|
|
}
|
|
foreach (var item3 in deletedAttributeRows)
|
|
{
|
|
if (!MetadataTokens.TryGetTableIndex(item3.kind, out var index))
|
|
{
|
|
throw new InvalidOperationException("Trying to delete a custom attribute for a parent kind that doesn't have a matching table index.");
|
|
}
|
|
metadata.AddCustomAttribute(MetadataTokens.Handle(index, 0), MetadataTokens.EntityHandle(TableIndex.MemberRef, 0), default(BlobHandle));
|
|
AddEncLogEntry(item3.parentRowId, customAttributeEncMapRows);
|
|
}
|
|
void AddEncLogEntry(int rowId, List<int> list)
|
|
{
|
|
list.Add(rowId);
|
|
metadata.AddEncLogEntry(MetadataTokens.CustomAttributeHandle(rowId), EditAndContinueOperation.Default);
|
|
}
|
|
void AddLogEntryOrDelete(int rowId, EntityHandle parent, bool add, List<int> customAttributeEncMapRows2)
|
|
{
|
|
if (add)
|
|
{
|
|
AddEncLogEntry(rowId, customAttributeEncMapRows2);
|
|
}
|
|
else
|
|
{
|
|
deletedAttributeRows.Add((rowId, parent.Kind));
|
|
}
|
|
}
|
|
void TrackCustomAttributeAdded(int nextRowId, EntityHandle parent)
|
|
{
|
|
if (!customAttributesAdded.TryGetValue(parent, out ArrayBuilder<int> value4))
|
|
{
|
|
value4 = ArrayBuilder<int>.GetInstance();
|
|
customAttributesAdded.Add(parent, value4);
|
|
}
|
|
value4.Add(nextRowId);
|
|
}
|
|
}
|
|
|
|
private void PopulateEncLogTableRows<T>(DefinitionIndex<T> index, TableIndex tableIndex) where T : class, IDefinition
|
|
{
|
|
foreach (T row in index.GetRows())
|
|
{
|
|
metadata.AddEncLogEntry(MetadataTokens.Handle(tableIndex, index.GetRowId(row)), EditAndContinueOperation.Default);
|
|
}
|
|
}
|
|
|
|
private void PopulateEncLogTableRows(TableIndex tableIndex, ImmutableArray<int> previousSizes, ImmutableArray<int> deltaSizes)
|
|
{
|
|
PopulateEncLogTableRows(tableIndex, previousSizes[(int)tableIndex] + 1, deltaSizes[(int)tableIndex]);
|
|
}
|
|
|
|
private void PopulateEncLogTableRows(TableIndex tableIndex, int firstRowId, int tokenCount)
|
|
{
|
|
for (int i = 0; i < tokenCount; i++)
|
|
{
|
|
metadata.AddEncLogEntry(MetadataTokens.Handle(tableIndex, firstRowId + i), EditAndContinueOperation.Default);
|
|
}
|
|
}
|
|
|
|
private void PopulateEncMapTableRows(ImmutableArray<int> rowCounts, List<int> customAttributeEncMapRows, List<int> paramEncMapRows)
|
|
{
|
|
ArrayBuilder<EntityHandle> instance = ArrayBuilder<EntityHandle>.GetInstance();
|
|
ImmutableArray<int> tableSizes = _previousGeneration.TableSizes;
|
|
ImmutableArray<int> deltaTableSizes = GetDeltaTableSizes(rowCounts);
|
|
AddReferencedTokens(instance, TableIndex.AssemblyRef, tableSizes, deltaTableSizes);
|
|
AddReferencedTokens(instance, TableIndex.ModuleRef, tableSizes, deltaTableSizes);
|
|
AddReferencedTokens(instance, TableIndex.MemberRef, tableSizes, deltaTableSizes);
|
|
AddReferencedTokens(instance, TableIndex.MethodSpec, tableSizes, deltaTableSizes);
|
|
AddReferencedTokens(instance, TableIndex.TypeRef, tableSizes, deltaTableSizes);
|
|
AddReferencedTokens(instance, TableIndex.TypeSpec, tableSizes, deltaTableSizes);
|
|
AddReferencedTokens(instance, TableIndex.StandAloneSig, tableSizes, deltaTableSizes);
|
|
AddDefinitionTokens(instance, _typeDefs, TableIndex.TypeDef);
|
|
AddDefinitionTokens(instance, _eventDefs, TableIndex.Event);
|
|
AddDefinitionTokens(instance, _fieldDefs, TableIndex.Field);
|
|
AddDefinitionTokens(instance, _methodDefs, TableIndex.MethodDef);
|
|
AddDefinitionTokens(instance, _propertyDefs, TableIndex.Property);
|
|
AddRowNumberTokens(instance, paramEncMapRows, TableIndex.Param);
|
|
AddReferencedTokens(instance, TableIndex.Constant, tableSizes, deltaTableSizes);
|
|
AddRowNumberTokens(instance, customAttributeEncMapRows, TableIndex.CustomAttribute);
|
|
AddReferencedTokens(instance, TableIndex.DeclSecurity, tableSizes, deltaTableSizes);
|
|
AddReferencedTokens(instance, TableIndex.ClassLayout, tableSizes, deltaTableSizes);
|
|
AddReferencedTokens(instance, TableIndex.FieldLayout, tableSizes, deltaTableSizes);
|
|
AddReferencedTokens(instance, TableIndex.EventMap, tableSizes, deltaTableSizes);
|
|
AddReferencedTokens(instance, TableIndex.PropertyMap, tableSizes, deltaTableSizes);
|
|
AddReferencedTokens(instance, TableIndex.MethodSemantics, tableSizes, deltaTableSizes);
|
|
AddReferencedTokens(instance, TableIndex.MethodImpl, tableSizes, deltaTableSizes);
|
|
AddReferencedTokens(instance, TableIndex.ImplMap, tableSizes, deltaTableSizes);
|
|
AddReferencedTokens(instance, TableIndex.FieldRva, tableSizes, deltaTableSizes);
|
|
AddReferencedTokens(instance, TableIndex.NestedClass, tableSizes, deltaTableSizes);
|
|
AddReferencedTokens(instance, TableIndex.GenericParam, tableSizes, deltaTableSizes);
|
|
AddReferencedTokens(instance, TableIndex.InterfaceImpl, tableSizes, deltaTableSizes);
|
|
AddReferencedTokens(instance, TableIndex.GenericParamConstraint, tableSizes, deltaTableSizes);
|
|
instance.Sort(HandleComparer.Default);
|
|
ArrayBuilder<EntityHandle>.Enumerator enumerator = instance.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
EntityHandle current = enumerator.Current;
|
|
metadata.AddEncMapEntry(current);
|
|
}
|
|
instance.Free();
|
|
if (_debugMetadataOpt != null)
|
|
{
|
|
ArrayBuilder<EntityHandle> instance2 = ArrayBuilder<EntityHandle>.GetInstance();
|
|
AddDefinitionTokens(instance2, _methodDefs, TableIndex.MethodDebugInformation);
|
|
instance2.Sort(HandleComparer.Default);
|
|
enumerator = instance2.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
EntityHandle current2 = enumerator.Current;
|
|
_debugMetadataOpt.AddEncMapEntry(current2);
|
|
}
|
|
instance2.Free();
|
|
}
|
|
}
|
|
|
|
private static void AddReferencedTokens(ArrayBuilder<EntityHandle> builder, TableIndex tableIndex, ImmutableArray<int> previousSizes, ImmutableArray<int> deltaSizes)
|
|
{
|
|
AddReferencedTokens(builder, tableIndex, previousSizes[(int)tableIndex] + 1, deltaSizes[(int)tableIndex]);
|
|
}
|
|
|
|
private static void AddReferencedTokens(ArrayBuilder<EntityHandle> builder, TableIndex tableIndex, int firstRowId, int nTokens)
|
|
{
|
|
for (int i = 0; i < nTokens; i++)
|
|
{
|
|
builder.Add(MetadataTokens.Handle(tableIndex, firstRowId + i));
|
|
}
|
|
}
|
|
|
|
private static void AddDefinitionTokens<T>(ArrayBuilder<EntityHandle> tokens, DefinitionIndex<T> index, TableIndex tableIndex) where T : class, IDefinition
|
|
{
|
|
foreach (T row in index.GetRows())
|
|
{
|
|
tokens.Add(MetadataTokens.Handle(tableIndex, index.GetRowId(row)));
|
|
}
|
|
}
|
|
|
|
private static void AddRowNumberTokens(ArrayBuilder<EntityHandle> tokens, IEnumerable<int> rowNumbers, TableIndex tableIndex)
|
|
{
|
|
foreach (int rowNumber in rowNumbers)
|
|
{
|
|
tokens.Add(MetadataTokens.Handle(tableIndex, rowNumber));
|
|
}
|
|
}
|
|
|
|
protected override void PopulateEventMapTableRows()
|
|
{
|
|
foreach (int row in _eventMap.GetRows())
|
|
{
|
|
metadata.AddEventMap(MetadataTokens.TypeDefinitionHandle(row), MetadataTokens.EventDefinitionHandle(_eventMap.GetRowId(row)));
|
|
}
|
|
}
|
|
|
|
protected override void PopulatePropertyMapTableRows()
|
|
{
|
|
foreach (int row in _propertyMap.GetRows())
|
|
{
|
|
metadata.AddPropertyMap(MetadataTokens.TypeDefinitionHandle(row), MetadataTokens.PropertyDefinitionHandle(_propertyMap.GetRowId(row)));
|
|
}
|
|
}
|
|
|
|
private bool TryGetExistingTypeDefIndex(ITypeDefinition item, out int index)
|
|
{
|
|
if (_previousGeneration.TypesAdded.TryGetValue(item, out index))
|
|
{
|
|
return true;
|
|
}
|
|
if (_definitionMap.TryGetTypeHandle(item, out var handle))
|
|
{
|
|
index = MetadataTokens.GetRowNumber(handle);
|
|
return true;
|
|
}
|
|
index = 0;
|
|
return false;
|
|
}
|
|
|
|
private bool TryGetExistingEventDefIndex(IEventDefinition item, out int index)
|
|
{
|
|
if (_previousGeneration.EventsAdded.TryGetValue(item, out index))
|
|
{
|
|
return true;
|
|
}
|
|
if (_definitionMap.TryGetEventHandle(item, out var handle))
|
|
{
|
|
index = MetadataTokens.GetRowNumber(handle);
|
|
return true;
|
|
}
|
|
index = 0;
|
|
return false;
|
|
}
|
|
|
|
private bool TryGetExistingFieldDefIndex(IFieldDefinition item, out int index)
|
|
{
|
|
if (_previousGeneration.FieldsAdded.TryGetValue(item, out index))
|
|
{
|
|
return true;
|
|
}
|
|
if (_definitionMap.TryGetFieldHandle(item, out var handle))
|
|
{
|
|
index = MetadataTokens.GetRowNumber(handle);
|
|
return true;
|
|
}
|
|
index = 0;
|
|
return false;
|
|
}
|
|
|
|
private bool TryGetExistingMethodDefIndex(IMethodDefinition item, out int index)
|
|
{
|
|
if (_previousGeneration.MethodsAdded.TryGetValue(item, out index))
|
|
{
|
|
return true;
|
|
}
|
|
if (_definitionMap.TryGetMethodHandle(item, out var handle))
|
|
{
|
|
index = MetadataTokens.GetRowNumber(handle);
|
|
return true;
|
|
}
|
|
index = 0;
|
|
return false;
|
|
}
|
|
|
|
private bool TryGetExistingPropertyDefIndex(IPropertyDefinition item, out int index)
|
|
{
|
|
if (_previousGeneration.PropertiesAdded.TryGetValue(item, out index))
|
|
{
|
|
return true;
|
|
}
|
|
if (_definitionMap.TryGetPropertyHandle(item, out var handle))
|
|
{
|
|
index = MetadataTokens.GetRowNumber(handle);
|
|
return true;
|
|
}
|
|
index = 0;
|
|
return false;
|
|
}
|
|
|
|
private bool TryGetExistingParameterDefIndex(IParameterDefinition item, out int index)
|
|
{
|
|
return _existingParameterDefs.TryGetValue(item, out index);
|
|
}
|
|
|
|
private bool TryGetExistingEventMapIndex(int item, out int index)
|
|
{
|
|
if (_previousGeneration.EventMapAdded.TryGetValue(item, out index))
|
|
{
|
|
return true;
|
|
}
|
|
if (_previousGeneration.TypeToEventMap.TryGetValue(item, out index))
|
|
{
|
|
return true;
|
|
}
|
|
index = 0;
|
|
return false;
|
|
}
|
|
|
|
private bool TryGetExistingPropertyMapIndex(int item, out int index)
|
|
{
|
|
if (_previousGeneration.PropertyMapAdded.TryGetValue(item, out index))
|
|
{
|
|
return true;
|
|
}
|
|
if (_previousGeneration.TypeToPropertyMap.TryGetValue(item, out index))
|
|
{
|
|
return true;
|
|
}
|
|
index = 0;
|
|
return false;
|
|
}
|
|
|
|
private bool TryGetExistingMethodImplIndex(MethodImplKey item, out int index)
|
|
{
|
|
if (_previousGeneration.MethodImplsAdded.TryGetValue(item, out index))
|
|
{
|
|
return true;
|
|
}
|
|
if (_previousGeneration.MethodImpls.TryGetValue(item, out index))
|
|
{
|
|
return true;
|
|
}
|
|
index = 0;
|
|
return false;
|
|
}
|
|
}
|