diff --git a/src/Features/Core/Portable/CodeFixes/Qualify/AbstractFullyQualifyCodeFixProvider.cs b/src/Features/Core/Portable/CodeFixes/Qualify/AbstractFullyQualifyCodeFixProvider.cs index 33d9f97d6db82..128a94cc9a692 100644 --- a/src/Features/Core/Portable/CodeFixes/Qualify/AbstractFullyQualifyCodeFixProvider.cs +++ b/src/Features/Core/Portable/CodeFixes/Qualify/AbstractFullyQualifyCodeFixProvider.cs @@ -140,16 +140,18 @@ private async Task> GetMatchingTypesAsync( var syntaxFacts = project.LanguageServices.GetService(); syntaxFacts.GetNameAndArityOfSimpleName(node, out var name, out var arity); - var symbolAndProjectIds = await DeclarationFinder.FindAllDeclarationsAsync( - project, name, this.IgnoreCase, SymbolFilter.Type, cancellationToken).ConfigureAwait(false); + var symbolAndProjectIds = await DeclarationFinder.FindAllDeclarationsWithNormalQueryAsync( + project, SearchQuery.Create(name, this.IgnoreCase), + SymbolFilter.Type, cancellationToken).ConfigureAwait(false); var symbols = symbolAndProjectIds.SelectAsArray(t => t.Symbol); // also lookup type symbols with the "Attribute" suffix. var inAttributeContext = syntaxFacts.IsAttributeName(node); if (inAttributeContext) { - var attributeSymbolAndProjectIds = await DeclarationFinder.FindAllDeclarationsAsync( - project, name + "Attribute", this.IgnoreCase, SymbolFilter.Type, cancellationToken).ConfigureAwait(false); + var attributeSymbolAndProjectIds = await DeclarationFinder.FindAllDeclarationsWithNormalQueryAsync( + project, SearchQuery.Create(name + "Attribute", this.IgnoreCase), + SymbolFilter.Type, cancellationToken).ConfigureAwait(false); symbols = symbols.Concat(attributeSymbolAndProjectIds.SelectAsArray(t => t.Symbol)); } @@ -189,8 +191,9 @@ private async Task> GetMatchingNamespacesAsync( return ImmutableArray.Empty; } - var symbolAndProjectIds = await DeclarationFinder.FindAllDeclarationsAsync( - project, name, this.IgnoreCase, SymbolFilter.Namespace, cancellationToken).ConfigureAwait(false); + var symbolAndProjectIds = await DeclarationFinder.FindAllDeclarationsWithNormalQueryAsync( + project, SearchQuery.Create(name, this.IgnoreCase), + SymbolFilter.Namespace, cancellationToken).ConfigureAwait(false); var symbols = symbolAndProjectIds.SelectAsArray(t => t.Symbol); diff --git a/src/Features/VisualBasic/Portable/CodeFixes/GenerateEvent/GenerateEventCodeFixProvider.vb b/src/Features/VisualBasic/Portable/CodeFixes/GenerateEvent/GenerateEventCodeFixProvider.vb index 9ace1e786c174..94dfc8f6270bc 100644 --- a/src/Features/VisualBasic/Portable/CodeFixes/GenerateEvent/GenerateEventCodeFixProvider.vb +++ b/src/Features/VisualBasic/Portable/CodeFixes/GenerateEvent/GenerateEventCodeFixProvider.vb @@ -107,7 +107,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.GenerateEvent Dim syntaxFactService = document.Project.Solution.Workspace.Services.GetLanguageServices(targetType.Language).GetService(Of ISyntaxFactsService) Dim eventHandlerName As String = actualEventName + "Handler" - Dim existingSymbolAndProjectIds = Await DeclarationFinder.FindSourceDeclarationsWithNormalQueryInLocalProcessAsync( + Dim existingSymbolAndProjectIds = Await DeclarationFinder.FindSourceDeclarationsWithNormalQueryAsync( document.Project.Solution, eventHandlerName, Not syntaxFactService.IsCaseSensitive, SymbolFilter.Type, cancellationToken).ConfigureAwait(False) Dim existingSymbols = existingSymbolAndProjectIds.SelectAsArray(Function(t) t.Symbol) diff --git a/src/Workspaces/Core/Portable/FindSymbols/Declarations/DeclarationFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/Declarations/DeclarationFinder.cs index 35d4aaa7a8cb4..da95fee4a35c0 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/Declarations/DeclarationFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/Declarations/DeclarationFinder.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.Internal.Log; using Microsoft.CodeAnalysis.Shared.Extensions; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.FindSymbols { @@ -16,7 +17,7 @@ private static Task AddCompilationDeclarationsWithNormalQueryAsync( Project project, SearchQuery query, SymbolFilter filter, ArrayBuilder list, CancellationToken cancellationToken) { - Debug.Assert(query.Kind != SearchKind.Custom); + Contract.ThrowIfTrue(query.Kind == SearchKind.Custom, "Custom queries are not supported in this API"); return AddCompilationDeclarationsWithNormalQueryAsync( project, query, filter, list, startingCompilation: null, @@ -33,7 +34,7 @@ private static async Task AddCompilationDeclarationsWithNormalQueryAsync( IAssemblySymbol startingAssembly, CancellationToken cancellationToken) { - Debug.Assert(query.Kind != SearchKind.Custom); + Contract.ThrowIfTrue(query.Kind == SearchKind.Custom, "Custom queries are not supported in this API"); using (Logger.LogBlock(FunctionId.SymbolFinder_Project_AddDeclarationsAsync, cancellationToken)) { @@ -67,7 +68,7 @@ private static async Task AddMetadataDeclarationsWithNormalQueryAsync( { // All entrypoints to this function are Find functions that are only searching // for specific strings (i.e. they never do a custom search). - Debug.Assert(query.Kind != SearchKind.Custom); + Contract.ThrowIfTrue(query.Kind == SearchKind.Custom, "Custom queries are not supported in this API"); using (Logger.LogBlock(FunctionId.SymbolFinder_Assembly_AddDeclarationsAsync, cancellationToken)) { diff --git a/src/Workspaces/Core/Portable/FindSymbols/Declarations/DeclarationFinder_AllDeclarations.cs b/src/Workspaces/Core/Portable/FindSymbols/Declarations/DeclarationFinder_AllDeclarations.cs index a6386d9de3e19..553dc3c0db527 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/Declarations/DeclarationFinder_AllDeclarations.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/Declarations/DeclarationFinder_AllDeclarations.cs @@ -1,12 +1,11 @@ // 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; -using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using System.Threading; using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Internal.Log; +using Microsoft.CodeAnalysis.Remote; using Microsoft.CodeAnalysis.Shared.Extensions; using Roslyn.Utilities; @@ -17,63 +16,38 @@ namespace Microsoft.CodeAnalysis.FindSymbols internal static partial class DeclarationFinder { - /// - /// Find the declared symbols from either source, referenced projects or metadata assemblies with the specified name. - /// - internal static async Task> FindAllDeclarationsAsync( - Project project, string name, bool ignoreCase, CancellationToken cancellationToken) + public static async Task> FindAllDeclarationsWithNormalQueryAsync( + Project project, SearchQuery query, SymbolFilter criteria, CancellationToken cancellationToken) { - if (name == null) + // All entrypoints to this function are Find functions that are only searching + // for specific strings (i.e. they never do a custom search). + Contract.ThrowIfTrue(query.Kind == SearchKind.Custom, "Custom queries are not supported in this API"); + + if (project == null) { - throw new ArgumentNullException(nameof(name)); + throw new ArgumentNullException(nameof(project)); } - if (string.IsNullOrWhiteSpace(name)) + if (query.Name != null && string.IsNullOrWhiteSpace(query.Name)) { return ImmutableArray.Empty; } - return await FindAllDeclarationsWithNormalQueryAsync( - project, SearchQuery.Create(name, ignoreCase), SymbolFilter.All, cancellationToken: cancellationToken).ConfigureAwait(false); - } + var (succeeded, results) = await TryFindAllDeclarationsWithNormalQueryInRemoteProcessAsync( + project, query, criteria, cancellationToken).ConfigureAwait(false); - /// - /// Find the declared symbols from either source, referenced projects or metadata assemblies with the specified name. - /// - internal static async Task> FindAllDeclarationsAsync( - Project project, string name, bool ignoreCase, SymbolFilter filter, CancellationToken cancellationToken = default(CancellationToken)) - { - if (name == null) + if (succeeded) { - throw new ArgumentNullException(nameof(name)); + return results; } - if (string.IsNullOrWhiteSpace(name)) - { - return ImmutableArray.Empty; - } - - return await FindAllDeclarationsWithNormalQueryAsync( - project, SearchQuery.Create(name, ignoreCase), filter, cancellationToken: cancellationToken).ConfigureAwait(false); + return await FindAllDeclarationsWithNormalQueryInCurrentProcessAsync( + project, query, criteria, cancellationToken).ConfigureAwait(false); } - internal static async Task> FindAllDeclarationsWithNormalQueryAsync( + internal static async Task> FindAllDeclarationsWithNormalQueryInCurrentProcessAsync( Project project, SearchQuery query, SymbolFilter criteria, CancellationToken cancellationToken) { - // All entrypoints to this function are Find functions that are only searching - // for specific strings (i.e. they never do a custom search). - Debug.Assert(query.Kind != SearchKind.Custom); - - if (project == null) - { - throw new ArgumentNullException(nameof(project)); - } - - if (query.Name != null && string.IsNullOrWhiteSpace(query.Name)) - { - return ImmutableArray.Empty; - } - var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); var list = ArrayBuilder.GetInstance(); @@ -115,5 +89,40 @@ await AddMetadataDeclarationsWithNormalQueryAsync( return list.ToImmutableAndFree(); } + + private static async Task<(bool, ImmutableArray)> TryFindAllDeclarationsWithNormalQueryInRemoteProcessAsync( + Project project, SearchQuery query, SymbolFilter criteria, CancellationToken cancellationToken) + { + var session = await SymbolFinder.TryGetRemoteSessionAsync( + project.Solution, cancellationToken).ConfigureAwait(false); + if (session != null) + { + var result = await session.InvokeAsync( + nameof(IRemoteSymbolFinder.FindAllDeclarationsWithNormalQueryAsync), + project.Id, query.Name, query.Kind, criteria).ConfigureAwait(false); + + var rehydrated = await RehydrateAsync( + project.Solution, result, cancellationToken).ConfigureAwait(false); + + return (true, rehydrated); + } + + return (false, ImmutableArray.Empty); + } + + private static async Task> RehydrateAsync( + Solution solution, SerializableSymbolAndProjectId[] array, CancellationToken cancellationToken) + { + var result = ArrayBuilder.GetInstance(); + + foreach (var dehydrated in array) + { + cancellationToken.ThrowIfCancellationRequested(); + var rehydrated = await dehydrated.RehydrateAsync(solution, cancellationToken).ConfigureAwait(false); + result.Add(rehydrated); + } + + return result.ToImmutableAndFree(); + } } } \ No newline at end of file diff --git a/src/Workspaces/Core/Portable/FindSymbols/Declarations/DeclarationFinder_SourceDeclarations.cs b/src/Workspaces/Core/Portable/FindSymbols/Declarations/DeclarationFinder_SourceDeclarations.cs index d4cd23a2df62a..fc7d7d57a526a 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/Declarations/DeclarationFinder_SourceDeclarations.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/Declarations/DeclarationFinder_SourceDeclarations.cs @@ -7,6 +7,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Internal.Log; +using Microsoft.CodeAnalysis.Remote; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.FindSymbols @@ -16,8 +17,13 @@ namespace Microsoft.CodeAnalysis.FindSymbols internal static partial class DeclarationFinder { - internal static async Task> FindSourceDeclarationsWithNormalQueryInLocalProcessAsync( - Solution solution, string name, bool ignoreCase, SymbolFilter filter, CancellationToken cancellationToken) + #region Dispatch Members + + // These are the public entrypoints to finding source declarations. They will attempt to + // remove the query to the OOP process, and will fallback to local processing if they can't. + + public static async Task> FindSourceDeclarationsWithNormalQueryAsync( + Solution solution, string name, bool ignoreCase, SymbolFilter criteria, CancellationToken cancellationToken) { if (solution == null) { @@ -34,20 +40,20 @@ internal static async Task> FindSourceDeclara return ImmutableArray.Empty; } - var query = SearchQuery.Create(name, ignoreCase); - var result = ArrayBuilder.GetInstance(); - foreach (var projectId in solution.ProjectIds) + var (succeded, results) = await TryFindSourceDeclarationsWithNormalQueryInRemoteProcessAsync( + solution, name, ignoreCase, criteria, cancellationToken).ConfigureAwait(false); + + if (succeded) { - var project = solution.GetProject(projectId); - await AddCompilationDeclarationsWithNormalQueryAsync( - project, query, filter, result, cancellationToken).ConfigureAwait(false); + return results; } - return result.ToImmutableAndFree(); + return await FindSourceDeclarationsWithNormalQueryInCurrentProcessAsync( + solution, name, ignoreCase, criteria, cancellationToken).ConfigureAwait(false); } - public static async Task> FindSourceDeclarationsithNormalQueryInLocalProcessAsync( - Project project, string name, bool ignoreCase, SymbolFilter filter, CancellationToken cancellationToken) + public static async Task> FindSourceDeclarationsWithNormalQueryAsync( + Project project, string name, bool ignoreCase, SymbolFilter criteria, CancellationToken cancellationToken) { if (project == null) { @@ -64,11 +70,95 @@ public static async Task> FindSourceDeclarati return ImmutableArray.Empty; } + var (succeded, results) = await TryFindSourceDeclarationsWithNormalQueryInRemoteProcessAsync( + project, name, ignoreCase, criteria, cancellationToken).ConfigureAwait(false); + + if (succeded) + { + return results; + } + + return await FindSourceDeclarationsWithNormalQueryInCurrentProcessAsync( + project, name, ignoreCase, criteria, cancellationToken).ConfigureAwait(false); + } + + #endregion + + #region Remote Dispatch + + // These are the members that actually try to send the request to the remote process. + + private static async Task<(bool, ImmutableArray)> TryFindSourceDeclarationsWithNormalQueryInRemoteProcessAsync( + Solution solution, string name, bool ignoreCase, SymbolFilter criteria, CancellationToken cancellationToken) + { + var session = await SymbolFinder.TryGetRemoteSessionAsync(solution, cancellationToken).ConfigureAwait(false); + if (session != null) + { + var result = await session.InvokeAsync( + nameof(IRemoteSymbolFinder.FindSolutionSourceDeclarationsWithNormalQuery), + name, ignoreCase, criteria).ConfigureAwait(false); + + var rehydrated = await RehydrateAsync( + solution, result, cancellationToken).ConfigureAwait(false); + + return (true, rehydrated); + } + + return (false, ImmutableArray.Empty); + } + + private static async Task<(bool, ImmutableArray)> TryFindSourceDeclarationsWithNormalQueryInRemoteProcessAsync( + Project project, string name, bool ignoreCase, SymbolFilter criteria, CancellationToken cancellationToken) + { + var session = await SymbolFinder.TryGetRemoteSessionAsync(project.Solution, cancellationToken).ConfigureAwait(false); + if (session != null) + { + var result = await session.InvokeAsync( + nameof(IRemoteSymbolFinder.FindProjectSourceDeclarationsWithNormalQuery), + project.Id, name, ignoreCase, criteria).ConfigureAwait(false); + + var rehydrated = await RehydrateAsync( + project.Solution, result, cancellationToken).ConfigureAwait(false); + + return (true, rehydrated); + } + + return (false, ImmutableArray.Empty); + } + + #endregion + + #region Local processing + + // These are the members that have the core logic that does the actual finding. They will + // be called 'in proc' in the remote process if we are able to remote the request. Or they + // will be called 'in proc' from within VS if we are not able to remote the request. + + internal static async Task> FindSourceDeclarationsWithNormalQueryInCurrentProcessAsync( + Solution solution, string name, bool ignoreCase, SymbolFilter criteria, CancellationToken cancellationToken) + { + var query = SearchQuery.Create(name, ignoreCase); + var result = ArrayBuilder.GetInstance(); + foreach (var projectId in solution.ProjectIds) + { + var project = solution.GetProject(projectId); + await AddCompilationDeclarationsWithNormalQueryAsync( + project, query, criteria, result, cancellationToken).ConfigureAwait(false); + } + + return result.ToImmutableAndFree(); + } + + internal static async Task> FindSourceDeclarationsWithNormalQueryInCurrentProcessAsync( + Project project, string name, bool ignoreCase, SymbolFilter filter, CancellationToken cancellationToken) + { var list = ArrayBuilder.GetInstance(); await AddCompilationDeclarationsWithNormalQueryAsync( project, SearchQuery.Create(name, ignoreCase), filter, list, cancellationToken).ConfigureAwait(false); return list.ToImmutableAndFree(); } + + #endregion } } \ No newline at end of file diff --git a/src/Workspaces/Core/Portable/FindSymbols/IRemoteSymbolFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/IRemoteSymbolFinder.cs index e4fc3d61bc1ad..fcf5d42a3c20d 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/IRemoteSymbolFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/IRemoteSymbolFinder.cs @@ -9,5 +9,14 @@ internal interface IRemoteSymbolFinder { Task FindReferencesAsync(SerializableSymbolAndProjectId symbolAndProjectIdArg, DocumentId[] documentArgs); Task FindLiteralReferencesAsync(object value); + + Task FindAllDeclarationsWithNormalQueryAsync( + ProjectId projectId, string name, SearchKind searchKind, SymbolFilter criteria); + + Task FindSolutionSourceDeclarationsWithNormalQuery( + string name, bool ignoreCase, SymbolFilter criteria); + + Task FindProjectSourceDeclarationsWithNormalQuery( + ProjectId projectId, string name, bool ignoreCase, SymbolFilter criteria); } } \ No newline at end of file diff --git a/src/Workspaces/Core/Portable/FindSymbols/SearchQuery.cs b/src/Workspaces/Core/Portable/FindSymbols/SearchQuery.cs index 0941f1abd8cb4..661b1ea0f1fdd 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/SearchQuery.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/SearchQuery.cs @@ -39,6 +39,8 @@ private SearchQuery(string name, SearchKind kind) var editDistance = new WordSimilarityChecker(name, substringsAreSimilar: false); _predicate = editDistance.AreSimilar; break; + default: + throw ExceptionUtilities.UnexpectedValue(kind); } } @@ -48,24 +50,19 @@ private SearchQuery(Func predicate) _predicate = predicate ?? throw new ArgumentNullException(nameof(predicate)); } + public static SearchQuery Create(string name, SearchKind kind) + => new SearchQuery(name, kind); + public static SearchQuery Create(string name, bool ignoreCase) - { - return new SearchQuery(name, ignoreCase ? SearchKind.ExactIgnoreCase : SearchKind.Exact); - } + => new SearchQuery(name, ignoreCase ? SearchKind.ExactIgnoreCase : SearchKind.Exact); public static SearchQuery CreateFuzzy(string name) - { - return new SearchQuery(name, SearchKind.Fuzzy); - } + => new SearchQuery(name, SearchKind.Fuzzy); public static SearchQuery CreateCustom(Func predicate) - { - return new SearchQuery(predicate); - } + => new SearchQuery(predicate); public Func GetPredicate() - { - return _predicate; - } + => _predicate; } } \ No newline at end of file diff --git a/src/Workspaces/Core/Portable/FindSymbols/SymbolFinder_Declarations_AllDeclarations.cs b/src/Workspaces/Core/Portable/FindSymbols/SymbolFinder_Declarations_AllDeclarations.cs index b8bc6b3b19bb0..9f016feb82cf3 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/SymbolFinder_Declarations_AllDeclarations.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/SymbolFinder_Declarations_AllDeclarations.cs @@ -1,14 +1,8 @@ // 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; using System.Collections.Generic; -using System.Collections.Immutable; -using System.Diagnostics; using System.Threading; using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Internal.Log; -using Microsoft.CodeAnalysis.Shared.Extensions; -using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.FindSymbols { @@ -20,8 +14,8 @@ public static partial class SymbolFinder public static async Task> FindDeclarationsAsync( Project project, string name, bool ignoreCase, CancellationToken cancellationToken = default(CancellationToken)) { - var declarations = await DeclarationFinder.FindAllDeclarationsAsync( - project, name, ignoreCase, cancellationToken).ConfigureAwait(false); + var declarations = await DeclarationFinder.FindAllDeclarationsWithNormalQueryAsync( + project, SearchQuery.Create(name, ignoreCase), SymbolFilter.All, cancellationToken).ConfigureAwait(false); return declarations.SelectAsArray(t => t.Symbol); } @@ -31,8 +25,8 @@ public static async Task> FindDeclarationsAsync( public static async Task> FindDeclarationsAsync( Project project, string name, bool ignoreCase, SymbolFilter filter, CancellationToken cancellationToken = default(CancellationToken)) { - var declarations = await DeclarationFinder.FindAllDeclarationsAsync( - project, name, ignoreCase, filter, cancellationToken).ConfigureAwait(false); + var declarations = await DeclarationFinder.FindAllDeclarationsWithNormalQueryAsync( + project, SearchQuery.Create(name, ignoreCase), filter, cancellationToken).ConfigureAwait(false); return declarations.SelectAsArray(t => t.Symbol); } } diff --git a/src/Workspaces/Core/Portable/FindSymbols/SymbolFinder_Declarations_SourceDeclarations.cs b/src/Workspaces/Core/Portable/FindSymbols/SymbolFinder_Declarations_SourceDeclarations.cs index f62b86349c37a..a2108844ba2cb 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/SymbolFinder_Declarations_SourceDeclarations.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/SymbolFinder_Declarations_SourceDeclarations.cs @@ -30,7 +30,7 @@ public static async Task> FindSourceDeclarationsAsync( { using (Logger.LogBlock(FunctionId.SymbolFinder_Solution_Name_FindSourceDeclarationsAsync, cancellationToken)) { - var declarations = await DeclarationFinder.FindSourceDeclarationsWithNormalQueryInLocalProcessAsync( + var declarations = await DeclarationFinder.FindSourceDeclarationsWithNormalQueryAsync( solution, name, ignoreCase, filter, cancellationToken).ConfigureAwait(false); return declarations.SelectAsArray(t => t.Symbol); } @@ -50,7 +50,7 @@ public static async Task> FindSourceDeclarationsAsync( { using (Logger.LogBlock(FunctionId.SymbolFinder_Project_Name_FindSourceDeclarationsAsync, cancellationToken)) { - var declarations = await DeclarationFinder.FindSourceDeclarationsithNormalQueryInLocalProcessAsync( + var declarations = await DeclarationFinder.FindSourceDeclarationsWithNormalQueryAsync( project, name, ignoreCase, filter, cancellationToken).ConfigureAwait(false); return declarations.SelectAsArray(t => t.Symbol); diff --git a/src/Workspaces/Core/Portable/FindSymbols/SymbolFinder_Remote.cs b/src/Workspaces/Core/Portable/FindSymbols/SymbolFinder_Remote.cs index 41158098860b4..af5551e541f54 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/SymbolFinder_Remote.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/SymbolFinder_Remote.cs @@ -8,7 +8,7 @@ namespace Microsoft.CodeAnalysis.FindSymbols { public static partial class SymbolFinder { - private static Task TryGetRemoteSessionAsync( + internal static Task TryGetRemoteSessionAsync( Solution solution, CancellationToken cancellationToken) => TryGetRemoteSessionAsync(solution, serverCallback: null, cancellationToken: cancellationToken); diff --git a/src/Workspaces/Core/Portable/FindSymbols/SymbolTree/SymbolTreeInfo.cs b/src/Workspaces/Core/Portable/FindSymbols/SymbolTree/SymbolTreeInfo.cs index cb0d3d33d0c13..0e8daa8c9ad1b 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/SymbolTree/SymbolTreeInfo.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/SymbolTree/SymbolTreeInfo.cs @@ -119,7 +119,7 @@ public Task> FindAsync( { // All entrypoints to this function are Find functions that are only searching // for specific strings (i.e. they never do a custom search). - Debug.Assert(query.Kind != SearchKind.Custom); + Contract.ThrowIfTrue(query.Kind == SearchKind.Custom, "Custom queries are not supported in this API"); return this.FindAsync( query, new AsyncLazy(assembly), @@ -132,7 +132,7 @@ public async Task> FindAsync( { // All entrypoints to this function are Find functions that are only searching // for specific strings (i.e. they never do a custom search). - Debug.Assert(query.Kind != SearchKind.Custom); + Contract.ThrowIfTrue(query.Kind == SearchKind.Custom, "Custom queries are not supported in this API"); var symbols = await FindAsyncWorker(query, lazyAssembly, cancellationToken).ConfigureAwait(false); @@ -146,7 +146,7 @@ private Task> FindAsyncWorker( { // All entrypoints to this function are Find functions that are only searching // for specific strings (i.e. they never do a custom search). - Debug.Assert(query.Kind != SearchKind.Custom); + Contract.ThrowIfTrue(query.Kind == SearchKind.Custom, "Custom queries are not supported in this API"); // If the query has a specific string provided, then call into the SymbolTreeInfo // helpers optimized for lookup based on an exact name. diff --git a/src/Workspaces/Remote/ServiceHub/ServiceHub.csproj b/src/Workspaces/Remote/ServiceHub/ServiceHub.csproj index 4b27d7d7402c6..26d66f271df3b 100644 --- a/src/Workspaces/Remote/ServiceHub/ServiceHub.csproj +++ b/src/Workspaces/Remote/ServiceHub/ServiceHub.csproj @@ -63,7 +63,7 @@ - + diff --git a/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_FindReferences.cs b/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_SymbolFinder.cs similarity index 68% rename from src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_FindReferences.cs rename to src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_SymbolFinder.cs index 8c58e16fd5feb..5b2a7f92fbc17 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_FindReferences.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_SymbolFinder.cs @@ -34,6 +34,40 @@ await SymbolFinder.FindLiteralReferencesInCurrentProcessAsync( value, solution, progressCallback, CancellationToken).ConfigureAwait(false); } + public async Task FindAllDeclarationsWithNormalQueryAsync( + ProjectId projectId, string name, SearchKind searchKind, SymbolFilter criteria) + { + var solution = await GetSolutionAsync().ConfigureAwait(false); + var project = solution.GetProject(projectId); + + var result = await DeclarationFinder.FindAllDeclarationsWithNormalQueryInCurrentProcessAsync( + project, SearchQuery.Create(name, searchKind), criteria, this.CancellationToken).ConfigureAwait(false); + + return result.Select(SerializableSymbolAndProjectId.Dehydrate).ToArray(); + } + + public async Task FindSolutionSourceDeclarationsWithNormalQuery( + string name, bool ignoreCase, SymbolFilter criteria) + { + var solution = await GetSolutionAsync().ConfigureAwait(false); + var result = await DeclarationFinder.FindSourceDeclarationsWithNormalQueryInCurrentProcessAsync( + solution, name, ignoreCase, criteria, CancellationToken).ConfigureAwait(false); + + return result.Select(SerializableSymbolAndProjectId.Dehydrate).ToArray(); + } + + public async Task FindProjectSourceDeclarationsWithNormalQuery( + ProjectId projectId, string name, bool ignoreCase, SymbolFilter criteria) + { + var solution = await GetSolutionAsync().ConfigureAwait(false); + var project = solution.GetProject(projectId); + + var result = await DeclarationFinder.FindSourceDeclarationsWithNormalQueryInCurrentProcessAsync( + project, name, ignoreCase, criteria, CancellationToken).ConfigureAwait(false); + + return result.Select(SerializableSymbolAndProjectId.Dehydrate).ToArray(); + } + private class FindLiteralReferencesProgressCallback : IStreamingFindLiteralReferencesProgress { private readonly CodeAnalysisService _service;