提交 94ef59bc 编写于 作者: C CyrusNajmabadi 提交者: GitHub

Merge pull request #14140 from CyrusNajmabadi/indexAllocations

Reduce the number of intermediary IEnumerables we create while buildind indices
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
...@@ -34,7 +35,7 @@ protected SearchScope(AbstractAddImportCodeFixProvider<TSimpleNameSyntax> provid ...@@ -34,7 +35,7 @@ protected SearchScope(AbstractAddImportCodeFixProvider<TSimpleNameSyntax> provid
CancellationToken = cancellationToken; CancellationToken = cancellationToken;
} }
protected abstract Task<IEnumerable<ISymbol>> FindDeclarationsAsync(string name, SymbolFilter filter, SearchQuery query); protected abstract Task<ImmutableArray<ISymbol>> FindDeclarationsAsync(string name, SymbolFilter filter, SearchQuery query);
public abstract SymbolReference CreateReference<T>(SymbolResult<T> symbol) where T : INamespaceOrTypeSymbol; public abstract SymbolReference CreateReference<T>(SymbolResult<T> symbol) where T : INamespaceOrTypeSymbol;
public async Task<IEnumerable<SymbolResult<ISymbol>>> FindDeclarationsAsync( public async Task<IEnumerable<SymbolResult<ISymbol>>> FindDeclarationsAsync(
...@@ -109,7 +110,7 @@ private class AllSymbolsProjectSearchScope : ProjectSearchScope ...@@ -109,7 +110,7 @@ private class AllSymbolsProjectSearchScope : ProjectSearchScope
{ {
} }
protected override Task<IEnumerable<ISymbol>> FindDeclarationsAsync( protected override Task<ImmutableArray<ISymbol>> FindDeclarationsAsync(
string name, SymbolFilter filter, SearchQuery searchQuery) string name, SymbolFilter filter, SearchQuery searchQuery)
{ {
return SymbolFinder.FindDeclarationsAsync(_project, searchQuery, filter, CancellationToken); return SymbolFinder.FindDeclarationsAsync(_project, searchQuery, filter, CancellationToken);
...@@ -133,14 +134,15 @@ private class SourceSymbolsProjectSearchScope : ProjectSearchScope ...@@ -133,14 +134,15 @@ private class SourceSymbolsProjectSearchScope : ProjectSearchScope
_projectToAssembly = projectToAssembly; _projectToAssembly = projectToAssembly;
} }
protected override async Task<IEnumerable<ISymbol>> FindDeclarationsAsync(string name, SymbolFilter filter, SearchQuery searchQuery) protected override async Task<ImmutableArray<ISymbol>> FindDeclarationsAsync(
string name, SymbolFilter filter, SearchQuery searchQuery)
{ {
var service = _project.Solution.Workspace.Services.GetService<ISymbolTreeInfoCacheService>(); var service = _project.Solution.Workspace.Services.GetService<ISymbolTreeInfoCacheService>();
var info = await service.TryGetSourceSymbolTreeInfoAsync(_project, CancellationToken).ConfigureAwait(false); var info = await service.TryGetSourceSymbolTreeInfoAsync(_project, CancellationToken).ConfigureAwait(false);
if (info == null) if (info == null)
{ {
// Looks like there was nothing in the cache. Return no results for now. // Looks like there was nothing in the cache. Return no results for now.
return SpecializedCollections.EmptyEnumerable<ISymbol>(); return ImmutableArray<ISymbol>.Empty;
} }
// Don't create the assembly until it is actually needed by the SymbolTreeInfo.FindAsync // Don't create the assembly until it is actually needed by the SymbolTreeInfo.FindAsync
...@@ -190,14 +192,14 @@ public override SymbolReference CreateReference<T>(SymbolResult<T> searchResult) ...@@ -190,14 +192,14 @@ public override SymbolReference CreateReference<T>(SymbolResult<T> searchResult)
_metadataReference); _metadataReference);
} }
protected override async Task<IEnumerable<ISymbol>> FindDeclarationsAsync( protected override async Task<ImmutableArray<ISymbol>> FindDeclarationsAsync(
string name, SymbolFilter filter, SearchQuery searchQuery) string name, SymbolFilter filter, SearchQuery searchQuery)
{ {
var service = _solution.Workspace.Services.GetService<ISymbolTreeInfoCacheService>(); var service = _solution.Workspace.Services.GetService<ISymbolTreeInfoCacheService>();
var info = await service.TryGetMetadataSymbolTreeInfoAsync(_solution, _metadataReference, CancellationToken).ConfigureAwait(false); var info = await service.TryGetMetadataSymbolTreeInfoAsync(_solution, _metadataReference, CancellationToken).ConfigureAwait(false);
if (info == null) if (info == null)
{ {
return SpecializedCollections.EmptyEnumerable<ISymbol>(); return ImmutableArray<ISymbol>.Empty;
} }
return await info.FindAsync(searchQuery, _assembly, filter, CancellationToken).ConfigureAwait(false); return await info.FindAsync(searchQuery, _assembly, filter, CancellationToken).ConfigureAwait(false);
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
...@@ -117,7 +118,7 @@ public static partial class SymbolFinder ...@@ -117,7 +118,7 @@ public static partial class SymbolFinder
/// <summary> /// <summary>
/// Find the declared symbols from either source, referenced projects or metadata assemblies with the specified name. /// Find the declared symbols from either source, referenced projects or metadata assemblies with the specified name.
/// </summary> /// </summary>
public static Task<IEnumerable<ISymbol>> FindDeclarationsAsync( public static async Task<IEnumerable<ISymbol>> FindDeclarationsAsync(
Project project, string name, bool ignoreCase, CancellationToken cancellationToken = default(CancellationToken)) Project project, string name, bool ignoreCase, CancellationToken cancellationToken = default(CancellationToken))
{ {
if (name == null) if (name == null)
...@@ -127,16 +128,17 @@ public static partial class SymbolFinder ...@@ -127,16 +128,17 @@ public static partial class SymbolFinder
if (string.IsNullOrWhiteSpace(name)) if (string.IsNullOrWhiteSpace(name))
{ {
return SpecializedTasks.EmptyEnumerable<ISymbol>(); return SpecializedCollections.EmptyEnumerable<ISymbol>();
} }
return FindDeclarationsAsync(project, SearchQuery.Create(name, ignoreCase), SymbolFilter.All, cancellationToken: cancellationToken); return await FindDeclarationsAsync(
project, SearchQuery.Create(name, ignoreCase), SymbolFilter.All, cancellationToken: cancellationToken).ConfigureAwait(false);
} }
/// <summary> /// <summary>
/// Find the declared symbols from either source, referenced projects or metadata assemblies with the specified name. /// Find the declared symbols from either source, referenced projects or metadata assemblies with the specified name.
/// </summary> /// </summary>
public static Task<IEnumerable<ISymbol>> FindDeclarationsAsync( public static async Task<IEnumerable<ISymbol>> FindDeclarationsAsync(
Project project, string name, bool ignoreCase, SymbolFilter filter, CancellationToken cancellationToken = default(CancellationToken)) Project project, string name, bool ignoreCase, SymbolFilter filter, CancellationToken cancellationToken = default(CancellationToken))
{ {
if (name == null) if (name == null)
...@@ -146,13 +148,14 @@ public static partial class SymbolFinder ...@@ -146,13 +148,14 @@ public static partial class SymbolFinder
if (string.IsNullOrWhiteSpace(name)) if (string.IsNullOrWhiteSpace(name))
{ {
return SpecializedTasks.EmptyEnumerable<ISymbol>(); return SpecializedCollections.EmptyEnumerable<ISymbol>();
} }
return FindDeclarationsAsync(project, SearchQuery.Create(name, ignoreCase), filter, cancellationToken: cancellationToken); return await FindDeclarationsAsync(
project, SearchQuery.Create(name, ignoreCase), filter, cancellationToken: cancellationToken).ConfigureAwait(false);
} }
internal static Task<IEnumerable<ISymbol>> FindDeclarationsAsync( internal static Task<ImmutableArray<ISymbol>> FindDeclarationsAsync(
Project project, SearchQuery query, SymbolFilter filter, CancellationToken cancellationToken) Project project, SearchQuery query, SymbolFilter filter, CancellationToken cancellationToken)
{ {
// All entrypoints to this function are Find functions that are only searching // All entrypoints to this function are Find functions that are only searching
...@@ -166,7 +169,7 @@ public static partial class SymbolFinder ...@@ -166,7 +169,7 @@ public static partial class SymbolFinder
if (query.Name != null && string.IsNullOrWhiteSpace(query.Name)) if (query.Name != null && string.IsNullOrWhiteSpace(query.Name))
{ {
return SpecializedTasks.EmptyEnumerable<ISymbol>(); return SpecializedTasks.EmptyImmutableArray<ISymbol>();
} }
using (Logger.LogBlock(FunctionId.SymbolFinder_FindDeclarationsAsync, cancellationToken)) using (Logger.LogBlock(FunctionId.SymbolFinder_FindDeclarationsAsync, cancellationToken))
...@@ -175,7 +178,7 @@ public static partial class SymbolFinder ...@@ -175,7 +178,7 @@ public static partial class SymbolFinder
} }
} }
private static async Task<IEnumerable<ISymbol>> FindDeclarationsAsyncImpl( private static async Task<ImmutableArray<ISymbol>> FindDeclarationsAsyncImpl(
Project project, SearchQuery query, SymbolFilter criteria, CancellationToken cancellationToken) Project project, SearchQuery query, SymbolFilter criteria, CancellationToken cancellationToken)
{ {
// All entrypoints to this function are Find functions that are only searching // All entrypoints to this function are Find functions that are only searching
...@@ -184,7 +187,7 @@ public static partial class SymbolFinder ...@@ -184,7 +187,7 @@ public static partial class SymbolFinder
var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
var list = new List<ISymbol>(); var list = ArrayBuilder<ISymbol>.GetInstance();
// get declarations from the compilation's assembly // get declarations from the compilation's assembly
await AddDeclarationsAsync(project, query, criteria, list, cancellationToken).ConfigureAwait(false); await AddDeclarationsAsync(project, query, criteria, list, cancellationToken).ConfigureAwait(false);
...@@ -205,7 +208,7 @@ public static partial class SymbolFinder ...@@ -205,7 +208,7 @@ public static partial class SymbolFinder
} }
} }
return TranslateNamespaces(list, compilation); return TranslateNamespaces(list.ToImmutableAndFree(), compilation);
} }
private static string GetMetadataReferenceFilePath(MetadataReference metadataReference) private static string GetMetadataReferenceFilePath(MetadataReference metadataReference)
...@@ -216,67 +219,92 @@ private static string GetMetadataReferenceFilePath(MetadataReference metadataRef ...@@ -216,67 +219,92 @@ private static string GetMetadataReferenceFilePath(MetadataReference metadataRef
/// <summary> /// <summary>
/// Makes certain all namespace symbols returned by API are from the compilation. /// Makes certain all namespace symbols returned by API are from the compilation.
/// </summary> /// </summary>
private static IEnumerable<ISymbol> TranslateNamespaces(List<ISymbol> symbols, Compilation compilation) private static ImmutableArray<ISymbol> TranslateNamespaces(
ImmutableArray<ISymbol> symbols, Compilation compilation)
{ {
var builder = ArrayBuilder<ISymbol>.GetInstance();
foreach (var symbol in symbols) foreach (var symbol in symbols)
{ {
var ns = symbol as INamespaceSymbol; var ns = symbol as INamespaceSymbol;
if (ns != null) if (ns != null)
{ {
yield return compilation.GetCompilationNamespace(ns); builder.Add(compilation.GetCompilationNamespace(ns));
} }
else else
{ {
yield return symbol; builder.Add(symbol);
} }
} }
var result = builder.Count == symbols.Length
? symbols
: builder.ToImmutable();
builder.Free();
return result;
} }
private static async Task AddDeclarationsAsync( private static Task AddDeclarationsAsync(
Project project, SearchQuery query, SymbolFilter filter, List<ISymbol> list, CancellationToken cancellationToken) Project project, SearchQuery query, SymbolFilter filter,
ArrayBuilder<ISymbol> list, CancellationToken cancellationToken)
{ {
await AddDeclarationsAsync( return AddDeclarationsAsync(
project, query, filter, list, project, query, filter, list,
startingCompilation: null, startingCompilation: null,
startingAssembly: null, startingAssembly: null,
cancellationToken: cancellationToken).ConfigureAwait(false); cancellationToken: cancellationToken);
} }
private static async Task AddDeclarationsAsync( private static async Task AddDeclarationsAsync(
Project project, Project project,
SearchQuery query, SearchQuery query,
SymbolFilter filter, SymbolFilter filter,
List<ISymbol> list, ArrayBuilder<ISymbol> list,
Compilation startingCompilation, Compilation startingCompilation,
IAssemblySymbol startingAssembly, IAssemblySymbol startingAssembly,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
using (Logger.LogBlock(FunctionId.SymbolFinder_Project_AddDeclarationsAsync, cancellationToken)) using (Logger.LogBlock(FunctionId.SymbolFinder_Project_AddDeclarationsAsync, cancellationToken))
using (var set = SharedPools.Default<HashSet<ISymbol>>().GetPooledObject())
{ {
if (!await project.ContainsSymbolsWithNameAsync(query.GetPredicate(), filter, cancellationToken).ConfigureAwait(false)) if (!await project.ContainsSymbolsWithNameAsync(query.GetPredicate(), filter, cancellationToken).ConfigureAwait(false))
{ {
return; return;
} }
var unfilteredSymbols = await GetUnfilteredSymbolsAsync(
project, query, filter, startingCompilation, startingAssembly, cancellationToken).ConfigureAwait(false);
list.AddRange(FilterByCriteria(unfilteredSymbols, filter));
}
}
private static async Task<ImmutableArray<ISymbol>> GetUnfilteredSymbolsAsync(
Project project,
SearchQuery query,
SymbolFilter filter,
Compilation startingCompilation,
IAssemblySymbol startingAssembly,
CancellationToken cancellationToken)
{
var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
if (startingCompilation != null && startingAssembly != null && compilation.Assembly != startingAssembly) if (startingCompilation != null && startingAssembly != null && compilation.Assembly != startingAssembly)
{ {
// Return symbols from skeleton assembly in this case so that symbols have the same language as startingCompilation. // Return symbols from skeleton assembly in this case so that symbols have the same language as startingCompilation.
list.AddRange( return compilation.GetSymbolsWithName(query.GetPredicate(), filter, cancellationToken)
FilterByCriteria(compilation.GetSymbolsWithName(query.GetPredicate(), filter, cancellationToken), filter) .Select(s => s.GetSymbolKey().Resolve(startingCompilation, cancellationToken: cancellationToken).Symbol)
.Select(s => s.GetSymbolKey().Resolve(startingCompilation, cancellationToken: cancellationToken).Symbol).WhereNotNull()); .WhereNotNull()
.ToImmutableArray();
} }
else else
{ {
list.AddRange(FilterByCriteria(compilation.GetSymbolsWithName(query.GetPredicate(), filter, cancellationToken), filter)); return compilation.GetSymbolsWithName(query.GetPredicate(), filter, cancellationToken)
} .ToImmutableArray();
} }
} }
private static async Task AddDeclarationsAsync( private static async Task AddDeclarationsAsync(
Solution solution, IAssemblySymbol assembly, PortableExecutableReference referenceOpt, Solution solution, IAssemblySymbol assembly, PortableExecutableReference referenceOpt,
SearchQuery query, SymbolFilter filter, List<ISymbol> list, CancellationToken cancellationToken) SearchQuery query, SymbolFilter filter, ArrayBuilder<ISymbol> list, CancellationToken cancellationToken)
{ {
// All entrypoints to this function are Find functions that are only searching // All entrypoints to this function are Find functions that are only searching
// for specific strings (i.e. they never do a custom search). // for specific strings (i.e. they never do a custom search).
...@@ -361,7 +389,8 @@ public static Task<IEnumerable<ISymbol>> FindSourceDeclarationsAsync(Project pro ...@@ -361,7 +389,8 @@ public static Task<IEnumerable<ISymbol>> FindSourceDeclarationsAsync(Project pro
/// <summary> /// <summary>
/// Find the symbols for declarations made in source with the specified name. /// Find the symbols for declarations made in source with the specified name.
/// </summary> /// </summary>
public static Task<IEnumerable<ISymbol>> FindSourceDeclarationsAsync(Project project, string name, bool ignoreCase, SymbolFilter filter, CancellationToken cancellationToken = default(CancellationToken)) public static async Task<IEnumerable<ISymbol>> FindSourceDeclarationsAsync(
Project project, string name, bool ignoreCase, SymbolFilter filter, CancellationToken cancellationToken = default(CancellationToken))
{ {
if (project == null) if (project == null)
{ {
...@@ -375,21 +404,22 @@ public static Task<IEnumerable<ISymbol>> FindSourceDeclarationsAsync(Project pro ...@@ -375,21 +404,22 @@ public static Task<IEnumerable<ISymbol>> FindSourceDeclarationsAsync(Project pro
if (string.IsNullOrWhiteSpace(name)) if (string.IsNullOrWhiteSpace(name))
{ {
return SpecializedTasks.EmptyEnumerable<ISymbol>(); return SpecializedCollections.EmptyEnumerable<ISymbol>();
} }
using (Logger.LogBlock(FunctionId.SymbolFinder_Project_Name_FindSourceDeclarationsAsync, cancellationToken)) using (Logger.LogBlock(FunctionId.SymbolFinder_Project_Name_FindSourceDeclarationsAsync, cancellationToken))
{ {
return FindSourceDeclarationsAsyncImpl(project, SearchQuery.Create(name, ignoreCase), filter, cancellationToken); return await FindSourceDeclarationsAsyncImpl(
project, SearchQuery.Create(name, ignoreCase), filter, cancellationToken).ConfigureAwait(false);
} }
} }
private static async Task<IEnumerable<ISymbol>> FindSourceDeclarationsAsyncImpl( private static async Task<ImmutableArray<ISymbol>> FindSourceDeclarationsAsyncImpl(
Project project, SearchQuery query, SymbolFilter filter, CancellationToken cancellationToken) Project project, SearchQuery query, SymbolFilter filter, CancellationToken cancellationToken)
{ {
var list = new List<ISymbol>(); var list = ArrayBuilder<ISymbol>.GetInstance();
await AddDeclarationsAsync(project, query, filter, list, cancellationToken).ConfigureAwait(false); await AddDeclarationsAsync(project, query, filter, list, cancellationToken).ConfigureAwait(false);
return list; return list.ToImmutableAndFree();
} }
/// <summary> /// <summary>
...@@ -446,13 +476,15 @@ public static Task<IEnumerable<ISymbol>> FindSourceDeclarationsAsync(Project pro ...@@ -446,13 +476,15 @@ public static Task<IEnumerable<ISymbol>> FindSourceDeclarationsAsync(Project pro
/// <summary> /// <summary>
/// Find the symbols for declarations made in source with a matching name. /// Find the symbols for declarations made in source with a matching name.
/// </summary> /// </summary>
public static Task<IEnumerable<ISymbol>> FindSourceDeclarationsAsync( public static async Task<IEnumerable<ISymbol>> FindSourceDeclarationsAsync(
Project project, Func<string, bool> predicate, SymbolFilter filter, CancellationToken cancellationToken = default(CancellationToken)) Project project, Func<string, bool> predicate, SymbolFilter filter, CancellationToken cancellationToken = default(CancellationToken))
{ {
return FindSourceDeclarationsAsync(project, SearchQuery.CreateCustom(predicate), filter, cancellationToken); return await FindSourceDeclarationsAsync(
project, SearchQuery.CreateCustom(predicate), filter, cancellationToken).ConfigureAwait(false);
} }
internal static async Task<IEnumerable<ISymbol>> FindSourceDeclarationsAsync(Project project, SearchQuery query, SymbolFilter filter, CancellationToken cancellationToken) internal static async Task<ImmutableArray<ISymbol>> FindSourceDeclarationsAsync(
Project project, SearchQuery query, SymbolFilter filter, CancellationToken cancellationToken)
{ {
if (project == null) if (project == null)
{ {
...@@ -461,26 +493,27 @@ internal static async Task<IEnumerable<ISymbol>> FindSourceDeclarationsAsync(Pro ...@@ -461,26 +493,27 @@ internal static async Task<IEnumerable<ISymbol>> FindSourceDeclarationsAsync(Pro
if (query.Name != null && string.IsNullOrWhiteSpace(query.Name)) if (query.Name != null && string.IsNullOrWhiteSpace(query.Name))
{ {
return SpecializedCollections.EmptyEnumerable<ISymbol>(); return ImmutableArray<ISymbol>.Empty;
} }
using (Logger.LogBlock(FunctionId.SymbolFinder_Project_Predicate_FindSourceDeclarationsAsync, cancellationToken)) using (Logger.LogBlock(FunctionId.SymbolFinder_Project_Predicate_FindSourceDeclarationsAsync, cancellationToken))
{ {
var result = new List<ISymbol>();
if (!await project.ContainsSymbolsWithNameAsync(query.GetPredicate(), filter, cancellationToken).ConfigureAwait(false)) if (!await project.ContainsSymbolsWithNameAsync(query.GetPredicate(), filter, cancellationToken).ConfigureAwait(false))
{ {
return result; return ImmutableArray<ISymbol>.Empty;
} }
var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
result.AddRange(FilterByCriteria(compilation.GetSymbolsWithName(query.GetPredicate(), filter, cancellationToken), filter)); var unfiltered = compilation.GetSymbolsWithName(query.GetPredicate(), filter, cancellationToken).ToImmutableArray();
return result; return FilterByCriteria(unfiltered, filter);
} }
} }
internal static IEnumerable<ISymbol> FilterByCriteria(IEnumerable<ISymbol> symbols, SymbolFilter criteria) internal static ImmutableArray<ISymbol> FilterByCriteria(
ImmutableArray<ISymbol> symbols, SymbolFilter criteria)
{ {
var builder = ArrayBuilder<ISymbol>.GetInstance();
foreach (var symbol in symbols) foreach (var symbol in symbols)
{ {
if (symbol.IsImplicitlyDeclared || symbol.IsAccessor()) if (symbol.IsImplicitlyDeclared || symbol.IsAccessor())
...@@ -490,9 +523,16 @@ internal static IEnumerable<ISymbol> FilterByCriteria(IEnumerable<ISymbol> symbo ...@@ -490,9 +523,16 @@ internal static IEnumerable<ISymbol> FilterByCriteria(IEnumerable<ISymbol> symbo
if (MeetCriteria(symbol, criteria)) if (MeetCriteria(symbol, criteria))
{ {
yield return symbol; builder.Add(symbol);
} }
} }
var result = builder.Count == symbols.Length
? symbols
: builder.ToImmutable();
builder.Free();
return result;
} }
private static bool MeetCriteria(ISymbol symbol, SymbolFilter filter) private static bool MeetCriteria(ISymbol symbol, SymbolFilter filter)
......
...@@ -114,7 +114,7 @@ internal partial class SymbolTreeInfo ...@@ -114,7 +114,7 @@ internal partial class SymbolTreeInfo
_spellCheckerTask = spellCheckerTask; _spellCheckerTask = spellCheckerTask;
} }
public Task<IEnumerable<ISymbol>> FindAsync( public Task<ImmutableArray<ISymbol>> FindAsync(
SearchQuery query, IAssemblySymbol assembly, SymbolFilter filter, CancellationToken cancellationToken) SearchQuery query, IAssemblySymbol assembly, SymbolFilter filter, CancellationToken cancellationToken)
{ {
// All entrypoints to this function are Find functions that are only searching // All entrypoints to this function are Find functions that are only searching
...@@ -124,7 +124,7 @@ internal partial class SymbolTreeInfo ...@@ -124,7 +124,7 @@ internal partial class SymbolTreeInfo
return this.FindAsync(query, new AsyncLazy<IAssemblySymbol>(assembly), filter, cancellationToken); return this.FindAsync(query, new AsyncLazy<IAssemblySymbol>(assembly), filter, cancellationToken);
} }
public async Task<IEnumerable<ISymbol>> FindAsync( public async Task<ImmutableArray<ISymbol>> FindAsync(
SearchQuery query, AsyncLazy<IAssemblySymbol> lazyAssembly, SymbolFilter filter, CancellationToken cancellationToken) SearchQuery query, AsyncLazy<IAssemblySymbol> lazyAssembly, SymbolFilter filter, CancellationToken cancellationToken)
{ {
// All entrypoints to this function are Find functions that are only searching // All entrypoints to this function are Find functions that are only searching
...@@ -136,7 +136,7 @@ internal partial class SymbolTreeInfo ...@@ -136,7 +136,7 @@ internal partial class SymbolTreeInfo
filter); filter);
} }
private Task<IEnumerable<ISymbol>> FindAsyncWorker( private Task<ImmutableArray<ISymbol>> FindAsyncWorker(
SearchQuery query, AsyncLazy<IAssemblySymbol> lazyAssembly, CancellationToken cancellationToken) SearchQuery query, AsyncLazy<IAssemblySymbol> lazyAssembly, CancellationToken cancellationToken)
{ {
// All entrypoints to this function are Find functions that are only searching // All entrypoints to this function are Find functions that are only searching
...@@ -161,18 +161,18 @@ internal partial class SymbolTreeInfo ...@@ -161,18 +161,18 @@ internal partial class SymbolTreeInfo
/// <summary> /// <summary>
/// Finds symbols in this assembly that match the provided name in a fuzzy manner. /// Finds symbols in this assembly that match the provided name in a fuzzy manner.
/// </summary> /// </summary>
private async Task<IEnumerable<ISymbol>> FuzzyFindAsync( private async Task<ImmutableArray<ISymbol>> FuzzyFindAsync(
AsyncLazy<IAssemblySymbol> lazyAssembly, string name, CancellationToken cancellationToken) AsyncLazy<IAssemblySymbol> lazyAssembly, string name, CancellationToken cancellationToken)
{ {
if (_spellCheckerTask.Status != TaskStatus.RanToCompletion) if (_spellCheckerTask.Status != TaskStatus.RanToCompletion)
{ {
// Spell checker isn't ready. Just return immediately. // Spell checker isn't ready. Just return immediately.
return SpecializedCollections.EmptyEnumerable<ISymbol>(); return ImmutableArray<ISymbol>.Empty;
} }
var spellChecker = _spellCheckerTask.Result; var spellChecker = _spellCheckerTask.Result;
var similarNames = spellChecker.FindSimilarWords(name, substringsAreSimilar: false); var similarNames = spellChecker.FindSimilarWords(name, substringsAreSimilar: false);
var result = new List<ISymbol>(); var result = ArrayBuilder<ISymbol>.GetInstance();
foreach (var similarName in similarNames) foreach (var similarName in similarNames)
{ {
...@@ -180,20 +180,20 @@ internal partial class SymbolTreeInfo ...@@ -180,20 +180,20 @@ internal partial class SymbolTreeInfo
result.AddRange(symbols); result.AddRange(symbols);
} }
return result; return result.ToImmutableAndFree();
} }
/// <summary> /// <summary>
/// Get all symbols that have a name matching the specified name. /// Get all symbols that have a name matching the specified name.
/// </summary> /// </summary>
private async Task<IEnumerable<ISymbol>> FindAsync( private async Task<ImmutableArray<ISymbol>> FindAsync(
AsyncLazy<IAssemblySymbol> lazyAssembly, AsyncLazy<IAssemblySymbol> lazyAssembly,
string name, string name,
bool ignoreCase, bool ignoreCase,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
var comparer = GetComparer(ignoreCase); var comparer = GetComparer(ignoreCase);
var result = new List<ISymbol>(); var results = ArrayBuilder<ISymbol>.GetInstance();
IAssemblySymbol assemblySymbol = null; IAssemblySymbol assemblySymbol = null;
foreach (var node in FindNodeIndices(name, comparer)) foreach (var node in FindNodeIndices(name, comparer))
...@@ -201,10 +201,10 @@ internal partial class SymbolTreeInfo ...@@ -201,10 +201,10 @@ internal partial class SymbolTreeInfo
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
assemblySymbol = assemblySymbol ?? await lazyAssembly.GetValueAsync(cancellationToken).ConfigureAwait(false); assemblySymbol = assemblySymbol ?? await lazyAssembly.GetValueAsync(cancellationToken).ConfigureAwait(false);
result.AddRange(Bind(node, assemblySymbol.GlobalNamespace, cancellationToken)); Bind(node, assemblySymbol.GlobalNamespace, results, cancellationToken);
} }
return result; return results.ToImmutableAndFree(); ;
} }
private static StringSliceComparer GetComparer(bool ignoreCase) private static StringSliceComparer GetComparer(bool ignoreCase)
...@@ -409,26 +409,8 @@ private int BinarySearch(string name) ...@@ -409,26 +409,8 @@ private int BinarySearch(string name)
#region Binding #region Binding
// returns all the symbols in the container corresponding to the node // returns all the symbols in the container corresponding to the node
private IEnumerable<ISymbol> Bind( private void Bind(
int index, INamespaceOrTypeSymbol rootContainer, CancellationToken cancellationToken) int index, INamespaceOrTypeSymbol rootContainer, ArrayBuilder<ISymbol> results, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
using (var symbols = SharedPools.Default<List<ISymbol>>().GetPooledObject())
{
BindWorker(index, rootContainer, symbols.Object, cancellationToken);
foreach (var symbol in symbols.Object)
{
cancellationToken.ThrowIfCancellationRequested();
yield return symbol;
}
}
}
// returns all the symbols in the container corresponding to the node
private void BindWorker(
int index, INamespaceOrTypeSymbol rootContainer, List<ISymbol> results, CancellationToken cancellationToken)
{ {
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
...@@ -444,18 +426,27 @@ private int BinarySearch(string name) ...@@ -444,18 +426,27 @@ private int BinarySearch(string name)
} }
else else
{ {
using (var containerSymbols = SharedPools.Default<List<ISymbol>>().GetPooledObject()) var containerSymbols = ArrayBuilder<ISymbol>.GetInstance();
try
{ {
BindWorker(node.ParentIndex, rootContainer, containerSymbols.Object, cancellationToken); Bind(node.ParentIndex, rootContainer, containerSymbols, cancellationToken);
foreach (var containerSymbol in containerSymbols.Object.OfType<INamespaceOrTypeSymbol>()) foreach (var containerSymbol in containerSymbols)
{ {
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
results.AddRange(containerSymbol.GetMembers(GetName(node))); var nsOrType = containerSymbol as INamespaceOrTypeSymbol;
if (nsOrType != null)
{
results.AddRange(nsOrType.GetMembers(GetName(node)));
} }
} }
} }
finally
{
containerSymbols.Free();
}
}
} }
private string GetName(Node node) private string GetName(Node node)
...@@ -541,16 +532,36 @@ internal void AssertEquivalentTo(SymbolTreeInfo other) ...@@ -541,16 +532,36 @@ internal void AssertEquivalentTo(SymbolTreeInfo other)
return result; return result;
} }
public IEnumerable<INamedTypeSymbol> GetDerivedMetadataTypes( public ImmutableArray<INamedTypeSymbol> GetDerivedMetadataTypes(
string baseTypeName, Compilation compilation, CancellationToken cancellationToken) string baseTypeName, Compilation compilation, CancellationToken cancellationToken)
{ {
var baseTypeNameIndex = BinarySearch(baseTypeName); var baseTypeNameIndex = BinarySearch(baseTypeName);
var derivedTypeIndices = _inheritanceMap[baseTypeNameIndex]; var derivedTypeIndices = _inheritanceMap[baseTypeNameIndex];
return from derivedTypeIndex in derivedTypeIndices var builder = ArrayBuilder<INamedTypeSymbol>.GetInstance();
from symbol in Bind(derivedTypeIndex, compilation.GlobalNamespace, cancellationToken)
let namedType = symbol as INamedTypeSymbol foreach (var derivedTypeIndex in derivedTypeIndices)
select namedType; {
var tempBuilder = ArrayBuilder<ISymbol>.GetInstance();
try
{
Bind(derivedTypeIndex, compilation.GlobalNamespace, tempBuilder, cancellationToken);
foreach (var symbol in tempBuilder)
{
var namedType = symbol as INamedTypeSymbol;
if (namedType != null)
{
builder.Add(namedType);
}
}
}
finally
{
tempBuilder.Free();
}
}
return builder.ToImmutableAndFree();
} }
} }
} }
\ No newline at end of file
...@@ -82,7 +82,8 @@ public partial class FindAllDeclarationsTests : TestBase ...@@ -82,7 +82,8 @@ public partial class FindAllDeclarationsTests : TestBase
InlineData("TestCase", true, WorkspaceKind.TwoNamespacesWithIdenticalClasses, new[] { "TestCase1.TestCase", "TestCase2.TestCase" }), InlineData("TestCase", true, WorkspaceKind.TwoNamespacesWithIdenticalClasses, new[] { "TestCase1.TestCase", "TestCase2.TestCase" }),
InlineData("TestCase", false, WorkspaceKind.TwoNamespacesWithIdenticalClasses, new[] { "TestCase1.TestCase", "TestCase2.TestCase" }), InlineData("TestCase", false, WorkspaceKind.TwoNamespacesWithIdenticalClasses, new[] { "TestCase1.TestCase", "TestCase2.TestCase" }),
InlineData("TestCase1.TestCase", true, WorkspaceKind.TwoNamespacesWithIdenticalClasses, new string[0]),] InlineData("TestCase1.TestCase", true, WorkspaceKind.TwoNamespacesWithIdenticalClasses, new string[0]),]
public static async Task FindDeclarationsAsync_Test(string searchTerm, bool ignoreCase, WorkspaceKind workspaceKind, string[] expectedResults)
public async Task FindDeclarationsAsync_Test(string searchTerm, bool ignoreCase, WorkspaceKind workspaceKind, string[] expectedResults)
{ {
var project = GetProject(workspaceKind); var project = GetProject(workspaceKind);
var declarations = await SymbolFinder.FindDeclarationsAsync(project, searchTerm, ignoreCase).ConfigureAwait(false); var declarations = await SymbolFinder.FindDeclarationsAsync(project, searchTerm, ignoreCase).ConfigureAwait(false);
...@@ -90,18 +91,18 @@ public static async Task FindDeclarationsAsync_Test(string searchTerm, bool igno ...@@ -90,18 +91,18 @@ public static async Task FindDeclarationsAsync_Test(string searchTerm, bool igno
} }
[Fact] [Fact]
public static async Task FindDeclarationsAsync_Test_NullProject() public async Task FindDeclarationsAsync_Test_NullProject()
{ {
await Assert.ThrowsAsync<ArgumentNullException>(async () => await Assert.ThrowsAnyAsync<ArgumentNullException>(async () =>
{ {
var declarations = await SymbolFinder.FindDeclarationsAsync(null, "Test", true); var declarations = await SymbolFinder.FindDeclarationsAsync(null, "Test", true);
}); });
} }
[Fact] [Fact]
public static async Task FindDeclarationsAsync_Test_NullString() public async Task FindDeclarationsAsync_Test_NullString()
{ {
await Assert.ThrowsAsync<ArgumentNullException>(async () => await Assert.ThrowsAnyAsync<ArgumentNullException>(async () =>
{ {
var project = GetProject(WorkspaceKind.SingleClass); var project = GetProject(WorkspaceKind.SingleClass);
var declarations = await SymbolFinder.FindDeclarationsAsync(project, null, true); var declarations = await SymbolFinder.FindDeclarationsAsync(project, null, true);
...@@ -109,9 +110,9 @@ public static async Task FindDeclarationsAsync_Test_NullString() ...@@ -109,9 +110,9 @@ public static async Task FindDeclarationsAsync_Test_NullString()
} }
[Fact] [Fact]
public static async Task FindDeclarationsAsync_Test_Cancellation() public async Task FindDeclarationsAsync_Test_Cancellation()
{ {
await Assert.ThrowsAsync<TaskCanceledException>(async () => await Assert.ThrowsAnyAsync<TaskCanceledException>(async () =>
{ {
var cts = new CancellationTokenSource(); var cts = new CancellationTokenSource();
cts.Cancel(); cts.Cancel();
...@@ -121,7 +122,7 @@ public static async Task FindDeclarationsAsync_Test_Cancellation() ...@@ -121,7 +122,7 @@ public static async Task FindDeclarationsAsync_Test_Cancellation()
} }
[Fact, WorkItem(1094411, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1094411")] [Fact, WorkItem(1094411, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1094411")]
public static async Task FindDeclarationsAsync_Metadata() public async Task FindDeclarationsAsync_Metadata()
{ {
var solution = CreateSolution(); var solution = CreateSolution();
var csharpId = ProjectId.CreateNewId(); var csharpId = ProjectId.CreateNewId();
...@@ -142,7 +143,7 @@ public static async Task FindDeclarationsAsync_Metadata() ...@@ -142,7 +143,7 @@ public static async Task FindDeclarationsAsync_Metadata()
} }
[Fact, WorkItem(6616, "https://github.com/dotnet/roslyn/issues/6616")] [Fact, WorkItem(6616, "https://github.com/dotnet/roslyn/issues/6616")]
public static async Task FindDeclarationsAsync_PreviousSubmission() public async Task FindDeclarationsAsync_PreviousSubmission()
{ {
var solution = CreateSolution(); var solution = CreateSolution();
...@@ -246,7 +247,8 @@ public class Inner ...@@ -246,7 +247,8 @@ public class Inner
InlineData("TestCase", true, WorkspaceKind.TwoNamespacesWithIdenticalClasses, new[] { "TestCase1.TestCase", "TestCase2.TestCase" }), InlineData("TestCase", true, WorkspaceKind.TwoNamespacesWithIdenticalClasses, new[] { "TestCase1.TestCase", "TestCase2.TestCase" }),
InlineData("TestCase", false, WorkspaceKind.TwoNamespacesWithIdenticalClasses, new[] { "TestCase1.TestCase", "TestCase2.TestCase" }), InlineData("TestCase", false, WorkspaceKind.TwoNamespacesWithIdenticalClasses, new[] { "TestCase1.TestCase", "TestCase2.TestCase" }),
InlineData("TestCase1.TestCase", true, WorkspaceKind.TwoNamespacesWithIdenticalClasses, new string[0]),] InlineData("TestCase1.TestCase", true, WorkspaceKind.TwoNamespacesWithIdenticalClasses, new string[0]),]
public static async Task FindSourceDeclarationsAsync_Project_Test(string searchTerm, bool ignoreCase, WorkspaceKind workspaceKind, string[] expectedResults)
public async Task FindSourceDeclarationsAsync_Project_Test(string searchTerm, bool ignoreCase, WorkspaceKind workspaceKind, string[] expectedResults)
{ {
var project = GetProject(workspaceKind); var project = GetProject(workspaceKind);
var declarations = await SymbolFinder.FindSourceDeclarationsAsync(project, searchTerm, ignoreCase).ConfigureAwait(false); var declarations = await SymbolFinder.FindSourceDeclarationsAsync(project, searchTerm, ignoreCase).ConfigureAwait(false);
...@@ -254,18 +256,18 @@ public static async Task FindSourceDeclarationsAsync_Project_Test(string searchT ...@@ -254,18 +256,18 @@ public static async Task FindSourceDeclarationsAsync_Project_Test(string searchT
} }
[Fact] [Fact]
public static async Task FindSourceDeclarationsAsync_Project_Test_NullProject() public async Task FindSourceDeclarationsAsync_Project_Test_NullProject()
{ {
await Assert.ThrowsAsync<ArgumentNullException>(async () => await Assert.ThrowsAnyAsync<ArgumentNullException>(async () =>
{ {
var declarations = await SymbolFinder.FindSourceDeclarationsAsync((Project)null, "Test", true); var declarations = await SymbolFinder.FindSourceDeclarationsAsync((Project)null, "Test", true);
}); });
} }
[Fact] [Fact]
public static async Task FindSourceDeclarationsAsync_Project_Test_NullString() public async Task FindSourceDeclarationsAsync_Project_Test_NullString()
{ {
await Assert.ThrowsAsync<ArgumentNullException>(async () => await Assert.ThrowsAnyAsync<ArgumentNullException>(async () =>
{ {
var project = GetProject(WorkspaceKind.SingleClass); var project = GetProject(WorkspaceKind.SingleClass);
var declarations = await SymbolFinder.FindSourceDeclarationsAsync(project, null, true); var declarations = await SymbolFinder.FindSourceDeclarationsAsync(project, null, true);
...@@ -273,9 +275,9 @@ public static async Task FindSourceDeclarationsAsync_Project_Test_NullString() ...@@ -273,9 +275,9 @@ public static async Task FindSourceDeclarationsAsync_Project_Test_NullString()
} }
[Fact] [Fact]
public static async Task FindSourceDeclarationsAsync_Project_Test_Cancellation() public async Task FindSourceDeclarationsAsync_Project_Test_Cancellation()
{ {
await Assert.ThrowsAsync<TaskCanceledException>(async () => await Assert.ThrowsAnyAsync<TaskCanceledException>(async () =>
{ {
var cts = new CancellationTokenSource(); var cts = new CancellationTokenSource();
var project = GetProject(WorkspaceKind.SingleClass); var project = GetProject(WorkspaceKind.SingleClass);
...@@ -353,7 +355,8 @@ public static async Task FindSourceDeclarationsAsync_Project_Test_Cancellation() ...@@ -353,7 +355,8 @@ public static async Task FindSourceDeclarationsAsync_Project_Test_Cancellation()
InlineData("TestCase", true, WorkspaceKind.TwoNamespacesWithIdenticalClasses, new[] { "TestCase1.TestCase", "TestCase2.TestCase" }), InlineData("TestCase", true, WorkspaceKind.TwoNamespacesWithIdenticalClasses, new[] { "TestCase1.TestCase", "TestCase2.TestCase" }),
InlineData("TestCase", false, WorkspaceKind.TwoNamespacesWithIdenticalClasses, new[] { "TestCase1.TestCase", "TestCase2.TestCase" }), InlineData("TestCase", false, WorkspaceKind.TwoNamespacesWithIdenticalClasses, new[] { "TestCase1.TestCase", "TestCase2.TestCase" }),
InlineData("TestCase1.TestCase", true, WorkspaceKind.TwoNamespacesWithIdenticalClasses, new string[0]),] InlineData("TestCase1.TestCase", true, WorkspaceKind.TwoNamespacesWithIdenticalClasses, new string[0]),]
public static async Task FindSourceDeclarationsAsync_Solution_Test(string searchTerm, bool ignoreCase, WorkspaceKind workspaceKind, string[] expectedResults)
public async Task FindSourceDeclarationsAsync_Solution_Test(string searchTerm, bool ignoreCase, WorkspaceKind workspaceKind, string[] expectedResults)
{ {
var solution = GetSolution(workspaceKind); var solution = GetSolution(workspaceKind);
var declarations = await SymbolFinder.FindSourceDeclarationsAsync(solution, searchTerm, ignoreCase).ConfigureAwait(false); var declarations = await SymbolFinder.FindSourceDeclarationsAsync(solution, searchTerm, ignoreCase).ConfigureAwait(false);
...@@ -361,18 +364,18 @@ public static async Task FindSourceDeclarationsAsync_Solution_Test(string search ...@@ -361,18 +364,18 @@ public static async Task FindSourceDeclarationsAsync_Solution_Test(string search
} }
[Fact] [Fact]
public static async Task FindSourceDeclarationsAsync_Solution_Test_NullProject() public async Task FindSourceDeclarationsAsync_Solution_Test_NullProject()
{ {
await Assert.ThrowsAsync<ArgumentNullException>(async () => await Assert.ThrowsAnyAsync<ArgumentNullException>(async () =>
{ {
var declarations = await SymbolFinder.FindSourceDeclarationsAsync((Solution)null, "Test", true); var declarations = await SymbolFinder.FindSourceDeclarationsAsync((Solution)null, "Test", true);
}); });
} }
[Fact] [Fact]
public static async Task FindSourceDeclarationsAsync_Solution_Test_NullString() public async Task FindSourceDeclarationsAsync_Solution_Test_NullString()
{ {
await Assert.ThrowsAsync<ArgumentNullException>(async () => await Assert.ThrowsAnyAsync<ArgumentNullException>(async () =>
{ {
var solution = GetSolution(WorkspaceKind.SingleClass); var solution = GetSolution(WorkspaceKind.SingleClass);
var declarations = await SymbolFinder.FindSourceDeclarationsAsync(solution, null, true); var declarations = await SymbolFinder.FindSourceDeclarationsAsync(solution, null, true);
...@@ -380,22 +383,14 @@ public static async Task FindSourceDeclarationsAsync_Solution_Test_NullString() ...@@ -380,22 +383,14 @@ public static async Task FindSourceDeclarationsAsync_Solution_Test_NullString()
} }
[Fact] [Fact]
public static void FindSourceDeclarationsAsync_Solution_Test_Cancellation() public async Task FindSourceDeclarationsAsync_Solution_Test_Cancellation()
{
Assert.Throws<AggregateException>(() =>
{ {
try await Assert.ThrowsAnyAsync<OperationCanceledException>(async () =>
{ {
var cts = new CancellationTokenSource(); var cts = new CancellationTokenSource();
var solution = GetSolution(WorkspaceKind.SingleClass); var solution = GetSolution(WorkspaceKind.SingleClass);
cts.Cancel(); cts.Cancel();
var declarations = SymbolFinder.FindSourceDeclarationsAsync(solution, "Test", true, SymbolFilter.All, cts.Token).Result; var declarations = await SymbolFinder.FindSourceDeclarationsAsync(solution, "Test", true, SymbolFilter.All, cts.Token);
}
catch (AggregateException ex)
{
VerifyInnerExceptionIsType<OperationCanceledException>(ex);
throw;
}
}); });
} }
...@@ -413,7 +408,8 @@ public static void FindSourceDeclarationsAsync_Solution_Test_Cancellation() ...@@ -413,7 +408,8 @@ public static void FindSourceDeclarationsAsync_Solution_Test_Cancellation()
InlineData(WorkspaceKind.TwoProjectsEachWithASingleClassWithSingleField, new[] { "TestCases", "TestCases.TestCase", "TestCases.TestCase.TestField" }), InlineData(WorkspaceKind.TwoProjectsEachWithASingleClassWithSingleField, new[] { "TestCases", "TestCases.TestCase", "TestCases.TestCase.TestField" }),
InlineData(WorkspaceKind.NestedClass, new[] { "TestCases", "TestCases.TestCase", "TestCases.TestCase.InnerTestCase" }), InlineData(WorkspaceKind.NestedClass, new[] { "TestCases", "TestCases.TestCase", "TestCases.TestCase.InnerTestCase" }),
InlineData(WorkspaceKind.TwoNamespacesWithIdenticalClasses, new[] { "TestCase1", "TestCase1.TestCase", "TestCase2.TestCase", "TestCase2" }),] InlineData(WorkspaceKind.TwoNamespacesWithIdenticalClasses, new[] { "TestCase1", "TestCase1.TestCase", "TestCase2.TestCase", "TestCase2" }),]
public static async Task FindSourceDeclarationsAsync_Project_Func_Test(WorkspaceKind workspaceKind, string[] expectedResults)
public async Task FindSourceDeclarationsAsync_Project_Func_Test(WorkspaceKind workspaceKind, string[] expectedResults)
{ {
var project = GetProject(workspaceKind); var project = GetProject(workspaceKind);
var declarations = await SymbolFinder.FindSourceDeclarationsAsync(project, str => str.Contains("Test")).ConfigureAwait(false); var declarations = await SymbolFinder.FindSourceDeclarationsAsync(project, str => str.Contains("Test")).ConfigureAwait(false);
...@@ -421,7 +417,7 @@ public static async Task FindSourceDeclarationsAsync_Project_Func_Test(Workspace ...@@ -421,7 +417,7 @@ public static async Task FindSourceDeclarationsAsync_Project_Func_Test(Workspace
} }
[Fact] [Fact]
public static async Task FindSourceDeclarationsAsync_Project_Func_Test_AlwaysTruePredicate() public async Task FindSourceDeclarationsAsync_Project_Func_Test_AlwaysTruePredicate()
{ {
var project = GetProject(WorkspaceKind.SingleClass); var project = GetProject(WorkspaceKind.SingleClass);
var declarations = await SymbolFinder.FindSourceDeclarationsAsync(project, str => true).ConfigureAwait(false); var declarations = await SymbolFinder.FindSourceDeclarationsAsync(project, str => true).ConfigureAwait(false);
...@@ -429,7 +425,7 @@ public static async Task FindSourceDeclarationsAsync_Project_Func_Test_AlwaysTru ...@@ -429,7 +425,7 @@ public static async Task FindSourceDeclarationsAsync_Project_Func_Test_AlwaysTru
} }
[Fact] [Fact]
public static async Task FindSourceDeclarationsAsync_Project_Func_Test_AlwaysFalsePredicate() public async Task FindSourceDeclarationsAsync_Project_Func_Test_AlwaysFalsePredicate()
{ {
var project = GetProject(WorkspaceKind.SingleClass); var project = GetProject(WorkspaceKind.SingleClass);
var declarations = await SymbolFinder.FindSourceDeclarationsAsync(project, str => false).ConfigureAwait(false); var declarations = await SymbolFinder.FindSourceDeclarationsAsync(project, str => false).ConfigureAwait(false);
...@@ -437,49 +433,33 @@ public static async Task FindSourceDeclarationsAsync_Project_Func_Test_AlwaysFal ...@@ -437,49 +433,33 @@ public static async Task FindSourceDeclarationsAsync_Project_Func_Test_AlwaysFal
} }
[Fact] [Fact]
public static void FindSourceDeclarationsAsync_Project_Func_Test_NullProject() public async Task FindSourceDeclarationsAsync_Project_Func_Test_NullProject()
{
Assert.Throws<AggregateException>(() =>
{
try
{ {
var declarations = SymbolFinder.FindSourceDeclarationsAsync((Project)null, str => str.Contains("Test")).Result; await Assert.ThrowsAnyAsync<ArgumentNullException>(async () =>
}
catch (AggregateException ex)
{ {
VerifyInnerExceptionArgumentNull(ex, "project"); var declarations = await SymbolFinder.FindSourceDeclarationsAsync((Project)null, str => str.Contains("Test"));
throw;
}
}); });
} }
[Fact] [Fact]
public static void FindSourceDeclarationsAsync_Project_Func_Test_NullPredicate() public async Task FindSourceDeclarationsAsync_Project_Func_Test_NullPredicate()
{ {
Assert.Throws<ArgumentNullException>(() => await Assert.ThrowsAnyAsync<ArgumentNullException>(async () =>
{ {
var project = GetProject(WorkspaceKind.SingleClass); var project = GetProject(WorkspaceKind.SingleClass);
var declarations = SymbolFinder.FindSourceDeclarationsAsync(project, null).Result; var declarations = await SymbolFinder.FindSourceDeclarationsAsync(project, null);
}); });
} }
[Fact] [Fact]
public static void FindSourceDeclarationsAsync_Project_Func_Test_Cancellation() public async Task FindSourceDeclarationsAsync_Project_Func_Test_Cancellation()
{
Assert.Throws<AggregateException>(() =>
{ {
try await Assert.ThrowsAnyAsync<OperationCanceledException>(async () =>
{ {
var cts = new CancellationTokenSource(); var cts = new CancellationTokenSource();
var project = GetProject(WorkspaceKind.SingleClass); var project = GetProject(WorkspaceKind.SingleClass);
cts.Cancel(); cts.Cancel();
var declarations = SymbolFinder.FindSourceDeclarationsAsync(project, str => str.Contains("Test"), SymbolFilter.All, cts.Token).Result; var declarations = await SymbolFinder.FindSourceDeclarationsAsync(project, str => str.Contains("Test"), SymbolFilter.All, cts.Token);
}
catch (AggregateException ex)
{
VerifyInnerExceptionIsType<OperationCanceledException>(ex);
throw;
}
}); });
} }
...@@ -497,7 +477,8 @@ public static void FindSourceDeclarationsAsync_Project_Func_Test_Cancellation() ...@@ -497,7 +477,8 @@ public static void FindSourceDeclarationsAsync_Project_Func_Test_Cancellation()
InlineData(WorkspaceKind.TwoProjectsEachWithASingleClassWithSingleField, new[] { "TestCases", "TestCases.TestCase", "TestCases.TestCase.TestField", "TestCases", "TestCases.TestCase", "TestCases.TestCase.TestField" }), InlineData(WorkspaceKind.TwoProjectsEachWithASingleClassWithSingleField, new[] { "TestCases", "TestCases.TestCase", "TestCases.TestCase.TestField", "TestCases", "TestCases.TestCase", "TestCases.TestCase.TestField" }),
InlineData(WorkspaceKind.NestedClass, new[] { "TestCases", "TestCases.TestCase", "TestCases.TestCase.InnerTestCase" }), InlineData(WorkspaceKind.NestedClass, new[] { "TestCases", "TestCases.TestCase", "TestCases.TestCase.InnerTestCase" }),
InlineData(WorkspaceKind.TwoNamespacesWithIdenticalClasses, new[] { "TestCase1", "TestCase1.TestCase", "TestCase2.TestCase", "TestCase2" }),] InlineData(WorkspaceKind.TwoNamespacesWithIdenticalClasses, new[] { "TestCase1", "TestCase1.TestCase", "TestCase2.TestCase", "TestCase2" }),]
public static async Task FindSourceDeclarationsAsync_Solution_Func_Test(WorkspaceKind workspaceKind, string[] expectedResult)
public async Task FindSourceDeclarationsAsync_Solution_Func_Test(WorkspaceKind workspaceKind, string[] expectedResult)
{ {
var solution = GetSolution(workspaceKind); var solution = GetSolution(workspaceKind);
var declarations = await SymbolFinder.FindSourceDeclarationsAsync(solution, str => str.Contains("Test")).ConfigureAwait(false); var declarations = await SymbolFinder.FindSourceDeclarationsAsync(solution, str => str.Contains("Test")).ConfigureAwait(false);
...@@ -505,7 +486,7 @@ public static async Task FindSourceDeclarationsAsync_Solution_Func_Test(Workspac ...@@ -505,7 +486,7 @@ public static async Task FindSourceDeclarationsAsync_Solution_Func_Test(Workspac
} }
[Fact] [Fact]
public static async Task FindSourceDeclarationsAsync_Solution_Func_Test_AlwaysTruePredicate() public async Task FindSourceDeclarationsAsync_Solution_Func_Test_AlwaysTruePredicate()
{ {
var solution = GetSolution(WorkspaceKind.SingleClass); var solution = GetSolution(WorkspaceKind.SingleClass);
var declarations = await SymbolFinder.FindSourceDeclarationsAsync(solution, str => true).ConfigureAwait(false); var declarations = await SymbolFinder.FindSourceDeclarationsAsync(solution, str => true).ConfigureAwait(false);
...@@ -513,7 +494,7 @@ public static async Task FindSourceDeclarationsAsync_Solution_Func_Test_AlwaysTr ...@@ -513,7 +494,7 @@ public static async Task FindSourceDeclarationsAsync_Solution_Func_Test_AlwaysTr
} }
[Fact] [Fact]
public static async Task FindSourceDeclarationsAsync_Solution_Func_Test_AlwaysFalsePredicate() public async Task FindSourceDeclarationsAsync_Solution_Func_Test_AlwaysFalsePredicate()
{ {
var solution = GetSolution(WorkspaceKind.SingleClass); var solution = GetSolution(WorkspaceKind.SingleClass);
var declarations = await SymbolFinder.FindSourceDeclarationsAsync(solution, str => false).ConfigureAwait(false); var declarations = await SymbolFinder.FindSourceDeclarationsAsync(solution, str => false).ConfigureAwait(false);
...@@ -521,54 +502,38 @@ public static async Task FindSourceDeclarationsAsync_Solution_Func_Test_AlwaysFa ...@@ -521,54 +502,38 @@ public static async Task FindSourceDeclarationsAsync_Solution_Func_Test_AlwaysFa
} }
[Fact] [Fact]
public static void FindSourceDeclarationsAsync_Solution_Func_Test_NullSolution() public async Task FindSourceDeclarationsAsync_Solution_Func_Test_NullSolution()
{
Assert.Throws<AggregateException>(() =>
{
try
{ {
var declarations = SymbolFinder.FindSourceDeclarationsAsync((Solution)null, str => str.Contains("Test")).Result; await Assert.ThrowsAnyAsync<ArgumentNullException>(async () =>
}
catch (AggregateException ex)
{ {
VerifyInnerExceptionArgumentNull(ex, "solution"); await SymbolFinder.FindSourceDeclarationsAsync((Solution)null, str => str.Contains("Test"));
throw;
}
}); });
} }
[Fact] [Fact]
public static void FindSourceDeclarationsAsync_Solution_Func_Test_NullPredicate() public async Task FindSourceDeclarationsAsync_Solution_Func_Test_NullPredicate()
{ {
Assert.Throws<ArgumentNullException>(() => await Assert.ThrowsAnyAsync<ArgumentNullException>(async () =>
{ {
var solution = GetSolution(WorkspaceKind.SingleClass); var solution = GetSolution(WorkspaceKind.SingleClass);
var declarations = SymbolFinder.FindSourceDeclarationsAsync(solution, null).Result; await SymbolFinder.FindSourceDeclarationsAsync(solution, null);
}); });
} }
[Fact] [Fact]
public static void FindSourceDeclarationsAsync_Solution_Func_Test_Cancellation() public async Task FindSourceDeclarationsAsync_Solution_Func_Test_Cancellation()
{
Assert.Throws<AggregateException>(() =>
{ {
try await Assert.ThrowsAnyAsync<OperationCanceledException>(async () =>
{ {
var cts = new CancellationTokenSource(); var cts = new CancellationTokenSource();
var solution = GetSolution(WorkspaceKind.SingleClass); var solution = GetSolution(WorkspaceKind.SingleClass);
cts.Cancel(); cts.Cancel();
var declarations = SymbolFinder.FindSourceDeclarationsAsync(solution, str => str.Contains("Test"), SymbolFilter.All, cts.Token).Result; await SymbolFinder.FindSourceDeclarationsAsync(solution, str => str.Contains("Test"), SymbolFilter.All, cts.Token);
}
catch (AggregateException ex)
{
VerifyInnerExceptionIsType<OperationCanceledException>(ex);
throw;
}
}); });
} }
[Fact] [Fact]
public static async Task TestSymbolTreeInfoSerialization() public async Task TestSymbolTreeInfoSerialization()
{ {
var solution = GetSolution(WorkspaceKind.SingleClass); var solution = GetSolution(WorkspaceKind.SingleClass);
var compilation = await solution.Projects.First().GetCompilationAsync(); var compilation = await solution.Projects.First().GetCompilationAsync();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册