diff --git a/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_WellKnownAttributes.cs b/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_WellKnownAttributes.cs index f851158023b322a047951908fa1d9f078a429c9a..3798f6a5fb8bdcf5a2a4ebb7b90b2152fe1ca4fe 100644 --- a/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_WellKnownAttributes.cs +++ b/src/Compilers/CSharp/Test/Emit/Attributes/AttributeTests_WellKnownAttributes.cs @@ -6891,7 +6891,7 @@ public class D : List Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "X").WithArguments("N.A", "Do not use").WithLocation(15, 16)); } - [Fact] + [ConditionalFact(typeof(IsEnglishLocal), Skip = "https://github.com/dotnet/roslyn/issues/28328")] [WorkItem(580832, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/580832")] public void ObsoleteOnVirtual_OnBase() { diff --git a/src/EditorFeatures/Core.Wpf/NavigateTo/NavigateToItemProvider.Searcher.cs b/src/EditorFeatures/Core.Wpf/NavigateTo/NavigateToItemProvider.Searcher.cs index 733654fd87ef60ed95b68c34806b5b5293ef0c83..48ada4437d87de87a2da39282ae565a87d9fac25 100644 --- a/src/EditorFeatures/Core.Wpf/NavigateTo/NavigateToItemProvider.Searcher.cs +++ b/src/EditorFeatures/Core.Wpf/NavigateTo/NavigateToItemProvider.Searcher.cs @@ -1,7 +1,7 @@ // 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; @@ -25,7 +25,7 @@ private class Searcher private readonly INavigateToCallback _callback; private readonly string _searchPattern; private readonly bool _searchCurrentDocument; - private readonly ISet _kinds; + private readonly IImmutableSet _kinds; private readonly Document _currentDocument; private readonly ProgressTracker _progress; private readonly IAsynchronousOperationListener _asyncListener; @@ -38,7 +38,7 @@ private class Searcher INavigateToCallback callback, string searchPattern, bool searchCurrentDocument, - ISet kinds, + IImmutableSet kinds, CancellationToken cancellationToken) { _solution = solution; @@ -108,7 +108,7 @@ private async Task SearchAsyncWorker(Project project) { using (cacheService.EnableCaching(project.Id)) { - var service = project.LanguageServices.GetService(); + var service = TryGetNavigateToSearchService(project); if (service != null) { var searchTask = _currentDocument != null diff --git a/src/EditorFeatures/Core.Wpf/NavigateTo/NavigateToItemProvider.cs b/src/EditorFeatures/Core.Wpf/NavigateTo/NavigateToItemProvider.cs index adb58bc9ff88a5d97d045a94f7e4427b06302995..480c09f7b14e7389eddd2137b436624402f4c4ed 100644 --- a/src/EditorFeatures/Core.Wpf/NavigateTo/NavigateToItemProvider.cs +++ b/src/EditorFeatures/Core.Wpf/NavigateTo/NavigateToItemProvider.cs @@ -4,9 +4,13 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.NavigateTo; using Microsoft.CodeAnalysis.Shared.TestHooks; using Microsoft.VisualStudio.Language.NavigateTo.Interfaces; using Roslyn.Utilities; +using INavigateToSearchService = Microsoft.CodeAnalysis.NavigateTo.INavigateToSearchService; +using INavigateToSearchService_RemoveInterfaceAboveAndRenameThisAfterInternalsVisibleToUsersUpdate = Microsoft.CodeAnalysis.NavigateTo.INavigateToSearchService_RemoveInterfaceAboveAndRenameThisAfterInternalsVisibleToUsersUpdate; namespace Microsoft.CodeAnalysis.Editor.Implementation.NavigateTo { @@ -30,21 +34,50 @@ internal partial class NavigateToItemProvider : INavigateToItemProvider2 _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; + ISet INavigateToItemProvider2.KindsProvided => KindsProvided; + + public ImmutableHashSet KindsProvided + { + get + { + var result = ImmutableHashSet.Create(StringComparer.Ordinal); + foreach (var project in _workspace.CurrentSolution.Projects) + { + var navigateToSearchService = TryGetNavigateToSearchService(project); + if (navigateToSearchService != null) + { + result = result.Union(navigateToSearchService.KindsProvided); + } + } + + return result; + } + } + + public bool CanFilter + { + get + { + foreach (var project in _workspace.CurrentSolution.Projects) + { + var navigateToSearchService = TryGetNavigateToSearchService(project); + if (navigateToSearchService is null) + { + // If we reach here, it means the current project does not support Navigate To, which is + // functionally equivalent to supporting filtering. + continue; + } + + if (!navigateToSearchService.CanFilter) + { + return false; + } + } + + // All projects either support filtering or do not support Navigate To at all + return true; + } + } public void StopSearch() { @@ -87,10 +120,10 @@ private bool GetSearchCurrentDocumentOptionWorker(INavigateToCallback callback) public void StartSearch(INavigateToCallback callback, string searchValue, INavigateToFilterParameters filter) { - StartSearch(callback, searchValue, filter.Kinds); + StartSearch(callback, searchValue, filter.Kinds.ToImmutableHashSet(StringComparer.Ordinal)); } - private void StartSearch(INavigateToCallback callback, string searchValue, ISet kinds) + private void StartSearch(INavigateToCallback callback, string searchValue, IImmutableSet kinds) { this.StopSearch(); @@ -118,5 +151,47 @@ private void StartSearch(INavigateToCallback callback, string searchValue, ISet< searcher.Search(); } + + private static INavigateToSearchService_RemoveInterfaceAboveAndRenameThisAfterInternalsVisibleToUsersUpdate TryGetNavigateToSearchService(Project project) + { + var service = project.LanguageServices.GetService(); + if (service != null) + { + return service; + } + +#pragma warning disable CS0618 // Type or member is obsolete +#pragma warning disable CS0612 // Type or member is obsolete + var legacyService = project.LanguageServices.GetService(); + if (legacyService != null) + { + return new ShimNavigateToSearchService(legacyService); + } +#pragma warning restore CS0612 // Type or member is obsolete +#pragma warning restore CS0618 // Type or member is obsolete + + return null; + } + + [Obsolete("https://github.com/dotnet/roslyn/issues/28343")] + private class ShimNavigateToSearchService : INavigateToSearchService_RemoveInterfaceAboveAndRenameThisAfterInternalsVisibleToUsersUpdate + { + private readonly INavigateToSearchService _navigateToSearchService; + + public ShimNavigateToSearchService(INavigateToSearchService navigateToSearchService) + { + _navigateToSearchService = navigateToSearchService; + } + + public IImmutableSet KindsProvided => ImmutableHashSet.Create(StringComparer.Ordinal); + + public bool CanFilter => false; + + public Task> SearchDocumentAsync(Document document, string searchPattern, IImmutableSet kinds, CancellationToken cancellationToken) + => _navigateToSearchService.SearchDocumentAsync(document, searchPattern, cancellationToken); + + public Task> SearchProjectAsync(Project project, string searchPattern, IImmutableSet kinds, CancellationToken cancellationToken) + => _navigateToSearchService.SearchProjectAsync(project, searchPattern, cancellationToken); + } } } diff --git a/src/Features/CSharp/Portable/NavigateTo/CSharpNavigateToSearchService.cs b/src/Features/CSharp/Portable/NavigateTo/CSharpNavigateToSearchService.cs index 8f4d56aa006910c2767a77b653b7bc596a9d154a..9b303f041e9d3913f6a9cb0568983a0b357cb70f 100644 --- a/src/Features/CSharp/Portable/NavigateTo/CSharpNavigateToSearchService.cs +++ b/src/Features/CSharp/Portable/NavigateTo/CSharpNavigateToSearchService.cs @@ -6,7 +6,7 @@ namespace Microsoft.CodeAnalysis.CSharp.NavigateTo { - [ExportLanguageService(typeof(INavigateToSearchService), LanguageNames.CSharp), Shared] + [ExportLanguageService(typeof(INavigateToSearchService_RemoveInterfaceAboveAndRenameThisAfterInternalsVisibleToUsersUpdate), LanguageNames.CSharp), Shared] internal class CSharpNavigateToSearchService : AbstractNavigateToSearchService { } diff --git a/src/Features/Core/Portable/NavigateTo/AbstractNavigateToSearchService.InProcess.cs b/src/Features/Core/Portable/NavigateTo/AbstractNavigateToSearchService.InProcess.cs index e68fcb20760029361ebfb3a2280963def6cea500..adca95b4ff9581e3492f13f5ea00decaad2c3647 100644 --- a/src/Features/Core/Portable/NavigateTo/AbstractNavigateToSearchService.InProcess.cs +++ b/src/Features/Core/Portable/NavigateTo/AbstractNavigateToSearchService.InProcess.cs @@ -23,21 +23,21 @@ internal abstract partial class AbstractNavigateToSearchService new ConditionalWeakTable>>(); public static Task> SearchProjectInCurrentProcessAsync( - Project project, string searchPattern, ISet kinds, CancellationToken cancellationToken) + Project project, string searchPattern, IImmutableSet kinds, CancellationToken cancellationToken) { return FindSearchResultsAsync( project, searchDocument: null, pattern: searchPattern, kinds, cancellationToken: cancellationToken); } public static Task> SearchDocumentInCurrentProcessAsync( - Document document, string searchPattern, ISet kinds, CancellationToken cancellationToken) + Document document, string searchPattern, IImmutableSet kinds, CancellationToken cancellationToken) { return FindSearchResultsAsync( document.Project, document, searchPattern, kinds, cancellationToken); } private static async Task> FindSearchResultsAsync( - Project project, Document searchDocument, string pattern, ISet kinds, CancellationToken cancellationToken) + Project project, Document searchDocument, string pattern, IImmutableSet 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); diff --git a/src/Features/Core/Portable/NavigateTo/AbstractNavigateToSearchService.Remote.cs b/src/Features/Core/Portable/NavigateTo/AbstractNavigateToSearchService.Remote.cs index 6a50e8251f5164c4453835c9bb563cfc9a9b5035..16b2313b44f945ef90b797b428899e56d2672d36 100644 --- a/src/Features/Core/Portable/NavigateTo/AbstractNavigateToSearchService.Remote.cs +++ b/src/Features/Core/Portable/NavigateTo/AbstractNavigateToSearchService.Remote.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Collections.Immutable; +using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Remote; @@ -12,25 +13,25 @@ namespace Microsoft.CodeAnalysis.NavigateTo internal abstract partial class AbstractNavigateToSearchService { private async Task> SearchDocumentInRemoteProcessAsync( - RemoteHostClient client, Document document, string searchPattern, ISet kinds, CancellationToken cancellationToken) + RemoteHostClient client, Document document, string searchPattern, IImmutableSet kinds, CancellationToken cancellationToken) { var solution = document.Project.Solution; var serializableResults = await client.TryRunCodeAnalysisRemoteAsync>( solution, nameof(IRemoteNavigateToSearchService.SearchDocumentAsync), - new object[] { document.Id, searchPattern, kinds }, cancellationToken).ConfigureAwait(false); + new object[] { document.Id, searchPattern, kinds.ToArray() }, cancellationToken).ConfigureAwait(false); return serializableResults.SelectAsArray(r => r.Rehydrate(solution)); } private async Task> SearchProjectInRemoteProcessAsync( - RemoteHostClient client, Project project, string searchPattern, ISet kinds, CancellationToken cancellationToken) + RemoteHostClient client, Project project, string searchPattern, IImmutableSet kinds, CancellationToken cancellationToken) { var solution = project.Solution; var serializableResults = await client.TryRunCodeAnalysisRemoteAsync>( solution, nameof(IRemoteNavigateToSearchService.SearchProjectAsync), - new object[] { project.Id, searchPattern, kinds }, cancellationToken).ConfigureAwait(false); + new object[] { project.Id, searchPattern, kinds.ToArray() }, 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 8bed4ea80626bd289400464b8ffbcad008aafc09..5c59623862831e69fffac78e60ea4c599bffdc8b 100644 --- a/src/Features/Core/Portable/NavigateTo/AbstractNavigateToSearchService.cs +++ b/src/Features/Core/Portable/NavigateTo/AbstractNavigateToSearchService.cs @@ -7,10 +7,26 @@ namespace Microsoft.CodeAnalysis.NavigateTo { - internal abstract partial class AbstractNavigateToSearchService : INavigateToSearchService + internal abstract partial class AbstractNavigateToSearchService : INavigateToSearchService_RemoveInterfaceAboveAndRenameThisAfterInternalsVisibleToUsersUpdate { + public IImmutableSet 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 async Task> SearchDocumentAsync( - Document document, string searchPattern, ISet kinds, CancellationToken cancellationToken) + Document document, string searchPattern, IImmutableSet kinds, CancellationToken cancellationToken) { var client = await TryGetRemoteHostClientAsync(document.Project, cancellationToken).ConfigureAwait(false); if (client == null) @@ -26,7 +42,7 @@ internal abstract partial class AbstractNavigateToSearchService : INavigateToSea } public async Task> SearchProjectAsync( - Project project, string searchPattern, ISet kinds, CancellationToken cancellationToken) + Project project, string searchPattern, IImmutableSet kinds, CancellationToken cancellationToken) { var client = await TryGetRemoteHostClientAsync(project, cancellationToken).ConfigureAwait(false); if (client == null) diff --git a/src/Features/Core/Portable/NavigateTo/INavigateToSearchService.cs b/src/Features/Core/Portable/NavigateTo/INavigateToSearchService.cs index dbaad77a924a075f63618bf78fc7091393ffb06c..a2279b65ba5a89891d747d3f428e3868d82debcc 100644 --- a/src/Features/Core/Portable/NavigateTo/INavigateToSearchService.cs +++ b/src/Features/Core/Portable/NavigateTo/INavigateToSearchService.cs @@ -1,6 +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; using System.Collections.Immutable; using System.Threading; using System.Threading.Tasks; @@ -8,9 +8,27 @@ namespace Microsoft.CodeAnalysis.NavigateTo { + [Obsolete("Use " + nameof(INavigateToSearchService_RemoveInterfaceAboveAndRenameThisAfterInternalsVisibleToUsersUpdate) + " instead.")] internal interface INavigateToSearchService : ILanguageService { - Task> SearchProjectAsync(Project project, string searchPattern, ISet kinds, CancellationToken cancellationToken); - Task> SearchDocumentAsync(Document document, string searchPattern, ISet kinds, CancellationToken cancellationToken); + Task> SearchProjectAsync(Project project, string searchPattern, CancellationToken cancellationToken); + Task> SearchDocumentAsync(Document document, string searchPattern, CancellationToken cancellationToken); + } + + // This will be renamed to replace INavigateToSearchService as part of https://github.com/dotnet/roslyn/issues/28343 + internal interface INavigateToSearchService_RemoveInterfaceAboveAndRenameThisAfterInternalsVisibleToUsersUpdate : ILanguageService + { + IImmutableSet KindsProvided + { + get; + } + + bool CanFilter + { + get; + } + + Task> SearchProjectAsync(Project project, string searchPattern, IImmutableSet kinds, CancellationToken cancellationToken); + Task> SearchDocumentAsync(Document document, string searchPattern, IImmutableSet kinds, CancellationToken cancellationToken); } } diff --git a/src/Features/VisualBasic/Portable/NavigateTo/VisualBasicNavigateToSearchService.vb b/src/Features/VisualBasic/Portable/NavigateTo/VisualBasicNavigateToSearchService.vb index bbaac1c4c5f47b4934aa703452a940cfb854d9ba..df770a4640a4f4d0cbd612614bbfe324bbf2e67e 100644 --- a/src/Features/VisualBasic/Portable/NavigateTo/VisualBasicNavigateToSearchService.vb +++ b/src/Features/VisualBasic/Portable/NavigateTo/VisualBasicNavigateToSearchService.vb @@ -5,7 +5,7 @@ Imports Microsoft.CodeAnalysis.Host.Mef Imports Microsoft.CodeAnalysis.NavigateTo Namespace Microsoft.CodeAnalysis.VisualBasic.NavigateTo - + Friend Class VisualBasicNavigateToSearchService Inherits AbstractNavigateToSearchService End Class