提交 42738393 编写于 作者: C CyrusNajmabadi 提交者: GitHub

Merge pull request #14048 from CyrusNajmabadi/findRefsImmutableArrays

Switch to using ImmutableArrays in findrefs.
......@@ -448,6 +448,11 @@ internal static ImmutableArray<T> Concat<T>(this ImmutableArray<T> first, Immuta
return first.AddRange(second);
}
internal static ImmutableArray<T> Concat<T>(this ImmutableArray<T> first, T second)
{
return first.Add(second);
}
internal static bool HasDuplicates<T>(this ImmutableArray<T> array, IEqualityComparer<T> comparer)
{
switch (array.Length)
......
......@@ -31,13 +31,13 @@ protected override bool CanFind(IMethodSymbol symbol)
return symbol.MethodKind == MethodKind.DelegateInvoke;
}
protected override async Task<IEnumerable<SymbolAndProjectId>> DetermineCascadedSymbolsAsync(
protected override async Task<ImmutableArray<SymbolAndProjectId>> DetermineCascadedSymbolsAsync(
SymbolAndProjectId<IMethodSymbol> symbolAndProjectId,
Solution solution,
IImmutableSet<Project> projects,
CancellationToken cancellationToken)
{
var result = new List<SymbolAndProjectId>();
var result = ImmutableArray.CreateBuilder<SymbolAndProjectId>();
var symbol = symbolAndProjectId.Symbol;
var beginInvoke = symbol.ContainingType.GetMembers(WellKnownMemberNames.DelegateBeginInvokeName).FirstOrDefault();
......@@ -57,19 +57,19 @@ protected override bool CanFind(IMethodSymbol symbol)
}
}
return result;
return result.ToImmutable();
}
protected override Task<IEnumerable<Document>> DetermineDocumentsToSearchAsync(
protected override Task<ImmutableArray<Document>> DetermineDocumentsToSearchAsync(
IMethodSymbol symbol,
Project project,
IImmutableSet<Document> documents,
CancellationToken cancellationToken)
{
return Task.FromResult(project.Documents);
return Task.FromResult(project.Documents.ToImmutableArray());
}
protected override async Task<IEnumerable<ReferenceLocation>> FindReferencesInDocumentAsync(
protected override async Task<ImmutableArray<ReferenceLocation>> FindReferencesInDocumentAsync(
IMethodSymbol methodSymbol,
Document document,
CancellationToken cancellationToken)
......@@ -100,8 +100,10 @@ protected override bool CanFind(IMethodSymbol symbol)
var invocations = nodes.Where(n => syntaxFactsService.IsInvocationExpression(n))
.Where(e => semanticModel.GetSymbolInfo(e, cancellationToken).Symbol.OriginalDefinition == methodSymbol);
return invocations.Concat(convertedAnonymousFunctions).Select(
var result = invocations.Concat(convertedAnonymousFunctions).Select(
e => new ReferenceLocation(document, null, e.GetLocation(), isImplicit: false, isWrittenTo: false, candidateReason: CandidateReason.None));
return result.ToImmutableArray();
}
}
}
......@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.LanguageServices;
......@@ -33,14 +34,14 @@ public static async Task<IEnumerable<SyntaxToken>> GetConstructorInitializerToke
return FindReferenceCache.GetConstructorInitializerTokens(syntaxFacts, model, root, cancellationToken);
}
internal static async Task<IEnumerable<SyntaxToken>> GetIdentifierOrGlobalNamespaceTokensWithTextAsync(
internal static async Task<ImmutableArray<SyntaxToken>> GetIdentifierOrGlobalNamespaceTokensWithTextAsync(
this Document document, string identifier, CancellationToken cancellationToken)
{
// model should exist already
SemanticModel model;
if (!document.TryGetSemanticModel(out model))
{
return Contract.FailWithReturn<IEnumerable<SyntaxToken>>("we should never reach here");
return Contract.FailWithReturn<ImmutableArray<SyntaxToken>>("we should never reach here");
}
// It's very costly to walk an entire tree. So if the tree is simple and doesn't contain
......@@ -48,13 +49,13 @@ public static async Task<IEnumerable<SyntaxToken>> GetConstructorInitializerToke
var info = await SyntaxTreeInfo.GetIdentifierInfoAsync(document, cancellationToken).ConfigureAwait(false);
if (!info.ProbablyContainsIdentifier(identifier))
{
return SpecializedCollections.EmptyEnumerable<SyntaxToken>();
return ImmutableArray<SyntaxToken>.Empty;
}
var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>();
if (syntaxFacts == null)
{
return SpecializedCollections.EmptyEnumerable<SyntaxToken>();
return ImmutableArray<SyntaxToken>.Empty;
}
var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false);
......
......@@ -58,7 +58,7 @@ public static SymbolInfo GetSymbolInfo(SemanticModel model, SyntaxNode node, Can
return null;
}
public static IEnumerable<SyntaxToken> GetIdentifierOrGlobalNamespaceTokensWithText(
public static ImmutableArray<SyntaxToken> GetIdentifierOrGlobalNamespaceTokensWithText(
ISyntaxFactsService syntaxFacts, Document document, VersionStamp version, SemanticModel model, SyntaxNode root, SourceText sourceText,
string text, CancellationToken cancellationToken)
{
......@@ -70,10 +70,12 @@ public static SymbolInfo GetSymbolInfo(SemanticModel model, SyntaxNode node, Can
return GetIdentifierOrGlobalNamespaceTokensWithText(syntaxFacts, document, version, root, sourceText, normalized, cancellationToken);
}
return entry.IdentifierCache.GetOrAdd(normalized, key => GetIdentifierOrGlobalNamespaceTokensWithText(syntaxFacts, document, version, root, sourceText, key, cancellationToken));
return entry.IdentifierCache.GetOrAdd(normalized,
key => GetIdentifierOrGlobalNamespaceTokensWithText(
syntaxFacts, document, version, root, sourceText, key, cancellationToken));
}
private static IList<SyntaxToken> GetIdentifierOrGlobalNamespaceTokensWithText(
private static ImmutableArray<SyntaxToken> GetIdentifierOrGlobalNamespaceTokensWithText(
ISyntaxFactsService syntaxFacts, Document document, VersionStamp version, SyntaxNode root, SourceText sourceText,
string text, CancellationToken cancellationToken)
{
......@@ -87,10 +89,10 @@ public static SymbolInfo GetSymbolInfo(SemanticModel model, SyntaxNode node, Can
}
// identifier is escaped
return root.DescendantTokens(descendIntoTrivia: true).Where(candidate).ToList();
return root.DescendantTokens(descendIntoTrivia: true).Where(candidate).ToImmutableArray();
}
private static IList<SyntaxToken> GetTokensFromText(
private static ImmutableArray<SyntaxToken> GetTokensFromText(
ISyntaxFactsService syntaxFacts, Document document, VersionStamp version, SyntaxNode root,
SourceText content, string text, Func<SyntaxToken, bool> candidate, CancellationToken cancellationToken)
{
......@@ -100,19 +102,20 @@ public static SymbolInfo GetSymbolInfo(SemanticModel model, SyntaxNode node, Can
{
if (SyntaxTreeIdentifierInfo.TryGetIdentifierLocations(document, version, text, positions.Object, cancellationToken))
{
return GetTokensFromText(root, positions.Object, text, candidate, cancellationToken).ToList();
return GetTokensFromText(root, positions.Object, text, candidate, cancellationToken);
}
}
return GetTokensFromText(syntaxFacts, root, content, text, candidate, cancellationToken).ToList();
return GetTokensFromText(syntaxFacts, root, content, text, candidate, cancellationToken);
}
return SpecializedCollections.EmptyList<SyntaxToken>();
return ImmutableArray<SyntaxToken>.Empty;
}
private static IEnumerable<SyntaxToken> GetTokensFromText(
private static ImmutableArray<SyntaxToken> GetTokensFromText(
SyntaxNode root, List<int> positions, string text, Func<SyntaxToken, bool> candidate, CancellationToken cancellationToken)
{
var result = ImmutableArray.CreateBuilder<SyntaxToken>();
foreach (var index in positions)
{
cancellationToken.ThrowIfCancellationRequested();
......@@ -122,14 +125,18 @@ public static SymbolInfo GetSymbolInfo(SemanticModel model, SyntaxNode node, Can
var span = token.Span;
if (!token.IsMissing && span.Start == index && span.Length == text.Length && candidate(token))
{
yield return token;
result.Add(token);
}
}
return result.ToImmutable();
}
private static IEnumerable<SyntaxToken> GetTokensFromText(
private static ImmutableArray<SyntaxToken> GetTokensFromText(
ISyntaxFactsService syntaxFacts, SyntaxNode root, SourceText content, string text, Func<SyntaxToken, bool> candidate, CancellationToken cancellationToken)
{
var result = ImmutableArray.CreateBuilder<SyntaxToken>();
var index = 0;
while ((index = content.IndexOf(text, index, syntaxFacts.IsCaseSensitive)) >= 0)
{
......@@ -141,12 +148,14 @@ public static SymbolInfo GetSymbolInfo(SemanticModel model, SyntaxNode node, Can
var span = token.Span;
if (!token.IsMissing && span.Start == index && span.Length == text.Length && candidate(token))
{
yield return token;
result.Add(token);
}
nextIndex = Math.Max(nextIndex, token.SpanStart);
index = nextIndex;
}
return result.ToImmutable();
}
public static IEnumerable<SyntaxToken> GetConstructorInitializerTokens(
......@@ -256,7 +265,7 @@ private class Entry
public ImmutableHashSet<string> AliasNameSet;
public List<SyntaxToken> ConstructorInitializerCache;
public readonly ConcurrentDictionary<string, IList<SyntaxToken>> IdentifierCache = new ConcurrentDictionary<string, IList<SyntaxToken>>();
public readonly ConcurrentDictionary<string, ImmutableArray<SyntaxToken>> IdentifierCache = new ConcurrentDictionary<string, ImmutableArray<SyntaxToken>>();
public readonly ConcurrentDictionary<SyntaxNode, SymbolInfo> SymbolInfoCache = new ConcurrentDictionary<SyntaxNode, SymbolInfo>();
}
}
......
......@@ -70,7 +70,7 @@ internal partial class FindReferencesSearchEngine
{
try
{
var references = await finder.FindReferencesInDocumentAsync(symbolAndProjectId, document, _cancellationToken).ConfigureAwait(false) ?? SpecializedCollections.EmptyEnumerable<ReferenceLocation>();
var references = await finder.FindReferencesInDocumentAsync(symbolAndProjectId, document, _cancellationToken).ConfigureAwait(false);
foreach (var location in references)
{
await HandleLocationAsync(symbolAndProjectId, location).ConfigureAwait(false);
......
......@@ -63,7 +63,7 @@ internal partial class FindReferencesSearchEngine
var symbol = symbolAndProjectId.Symbol;
var finder = symbolAndFinder.Item2;
var documents = await finder.DetermineDocumentsToSearchAsync(symbol, project, _documents, _cancellationToken).ConfigureAwait(false) ?? SpecializedCollections.EmptyEnumerable<Document>();
var documents = await finder.DetermineDocumentsToSearchAsync(symbol, project, _documents, _cancellationToken).ConfigureAwait(false);
foreach (var document in documents.Distinct().WhereNotNull())
{
if (_documents == null || _documents.Contains(document))
......@@ -114,7 +114,7 @@ internal partial class FindReferencesSearchEngine
{
_cancellationToken.ThrowIfCancellationRequested();
var projects = await f.DetermineProjectsToSearchAsync(s.Symbol, _solution, scope, _cancellationToken).ConfigureAwait(false) ?? SpecializedCollections.EmptyEnumerable<Project>();
var projects = await f.DetermineProjectsToSearchAsync(s.Symbol, _solution, scope, _cancellationToken).ConfigureAwait(false);
foreach (var project in projects.Distinct().WhereNotNull())
{
if (scope == null || scope.Contains(project))
......
......@@ -20,7 +20,7 @@ protected sealed override bool CanFind(TSymbol symbol)
return true;
}
protected override Task<IEnumerable<Document>> DetermineDocumentsToSearchAsync(
protected override Task<ImmutableArray<Document>> DetermineDocumentsToSearchAsync(
TSymbol symbol,
Project project,
IImmutableSet<Document> documents,
......@@ -29,24 +29,24 @@ protected sealed override bool CanFind(TSymbol symbol)
var location = symbol.Locations.FirstOrDefault();
if (location == null || !location.IsInSource)
{
return SpecializedTasks.EmptyEnumerable<Document>();
return SpecializedTasks.EmptyImmutableArray<Document>();
}
var document = project.GetDocument(location.SourceTree);
if (document == null)
{
return SpecializedTasks.EmptyEnumerable<Document>();
return SpecializedTasks.EmptyImmutableArray<Document>();
}
if (documents != null && !documents.Contains(document))
{
return SpecializedTasks.EmptyEnumerable<Document>();
return SpecializedTasks.EmptyImmutableArray<Document>();
}
return Task.FromResult(SpecializedCollections.SingletonEnumerable<Document>(document));
return Task.FromResult(ImmutableArray.Create(document));
}
protected override async Task<IEnumerable<ReferenceLocation>> FindReferencesInDocumentAsync(
protected override async Task<ImmutableArray<ReferenceLocation>> FindReferencesInDocumentAsync(
TSymbol symbol,
Document document,
CancellationToken cancellationToken)
......@@ -64,10 +64,11 @@ protected sealed override bool CanFind(TSymbol symbol)
var root = await syntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false);
var tokens = root.DescendantTokens();
return await FindReferencesInTokensWithSymbolNameAsync(symbol, document, tokens, cancellationToken).ConfigureAwait(false);
return await FindReferencesInTokensWithSymbolNameAsync(
symbol, document, tokens, cancellationToken).ConfigureAwait(false);
}
return SpecializedCollections.EmptyEnumerable<ReferenceLocation>();
return ImmutableArray<ReferenceLocation>.Empty;
}
private static ISymbol GetContainer(ISymbol symbol)
......@@ -89,7 +90,7 @@ private static ISymbol GetContainer(ISymbol symbol)
return null;
}
protected Task<IEnumerable<ReferenceLocation>> FindReferencesInTokensWithSymbolNameAsync(
protected Task<ImmutableArray<ReferenceLocation>> FindReferencesInTokensWithSymbolNameAsync(
TSymbol symbol,
Document document,
IEnumerable<SyntaxToken> tokens,
......@@ -108,7 +109,7 @@ private static ISymbol GetContainer(ISymbol symbol)
cancellationToken);
}
private Task<IEnumerable<ReferenceLocation>> FindReferencesInContainerAsync(
private Task<ImmutableArray<ReferenceLocation>> FindReferencesInContainerAsync(
TSymbol symbol,
ISymbol container,
Document document,
......
......@@ -17,7 +17,7 @@ protected AbstractMethodOrPropertyOrEventSymbolReferenceFinder()
{
}
protected override async Task<IEnumerable<SymbolAndProjectId>> DetermineCascadedSymbolsAsync(
protected override async Task<ImmutableArray<SymbolAndProjectId>> DetermineCascadedSymbolsAsync(
SymbolAndProjectId<TSymbol> symbolAndProjectId,
Solution solution,
IImmutableSet<Project> projects,
......@@ -37,23 +37,28 @@ protected AbstractMethodOrPropertyOrEventSymbolReferenceFinder()
{
// We have a normal method. Find any interface methods that it implicitly or
// explicitly implements and cascade down to those.
var interfaceMembersImplemented = await SymbolFinder.FindImplementedInterfaceMembersAsync(
var interfaceMembersImplementedStream = await SymbolFinder.FindImplementedInterfaceMembersAsync(
symbolAndProjectId, solution, projects, cancellationToken).ConfigureAwait(false);
var interfaceMembersImplemented = interfaceMembersImplementedStream.ToImmutableArray();
// Finally, methods can cascade through virtual/override inheritance. NOTE(cyrusn):
// We only need to go up or down one level. Then, when we're finding references on
// those members, we'll end up traversing the entire hierarchy.
var overrides = await SymbolFinder.FindOverridesAsync(
var overridesStream = await SymbolFinder.FindOverridesAsync(
symbolAndProjectId, solution, projects, cancellationToken).ConfigureAwait(false);
var overrides = overridesStream.ToImmutableArray();
var overriddenMember = symbolAndProjectId.WithSymbol(symbol.OverriddenMember());
return overriddenMember.Symbol == null
? interfaceMembersImplemented.Concat(overrides)
: interfaceMembersImplemented.Concat(overrides).Concat(overriddenMember);
if (overriddenMember.Symbol == null)
{
return interfaceMembersImplemented.Concat(overrides);
}
return interfaceMembersImplemented.Concat(overrides).Concat(overriddenMember);
}
}
return SpecializedCollections.EmptyEnumerable<SymbolAndProjectId>();
return ImmutableArray<SymbolAndProjectId>.Empty;
}
}
}
\ No newline at end of file
......@@ -19,7 +19,7 @@ protected override bool CanFind(IMethodSymbol symbol)
return symbol.MethodKind == MethodKind.Constructor;
}
protected override Task<IEnumerable<Document>> DetermineDocumentsToSearchAsync(
protected override Task<ImmutableArray<Document>> DetermineDocumentsToSearchAsync(
IMethodSymbol symbol,
Project project,
IImmutableSet<Document> documents,
......@@ -51,7 +51,7 @@ protected override bool CanFind(IMethodSymbol symbol)
}, cancellationToken);
}
protected override async Task<IEnumerable<ReferenceLocation>> FindReferencesInDocumentAsync(
protected override async Task<ImmutableArray<ReferenceLocation>> FindReferencesInDocumentAsync(
IMethodSymbol methodSymbol,
Document document,
CancellationToken cancellationToken)
......
......@@ -19,7 +19,7 @@ protected override bool CanFind(IMethodSymbol symbol)
return symbol.MethodKind == MethodKind.Constructor;
}
protected override async Task<IEnumerable<Document>> DetermineDocumentsToSearchAsync(
protected override async Task<ImmutableArray<Document>> DetermineDocumentsToSearchAsync(
IMethodSymbol symbol,
Project project,
IImmutableSet<Document> documents,
......@@ -35,7 +35,9 @@ protected override bool CanFind(IMethodSymbol symbol)
: SpecializedCollections.EmptyEnumerable<Document>();
return documentsWithName.Concat(documentsWithType)
.Concat(documentsWithAttribute).Distinct();
.Concat(documentsWithAttribute)
.Distinct()
.ToImmutableArray();
}
private static bool IsPotentialReference(
......@@ -50,7 +52,7 @@ protected override bool CanFind(IMethodSymbol symbol)
predefinedType == actualType;
}
protected override async Task<IEnumerable<ReferenceLocation>> FindReferencesInDocumentAsync(
protected override async Task<ImmutableArray<ReferenceLocation>> FindReferencesInDocumentAsync(
IMethodSymbol methodSymbol,
Document document,
CancellationToken cancellationToken)
......@@ -69,7 +71,7 @@ protected override bool CanFind(IMethodSymbol symbol)
return t => syntaxFacts.GetBindableParent(t);
}
private async Task<IEnumerable<ReferenceLocation>> FindReferencesInDocumentWorkerAsync(
private async Task<ImmutableArray<ReferenceLocation>> FindReferencesInDocumentWorkerAsync(
IMethodSymbol symbol,
Document document,
Func<SyntaxToken, SyntaxNode> findParentNode,
......@@ -82,7 +84,7 @@ protected override bool CanFind(IMethodSymbol symbol)
return ordinaryRefs.Concat(attributeRefs).Concat(predefinedTypeRefs);
}
private Task<IEnumerable<ReferenceLocation>> FindOrdinaryReferencesAsync(
private Task<ImmutableArray<ReferenceLocation>> FindOrdinaryReferencesAsync(
IMethodSymbol symbol,
Document document,
Func<SyntaxToken, SyntaxNode> findParentNode,
......@@ -92,7 +94,7 @@ protected override bool CanFind(IMethodSymbol symbol)
return FindReferencesInDocumentUsingIdentifierAsync(symbol, name, document, cancellationToken, findParentNode);
}
private Task<IEnumerable<ReferenceLocation>> FindPredefinedTypeReferencesAsync(
private Task<ImmutableArray<ReferenceLocation>> FindPredefinedTypeReferencesAsync(
IMethodSymbol symbol,
Document document,
CancellationToken cancellationToken)
......@@ -100,7 +102,7 @@ protected override bool CanFind(IMethodSymbol symbol)
var predefinedType = symbol.ContainingType.SpecialType.ToPredefinedType();
if (predefinedType == PredefinedType.None)
{
return SpecializedTasks.EmptyEnumerable<ReferenceLocation>();
return SpecializedTasks.EmptyImmutableArray<ReferenceLocation>();
}
var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>();
......@@ -109,7 +111,7 @@ protected override bool CanFind(IMethodSymbol symbol)
cancellationToken);
}
private Task<IEnumerable<ReferenceLocation>> FindAttributeReferencesAsync(
private Task<ImmutableArray<ReferenceLocation>> FindAttributeReferencesAsync(
IMethodSymbol symbol,
Document document,
CancellationToken cancellationToken)
......@@ -119,7 +121,7 @@ protected override bool CanFind(IMethodSymbol symbol)
string simpleName;
return TryGetNameWithoutAttributeSuffix(symbol.ContainingType.Name, syntaxFacts, out simpleName)
? FindReferencesInDocumentUsingIdentifierAsync(symbol, simpleName, document, cancellationToken)
: SpecializedTasks.EmptyEnumerable<ReferenceLocation>();
: SpecializedTasks.EmptyImmutableArray<ReferenceLocation>();
}
}
}
......@@ -15,30 +15,30 @@ protected override bool CanFind(IMethodSymbol symbol)
return symbol.MethodKind == MethodKind.Destructor;
}
protected override Task<IEnumerable<SymbolAndProjectId>> DetermineCascadedSymbolsAsync(
protected override Task<ImmutableArray<SymbolAndProjectId>> DetermineCascadedSymbolsAsync(
SymbolAndProjectId<IMethodSymbol> symbol,
Solution solution,
IImmutableSet<Project> projects,
CancellationToken cancellationToken)
{
return SpecializedTasks.EmptyEnumerable<SymbolAndProjectId>();
return SpecializedTasks.EmptyImmutableArray<SymbolAndProjectId>();
}
protected override Task<IEnumerable<Document>> DetermineDocumentsToSearchAsync(
protected override Task<ImmutableArray<Document>> DetermineDocumentsToSearchAsync(
IMethodSymbol symbol,
Project project,
IImmutableSet<Document> documents,
CancellationToken cancellationToken)
{
return SpecializedTasks.EmptyEnumerable<Document>();
return SpecializedTasks.EmptyImmutableArray<Document>();
}
protected override Task<IEnumerable<ReferenceLocation>> FindReferencesInDocumentAsync(
protected override Task<ImmutableArray<ReferenceLocation>> FindReferencesInDocumentAsync(
IMethodSymbol methodSymbol,
Document document,
CancellationToken cancellationToken)
{
return SpecializedTasks.EmptyEnumerable<ReferenceLocation>();
return SpecializedTasks.EmptyImmutableArray<ReferenceLocation>();
}
}
}
......@@ -17,30 +17,31 @@ protected override bool CanFind(IEventSymbol symbol)
return true;
}
protected override async Task<IEnumerable<SymbolAndProjectId>> DetermineCascadedSymbolsAsync(
protected override async Task<ImmutableArray<SymbolAndProjectId>> DetermineCascadedSymbolsAsync(
SymbolAndProjectId<IEventSymbol> symbolAndProjectId,
Solution solution,
IImmutableSet<Project> projects,
CancellationToken cancellationToken)
{
var baseSymbols = await base.DetermineCascadedSymbolsAsync(symbolAndProjectId, solution, projects, cancellationToken).ConfigureAwait(false);
baseSymbols = baseSymbols ?? SpecializedCollections.EmptyEnumerable<SymbolAndProjectId>();
var symbol = symbolAndProjectId.Symbol;
var backingFields = symbol.ContainingType.GetMembers()
.OfType<IFieldSymbol>()
.Where(f => symbol.Equals(f.AssociatedSymbol))
.Select(s => (SymbolAndProjectId)symbolAndProjectId.WithSymbol(s));
.Select(s => (SymbolAndProjectId)symbolAndProjectId.WithSymbol(s))
.ToImmutableArray();
var associatedNamedTypes = symbol.ContainingType.GetTypeMembers()
.Where(n => symbol.Equals(n.AssociatedSymbol))
.Select(s => (SymbolAndProjectId)symbolAndProjectId.WithSymbol(s));
.Select(s => (SymbolAndProjectId)symbolAndProjectId.WithSymbol(s))
.ToImmutableArray();
return baseSymbols.Concat(backingFields)
.Concat(associatedNamedTypes);
}
protected override Task<IEnumerable<Document>> DetermineDocumentsToSearchAsync(
protected override Task<ImmutableArray<Document>> DetermineDocumentsToSearchAsync(
IEventSymbol symbol,
Project project,
IImmutableSet<Document> documents,
......@@ -49,7 +50,7 @@ protected override bool CanFind(IEventSymbol symbol)
return FindDocumentsAsync(project, documents, cancellationToken, symbol.Name);
}
protected override Task<IEnumerable<ReferenceLocation>> FindReferencesInDocumentAsync(
protected override Task<ImmutableArray<ReferenceLocation>> FindReferencesInDocumentAsync(
IEventSymbol symbol,
Document document,
CancellationToken cancellationToken)
......
......@@ -16,7 +16,7 @@ protected override bool CanFind(IMethodSymbol symbol)
return symbol.MethodKind == MethodKind.ExplicitInterfaceImplementation;
}
protected override Task<IEnumerable<SymbolAndProjectId>> DetermineCascadedSymbolsAsync(
protected override Task<ImmutableArray<SymbolAndProjectId>> DetermineCascadedSymbolsAsync(
SymbolAndProjectId<IMethodSymbol> symbolAndProjectId,
Solution solution,
IImmutableSet<Project> projects,
......@@ -25,26 +25,26 @@ protected override bool CanFind(IMethodSymbol symbol)
// An explicit interface method will cascade to all the methods that it implements.
return Task.FromResult(
symbolAndProjectId.Symbol.ExplicitInterfaceImplementations.Select(
ei => symbolAndProjectId.WithSymbol((ISymbol)ei)));
ei => symbolAndProjectId.WithSymbol((ISymbol)ei)).ToImmutableArray());
}
protected override Task<IEnumerable<Document>> DetermineDocumentsToSearchAsync(
protected override Task<ImmutableArray<Document>> DetermineDocumentsToSearchAsync(
IMethodSymbol symbol,
Project project,
IImmutableSet<Document> documents,
CancellationToken cancellationToken)
{
// An explicit method can't be referenced anywhere.
return SpecializedTasks.Default<IEnumerable<Document>>();
return SpecializedTasks.EmptyImmutableArray<Document>();
}
protected override Task<IEnumerable<ReferenceLocation>> FindReferencesInDocumentAsync(
protected override Task<ImmutableArray<ReferenceLocation>> FindReferencesInDocumentAsync(
IMethodSymbol symbol,
Document document,
CancellationToken cancellationToken)
{
// An explicit method can't be referenced anywhere.
return SpecializedTasks.Default<IEnumerable<ReferenceLocation>>();
return SpecializedTasks.EmptyImmutableArray<ReferenceLocation>();
}
}
}
......@@ -15,7 +15,7 @@ protected override bool CanFind(IFieldSymbol symbol)
return true;
}
protected override Task<IEnumerable<SymbolAndProjectId>> DetermineCascadedSymbolsAsync(
protected override Task<ImmutableArray<SymbolAndProjectId>> DetermineCascadedSymbolsAsync(
SymbolAndProjectId<IFieldSymbol> symbolAndProjectId,
Solution solution,
IImmutableSet<Project> projects,
......@@ -25,16 +25,15 @@ protected override bool CanFind(IFieldSymbol symbol)
if (symbol.AssociatedSymbol != null)
{
return Task.FromResult(
SpecializedCollections.SingletonEnumerable(
symbolAndProjectId.WithSymbol(symbol.AssociatedSymbol)));
ImmutableArray.Create(symbolAndProjectId.WithSymbol(symbol.AssociatedSymbol)));
}
else
{
return SpecializedTasks.EmptyEnumerable<SymbolAndProjectId>();
return SpecializedTasks.EmptyImmutableArray<SymbolAndProjectId>();
}
}
protected override Task<IEnumerable<Document>> DetermineDocumentsToSearchAsync(
protected override Task<ImmutableArray<Document>> DetermineDocumentsToSearchAsync(
IFieldSymbol symbol,
Project project,
IImmutableSet<Document> documents,
......@@ -43,7 +42,7 @@ protected override bool CanFind(IFieldSymbol symbol)
return FindDocumentsAsync(project, documents, cancellationToken, symbol.Name);
}
protected override Task<IEnumerable<ReferenceLocation>> FindReferencesInDocumentAsync(
protected override Task<ImmutableArray<ReferenceLocation>> FindReferencesInDocumentAsync(
IFieldSymbol symbol,
Document document,
CancellationToken cancellationToken)
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Host;
......@@ -14,7 +15,7 @@ namespace Microsoft.CodeAnalysis.FindSymbols.Finders
/// </summary>
internal interface ILanguageServiceReferenceFinder : ILanguageService
{
Task<IEnumerable<SymbolAndProjectId>> DetermineCascadedSymbolsAsync(
Task<ImmutableArray<SymbolAndProjectId>> DetermineCascadedSymbolsAsync(
SymbolAndProjectId symbolAndProjectId, Project project, CancellationToken cancellationToken);
}
}
\ No newline at end of file
......@@ -28,7 +28,7 @@ internal interface IReferenceFinder
///
/// Implementations of this method must be thread-safe.
/// </summary>
Task<IEnumerable<Project>> DetermineProjectsToSearchAsync(ISymbol symbol, Solution solution, IImmutableSet<Project> projects = null, CancellationToken cancellationToken = default(CancellationToken));
Task<ImmutableArray<Project>> DetermineProjectsToSearchAsync(ISymbol symbol, Solution solution, IImmutableSet<Project> projects = null, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Called by the find references search engine to determine which documents in the supplied
......@@ -42,7 +42,7 @@ internal interface IReferenceFinder
///
/// Implementations of this method must be thread-safe.
/// </summary>
Task<IEnumerable<Document>> DetermineDocumentsToSearchAsync(ISymbol symbol, Project project, IImmutableSet<Document> documents, CancellationToken cancellationToken = default(CancellationToken));
Task<ImmutableArray<Document>> DetermineDocumentsToSearchAsync(ISymbol symbol, Project project, IImmutableSet<Document> documents, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Called by the find references search engine to determine the set of reference locations
......@@ -51,7 +51,7 @@ internal interface IReferenceFinder
///
/// Implementations of this method must be thread-safe.
/// </summary>
Task<IEnumerable<ReferenceLocation>> FindReferencesInDocumentAsync(
Task<ImmutableArray<ReferenceLocation>> FindReferencesInDocumentAsync(
SymbolAndProjectId symbolAndProjectId, Document document, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
......@@ -62,7 +62,7 @@ internal interface IReferenceFinder
///
/// Implementations of this method must be thread-safe.
/// </summary>
Task<IEnumerable<SymbolAndProjectId>> DetermineCascadedSymbolsAsync(
Task<ImmutableArray<SymbolAndProjectId>> DetermineCascadedSymbolsAsync(
SymbolAndProjectId symbolAndProject, Solution solution, IImmutableSet<Project> projects = null, CancellationToken cancellationToken = default(CancellationToken));
}
}
......@@ -11,7 +11,7 @@ namespace Microsoft.CodeAnalysis.FindSymbols.Finders
{
internal class LinkedFileReferenceFinder : IReferenceFinder
{
public async Task<IEnumerable<SymbolAndProjectId>> DetermineCascadedSymbolsAsync(
public async Task<ImmutableArray<SymbolAndProjectId>> DetermineCascadedSymbolsAsync(
SymbolAndProjectId symbolAndProjectId, Solution solution, IImmutableSet<Project> projects = null, CancellationToken cancellationToken = default(CancellationToken))
{
var linkedSymbols = new HashSet<SymbolAndProjectId>();
......@@ -59,23 +59,23 @@ internal class LinkedFileReferenceFinder : IReferenceFinder
}
}
return linkedSymbols;
return linkedSymbols.ToImmutableArray();
}
public Task<IEnumerable<Document>> DetermineDocumentsToSearchAsync(ISymbol symbol, Project project, IImmutableSet<Document> documents, CancellationToken cancellationToken = default(CancellationToken))
public Task<ImmutableArray<Document>> DetermineDocumentsToSearchAsync(ISymbol symbol, Project project, IImmutableSet<Document> documents, CancellationToken cancellationToken = default(CancellationToken))
{
return SpecializedTasks.EmptyEnumerable<Document>();
return SpecializedTasks.EmptyImmutableArray<Document>();
}
public Task<IEnumerable<Project>> DetermineProjectsToSearchAsync(ISymbol symbol, Solution solution, IImmutableSet<Project> projects = null, CancellationToken cancellationToken = default(CancellationToken))
public Task<ImmutableArray<Project>> DetermineProjectsToSearchAsync(ISymbol symbol, Solution solution, IImmutableSet<Project> projects = null, CancellationToken cancellationToken = default(CancellationToken))
{
return SpecializedTasks.EmptyEnumerable<Project>();
return SpecializedTasks.EmptyImmutableArray<Project>();
}
public Task<IEnumerable<ReferenceLocation>> FindReferencesInDocumentAsync(
public Task<ImmutableArray<ReferenceLocation>> FindReferencesInDocumentAsync(
SymbolAndProjectId symbolAndProjectId, Document document, CancellationToken cancellationToken = default(CancellationToken))
{
return SpecializedTasks.EmptyEnumerable<ReferenceLocation>();
return SpecializedTasks.EmptyImmutableArray<ReferenceLocation>();
}
}
}
......@@ -15,7 +15,7 @@ protected override bool CanFind(ITypeParameterSymbol symbol)
return symbol.TypeParameterKind == TypeParameterKind.Method;
}
protected override Task<IEnumerable<SymbolAndProjectId>> DetermineCascadedSymbolsAsync(
protected override Task<ImmutableArray<SymbolAndProjectId>> DetermineCascadedSymbolsAsync(
SymbolAndProjectId<ITypeParameterSymbol> symbolAndProjectId,
Solution solution,
IImmutableSet<Project> projects,
......@@ -29,21 +29,21 @@ protected override bool CanFind(ITypeParameterSymbol symbol)
{
if (method.PartialDefinitionPart != null && ordinal < method.PartialDefinitionPart.TypeParameters.Length)
{
return Task.FromResult(SpecializedCollections.SingletonEnumerable(
return Task.FromResult(ImmutableArray.Create(
symbolAndProjectId.WithSymbol((ISymbol)method.PartialDefinitionPart.TypeParameters[ordinal])));
}
if (method.PartialImplementationPart != null && ordinal < method.PartialImplementationPart.TypeParameters.Length)
{
return Task.FromResult(SpecializedCollections.SingletonEnumerable(
return Task.FromResult(ImmutableArray.Create(
symbolAndProjectId.WithSymbol((ISymbol)method.PartialImplementationPart.TypeParameters[ordinal])));
}
}
return SpecializedTasks.EmptyEnumerable<SymbolAndProjectId>();
return SpecializedTasks.EmptyImmutableArray<SymbolAndProjectId>();
}
protected override Task<IEnumerable<Document>> DetermineDocumentsToSearchAsync(
protected override Task<ImmutableArray<Document>> DetermineDocumentsToSearchAsync(
ITypeParameterSymbol symbol,
Project project,
IImmutableSet<Document> documents,
......@@ -72,7 +72,7 @@ private static string GetMemberNameWithoutInterfaceName(string fullName)
: fullName;
}
protected override Task<IEnumerable<ReferenceLocation>> FindReferencesInDocumentAsync(
protected override Task<ImmutableArray<ReferenceLocation>> FindReferencesInDocumentAsync(
ITypeParameterSymbol symbol,
Document document,
CancellationToken cancellationToken)
......
......@@ -19,45 +19,39 @@ protected override bool CanFind(INamedTypeSymbol symbol)
return symbol.TypeKind != TypeKind.Error;
}
protected override Task<IEnumerable<SymbolAndProjectId>> DetermineCascadedSymbolsAsync(
protected override Task<ImmutableArray<SymbolAndProjectId>> DetermineCascadedSymbolsAsync(
SymbolAndProjectId<INamedTypeSymbol> symbolAndProjectId,
Solution solution,
IImmutableSet<Project> projects,
CancellationToken cancellationToken)
{
List<SymbolAndProjectId> result = null;
var result = ArrayBuilder<SymbolAndProjectId>.GetInstance();
var symbol = symbolAndProjectId.Symbol;
if (symbol.AssociatedSymbol != null)
{
result = Add(result, symbolAndProjectId, SpecializedCollections.SingletonEnumerable(symbol.AssociatedSymbol));
Add(result, symbolAndProjectId, ImmutableArray.Create(symbol.AssociatedSymbol));
}
// cascade to constructors
result = Add(result, symbolAndProjectId, symbol.Constructors);
Add(result, symbolAndProjectId, symbol.Constructors);
// cascade to destructor
result = Add(result, symbolAndProjectId, symbol.GetMembers(WellKnownMemberNames.DestructorName));
Add(result, symbolAndProjectId, symbol.GetMembers(WellKnownMemberNames.DestructorName));
return Task.FromResult<IEnumerable<SymbolAndProjectId>>(
result ?? SpecializedCollections.EmptyList<SymbolAndProjectId>());
return Task.FromResult(result.ToImmutableAndFree());
}
private List<SymbolAndProjectId> Add(
List<SymbolAndProjectId> result,
private void Add<TSymbol>(
ArrayBuilder<SymbolAndProjectId> result,
SymbolAndProjectId symbolAndProjectId,
IEnumerable<ISymbol> enumerable)
ImmutableArray<TSymbol> enumerable) where TSymbol : ISymbol
{
if (enumerable != null)
{
result = result ?? new List<SymbolAndProjectId>();
result.AddRange(enumerable.Select(s => symbolAndProjectId.WithSymbol(s)));
}
return result;
result.AddRange(enumerable.Select(
s => symbolAndProjectId.WithSymbol((ISymbol)s)));
}
protected override async Task<IEnumerable<Document>> DetermineDocumentsToSearchAsync(
protected override async Task<ImmutableArray<Document>> DetermineDocumentsToSearchAsync(
INamedTypeSymbol symbol,
Project project,
IImmutableSet<Document> documents,
......@@ -69,9 +63,10 @@ protected override bool CanFind(INamedTypeSymbol symbol)
string simpleName;
var documentsWithAttribute = TryGetNameWithoutAttributeSuffix(symbol.Name, project.LanguageServices.GetService<ISyntaxFactsService>(), out simpleName)
? await FindDocumentsAsync(project, documents, cancellationToken, simpleName).ConfigureAwait(false)
: SpecializedCollections.EmptyEnumerable<Document>();
: ImmutableArray<Document>.Empty;
return documentsWithName.Concat(documentsWithType).Concat(documentsWithAttribute);
return documentsWithName.Concat(documentsWithType)
.Concat(documentsWithAttribute);
}
private static bool IsPotentialReference(
......@@ -86,7 +81,7 @@ protected override bool CanFind(INamedTypeSymbol symbol)
predefinedType == actualType;
}
protected override async Task<IEnumerable<ReferenceLocation>> FindReferencesInDocumentAsync(
protected override async Task<ImmutableArray<ReferenceLocation>> FindReferencesInDocumentAsync(
INamedTypeSymbol namedType,
Document document,
CancellationToken cancellationToken)
......@@ -97,7 +92,7 @@ protected override bool CanFind(INamedTypeSymbol symbol)
return nonAliasReferences.Concat(aliasReferences);
}
internal static async Task<IEnumerable<ReferenceLocation>> FindNonAliasReferencesAsync(
internal static async Task<ImmutableArray<ReferenceLocation>> FindNonAliasReferencesAsync(
INamedTypeSymbol symbol,
Document document,
CancellationToken cancellationToken)
......@@ -108,7 +103,7 @@ protected override bool CanFind(INamedTypeSymbol symbol)
return ordinaryRefs.Concat(attributeRefs).Concat(predefinedTypeRefs);
}
private static Task<IEnumerable<ReferenceLocation>> FindOrdinaryReferencesAsync(
private static Task<ImmutableArray<ReferenceLocation>> FindOrdinaryReferencesAsync(
INamedTypeSymbol namedType,
Document document,
CancellationToken cancellationToken)
......@@ -119,7 +114,7 @@ protected override bool CanFind(INamedTypeSymbol symbol)
namedType.Name, document, symbolsMatch, cancellationToken);
}
private static Task<IEnumerable<ReferenceLocation>> FindPredefinedTypeReferencesAsync(
private static Task<ImmutableArray<ReferenceLocation>> FindPredefinedTypeReferencesAsync(
INamedTypeSymbol symbol,
Document document,
CancellationToken cancellationToken)
......@@ -127,7 +122,7 @@ protected override bool CanFind(INamedTypeSymbol symbol)
var predefinedType = symbol.SpecialType.ToPredefinedType();
if (predefinedType == PredefinedType.None)
{
return SpecializedTasks.EmptyEnumerable<ReferenceLocation>();
return SpecializedTasks.EmptyImmutableArray<ReferenceLocation>();
}
var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>();
......@@ -137,7 +132,7 @@ protected override bool CanFind(INamedTypeSymbol symbol)
cancellationToken);
}
private static Task<IEnumerable<ReferenceLocation>> FindAttributeReferencesAsync(
private static Task<ImmutableArray<ReferenceLocation>> FindAttributeReferencesAsync(
INamedTypeSymbol namedType,
Document document,
CancellationToken cancellationToken)
......@@ -148,7 +143,7 @@ protected override bool CanFind(INamedTypeSymbol symbol)
string simpleName;
return TryGetNameWithoutAttributeSuffix(namedType.Name, syntaxFacts, out simpleName)
? FindReferencesInDocumentUsingIdentifierAsync(simpleName, document, symbolsMatch, cancellationToken)
: SpecializedTasks.EmptyEnumerable<ReferenceLocation>();
: SpecializedTasks.EmptyImmutableArray<ReferenceLocation>();
}
}
}
......@@ -19,7 +19,7 @@ protected override bool CanFind(INamespaceSymbol symbol)
return true;
}
protected override Task<IEnumerable<Document>> DetermineDocumentsToSearchAsync(
protected override Task<ImmutableArray<Document>> DetermineDocumentsToSearchAsync(
INamespaceSymbol symbol,
Project project,
IImmutableSet<Document> documents,
......@@ -35,7 +35,7 @@ private static string GetNamespaceIdentifierName(INamespaceSymbol symbol, Projec
: symbol.Name;
}
protected override async Task<IEnumerable<ReferenceLocation>> FindReferencesInDocumentAsync(
protected override async Task<ImmutableArray<ReferenceLocation>> FindReferencesInDocumentAsync(
INamespaceSymbol symbol,
Document document,
CancellationToken cancellationToken)
......
......@@ -16,7 +16,7 @@ protected override bool CanFind(IMethodSymbol symbol)
return symbol.MethodKind == MethodKind.UserDefinedOperator;
}
protected override Task<IEnumerable<Document>> DetermineDocumentsToSearchAsync(
protected override Task<ImmutableArray<Document>> DetermineDocumentsToSearchAsync(
IMethodSymbol symbol,
Project project,
IImmutableSet<Document> documents,
......@@ -26,7 +26,7 @@ protected override bool CanFind(IMethodSymbol symbol)
return FindDocumentsAsync(project, documents, op, cancellationToken);
}
protected override Task<IEnumerable<ReferenceLocation>> FindReferencesInDocumentAsync(
protected override Task<ImmutableArray<ReferenceLocation>> FindReferencesInDocumentAsync(
IMethodSymbol symbol,
Document document,
CancellationToken cancellationToken)
......
......@@ -23,7 +23,7 @@ protected override bool CanFind(IMethodSymbol symbol)
symbol.MethodKind == MethodKind.LocalFunction;
}
protected override async Task<IEnumerable<SymbolAndProjectId>> DetermineCascadedSymbolsAsync(
protected override async Task<ImmutableArray<SymbolAndProjectId>> DetermineCascadedSymbolsAsync(
SymbolAndProjectId<IMethodSymbol> symbolAndProjectId,
Solution solution,
IImmutableSet<Project> projects,
......@@ -34,7 +34,7 @@ protected override bool CanFind(IMethodSymbol symbol)
var symbol = symbolAndProjectId.Symbol;
if (symbol.ContainingType.TypeKind == TypeKind.Delegate)
{
return SpecializedCollections.SingletonEnumerable(
return ImmutableArray.Create(
symbolAndProjectId.WithSymbol((ISymbol)symbol.ContainingType));
}
else
......@@ -44,36 +44,33 @@ protected override bool CanFind(IMethodSymbol symbol)
if (otherPartsOfPartial == null && baseCascadedSymbols == null)
{
return null;
return ImmutableArray<SymbolAndProjectId>.Empty;
}
otherPartsOfPartial = otherPartsOfPartial ?? SpecializedCollections.EmptyEnumerable<SymbolAndProjectId>();
baseCascadedSymbols = baseCascadedSymbols ?? SpecializedCollections.EmptyEnumerable<SymbolAndProjectId>();
return otherPartsOfPartial.Concat(baseCascadedSymbols);
}
}
private IEnumerable<SymbolAndProjectId> GetOtherPartsOfPartial(
private ImmutableArray<SymbolAndProjectId> GetOtherPartsOfPartial(
SymbolAndProjectId<IMethodSymbol> symbolAndProjectId)
{
var symbol = symbolAndProjectId.Symbol;
if (symbol.PartialDefinitionPart != null)
{
return SpecializedCollections.SingletonEnumerable(
return ImmutableArray.Create(
symbolAndProjectId.WithSymbol((ISymbol)symbol.PartialDefinitionPart));
}
if (symbol.PartialImplementationPart != null)
{
return SpecializedCollections.SingletonEnumerable(
return ImmutableArray.Create(
symbolAndProjectId.WithSymbol((ISymbol)symbol.PartialImplementationPart));
}
return null;
return ImmutableArray<SymbolAndProjectId>.Empty;
}
protected override async Task<IEnumerable<Document>> DetermineDocumentsToSearchAsync(
protected override async Task<ImmutableArray<Document>> DetermineDocumentsToSearchAsync(
IMethodSymbol methodSymbol,
Project project,
IImmutableSet<Document> documents,
......@@ -97,7 +94,7 @@ protected override bool CanFind(IMethodSymbol symbol)
var ordinaryDocuments = await FindDocumentsAsync(project, documents, cancellationToken, methodSymbol.Name).ConfigureAwait(false);
var forEachDocuments = IsForEachMethod(methodSymbol)
? await FindDocumentsWithForEachStatementsAsync(project, documents, cancellationToken).ConfigureAwait(false)
: SpecializedCollections.EmptyEnumerable<Document>();
: ImmutableArray<Document>.Empty;
return ordinaryDocuments.Concat(forEachDocuments);
}
......@@ -109,7 +106,7 @@ private bool IsForEachMethod(IMethodSymbol methodSymbol)
methodSymbol.Name == WellKnownMemberNames.MoveNextMethodName;
}
protected override async Task<IEnumerable<ReferenceLocation>> FindReferencesInDocumentAsync(
protected override async Task<ImmutableArray<ReferenceLocation>> FindReferencesInDocumentAsync(
IMethodSymbol symbol,
Document document,
CancellationToken cancellationToken)
......@@ -122,7 +119,7 @@ private bool IsForEachMethod(IMethodSymbol methodSymbol)
var forEachMatches = IsForEachMethod(symbol)
? await FindReferencesInForEachStatementsAsync(symbol, document, cancellationToken).ConfigureAwait(false)
: SpecializedCollections.EmptyEnumerable<ReferenceLocation>();
: ImmutableArray<ReferenceLocation>.Empty;
return nameMatches.Concat(forEachMatches);
}
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
......@@ -8,7 +7,6 @@
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.Utilities;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.FindSymbols.Finders
{
......@@ -19,7 +17,7 @@ protected override bool CanFind(IParameterSymbol symbol)
return true;
}
protected override Task<IEnumerable<Document>> DetermineDocumentsToSearchAsync(
protected override Task<ImmutableArray<Document>> DetermineDocumentsToSearchAsync(
IParameterSymbol symbol,
Project project,
IImmutableSet<Document> documents,
......@@ -33,7 +31,7 @@ protected override bool CanFind(IParameterSymbol symbol)
return FindDocumentsAsync(project, documents, cancellationToken, symbol.Name);
}
protected override Task<IEnumerable<ReferenceLocation>> FindReferencesInDocumentAsync(
protected override Task<ImmutableArray<ReferenceLocation>> FindReferencesInDocumentAsync(
IParameterSymbol symbol,
Document document,
CancellationToken cancellationToken)
......@@ -41,7 +39,7 @@ protected override bool CanFind(IParameterSymbol symbol)
return FindReferencesInDocumentUsingSymbolNameAsync(symbol, document, cancellationToken);
}
protected override async Task<IEnumerable<SymbolAndProjectId>> DetermineCascadedSymbolsAsync(
protected override async Task<ImmutableArray<SymbolAndProjectId>> DetermineCascadedSymbolsAsync(
SymbolAndProjectId<IParameterSymbol> parameterAndProjectId,
Solution solution,
IImmutableSet<Project> projects,
......@@ -50,7 +48,7 @@ protected override bool CanFind(IParameterSymbol symbol)
var parameter = parameterAndProjectId.Symbol;
if (parameter.IsThis)
{
return null;
return ImmutableArray<SymbolAndProjectId>.Empty;
}
var anonymousFunctionParameterCascades = await CascadeBetweenAnonymousFunctionParametersAsync(
......@@ -64,12 +62,12 @@ protected override bool CanFind(IParameterSymbol symbol)
CascadeBetweenPartialMethodParameters(parameterAndProjectId));
}
private async Task<IEnumerable<SymbolAndProjectId>> CascadeBetweenAnonymousFunctionParametersAsync(
private async Task<ImmutableArray<SymbolAndProjectId>> CascadeBetweenAnonymousFunctionParametersAsync(
Solution solution,
SymbolAndProjectId<IParameterSymbol> parameterAndProjectId,
CancellationToken cancellationToken)
{
List<SymbolAndProjectId> results = null;
var results = ArrayBuilder<SymbolAndProjectId>.GetInstance();
var parameter = parameterAndProjectId.Symbol;
if (parameter.ContainingSymbol.IsAnonymousFunction())
......@@ -94,7 +92,6 @@ protected override bool CanFind(IParameterSymbol symbol)
var container = GetContainer(semanticModel, parameterNode, syntaxFactsService);
if (container != null)
{
results = new List<SymbolAndProjectId>();
results.AddRange(CascadeBetweenAnonymousFunctionParameters(
document, semanticModel, container, parameterAndProjectId, convertedType, cancellationToken));
}
......@@ -110,21 +107,16 @@ protected override bool CanFind(IParameterSymbol symbol)
int ordinal = parameter.Ordinal;
if (invokeMethod != null && ordinal < invokeMethod.Parameters.Length)
{
if (results == null)
{
results = new List<SymbolAndProjectId>();
}
results.Add(parameterAndProjectId.WithSymbol(
invokeMethod.Parameters[ordinal]));
}
}
}
return results ?? SpecializedCollections.EmptyEnumerable<SymbolAndProjectId>();
return results.ToImmutableAndFree();
}
private IEnumerable<SymbolAndProjectId> CascadeBetweenAnonymousFunctionParameters(
private ImmutableArray<SymbolAndProjectId> CascadeBetweenAnonymousFunctionParameters(
Document document,
SemanticModel semanticModel,
SyntaxNode container,
......@@ -132,6 +124,8 @@ protected override bool CanFind(IParameterSymbol symbol)
ITypeSymbol convertedType1,
CancellationToken cancellationToken)
{
var result = ArrayBuilder<SymbolAndProjectId>.GetInstance();
var parameter = parameterAndProjectId.Symbol;
var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>();
foreach (var token in container.DescendantTokens())
......@@ -149,11 +143,13 @@ protected override bool CanFind(IParameterSymbol symbol)
if (convertedType1.Equals(convertedType2))
{
yield return parameterAndProjectId.WithSymbol(symbol);
result.Add(parameterAndProjectId.WithSymbol(symbol));
}
}
}
}
return result.ToImmutableAndFree();
}
private bool ParameterNamesMatch(ISyntaxFactsService syntaxFacts, IMethodSymbol methodSymbol1, IMethodSymbol methodSymbol2)
......@@ -184,12 +180,12 @@ private SyntaxNode GetContainer(SemanticModel semanticModel, SyntaxNode paramete
return syntaxFactsService.GetContainingVariableDeclaratorOfFieldDeclaration(parameterNode);
}
private async Task<IEnumerable<SymbolAndProjectId>> CascadeBetweenPropertyOrEventAndAccessorParameterAsync(
private async Task<ImmutableArray<SymbolAndProjectId>> CascadeBetweenPropertyOrEventAndAccessorParameterAsync(
Solution solution,
SymbolAndProjectId<IParameterSymbol> parameterAndProjectId,
CancellationToken cancellationToken)
{
var results = new List<SymbolAndProjectId>();
var results = ArrayBuilder<SymbolAndProjectId>.GetInstance();
var parameter = parameterAndProjectId.Symbol;
var ordinal = parameter.Ordinal;
......@@ -272,12 +268,14 @@ private SyntaxNode GetContainer(SemanticModel semanticModel, SyntaxNode paramete
}
}
return results;
return results.ToImmutableAndFree();
}
private IEnumerable<SymbolAndProjectId> CascadeBetweenPartialMethodParameters(
private ImmutableArray<SymbolAndProjectId> CascadeBetweenPartialMethodParameters(
SymbolAndProjectId<IParameterSymbol> parameterAndProjectId)
{
var result = ArrayBuilder<SymbolAndProjectId>.GetInstance();
var parameter = parameterAndProjectId.Symbol;
if (parameter.ContainingSymbol is IMethodSymbol)
{
......@@ -285,14 +283,18 @@ private SyntaxNode GetContainer(SemanticModel semanticModel, SyntaxNode paramete
var method = (IMethodSymbol)parameter.ContainingSymbol;
if (method.PartialDefinitionPart != null && ordinal < method.PartialDefinitionPart.Parameters.Length)
{
yield return parameterAndProjectId.WithSymbol(method.PartialDefinitionPart.Parameters[ordinal]);
result.Add(
parameterAndProjectId.WithSymbol(method.PartialDefinitionPart.Parameters[ordinal]));
}
if (method.PartialImplementationPart != null && ordinal < method.PartialImplementationPart.Parameters.Length)
{
yield return parameterAndProjectId.WithSymbol(method.PartialImplementationPart.Parameters[ordinal]);
result.Add(
parameterAndProjectId.WithSymbol(method.PartialImplementationPart.Parameters[ordinal]));
}
}
return result.ToImmutableAndFree();
}
}
}
}
\ No newline at end of file
......@@ -16,7 +16,7 @@ protected override bool CanFind(IMethodSymbol symbol)
return symbol.MethodKind.IsPropertyAccessor();
}
protected override async Task<IEnumerable<SymbolAndProjectId>> DetermineCascadedSymbolsAsync(
protected override async Task<ImmutableArray<SymbolAndProjectId>> DetermineCascadedSymbolsAsync(
SymbolAndProjectId<IMethodSymbol> symbolAndProjectId,
Solution solution,
IImmutableSet<Project> projects,
......@@ -28,18 +28,18 @@ protected override bool CanFind(IMethodSymbol symbol)
var symbol = symbolAndProjectId.Symbol;
if (symbol.AssociatedSymbol != null)
{
result = result.Concat(symbolAndProjectId.WithSymbol(symbol.AssociatedSymbol));
result = result.Add(symbolAndProjectId.WithSymbol(symbol.AssociatedSymbol));
}
return result;
}
protected override Task<IEnumerable<Document>> DetermineDocumentsToSearchAsync(IMethodSymbol symbol, Project project, IImmutableSet<Document> documents, CancellationToken cancellationToken)
protected override Task<ImmutableArray<Document>> DetermineDocumentsToSearchAsync(IMethodSymbol symbol, Project project, IImmutableSet<Document> documents, CancellationToken cancellationToken)
{
return FindDocumentsAsync(project, documents, cancellationToken, symbol.Name);
}
protected override Task<IEnumerable<ReferenceLocation>> FindReferencesInDocumentAsync(IMethodSymbol symbol, Document document, CancellationToken cancellationToken)
protected override Task<ImmutableArray<ReferenceLocation>> FindReferencesInDocumentAsync(IMethodSymbol symbol, Document document, CancellationToken cancellationToken)
{
return FindReferencesInDocumentUsingSymbolNameAsync(symbol, document, cancellationToken);
}
......
......@@ -19,37 +19,37 @@ protected override bool CanFind(IPropertySymbol symbol)
return true;
}
protected override async Task<IEnumerable<SymbolAndProjectId>> DetermineCascadedSymbolsAsync(
protected override async Task<ImmutableArray<SymbolAndProjectId>> DetermineCascadedSymbolsAsync(
SymbolAndProjectId<IPropertySymbol> symbolAndProjectId,
Solution solution,
IImmutableSet<Project> projects,
CancellationToken cancellationToken)
{
var baseSymbols = await base.DetermineCascadedSymbolsAsync(symbolAndProjectId, solution, projects, cancellationToken).ConfigureAwait(false);
baseSymbols = baseSymbols ?? SpecializedCollections.EmptyEnumerable<SymbolAndProjectId>();
var symbol = symbolAndProjectId.Symbol;
var backingFields = symbol.ContainingType.GetMembers()
.OfType<IFieldSymbol>()
.Where(f => symbol.Equals(f.AssociatedSymbol))
.Select(f => (SymbolAndProjectId)symbolAndProjectId.WithSymbol(f));
.Select(f => (SymbolAndProjectId)symbolAndProjectId.WithSymbol(f))
.ToImmutableArray();
var result = baseSymbols.Concat(backingFields);
if (symbol.GetMethod != null)
{
result = result.Concat(symbolAndProjectId.WithSymbol(symbol.GetMethod));
result = result.Add(symbolAndProjectId.WithSymbol(symbol.GetMethod));
}
if (symbol.SetMethod != null)
{
result = result.Concat(symbolAndProjectId.WithSymbol(symbol.SetMethod));
result = result.Add(symbolAndProjectId.WithSymbol(symbol.SetMethod));
}
return result;
}
protected override async Task<IEnumerable<Document>> DetermineDocumentsToSearchAsync(
protected override async Task<ImmutableArray<Document>> DetermineDocumentsToSearchAsync(
IPropertySymbol symbol,
Project project,
IImmutableSet<Document> documents,
......@@ -59,17 +59,19 @@ protected override bool CanFind(IPropertySymbol symbol)
var forEachDocuments = IsForEachProperty(symbol)
? await FindDocumentsWithForEachStatementsAsync(project, documents, cancellationToken).ConfigureAwait(false)
: SpecializedCollections.EmptyEnumerable<Document>();
: ImmutableArray<Document>.Empty;
var elementAccessDocument = symbol.IsIndexer
? await FindDocumentWithElementAccessExpressionsAsync(project, documents, cancellationToken).ConfigureAwait(false)
: SpecializedCollections.EmptyEnumerable<Document>();
: ImmutableArray<Document>.Empty;
var indexerMemberCrefDocument = symbol.IsIndexer
? await FindDocumentWithIndexerMemberCrefAsync(project, documents, cancellationToken).ConfigureAwait(false)
: SpecializedCollections.EmptyEnumerable<Document>();
: ImmutableArray<Document>.Empty;
return ordinaryDocuments.Concat(forEachDocuments).Concat(elementAccessDocument).Concat(indexerMemberCrefDocument);
return ordinaryDocuments.Concat(forEachDocuments)
.Concat(elementAccessDocument)
.Concat(indexerMemberCrefDocument);
}
private static bool IsForEachProperty(IPropertySymbol symbol)
......@@ -77,7 +79,7 @@ private static bool IsForEachProperty(IPropertySymbol symbol)
return symbol.Name == WellKnownMemberNames.CurrentPropertyName;
}
protected override async Task<IEnumerable<ReferenceLocation>> FindReferencesInDocumentAsync(
protected override async Task<ImmutableArray<ReferenceLocation>> FindReferencesInDocumentAsync(
IPropertySymbol symbol,
Document document,
CancellationToken cancellationToken)
......@@ -86,16 +88,17 @@ private static bool IsForEachProperty(IPropertySymbol symbol)
var forEachReferences = IsForEachProperty(symbol)
? await FindReferencesInForEachStatementsAsync(symbol, document, cancellationToken).ConfigureAwait(false)
: SpecializedCollections.EmptyEnumerable<ReferenceLocation>();
: ImmutableArray<ReferenceLocation>.Empty;
var elementAccessReferences = symbol.IsIndexer
? await FindElementAccessReferencesAndIndexerMemberCrefReferencesAsync(symbol, document, cancellationToken).ConfigureAwait(false)
: SpecializedCollections.EmptyEnumerable<ReferenceLocation>();
: ImmutableArray<ReferenceLocation>.Empty;
return nameReferences.Concat(forEachReferences).Concat(elementAccessReferences);
return nameReferences.Concat(forEachReferences)
.Concat(elementAccessReferences);
}
private Task<IEnumerable<Document>> FindDocumentWithElementAccessExpressionsAsync(
private Task<ImmutableArray<Document>> FindDocumentWithElementAccessExpressionsAsync(
Project project, IImmutableSet<Document> documents, CancellationToken cancellationToken)
{
return FindDocumentsAsync(project, documents, async (d, c) =>
......@@ -105,7 +108,7 @@ private static bool IsForEachProperty(IPropertySymbol symbol)
}, cancellationToken);
}
private Task<IEnumerable<Document>> FindDocumentWithIndexerMemberCrefAsync(
private Task<ImmutableArray<Document>> FindDocumentWithIndexerMemberCrefAsync(
Project project, IImmutableSet<Document> documents, CancellationToken cancellationToken)
{
return FindDocumentsAsync(project, documents, async (d, c) =>
......@@ -115,7 +118,7 @@ private static bool IsForEachProperty(IPropertySymbol symbol)
}, cancellationToken);
}
private async Task<IEnumerable<ReferenceLocation>> FindElementAccessReferencesAndIndexerMemberCrefReferencesAsync(
private async Task<ImmutableArray<ReferenceLocation>> FindElementAccessReferencesAndIndexerMemberCrefReferencesAsync(
IPropertySymbol symbol,
Document document,
CancellationToken cancellationToken)
......@@ -132,7 +135,7 @@ private static bool IsForEachProperty(IPropertySymbol symbol)
var elementAccessExpressionsAndIndexerMemberCref = elementAccessExpressions.Concat(indexerMemberCref);
var locations = new List<ReferenceLocation>();
var locations = ArrayBuilder<ReferenceLocation>.GetInstance();
foreach (var node in elementAccessExpressionsAndIndexerMemberCref)
{
......@@ -169,7 +172,7 @@ private static bool IsForEachProperty(IPropertySymbol symbol)
}
}
return locations;
return locations.ToImmutableAndFree();
}
}
}
......@@ -14,7 +14,7 @@ protected override bool CanFind(ITypeParameterSymbol symbol)
return symbol.TypeParameterKind != TypeParameterKind.Method;
}
protected override Task<IEnumerable<Document>> DetermineDocumentsToSearchAsync(
protected override Task<ImmutableArray<Document>> DetermineDocumentsToSearchAsync(
ITypeParameterSymbol symbol,
Project project,
IImmutableSet<Document> documents,
......@@ -30,7 +30,7 @@ protected override bool CanFind(ITypeParameterSymbol symbol)
return FindDocumentsAsync(project, documents, cancellationToken, symbol.Name, symbol.ContainingType.Name);
}
protected override Task<IEnumerable<ReferenceLocation>> FindReferencesInDocumentAsync(
protected override Task<ImmutableArray<ReferenceLocation>> FindReferencesInDocumentAsync(
ITypeParameterSymbol symbol,
Document document,
CancellationToken cancellationToken)
......
......@@ -218,7 +218,7 @@ public static partial class SymbolFinder
return result.Select(s => s.Symbol).ToList();
}
internal static async Task<IEnumerable<SymbolAndProjectId>> FindImplementationsAsync(
internal static async Task<ImmutableArray<SymbolAndProjectId>> FindImplementationsAsync(
SymbolAndProjectId symbolAndProjectId, Solution solution, IImmutableSet<Project> projects = null, CancellationToken cancellationToken = default(CancellationToken))
{
// A symbol can only have implementations if it's an interface or a
......@@ -230,14 +230,14 @@ public static partial class SymbolFinder
var implementingTypes = await DependentTypeFinder.FindTransitivelyImplementingTypesAsync(namedTypeSymbol, solution, projects, cancellationToken).ConfigureAwait(false);
return implementingTypes.Select(s => (SymbolAndProjectId)s)
.Where(IsAccessible)
.ToList();
.ToImmutableArray();
}
else if (symbol.IsImplementableMember())
{
var containingType = symbol.ContainingType.OriginalDefinition;
var allTypes = await DependentTypeFinder.FindTransitivelyImplementingTypesAsync(containingType, solution, projects, cancellationToken).ConfigureAwait(false);
List<SymbolAndProjectId> results = null;
ImmutableArray<SymbolAndProjectId>.Builder results = null;
foreach (var t in allTypes.Convert<INamedTypeSymbol, ITypeSymbol>())
{
foreach (var m in t.FindImplementationsForInterfaceMember(symbol, solution.Workspace, cancellationToken))
......@@ -246,7 +246,7 @@ public static partial class SymbolFinder
var bestDef = sourceDef.Symbol != null ? sourceDef : m;
if (IsAccessible(bestDef))
{
results = results ?? new List<SymbolAndProjectId>();
results = results ?? ImmutableArray.CreateBuilder<SymbolAndProjectId>();
results.Add(bestDef.WithSymbol(bestDef.Symbol.OriginalDefinition));
}
}
......@@ -254,11 +254,12 @@ public static partial class SymbolFinder
if (results != null)
{
return results.Distinct(SymbolAndProjectIdComparer.SymbolEquivalenceInstance);
return results.Distinct(SymbolAndProjectIdComparer.SymbolEquivalenceInstance)
.ToImmutableArray();
}
}
return SpecializedCollections.EmptyEnumerable<SymbolAndProjectId>();
return ImmutableArray<SymbolAndProjectId>.Empty;
}
private static bool IsAccessible(SymbolAndProjectId symbolAndProjectId)
......@@ -278,7 +279,8 @@ private static bool IsAccessible(SymbolAndProjectId symbolAndProjectId)
/// <summary>
/// Finds all the callers of a specified symbol.
/// </summary>
public static Task<IEnumerable<SymbolCallerInfo>> FindCallersAsync(ISymbol symbol, Solution solution, CancellationToken cancellationToken = default(CancellationToken))
public static Task<IEnumerable<SymbolCallerInfo>> FindCallersAsync(
ISymbol symbol, Solution solution, CancellationToken cancellationToken = default(CancellationToken))
{
return FindCallersAsync(symbol, solution, documents: null, cancellationToken: cancellationToken);
}
......@@ -322,7 +324,7 @@ public static async Task<IEnumerable<SymbolCallerInfo>> FindCallersAsync(ISymbol
return results ?? SpecializedCollections.EmptyEnumerable<SymbolCallerInfo>();
}
private static Task<IEnumerable<ReferencedSymbol>> FindCallReferencesAsync(
private static async Task<ImmutableArray<ReferencedSymbol>> FindCallReferencesAsync(
Solution solution,
ISymbol symbol,
IImmutableSet<Document> documents,
......@@ -334,11 +336,13 @@ public static async Task<IEnumerable<SymbolCallerInfo>> FindCallersAsync(ISymbol
symbol.Kind == SymbolKind.Method ||
symbol.Kind == SymbolKind.Property)
{
return SymbolFinder.FindReferencesAsync(symbol, solution, documents, cancellationToken);
var result = await FindReferencesAsync(
symbol, solution, documents, cancellationToken).ConfigureAwait(false);
return result.ToImmutableArray();
}
}
return SpecializedTasks.EmptyEnumerable<ReferencedSymbol>();
return ImmutableArray<ReferencedSymbol>.Empty;
}
private static bool OriginalSymbolsMatch(
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Collections.Immutable
Imports System.Composition
Imports System.Threading
Imports System.Threading.Tasks
......@@ -14,47 +15,48 @@ Namespace Microsoft.CodeAnalysis.FindSymbols
Public Function DetermineCascadedSymbolsAsync(symbolAndProjectId As SymbolAndProjectId,
project As Project,
cancellationToken As CancellationToken) As Task(Of IEnumerable(Of SymbolAndProjectId)) Implements ILanguageServiceReferenceFinder.DetermineCascadedSymbolsAsync
cancellationToken As CancellationToken) As Task(Of ImmutableArray(Of SymbolAndProjectId)) Implements ILanguageServiceReferenceFinder.DetermineCascadedSymbolsAsync
Dim symbol = symbolAndProjectId.Symbol
If Symbol.Kind = SymbolKind.Property Then
If symbol.Kind = SymbolKind.Property Then
Return DetermineCascadedSymbolsAsync(
symbolAndProjectId.WithSymbol(DirectCast(symbol, IPropertySymbol)),
project, cancellationToken)
ElseIf Symbol.Kind = SymbolKind.NamedType Then
ElseIf symbol.Kind = SymbolKind.NamedType Then
Return DetermineCascadedSymbolsAsync(
symbolAndProjectId.WithSymbol(DirectCast(symbol, INamedTypeSymbol)),
project, cancellationToken)
Else
Return Task.FromResult(Of IEnumerable(Of SymbolAndProjectId))(Nothing)
Return Task.FromResult(ImmutableArray(Of SymbolAndProjectId).Empty)
End If
End Function
Private Async Function DetermineCascadedSymbolsAsync(
[propertyAndProjectId] As SymbolAndProjectId(Of IPropertySymbol),
project As Project,
cancellationToken As CancellationToken) As Task(Of IEnumerable(Of SymbolAndProjectId))
cancellationToken As CancellationToken) As Task(Of ImmutableArray(Of SymbolAndProjectId))
Dim [property] = propertyAndProjectId.Symbol
Dim compilation = Await project.GetCompilationAsync(cancellationToken).ConfigureAwait(False)
Dim relatedSymbol = [property].FindRelatedExplicitlyDeclaredSymbol(compilation)
Return If([property].Equals(relatedSymbol),
SpecializedCollections.EmptyEnumerable(Of SymbolAndProjectId),
SpecializedCollections.SingletonEnumerable(
ImmutableArray(Of SymbolAndProjectId).Empty,
ImmutableArray.Create(
SymbolAndProjectId.Create(relatedSymbol, project.Id)))
End Function
Private Async Function DetermineCascadedSymbolsAsync(
namedType As SymbolAndProjectId(Of INamedTypeSymbol),
project As Project,
cancellationToken As CancellationToken) As Task(Of IEnumerable(Of SymbolAndProjectId))
cancellationToken As CancellationToken) As Task(Of ImmutableArray(Of SymbolAndProjectId))
Dim compilation = Await project.GetCompilationAsync(cancellationToken).ConfigureAwait(False)
' If this is a WinForms project, then the VB 'my' feature may have synthesized
' a property that would return an instance of the main Form type for the project.
' Search for such properties and cascade to them as well.
Return GetMatchingMyPropertySymbols(namedType, project.Id, compilation, cancellationToken).Distinct().ToList()
Return GetMatchingMyPropertySymbols(namedType, project.Id, compilation, cancellationToken).
Distinct().ToImmutableArray()
End Function
Private Function GetMatchingMyPropertySymbols(
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册