diff --git a/src/EditorFeatures/Core.Wpf/NavigateTo/NavigateToItemProvider.Searcher.cs b/src/EditorFeatures/Core.Wpf/NavigateTo/NavigateToItemProvider.Searcher.cs index 6da8f598c248a23ba1e9dc2db93cbb1b4e4d64af..733654fd87ef60ed95b68c34806b5b5293ef0c83 100644 --- a/src/EditorFeatures/Core.Wpf/NavigateTo/NavigateToItemProvider.Searcher.cs +++ b/src/EditorFeatures/Core.Wpf/NavigateTo/NavigateToItemProvider.Searcher.cs @@ -1,17 +1,16 @@ // 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.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Internal.Log; using Microsoft.CodeAnalysis.NavigateTo; -using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.TestHooks; using Microsoft.CodeAnalysis.Shared.Utilities; using Microsoft.CodeAnalysis.Text.Shared.Extensions; using Microsoft.VisualStudio.Language.NavigateTo.Interfaces; -using Microsoft.VisualStudio.Text; using Microsoft.VisualStudio.Text.PatternMatching; using Roslyn.Utilities; @@ -26,6 +25,7 @@ private class Searcher private readonly INavigateToCallback _callback; private readonly string _searchPattern; private readonly bool _searchCurrentDocument; + private readonly ISet _kinds; private readonly Document _currentDocument; private readonly ProgressTracker _progress; private readonly IAsynchronousOperationListener _asyncListener; @@ -38,6 +38,7 @@ private class Searcher INavigateToCallback callback, string searchPattern, bool searchCurrentDocument, + ISet kinds, CancellationToken cancellationToken) { _solution = solution; @@ -45,6 +46,7 @@ private class Searcher _callback = callback; _searchPattern = searchPattern; _searchCurrentDocument = searchCurrentDocument; + _kinds = kinds; _cancellationToken = cancellationToken; _progress = new ProgressTracker(callback.ReportProgress); _asyncListener = asyncListener; @@ -110,8 +112,8 @@ private async Task SearchAsyncWorker(Project project) if (service != null) { var searchTask = _currentDocument != null - ? service.SearchDocumentAsync(_currentDocument, _searchPattern, _cancellationToken) - : service.SearchProjectAsync(project, _searchPattern, _cancellationToken); + ? service.SearchDocumentAsync(_currentDocument, _searchPattern, _kinds, _cancellationToken) + : service.SearchProjectAsync(project, _searchPattern, _kinds, _cancellationToken); var results = await searchTask.ConfigureAwait(false); if (results != null) @@ -126,7 +128,6 @@ private async Task SearchAsyncWorker(Project project) } } -#pragma warning disable CS0618 // MatchKind is obsolete private void ReportMatchResult(Project project, INavigateToSearchResult result) { var matchedSpans = result.NameMatchSpans.SelectAsArray(t => t.ToSpan()); @@ -163,7 +164,6 @@ private PatternMatchKind GetPatternMatchKind(NavigateToMatchKind matchKind) default: throw ExceptionUtilities.UnexpectedValue(matchKind); } } -#pragma warning restore CS0618 // MatchKind is obsolete /// /// Returns the name for the language used by the old Navigate To providers. diff --git a/src/EditorFeatures/Core.Wpf/NavigateTo/NavigateToItemProvider.cs b/src/EditorFeatures/Core.Wpf/NavigateTo/NavigateToItemProvider.cs index 93d222cc71457ba945d69c508786bb0ae9c5f6d0..d4997d3f00353ddd8a2c282e0486d88c3cfd3e3b 100644 --- a/src/EditorFeatures/Core.Wpf/NavigateTo/NavigateToItemProvider.cs +++ b/src/EditorFeatures/Core.Wpf/NavigateTo/NavigateToItemProvider.cs @@ -3,16 +3,14 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; -using System.Linq; using System.Threading; using Microsoft.CodeAnalysis.Shared.TestHooks; -using Microsoft.VisualStudio.Language.Intellisense; using Microsoft.VisualStudio.Language.NavigateTo.Interfaces; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Editor.Implementation.NavigateTo { - internal partial class NavigateToItemProvider : INavigateToItemProvider + internal partial class NavigateToItemProvider : INavigateToItemProvider2 { private readonly Workspace _workspace; private readonly IAsynchronousOperationListener _asyncListener; @@ -32,6 +30,22 @@ internal partial class NavigateToItemProvider : INavigateToItemProvider _displayFactory = new NavigateToItemDisplayFactory(); } + public ISet KindsProvided { get; } = ImmutableHashSet.Create( + NavigateToItemKind.Class, + NavigateToItemKind.Constant, + NavigateToItemKind.Delegate, + NavigateToItemKind.Enum, + NavigateToItemKind.EnumItem, + NavigateToItemKind.Event, + NavigateToItemKind.Field, + NavigateToItemKind.Interface, + NavigateToItemKind.Method, + NavigateToItemKind.Module, + NavigateToItemKind.Property, + NavigateToItemKind.Structure); + + public bool CanFilter => true; + public void StopSearch() { _cancellationTokenSource.Cancel(); @@ -46,25 +60,7 @@ public void Dispose() public void StartSearch(INavigateToCallback callback, string searchValue) { - this.StopSearch(); - - if (string.IsNullOrWhiteSpace(searchValue)) - { - callback.Done(); - return; - } - - var searchCurrentDocument = GetSearchCurrentDocumentOption(callback); - var searcher = new Searcher( - _workspace.CurrentSolution, - _asyncListener, - _displayFactory, - callback, - searchValue, - searchCurrentDocument, - _cancellationTokenSource.Token); - - searcher.Search(); + StartSearch(callback, searchValue, KindsProvided); } private bool GetSearchCurrentDocumentOption(INavigateToCallback callback) @@ -88,5 +84,34 @@ private bool GetSearchCurrentDocumentOptionWorker(INavigateToCallback callback) var options2 = callback.Options as INavigateToOptions2; return options2?.SearchCurrentDocument ?? false; } + + public void StartSearch(INavigateToCallback callback, string searchValue, INavigateToFilterParameters filter) + { + StartSearch(callback, searchValue, filter.Kinds); + } + + private void StartSearch(INavigateToCallback callback, string searchValue, ISet kinds) + { + this.StopSearch(); + + if (string.IsNullOrWhiteSpace(searchValue)) + { + callback.Done(); + return; + } + + var searchCurrentDocument = GetSearchCurrentDocumentOption(callback); + var searcher = new Searcher( + _workspace.CurrentSolution, + _asyncListener, + _displayFactory, + callback, + searchValue, + searchCurrentDocument, + kinds, + _cancellationTokenSource.Token); + + searcher.Search(); + } } } diff --git a/src/Features/Core/Portable/NavigateTo/AbstractNavigateToSearchService.InProcess.cs b/src/Features/Core/Portable/NavigateTo/AbstractNavigateToSearchService.InProcess.cs index b44eb5b39b4eb9d6bd221be4876088f7278eafde..d3c99e95e853f176e47d2113823070604a160fc8 100644 --- a/src/Features/Core/Portable/NavigateTo/AbstractNavigateToSearchService.InProcess.cs +++ b/src/Features/Core/Portable/NavigateTo/AbstractNavigateToSearchService.InProcess.cs @@ -1,8 +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.Linq; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; @@ -22,21 +22,21 @@ internal abstract partial class AbstractNavigateToSearchService new ConditionalWeakTable>>(); public static Task> SearchProjectInCurrentProcessAsync( - Project project, string searchPattern, CancellationToken cancellationToken) + Project project, string searchPattern, ISet kinds, CancellationToken cancellationToken) { return FindSearchResultsAsync( - project, searchDocument: null, pattern: searchPattern, cancellationToken: cancellationToken); + project, searchDocument: null, pattern: searchPattern, kinds, cancellationToken: cancellationToken); } public static Task> SearchDocumentInCurrentProcessAsync( - Document document, string searchPattern, CancellationToken cancellationToken) + Document document, string searchPattern, ISet kinds, CancellationToken cancellationToken) { return FindSearchResultsAsync( - document.Project, document, searchPattern, cancellationToken); + document.Project, document, searchPattern, kinds, cancellationToken); } private static async Task> FindSearchResultsAsync( - Project project, Document searchDocument, string pattern, CancellationToken cancellationToken) + Project project, Document searchDocument, string pattern, ISet kinds, CancellationToken cancellationToken) { // If the user created a dotted pattern then we'll grab the last part of the name var (patternName, patternContainerOpt) = PatternMatcher.GetNameAndContainer(pattern); @@ -63,10 +63,10 @@ internal abstract partial class AbstractNavigateToSearchService // scratch. #if true var task = searchDocument != null - ? ComputeSearchResultsAsync(project, searchDocument, nameMatcher, containerMatcherOpt, nameMatches, containerMatches, cancellationToken) - : TryFilterPreviousSearchResultsAsync(project, searchDocument, pattern, nameMatcher, containerMatcherOpt, nameMatches, containerMatches, cancellationToken); + ? ComputeSearchResultsAsync(project, searchDocument, nameMatcher, containerMatcherOpt, kinds, nameMatches, containerMatches, cancellationToken) + : TryFilterPreviousSearchResultsAsync(project, searchDocument, pattern, nameMatcher, containerMatcherOpt, kinds, nameMatches, containerMatches, cancellationToken); #else - var task = ComputeSearchResultsAsync(project, searchDocument, nameMatcher, containerMatcherOpt, nameMatches, containerMatches, cancellationToken); + var task = ComputeSearchResultsAsync(project, searchDocument, nameMatcher, containerMatcherOpt, kinds, nameMatches, containerMatches, cancellationToken); #endif var searchResults = await task.ConfigureAwait(false); @@ -83,6 +83,7 @@ internal abstract partial class AbstractNavigateToSearchService private static async Task> TryFilterPreviousSearchResultsAsync( Project project, Document searchDocument, string pattern, PatternMatcher nameMatcher, PatternMatcher containerMatcherOpt, + ISet kinds, ArrayBuilder nameMatches, ArrayBuilder containerMatches, CancellationToken cancellationToken) { @@ -99,6 +100,7 @@ internal abstract partial class AbstractNavigateToSearchService searchResults = FilterPreviousResults( previousResult.Item2, nameMatcher, containerMatcherOpt, + kinds, nameMatches, containerMatches, cancellationToken); } else @@ -108,6 +110,7 @@ internal abstract partial class AbstractNavigateToSearchService searchResults = await ComputeSearchResultsAsync( project, searchDocument, nameMatcher, containerMatcherOpt, + kinds, nameMatches, containerMatches, cancellationToken).ConfigureAwait(false); } @@ -126,6 +129,7 @@ internal abstract partial class AbstractNavigateToSearchService private static ImmutableArray FilterPreviousResults( ImmutableArray previousResults, PatternMatcher nameMatcher, PatternMatcher containerMatcherOpt, + ISet kinds, ArrayBuilder nameMatches, ArrayBuilder containerMatches, CancellationToken cancellationToken) { @@ -137,7 +141,7 @@ internal abstract partial class AbstractNavigateToSearchService var info = previousResult.DeclaredSymbolInfo; AddResultIfMatch( - document, info, nameMatcher, containerMatcherOpt, + document, info, nameMatcher, containerMatcherOpt, kinds, nameMatches, containerMatches, result, cancellationToken); } @@ -147,6 +151,7 @@ internal abstract partial class AbstractNavigateToSearchService private static async Task> ComputeSearchResultsAsync( Project project, Document searchDocument, PatternMatcher nameMatcher, PatternMatcher containerMatcherOpt, + ISet kinds, ArrayBuilder nameMatches, ArrayBuilder containerMatches, CancellationToken cancellationToken) { @@ -165,7 +170,8 @@ internal abstract partial class AbstractNavigateToSearchService { AddResultIfMatch( document, declaredSymbolInfo, - nameMatcher, containerMatcherOpt, + nameMatcher, containerMatcherOpt, + kinds, nameMatches, containerMatches, result, cancellationToken); } @@ -177,6 +183,7 @@ internal abstract partial class AbstractNavigateToSearchService private static void AddResultIfMatch( Document document, DeclaredSymbolInfo declaredSymbolInfo, PatternMatcher nameMatcher, PatternMatcher containerMatcherOpt, + ISet kinds, ArrayBuilder nameMatches, ArrayBuilder containerMatches, ArrayBuilder result, CancellationToken cancellationToken) { @@ -184,7 +191,8 @@ internal abstract partial class AbstractNavigateToSearchService containerMatches.Clear(); cancellationToken.ThrowIfCancellationRequested(); - if (nameMatcher.AddMatches(declaredSymbolInfo.Name, nameMatches) && + if (kinds.Contains(GetItemKind(declaredSymbolInfo)) && + nameMatcher.AddMatches(declaredSymbolInfo.Name, nameMatches) && containerMatcherOpt?.AddMatches(declaredSymbolInfo.FullyQualifiedContainerName, containerMatches) != false) { result.Add(ConvertResult( diff --git a/src/Features/Core/Portable/NavigateTo/AbstractNavigateToSearchService.Remote.cs b/src/Features/Core/Portable/NavigateTo/AbstractNavigateToSearchService.Remote.cs index f7bf8a75e7677b82cb6b963d7ef70de80caa4e6c..6a50e8251f5164c4453835c9bb563cfc9a9b5035 100644 --- a/src/Features/Core/Portable/NavigateTo/AbstractNavigateToSearchService.Remote.cs +++ b/src/Features/Core/Portable/NavigateTo/AbstractNavigateToSearchService.Remote.cs @@ -1,12 +1,9 @@ // 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.Linq; using System.Threading; using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Experiments; using Microsoft.CodeAnalysis.Remote; using Roslyn.Utilities; @@ -15,25 +12,25 @@ namespace Microsoft.CodeAnalysis.NavigateTo internal abstract partial class AbstractNavigateToSearchService { private async Task> SearchDocumentInRemoteProcessAsync( - RemoteHostClient client, Document document, string searchPattern, CancellationToken cancellationToken) + RemoteHostClient client, Document document, string searchPattern, ISet kinds, CancellationToken cancellationToken) { var solution = document.Project.Solution; var serializableResults = await client.TryRunCodeAnalysisRemoteAsync>( solution, nameof(IRemoteNavigateToSearchService.SearchDocumentAsync), - new object[] { document.Id, searchPattern }, cancellationToken).ConfigureAwait(false); + new object[] { document.Id, searchPattern, kinds }, cancellationToken).ConfigureAwait(false); return serializableResults.SelectAsArray(r => r.Rehydrate(solution)); } private async Task> SearchProjectInRemoteProcessAsync( - RemoteHostClient client, Project project, string searchPattern, CancellationToken cancellationToken) + RemoteHostClient client, Project project, string searchPattern, ISet kinds, CancellationToken cancellationToken) { var solution = project.Solution; var serializableResults = await client.TryRunCodeAnalysisRemoteAsync>( solution, nameof(IRemoteNavigateToSearchService.SearchProjectAsync), - new object[] { project.Id, searchPattern }, cancellationToken).ConfigureAwait(false); + new object[] { project.Id, searchPattern, kinds }, cancellationToken).ConfigureAwait(false); return serializableResults.SelectAsArray(r => r.Rehydrate(solution)); } diff --git a/src/Features/Core/Portable/NavigateTo/AbstractNavigateToSearchService.cs b/src/Features/Core/Portable/NavigateTo/AbstractNavigateToSearchService.cs index 90f029a33639bd0c2ed767264a564b1f13785fc0..8bed4ea80626bd289400464b8ffbcad008aafc09 100644 --- a/src/Features/Core/Portable/NavigateTo/AbstractNavigateToSearchService.cs +++ b/src/Features/Core/Portable/NavigateTo/AbstractNavigateToSearchService.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Collections.Generic; using System.Collections.Immutable; using System.Threading; using System.Threading.Tasks; @@ -9,34 +10,34 @@ namespace Microsoft.CodeAnalysis.NavigateTo internal abstract partial class AbstractNavigateToSearchService : INavigateToSearchService { public async Task> SearchDocumentAsync( - Document document, string searchPattern, CancellationToken cancellationToken) + Document document, string searchPattern, ISet kinds, CancellationToken cancellationToken) { var client = await TryGetRemoteHostClientAsync(document.Project, cancellationToken).ConfigureAwait(false); if (client == null) { return await SearchDocumentInCurrentProcessAsync( - document, searchPattern, cancellationToken).ConfigureAwait(false); + document, searchPattern, kinds, cancellationToken).ConfigureAwait(false); } else { return await SearchDocumentInRemoteProcessAsync( - client, document, searchPattern, cancellationToken).ConfigureAwait(false); + client, document, searchPattern, kinds, cancellationToken).ConfigureAwait(false); } } public async Task> SearchProjectAsync( - Project project, string searchPattern, CancellationToken cancellationToken) + Project project, string searchPattern, ISet kinds, CancellationToken cancellationToken) { var client = await TryGetRemoteHostClientAsync(project, cancellationToken).ConfigureAwait(false); if (client == null) { return await SearchProjectInCurrentProcessAsync( - project, searchPattern, cancellationToken).ConfigureAwait(false); + project, searchPattern, kinds, cancellationToken).ConfigureAwait(false); } else { return await SearchProjectInRemoteProcessAsync( - client, project, searchPattern, cancellationToken).ConfigureAwait(false); + client, project, searchPattern, kinds, cancellationToken).ConfigureAwait(false); } } } diff --git a/src/Features/Core/Portable/NavigateTo/INavigateToSearchService.cs b/src/Features/Core/Portable/NavigateTo/INavigateToSearchService.cs index 6350059a3150390d65374801f28952cafc022fae..dbaad77a924a075f63618bf78fc7091393ffb06c 100644 --- a/src/Features/Core/Portable/NavigateTo/INavigateToSearchService.cs +++ b/src/Features/Core/Portable/NavigateTo/INavigateToSearchService.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Collections.Generic; using System.Collections.Immutable; using System.Threading; using System.Threading.Tasks; @@ -9,7 +10,7 @@ namespace Microsoft.CodeAnalysis.NavigateTo { internal interface INavigateToSearchService : ILanguageService { - Task> SearchProjectAsync(Project project, string searchPattern, CancellationToken cancellationToken); - Task> SearchDocumentAsync(Document document, string searchPattern, CancellationToken cancellationToken); + Task> SearchProjectAsync(Project project, string searchPattern, ISet kinds, CancellationToken cancellationToken); + Task> SearchDocumentAsync(Document document, string searchPattern, ISet kinds, CancellationToken cancellationToken); } } diff --git a/src/Features/Core/Portable/NavigateTo/IRemoteNavigateToSearchService.cs b/src/Features/Core/Portable/NavigateTo/IRemoteNavigateToSearchService.cs index 16f5a09bd071540f4763f45a9e1c7999f78efbff..cab451a156f5f73a56dc1897d96598bcf77bf286 100644 --- a/src/Features/Core/Portable/NavigateTo/IRemoteNavigateToSearchService.cs +++ b/src/Features/Core/Portable/NavigateTo/IRemoteNavigateToSearchService.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Generic; -using System.Collections.Immutable; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Remote; @@ -10,7 +9,7 @@ namespace Microsoft.CodeAnalysis.NavigateTo { internal interface IRemoteNavigateToSearchService { - Task> SearchDocumentAsync(DocumentId documentId, string searchPattern, CancellationToken cancellationToken); - Task> SearchProjectAsync(ProjectId projectId, string searchPattern, CancellationToken cancellationToken); + Task> SearchDocumentAsync(DocumentId documentId, string searchPattern, string[] kinds, CancellationToken cancellationToken); + Task> SearchProjectAsync(ProjectId projectId, string searchPattern, string[] kinds, CancellationToken cancellationToken); } } diff --git a/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_NavigateTo.cs b/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_NavigateTo.cs index 2efbebf55f97b16944a8404498abb4282acc758e..6888b67caf09e3a7b66bb4eba6ef10b4c25f213e 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_NavigateTo.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_NavigateTo.cs @@ -11,7 +11,7 @@ namespace Microsoft.CodeAnalysis.Remote internal partial class CodeAnalysisService : IRemoteNavigateToSearchService { public Task> SearchDocumentAsync( - DocumentId documentId, string searchPattern, CancellationToken cancellationToken) + DocumentId documentId, string searchPattern, string[] kinds, CancellationToken cancellationToken) { return RunServiceAsync(async token => { @@ -21,7 +21,7 @@ internal partial class CodeAnalysisService : IRemoteNavigateToSearchService var project = solution.GetDocument(documentId); var result = await AbstractNavigateToSearchService.SearchDocumentInCurrentProcessAsync( - project, searchPattern, token).ConfigureAwait(false); + project, searchPattern, kinds.ToImmutableHashSet(), token).ConfigureAwait(false); return Convert(result); } @@ -29,7 +29,7 @@ internal partial class CodeAnalysisService : IRemoteNavigateToSearchService } public Task> SearchProjectAsync( - ProjectId projectId, string searchPattern, CancellationToken cancellationToken) + ProjectId projectId, string searchPattern, string[] kinds, CancellationToken cancellationToken) { return RunServiceAsync(async token => { @@ -39,7 +39,7 @@ internal partial class CodeAnalysisService : IRemoteNavigateToSearchService var project = solution.GetProject(projectId); var result = await AbstractNavigateToSearchService.SearchProjectInCurrentProcessAsync( - project, searchPattern, token).ConfigureAwait(false); + project, searchPattern, kinds.ToImmutableHashSet(), token).ConfigureAwait(false); return Convert(result); }