提交 a7afaa62 编写于 作者: C Cyrus Najmabadi

Extract type

上级 4fb54744
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Runtime.CompilerServices;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.FindSymbols
{
// Must cache using SymbolKey+ProjectId. That's because the same symbol key may be found among many projects, but
// the same operation on the same symbol key might produce different results depending on which project it was found
// in. For example, each symbol's project may have a different set of downstream dependent projects. As such,
// there may be a different set of related symbols found for each.
internal static partial class DependentTypeFinder
{
private class KeyEqualityComparer : IEqualityComparer<(SymbolKey, ProjectId, IImmutableSet<Project>)>
{
public static readonly KeyEqualityComparer Instance = new KeyEqualityComparer();
private KeyEqualityComparer()
{
}
public bool Equals((SymbolKey, ProjectId, IImmutableSet<Project>) x,
(SymbolKey, ProjectId, IImmutableSet<Project>) y)
{
var (xSymbolKey, xProjectId, xProjects) = x;
var (ySymbolKey, yProjectId, yProjects) = y;
if (!xSymbolKey.Equals(ySymbolKey))
return false;
if (!xProjectId.Equals(yProjectId))
return false;
if (xProjects is null)
return yProjects is null;
if (yProjects is null)
return false;
return xProjects.SetEquals(yProjects);
}
public int GetHashCode((SymbolKey, ProjectId, IImmutableSet<Project>) obj)
{
var (symbolKey, projectId, projects) = obj;
var projectsHash = 0;
if (projects != null)
{
foreach (var project in projects)
projectsHash += project.GetHashCode();
}
return Hash.Combine(symbolKey.GetHashCode(),
Hash.Combine(projectId, projectsHash));
}
}
}
}
......@@ -471,8 +471,6 @@ private static void AddRange(SymbolSet foundTypes, SymbolSet result)
// As long as there are new types to search for, keep looping.
while (typesToSearchFor.Count > 0)
{
tempBuffer.Clear();
foreach (var reference in compilation.References.OfType<PortableExecutableReference>())
{
cancellationToken.ThrowIfCancellationRequested();
......@@ -483,19 +481,8 @@ private static void AddRange(SymbolSet foundTypes, SymbolSet result)
cancellationToken).ConfigureAwait(false);
}
// Clear out the information about the types we're looking for. We'll
// fill these in if we discover any more types that we need to keep searching
// for.
typesToSearchFor.Clear();
foreach (var derivedType in tempBuffer)
{
if (result.Add(derivedType))
{
if (transitive && shouldContinueSearching(derivedType))
typesToSearchFor.Add(derivedType);
}
}
PropagateTemporaryResults(
result, typesToSearchFor, tempBuffer, transitive, shouldContinueSearching);
}
}
......@@ -582,8 +569,6 @@ private static bool TypeHasInterfaceInSet(INamedTypeSymbol type, SymbolSet set)
// As long as there are new types to search for, keep looping.
while (typesToSearchFor.Count > 0)
{
tempBuffer.Clear();
foreach (var type in typesToSearchFor)
{
cancellationToken.ThrowIfCancellationRequested();
......@@ -634,20 +619,40 @@ private static bool TypeHasInterfaceInSet(INamedTypeSymbol type, SymbolSet set)
cancellationToken).ConfigureAwait(false);
}
// Clear out the information about the types we're looking for. We'll
// fill these in if we discover any more types that we need to keep searching
// for.
typesToSearchFor.Clear();
PropagateTemporaryResults(
result, typesToSearchFor, tempBuffer, transitive, shouldContinueSearching);
}
}
/// <summary>
/// Moves all the types in <paramref name="tempBuffer"/> to <paramref name="result"/>. If these are types we
/// haven't seen before, and the caller says we <paramref name="shouldContinueSearching"/> on them, then add
/// them to <paramref name="typesToSearchFor"/> for the next round of searching.
/// </summary>
private static void PropagateTemporaryResults(
SymbolSet result,
SymbolSet typesToSearchFor,
SymbolSet tempBuffer,
bool transitive,
Func<INamedTypeSymbol, bool> shouldContinueSearching)
{
// Clear out the information about the types we're looking for. We'll
// fill these in if we discover any more types that we need to keep searching
// for.
typesToSearchFor.Clear();
foreach (var derivedType in tempBuffer)
foreach (var derivedType in tempBuffer)
{
// See if it's a type we've never seen before.
if (result.Add(derivedType))
{
if (result.Add(derivedType))
{
if (transitive && shouldContinueSearching(derivedType))
typesToSearchFor.Add(derivedType);
}
// If we should keep going, add it to the next batch of items we'll search for in this project.
if (transitive && shouldContinueSearching(derivedType))
typesToSearchFor.Add(derivedType);
}
}
tempBuffer.Clear();
}
private static async Task AddSourceTypesThatDeriveFromNameAsync(
......@@ -714,50 +719,5 @@ public static PooledDisposer<PooledHashSet<INamedTypeSymbol>> GetSymbolSet(out S
instance = pooledInstance;
return new PooledDisposer<PooledHashSet<INamedTypeSymbol>>(pooledInstance);
}
private class KeyEqualityComparer : IEqualityComparer<(SymbolKey, ProjectId, IImmutableSet<Project>)>
{
public static readonly KeyEqualityComparer Instance = new KeyEqualityComparer();
private KeyEqualityComparer()
{
}
public bool Equals((SymbolKey, ProjectId, IImmutableSet<Project>) x,
(SymbolKey, ProjectId, IImmutableSet<Project>) y)
{
var (xSymbolKey, xProjectId, xProjects) = x;
var (ySymbolKey, yProjectId, yProjects) = y;
if (!xSymbolKey.Equals(ySymbolKey))
return false;
if (!xProjectId.Equals(yProjectId))
return false;
if (xProjects is null)
return yProjects is null;
if (yProjects is null)
return false;
return xProjects.SetEquals(yProjects);
}
public int GetHashCode((SymbolKey, ProjectId, IImmutableSet<Project>) obj)
{
var (symbolKey, projectId, projects) = obj;
var projectsHash = 0;
if (projects != null)
{
foreach (var project in projects)
projectsHash += project.GetHashCode();
}
return Hash.Combine(symbolKey.GetHashCode(),
Hash.Combine(projectId, projectsHash));
}
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册