From df9f330c3462101a45fa308e82b4ce15b93fcf9b Mon Sep 17 00:00:00 2001 From: CyrusNajmabadi Date: Sat, 8 Apr 2017 16:16:07 -0700 Subject: [PATCH 1/5] Move part of the SymbolFinder out of proc. --- .../DeclarationFinder_AllDeclarations.cs | 51 +++++++++++++++++++ .../FindSymbols/IRemoteSymbolFinder.cs | 3 ++ .../Core/Portable/FindSymbols/SearchQuery.cs | 21 ++++---- .../FindSymbols/SymbolFinder_Remote.cs | 2 +- .../Remote/ServiceHub/ServiceHub.csproj | 2 +- ...cs => CodeAnalysisService_SymbolFinder.cs} | 12 +++++ 6 files changed, 77 insertions(+), 14 deletions(-) rename src/Workspaces/Remote/ServiceHub/Services/{CodeAnalysisService_FindReferences.cs => CodeAnalysisService_SymbolFinder.cs} (85%) diff --git a/src/Workspaces/Core/Portable/FindSymbols/Declarations/DeclarationFinder_AllDeclarations.cs b/src/Workspaces/Core/Portable/FindSymbols/Declarations/DeclarationFinder_AllDeclarations.cs index a6386d9de3e19..d836071168c2d 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/Declarations/DeclarationFinder_AllDeclarations.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/Declarations/DeclarationFinder_AllDeclarations.cs @@ -7,6 +7,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Internal.Log; +using Microsoft.CodeAnalysis.Remote; using Microsoft.CodeAnalysis.Shared.Extensions; using Roslyn.Utilities; @@ -74,6 +75,21 @@ internal static async Task> FindAllDeclaratio return ImmutableArray.Empty; } + var (succeeded, results) = await TryFindAllDeclarationsWithNormalQueryInRemoteProcessAsync( + project, query, criteria, cancellationToken).ConfigureAwait(false); + + if (succeeded) + { + return results; + } + + return await FindAllDeclarationsWithNormalQueryInCurrentProcessAsync( + project, query, criteria, cancellationToken).ConfigureAwait(false); + } + + internal static async Task> FindAllDeclarationsWithNormalQueryInCurrentProcessAsync( + Project project, SearchQuery query, SymbolFilter criteria, CancellationToken cancellationToken) + { var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); var list = ArrayBuilder.GetInstance(); @@ -115,5 +131,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/IRemoteSymbolFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/IRemoteSymbolFinder.cs index e4fc3d61bc1ad..472cd59939fd1 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/IRemoteSymbolFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/IRemoteSymbolFinder.cs @@ -9,5 +9,8 @@ internal interface IRemoteSymbolFinder { Task FindReferencesAsync(SerializableSymbolAndProjectId symbolAndProjectIdArg, DocumentId[] documentArgs); Task FindLiteralReferencesAsync(object value); + + Task FindAllDeclarationsWithNormalQueryAsync( + ProjectId projectId, string name, SearchKind searchKind, 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_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/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 85% rename from src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_FindReferences.cs rename to src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_SymbolFinder.cs index 8c58e16fd5feb..5dec593c57031 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_FindReferences.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_SymbolFinder.cs @@ -34,6 +34,18 @@ 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(); + } + private class FindLiteralReferencesProgressCallback : IStreamingFindLiteralReferencesProgress { private readonly CodeAnalysisService _service; From 556ca2bf86301fb44083f61a02bcc08bee86cf6b Mon Sep 17 00:00:00 2001 From: CyrusNajmabadi Date: Sat, 8 Apr 2017 16:32:20 -0700 Subject: [PATCH 2/5] Move the rest of DeclarationFinder over to using OOP if it can. --- .../GenerateEventCodeFixProvider.vb | 2 +- .../DeclarationFinder_SourceDeclarations.cs | 79 +++++++++++++++++-- .../FindSymbols/IRemoteSymbolFinder.cs | 6 ++ ...lFinder_Declarations_SourceDeclarations.cs | 4 +- .../CodeAnalysisService_SymbolFinder.cs | 22 ++++++ 5 files changed, 105 insertions(+), 8 deletions(-) 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_SourceDeclarations.cs b/src/Workspaces/Core/Portable/FindSymbols/Declarations/DeclarationFinder_SourceDeclarations.cs index d4cd23a2df62a..b1935a1ece4f8 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,8 @@ namespace Microsoft.CodeAnalysis.FindSymbols internal static partial class DeclarationFinder { - internal static async Task> FindSourceDeclarationsWithNormalQueryInLocalProcessAsync( - Solution solution, string name, bool ignoreCase, SymbolFilter filter, CancellationToken cancellationToken) + internal static async Task> FindSourceDeclarationsWithNormalQueryAsync( + Solution solution, string name, bool ignoreCase, SymbolFilter criteria, CancellationToken cancellationToken) { if (solution == null) { @@ -34,20 +35,54 @@ internal static async Task> FindSourceDeclara return ImmutableArray.Empty; } + var (succeded, results) = await TryFindSourceDeclarationsWithNormalQueryInRemoteProcessAsync( + solution, name, ignoreCase, criteria, cancellationToken).ConfigureAwait(false); + + if (succeded) + { + return results; + } + + return await FindSourceDeclarationsWithNormalQueryInCurrentProcessAsync( + solution, name, ignoreCase, criteria, cancellationToken).ConfigureAwait(false); + } + + 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, filter, result, cancellationToken).ConfigureAwait(false); + project, query, criteria, result, cancellationToken).ConfigureAwait(false); } return result.ToImmutableAndFree(); } - public static async Task> FindSourceDeclarationsithNormalQueryInLocalProcessAsync( - Project project, string name, bool ignoreCase, SymbolFilter filter, CancellationToken cancellationToken) + 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); + } + + public static async Task> FindSourceDeclarationsithNormalQueryAsync( + Project project, string name, bool ignoreCase, SymbolFilter criteria, CancellationToken cancellationToken) { if (project == null) { @@ -64,6 +99,40 @@ 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); + } + + 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); + } + + 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), diff --git a/src/Workspaces/Core/Portable/FindSymbols/IRemoteSymbolFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/IRemoteSymbolFinder.cs index 472cd59939fd1..fcf5d42a3c20d 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/IRemoteSymbolFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/IRemoteSymbolFinder.cs @@ -12,5 +12,11 @@ internal interface IRemoteSymbolFinder 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/SymbolFinder_Declarations_SourceDeclarations.cs b/src/Workspaces/Core/Portable/FindSymbols/SymbolFinder_Declarations_SourceDeclarations.cs index f62b86349c37a..f92cc07fea300 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.FindSourceDeclarationsithNormalQueryAsync( project, name, ignoreCase, filter, cancellationToken).ConfigureAwait(false); return declarations.SelectAsArray(t => t.Symbol); diff --git a/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_SymbolFinder.cs b/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_SymbolFinder.cs index 5dec593c57031..5b2a7f92fbc17 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_SymbolFinder.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_SymbolFinder.cs @@ -46,6 +46,28 @@ public async Task FindAllDeclarationsWithNorma 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; From 8a86f631965efa8ae8a1897df78cabaf3117989e Mon Sep 17 00:00:00 2001 From: CyrusNajmabadi Date: Sat, 8 Apr 2017 16:36:36 -0700 Subject: [PATCH 3/5] Add comments and organize code. --- .../DeclarationFinder_SourceDeclarations.cs | 91 ++++++++++++------- 1 file changed, 56 insertions(+), 35 deletions(-) diff --git a/src/Workspaces/Core/Portable/FindSymbols/Declarations/DeclarationFinder_SourceDeclarations.cs b/src/Workspaces/Core/Portable/FindSymbols/Declarations/DeclarationFinder_SourceDeclarations.cs index b1935a1ece4f8..40e064407c941 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/Declarations/DeclarationFinder_SourceDeclarations.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/Declarations/DeclarationFinder_SourceDeclarations.cs @@ -17,7 +17,12 @@ namespace Microsoft.CodeAnalysis.FindSymbols internal static partial class DeclarationFinder { - internal static async Task> FindSourceDeclarationsWithNormalQueryAsync( + #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) @@ -47,40 +52,6 @@ internal static async Task> FindSourceDeclara solution, name, ignoreCase, criteria, cancellationToken).ConfigureAwait(false); } - 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(); - } - - 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); - } - public static async Task> FindSourceDeclarationsithNormalQueryAsync( Project project, string name, bool ignoreCase, SymbolFilter criteria, CancellationToken cancellationToken) { @@ -111,6 +82,31 @@ public static async Task> FindSourceDeclarati 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) { @@ -130,6 +126,29 @@ public static async Task> FindSourceDeclarati 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) { @@ -139,5 +158,7 @@ await AddCompilationDeclarationsWithNormalQueryAsync( filter, list, cancellationToken).ConfigureAwait(false); return list.ToImmutableAndFree(); } + + #endregion } } \ No newline at end of file From 0482b0e3028be533cee6fe9deb2ba1e0fc84057e Mon Sep 17 00:00:00 2001 From: CyrusNajmabadi Date: Sat, 8 Apr 2017 16:44:26 -0700 Subject: [PATCH 4/5] Cleanup, and move to more strict contracts. --- .../AbstractFullyQualifyCodeFixProvider.cs | 15 +++--- .../Declarations/DeclarationFinder.cs | 7 +-- .../DeclarationFinder_AllDeclarations.cs | 46 +------------------ ...mbolFinder_Declarations_AllDeclarations.cs | 14 ++---- .../FindSymbols/SymbolTree/SymbolTreeInfo.cs | 6 +-- 5 files changed, 22 insertions(+), 66 deletions(-) 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/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 d836071168c2d..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,10 @@ // 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; @@ -18,52 +16,12 @@ 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) - { - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - - if (string.IsNullOrWhiteSpace(name)) - { - return ImmutableArray.Empty; - } - - return await FindAllDeclarationsWithNormalQueryAsync( - project, SearchQuery.Create(name, ignoreCase), SymbolFilter.All, cancellationToken: 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) - { - throw new ArgumentNullException(nameof(name)); - } - - if (string.IsNullOrWhiteSpace(name)) - { - return ImmutableArray.Empty; - } - - return await FindAllDeclarationsWithNormalQueryAsync( - project, SearchQuery.Create(name, ignoreCase), filter, cancellationToken: cancellationToken).ConfigureAwait(false); - } - - internal static async Task> FindAllDeclarationsWithNormalQueryAsync( + public static async Task> FindAllDeclarationsWithNormalQueryAsync( 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); + Contract.ThrowIfTrue(query.Kind == SearchKind.Custom, "Custom queries are not supported in this API"); if (project == null) { 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/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. From 9440af426c3c47c7566ec66d3c546653a3bc53f1 Mon Sep 17 00:00:00 2001 From: CyrusNajmabadi Date: Sat, 8 Apr 2017 17:06:00 -0700 Subject: [PATCH 5/5] Fix spelling. --- .../Declarations/DeclarationFinder_SourceDeclarations.cs | 2 +- .../FindSymbols/SymbolFinder_Declarations_SourceDeclarations.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Workspaces/Core/Portable/FindSymbols/Declarations/DeclarationFinder_SourceDeclarations.cs b/src/Workspaces/Core/Portable/FindSymbols/Declarations/DeclarationFinder_SourceDeclarations.cs index 40e064407c941..fc7d7d57a526a 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/Declarations/DeclarationFinder_SourceDeclarations.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/Declarations/DeclarationFinder_SourceDeclarations.cs @@ -52,7 +52,7 @@ public static async Task> FindSourceDeclarati solution, name, ignoreCase, criteria, cancellationToken).ConfigureAwait(false); } - public static async Task> FindSourceDeclarationsithNormalQueryAsync( + public static async Task> FindSourceDeclarationsWithNormalQueryAsync( Project project, string name, bool ignoreCase, SymbolFilter criteria, CancellationToken cancellationToken) { if (project == null) diff --git a/src/Workspaces/Core/Portable/FindSymbols/SymbolFinder_Declarations_SourceDeclarations.cs b/src/Workspaces/Core/Portable/FindSymbols/SymbolFinder_Declarations_SourceDeclarations.cs index f92cc07fea300..a2108844ba2cb 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/SymbolFinder_Declarations_SourceDeclarations.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/SymbolFinder_Declarations_SourceDeclarations.cs @@ -50,7 +50,7 @@ public static async Task> FindSourceDeclarationsAsync( { using (Logger.LogBlock(FunctionId.SymbolFinder_Project_Name_FindSourceDeclarationsAsync, cancellationToken)) { - var declarations = await DeclarationFinder.FindSourceDeclarationsithNormalQueryAsync( + var declarations = await DeclarationFinder.FindSourceDeclarationsWithNormalQueryAsync( project, name, ignoreCase, filter, cancellationToken).ConfigureAwait(false); return declarations.SelectAsArray(t => t.Symbol);