/// <summary> /// Loops through all type forwarders in metadata, adding them to the given table /// </summary> private void PopulateTableWithExportedTypes(Dictionary <NamespaceDefinitionHandle, NamespaceDataBuilder> table) { Debug.Assert(table != null); foreach (var exportedTypeHandle in _metadataReader.ExportedTypes) { ExportedType exportedType = _metadataReader.GetExportedType(exportedTypeHandle); if (exportedType.Implementation.Kind == HandleKind.ExportedType) { continue; // skip nested exported types. } NamespaceDefinitionHandle namespaceHandle = exportedType.Namespace; NamespaceDataBuilder builder; if (table.TryGetValue(namespaceHandle, out builder)) { builder.ExportedTypes.Add(exportedTypeHandle); } else { Debug.Assert(namespaceHandle.HasFullName); StringHandle simpleName = GetSimpleName(namespaceHandle); string fullName = _metadataReader.GetString(namespaceHandle); var newData = new NamespaceDataBuilder(namespaceHandle, simpleName, fullName); newData.ExportedTypes.Add(exportedTypeHandle); table.Add(namespaceHandle, newData); } } }
public void MergeInto(NamespaceDataBuilder other) { Parent = default(NamespaceDefinitionHandle); other.Namespaces.AddRange(this.Namespaces); other.TypeDefinitions.AddRange(this.TypeDefinitions); other.ExportedTypes.AddRange(this.ExportedTypes); }
/// <summary> /// This will take 'table' and merge all of the NamespaceData instances that point to the same /// namespace. It has to create 'stringTable' as an intermediate dictionary, so it will hand it /// back to the caller should the caller want to use it. /// </summary> private static void MergeDuplicateNamespaces(Dictionary <NamespaceDefinitionHandle, NamespaceDataBuilder> table, out Dictionary <string, NamespaceDataBuilder> stringTable) { var namespaces = new Dictionary <string, NamespaceDataBuilder>(); List <KeyValuePair <NamespaceDefinitionHandle, NamespaceDataBuilder> >?remaps = null; foreach (var group in table) { NamespaceDataBuilder data = group.Value; NamespaceDataBuilder?existingRecord; if (namespaces.TryGetValue(data.FullName, out existingRecord)) { // Children should not exist until the next step. Debug.Assert(data.Namespaces !.Count == 0); data.MergeInto(existingRecord); remaps ??= new List <KeyValuePair <NamespaceDefinitionHandle, NamespaceDataBuilder> >(); remaps.Add(new KeyValuePair <NamespaceDefinitionHandle, NamespaceDataBuilder>(group.Key, existingRecord)); } else { namespaces.Add(data.FullName, data); } } // Needs to be done outside of foreach (var group in table) to avoid modifying the dictionary while foreach'ing over it. if (remaps != null) { foreach (var tuple in remaps) { table[tuple.Key] = tuple.Value; } } stringTable = namespaces; }
/// <summary> /// Loops through all type definitions in metadata, adding them to the given table /// </summary> private void PopulateTableWithTypeDefinitions(Dictionary <NamespaceDefinitionHandle, NamespaceDataBuilder> table) { Debug.Assert(table != null); foreach (var typeHandle in _metadataReader.TypeDefinitions) { TypeDefinition type = _metadataReader.GetTypeDefinition(typeHandle); if (type.Attributes.IsNested()) { continue; } NamespaceDefinitionHandle namespaceHandle = _metadataReader.TypeDefTable.GetNamespace(typeHandle); NamespaceDataBuilder builder; if (table.TryGetValue(namespaceHandle, out builder)) { builder.TypeDefinitions.Add(typeHandle); } else { StringHandle name = GetSimpleName(namespaceHandle); string fullName = _metadataReader.GetString(namespaceHandle); var newData = new NamespaceDataBuilder(namespaceHandle, name, fullName); newData.TypeDefinitions.Add(typeHandle); table.Add(namespaceHandle, newData); } } }
/// <summary> /// Quick convenience method that handles linking together child + parent /// </summary> private void LinkChildDataToParentData(NamespaceDataBuilder child, NamespaceDataBuilder parent) { Debug.Assert(child != null && parent != null); Debug.Assert(!child.Handle.IsNil); child.Parent = parent.Handle; parent.Namespaces.Add(child.Handle); }
/// <summary> /// Links a child to its parent namespace. If the parent namespace doesn't exist, this will create a /// synthetic one. This will automatically link any synthetic namespaces it creates up to its parents. /// </summary> private void LinkChildToParentNamespace(Dictionary <string, NamespaceDataBuilder> existingNamespaces, NamespaceDataBuilder realChild, ref List <NamespaceDataBuilder> syntheticNamespaces) { Debug.Assert(realChild.Handle.HasFullName); string childName = realChild.FullName; var child = realChild; // The condition for this loop is very complex -- essentially, we keep going // until we: // A. Encounter the root namespace as 'child' // B. Find a preexisting namespace as 'parent' while (true) { int lastIndex = childName.LastIndexOf('.'); string parentName; if (lastIndex == -1) { if (childName.Length == 0) { return; } else { parentName = String.Empty; } } else { parentName = childName.Substring(0, lastIndex); } NamespaceDataBuilder parentData; if (existingNamespaces.TryGetValue(parentName, out parentData)) { LinkChildDataToParentData(child, parentData); return; } if (syntheticNamespaces != null) { foreach (var data in syntheticNamespaces) { if (data.FullName == parentName) { LinkChildDataToParentData(child, data); return; } } } else { syntheticNamespaces = new List <NamespaceDataBuilder>(); } var syntheticParent = SynthesizeNamespaceData(parentName, realChild.Handle); LinkChildDataToParentData(child, syntheticParent); syntheticNamespaces.Add(syntheticParent); childName = syntheticParent.FullName; child = syntheticParent; } }
/// <summary> /// Loops through all type forwarders in metadata, adding them to the given table /// </summary> private void PopulateTableWithExportedTypes(Dictionary<NamespaceDefinitionHandle, NamespaceDataBuilder> table) { Debug.Assert(table != null); foreach (var exportedTypeHandle in _metadataReader.ExportedTypes) { ExportedType exportedType = _metadataReader.GetExportedType(exportedTypeHandle); if (exportedType.Implementation.Kind == HandleKind.ExportedType) { continue; // skip nested exported types. } NamespaceDefinitionHandle namespaceHandle = exportedType.NamespaceDefinition; NamespaceDataBuilder builder; if (table.TryGetValue(namespaceHandle, out builder)) { builder.ExportedTypes.Add(exportedTypeHandle); } else { Debug.Assert(namespaceHandle.HasFullName); StringHandle simpleName = GetSimpleName(namespaceHandle); string fullName = _metadataReader.GetString(namespaceHandle); var newData = new NamespaceDataBuilder(namespaceHandle, simpleName, fullName); newData.ExportedTypes.Add(exportedTypeHandle); table.Add(namespaceHandle, newData); } } }
/// <summary> /// Loops through all type definitions in metadata, adding them to the given table /// </summary> private void PopulateTableWithTypeDefinitions(Dictionary<NamespaceDefinitionHandle, NamespaceDataBuilder> table) { Debug.Assert(table != null); foreach (var typeHandle in _metadataReader.TypeDefinitions) { TypeDefinition type = _metadataReader.GetTypeDefinition(typeHandle); if (type.Attributes.IsNested()) { continue; } NamespaceDefinitionHandle namespaceHandle = _metadataReader.TypeDefTable.GetNamespaceDefinition(typeHandle); NamespaceDataBuilder builder; if (table.TryGetValue(namespaceHandle, out builder)) { builder.TypeDefinitions.Add(typeHandle); } else { StringHandle name = GetSimpleName(namespaceHandle); string fullName = _metadataReader.GetString(namespaceHandle); var newData = new NamespaceDataBuilder(namespaceHandle, name, fullName); newData.TypeDefinitions.Add(typeHandle); table.Add(namespaceHandle, newData); } } }
/// <summary> /// Links a child to its parent namespace. If the parent namespace doesn't exist, this will create a /// synthetic one. This will automatically link any synthetic namespaces it creates up to its parents. /// </summary> private void LinkChildToParentNamespace(Dictionary<string, NamespaceDataBuilder> existingNamespaces, NamespaceDataBuilder realChild, ref List<NamespaceDataBuilder> syntheticNamespaces) { Debug.Assert(realChild.Handle.HasFullName); string childName = realChild.FullName; var child = realChild; // The condition for this loop is very complex -- essentially, we keep going // until we: // A. Encounter the root namespace as 'child' // B. Find a preexisting namespace as 'parent' while (true) { int lastIndex = childName.LastIndexOf('.'); string parentName; if (lastIndex == -1) { if (childName.Length == 0) { return; } else { parentName = String.Empty; } } else { parentName = childName.Substring(0, lastIndex); } NamespaceDataBuilder parentData; if (existingNamespaces.TryGetValue(parentName, out parentData)) { LinkChildDataToParentData(child, parentData); return; } if (syntheticNamespaces != null) { foreach (var data in syntheticNamespaces) { if (data.FullName == parentName) { LinkChildDataToParentData(child, data); return; } } } else { syntheticNamespaces = new List<NamespaceDataBuilder>(); } var syntheticParent = SynthesizeNamespaceData(parentName, realChild.Handle); LinkChildDataToParentData(child, syntheticParent); syntheticNamespaces.Add(syntheticParent); childName = syntheticParent.FullName; child = syntheticParent; } }