提交 eb7d42e6 编写于 作者: C CyrusNajmabadi

Store metadata inheritance info in SymbolTreeInfo.

上级 dd87f508
......@@ -268,18 +268,18 @@ private static IEnumerable<ISymbol> TranslateNamespaces(List<ISymbol> symbols, C
}
}
internal static async Task<IEnumerable<ISymbol>> FindDeclarationsAsync(
Solution solution, IAssemblySymbol assembly, PortableExecutableReference reference, SearchQuery query, SymbolFilter filter, CancellationToken cancellationToken)
{
if (query.Name != null && string.IsNullOrWhiteSpace(query.Name))
{
return SpecializedCollections.EmptyEnumerable<ISymbol>();
}
var result = new List<ISymbol>();
await AddDeclarationsAsync(solution, assembly, reference, query, filter, result, cancellationToken).ConfigureAwait(false);
return result;
}
//internal static async Task<IEnumerable<ISymbol>> FindDeclarationsAsync(
// Solution solution, IAssemblySymbol assembly, PortableExecutableReference reference, SearchQuery query, SymbolFilter filter, CancellationToken cancellationToken)
//{
// if (query.Name != null && string.IsNullOrWhiteSpace(query.Name))
// {
// return SpecializedCollections.EmptyEnumerable<ISymbol>();
// }
// var result = new List<ISymbol>();
// await AddDeclarationsAsync(solution, assembly, reference, query, filter, result, cancellationToken).ConfigureAwait(false);
// return result;
//}
private static async Task AddDeclarationsAsync(
Solution solution, IAssemblySymbol assembly, PortableExecutableReference referenceOpt,
......
......@@ -6,6 +6,7 @@
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Collections;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.FindSymbols
......@@ -22,6 +23,15 @@ internal partial class SymbolTreeInfo
/// </summary>
private readonly IReadOnlyList<Node> _nodes;
/// <summary>
/// Inheritance information for the types in this assembly. The mapping is between
/// a type's simple name (like 'IDictionary') and the metadata names of types that
/// implement it or derive from it (like 'System.Collections.Generic.IDictionary`2).
///
/// This mapping is only produced for metadata assemblies.
/// </summary>
private readonly OrderPreservingMultiDictionary<string, string> _inheritanceMap;
/// <summary>
/// The task that produces the spell checker we use for fuzzy match queries.
/// We use a task so that we can generate the <see cref="SymbolTreeInfo"/>
......@@ -52,10 +62,15 @@ internal partial class SymbolTreeInfo
: StringComparer.Ordinal.Compare(s1, s2);
};
private SymbolTreeInfo(VersionStamp version, IReadOnlyList<Node> orderedNodes, Task<SpellChecker> spellCheckerTask)
private SymbolTreeInfo(
VersionStamp version,
IReadOnlyList<Node> orderedNodes,
OrderPreservingMultiDictionary<string, string> inheritanceMap,
Task<SpellChecker> spellCheckerTask)
{
_version = version;
_nodes = orderedNodes;
_inheritanceMap = inheritanceMap;
_spellCheckerTask = spellCheckerTask;
}
......@@ -400,11 +415,12 @@ internal bool IsEquivalent(SymbolTreeInfo other)
}
private static SymbolTreeInfo CreateSymbolTreeInfo(
Solution solution, VersionStamp version, string filePath, List<Node> unsortedNodes)
Solution solution, VersionStamp version, string filePath, List<Node> unsortedNodes,
OrderPreservingMultiDictionary<string, string> inheritanceMap)
{
var sortedNodes = SortNodes(unsortedNodes);
var createSpellCheckerTask = GetSpellCheckerTask(solution, version, filePath, sortedNodes);
return new SymbolTreeInfo(version, sortedNodes, createSpellCheckerTask);
return new SymbolTreeInfo(version, sortedNodes, inheritanceMap, createSpellCheckerTask);
}
}
}
\ No newline at end of file
......@@ -14,6 +14,14 @@ namespace Microsoft.CodeAnalysis.FindSymbols
{
internal partial class SymbolTreeInfo
{
private static string GetMetadataNameWithoutBackticks(MetadataReader reader, StringHandle name)
{
var typeName = reader.GetString(name);
var index = typeName.IndexOf('`');
typeName = index > 0 ? typeName.Substring(0, index) : typeName;
return typeName;
}
private static Metadata GetMetadataNoThrow(PortableExecutableReference reference)
{
try
......@@ -88,6 +96,7 @@ private static Metadata GetMetadataNoThrow(PortableExecutableReference reference
Solution solution, VersionStamp version, PortableExecutableReference reference, CancellationToken cancellationToken)
{
var unsortedNodes = new List<Node> { new Node("", Node.RootNodeParentIndex) };
var inheritanceMap = new OrderPreservingMultiDictionary<string, string>();
foreach (var moduleMetadata in GetModuleMetadata(GetMetadataNoThrow(reference)))
{
......@@ -101,21 +110,32 @@ private static Metadata GetMetadataNoThrow(PortableExecutableReference reference
continue;
}
GenerateMetadataNodes(reader, unsortedNodes);
GenerateMetadataNodes(reader, unsortedNodes, inheritanceMap);
}
return CreateSymbolTreeInfo(solution, version, reference.FilePath, unsortedNodes);
return CreateSymbolTreeInfo(
solution,
version,
reference.FilePath,
unsortedNodes,
inheritanceMap);
}
private static void GenerateMetadataNodes(MetadataReader metadataReader, List<Node> unsortedNodes)
private static void GenerateMetadataNodes(
MetadataReader metadataReader,
List<Node> unsortedNodes,
OrderPreservingMultiDictionary<string, string> inheritanceMap)
{
GenerateMetadataNodes(metadataReader, metadataReader.GetNamespaceDefinitionRoot(), unsortedNodes);
GenerateMetadataNodes(
metadataReader, metadataReader.GetNamespaceDefinitionRoot(),
unsortedNodes, inheritanceMap);
}
private static void GenerateMetadataNodes(
MetadataReader reader,
NamespaceDefinition globalNamespace,
List<Node> unsortedNodes)
List<Node> unsortedNodes,
OrderPreservingMultiDictionary<string, string> inheritanceMap)
{
var definitionMap = OrderPreservingMultiDictionary<string, MetadataDefinition>.GetInstance();
try
......@@ -124,10 +144,15 @@ private static void GenerateMetadataNodes(MetadataReader metadataReader, List<No
foreach (var kvp in definitionMap)
{
if (UnicodeCharacterUtilities.IsValidIdentifier(kvp.Key))
var definitionName = kvp.Key;
if (UnicodeCharacterUtilities.IsValidIdentifier(definitionName))
{
GenerateMetadataNodes(reader, kvp.Key, 0 /*index of root node*/, kvp.Value, unsortedNodes);
GenerateMetadataNodes(
reader, definitionName, 0 /*index of root node*/,
kvp.Value, unsortedNodes, inheritanceMap);
}
PopulateInheritanceMap(reader, inheritanceMap, kvp);
}
}
finally
......@@ -136,12 +161,90 @@ private static void GenerateMetadataNodes(MetadataReader metadataReader, List<No
}
}
private static void PopulateInheritanceMap(MetadataReader reader, OrderPreservingMultiDictionary<string, string> inheritanceMap, KeyValuePair<string, OrderPreservingMultiDictionary<string, MetadataDefinition>.ValueSet> kvp)
{
foreach (var symbolDefinition in kvp.Value)
{
if (symbolDefinition.Kind == MetadataDefinitionKind.Type)
{
PopulateInheritance(
reader, symbolDefinition.Type, inheritanceMap);
}
}
}
private static void PopulateInheritance(
MetadataReader reader,
TypeDefinition typeDefinition,
OrderPreservingMultiDictionary<string, string> inheritanceMap)
{
var interfaceImplHandles = typeDefinition.GetInterfaceImplementations();
if (typeDefinition.BaseType.IsNil &&
interfaceImplHandles.Count == 0)
{
return;
}
var typeDefinitionFullName = typeDefinition.Namespace.IsNil
? reader.GetString(typeDefinition.Name)
: $"{reader.GetString(typeDefinition.Namespace)}.{reader.GetString(typeDefinition.Name)}";
PopulateInheritance(
reader, typeDefinitionFullName,
typeDefinition.BaseType, inheritanceMap);
foreach (var interfaceImplHandle in interfaceImplHandles)
{
if (!interfaceImplHandle.IsNil)
{
var interfaceImpl = reader.GetInterfaceImplementation(interfaceImplHandle);
PopulateInheritance(
reader, typeDefinitionFullName,
interfaceImpl.Interface, inheritanceMap);
}
}
}
private static void PopulateInheritance(
MetadataReader reader,
string typeDefinitionFullName,
EntityHandle baseTypeOrInterfaceHandle,
OrderPreservingMultiDictionary<string, string> inheritanceMap)
{
if (baseTypeOrInterfaceHandle.Kind == HandleKind.TypeDefinition)
{
var baseDefinitionHandle = (TypeDefinitionHandle)baseTypeOrInterfaceHandle;
if (!baseDefinitionHandle.IsNil)
{
var baseDefinition = reader.GetTypeDefinition(baseDefinitionHandle);
var baseName = GetMetadataNameWithoutBackticks(
reader, baseDefinition.Name);
inheritanceMap.Add(baseName, typeDefinitionFullName);
}
}
else if (baseTypeOrInterfaceHandle.Kind == HandleKind.TypeReference)
{
var baseReferenceHandle = (TypeReferenceHandle)baseTypeOrInterfaceHandle;
if (!baseReferenceHandle.IsNil)
{
var baseReference = reader.GetTypeReference(baseReferenceHandle);
var baseName = GetMetadataNameWithoutBackticks(
reader, baseReference.Name);
inheritanceMap.Add(baseName, typeDefinitionFullName);
}
}
}
private static void GenerateMetadataNodes(
MetadataReader reader,
string name,
int parentIndex,
OrderPreservingMultiDictionary<string, MetadataDefinition>.ValueSet definitionsWithSameName,
List<Node> unsortedNodes)
List<Node> unsortedNodes,
OrderPreservingMultiDictionary<string, string> inheritanceMap)
{
var node = new Node(name, parentIndex);
var nodeIndex = unsortedNodes.Count;
......@@ -160,8 +263,11 @@ private static void GenerateMetadataNodes(MetadataReader metadataReader, List<No
{
if (UnicodeCharacterUtilities.IsValidIdentifier(kvp.Key))
{
GenerateMetadataNodes(reader, kvp.Key, nodeIndex, kvp.Value, unsortedNodes);
GenerateMetadataNodes(reader, kvp.Key, nodeIndex,
kvp.Value, unsortedNodes, inheritanceMap);
}
PopulateInheritanceMap(reader, inheritanceMap, kvp);
}
}
finally
......@@ -313,9 +419,7 @@ public MetadataDefinition(MetadataDefinitionKind kind, string name)
public static MetadataDefinition Create(
MetadataReader reader, TypeDefinition definition)
{
var typeName = reader.GetString(definition.Name);
var index = typeName.IndexOf('`');
typeName = index > 0 ? typeName.Substring(0, index) : typeName;
string typeName = GetMetadataNameWithoutBackticks(reader, definition.Name);
return new MetadataDefinition(
MetadataDefinitionKind.Type,
......
......@@ -5,6 +5,7 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Collections;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.Serialization;
......@@ -15,7 +16,7 @@ namespace Microsoft.CodeAnalysis.FindSymbols
internal partial class SymbolTreeInfo : IObjectWritable
{
private const string PrefixMetadataSymbolTreeInfo = "<MetadataSymbolTreeInfoPersistence>_";
private const string SerializationFormat = "10";
private const string SerializationFormat = "12";
/// <summary>
/// Loads the SymbolTreeInfo for a given assembly symbol (metadata or project). If the
......@@ -180,6 +181,18 @@ public void WriteTo(ObjectWriter writer)
writer.WriteString(node.Name);
writer.WriteInt32(node.ParentIndex);
}
writer.WriteInt32(_inheritanceMap.Keys.Count);
foreach (var kvp in _inheritanceMap)
{
writer.WriteString(kvp.Key);
writer.WriteInt32(kvp.Value.Count);
foreach (var v in kvp.Value)
{
writer.WriteString(v);
}
}
}
internal static SymbolTreeInfo ReadSymbolTreeInfo_ForTestingPurposesOnly(ObjectReader reader)
......@@ -198,15 +211,9 @@ internal static SymbolTreeInfo ReadSymbolTreeInfo_ForTestingPurposesOnly(ObjectR
{
var version = VersionStamp.ReadFrom(reader);
var count = reader.ReadInt32();
if (count == 0)
{
return new SymbolTreeInfo(version, ImmutableArray<Node>.Empty,
Task.FromResult(new SpellChecker(version, BKTree.Empty)));
}
var nodes = new Node[count];
for (var i = 0; i < count; i++)
var nodeCount = reader.ReadInt32();
var nodes = new Node[nodeCount];
for (var i = 0; i < nodeCount; i++)
{
var name = reader.ReadString();
var parentIndex = reader.ReadInt32();
......@@ -214,8 +221,22 @@ internal static SymbolTreeInfo ReadSymbolTreeInfo_ForTestingPurposesOnly(ObjectR
nodes[i] = new Node(name, parentIndex);
}
var inheritanceMap = new OrderPreservingMultiDictionary<string, string>();
var inheritanceMapKeyCount = reader.ReadInt32();
for (var i = 0; i < inheritanceMapKeyCount; i++)
{
var key = reader.ReadString();
var valueCount = reader.ReadInt32();
for (var j = 0; j < valueCount; j++)
{
var value = reader.ReadString();
inheritanceMap.Add(key, value);
}
}
var spellCheckerTask = createSpellCheckerTask(version, nodes);
return new SymbolTreeInfo(version, nodes, spellCheckerTask);
return new SymbolTreeInfo(version, nodes, inheritanceMap, spellCheckerTask);
}
}
catch
......
......@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Collections;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.FindSymbols
......@@ -45,7 +46,8 @@ private static void FreeSymbolMap(MultiDictionary<string, ISymbol> symbolMap)
GenerateSourceNodes(assembly.GlobalNamespace, unsortedNodes, s_getMembersNoPrivate);
return CreateSymbolTreeInfo(solution, version, filePath, unsortedNodes);
var inheritanceMap = new OrderPreservingMultiDictionary<string, string>();
return CreateSymbolTreeInfo(solution, version, filePath, unsortedNodes, inheritanceMap);
}
// generate nodes for the global namespace an all descendants
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册