WorkspaceSymbolsHandler.cs 3.0 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
// 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.Immutable;
using System.Composition;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.NavigateTo;
using Microsoft.VisualStudio.LanguageServer.Protocol;

namespace Microsoft.CodeAnalysis.LanguageServer.Handler
{
    [Shared]
    [ExportLspMethod(Methods.WorkspaceSymbolName)]
    internal class WorkspaceSymbolsHandler : IRequestHandler<WorkspaceSymbolParams, SymbolInformation[]>
    {
        public async Task<SymbolInformation[]> HandleRequestAsync(Solution solution, WorkspaceSymbolParams request,
18
            ClientCapabilities clientCapabilities, CancellationToken cancellationToken, bool keepThreadContext = false)
19
        {
20 21
            var searchTasks = Task.WhenAll(solution.Projects.Select(project => SearchProjectAsync(project, request, keepThreadContext, cancellationToken)));
            return (await searchTasks.ConfigureAwait(keepThreadContext)).SelectMany(s => s).ToArray();
22 23

            // local functions
24
            static async Task<ImmutableArray<SymbolInformation>> SearchProjectAsync(Project project, WorkspaceSymbolParams request, bool keepThreadContext, CancellationToken cancellationToken)
25 26 27 28 29 30 31 32 33 34 35
            {
                var searchService = project.LanguageServices.GetService<INavigateToSearchService_RemoveInterfaceAboveAndRenameThisAfterInternalsVisibleToUsersUpdate>();
                if (searchService != null)
                {
                    // TODO - Update Kinds Provided to return all necessary symbols.
                    // https://github.com/dotnet/roslyn/projects/45#card-20033822
                    var items = await searchService.SearchProjectAsync(
                        project,
                        ImmutableArray<Document>.Empty,
                        request.Query,
                        searchService.KindsProvided,
36 37 38
                        cancellationToken).ConfigureAwait(keepThreadContext);
                    var projectSymbolsTasks = Task.WhenAll(items.Select(item => CreateSymbolInformation(item, keepThreadContext, cancellationToken)));
                    return (await projectSymbolsTasks.ConfigureAwait(keepThreadContext)).ToImmutableArray();
39 40 41 42
                }

                return ImmutableArray.Create<SymbolInformation>();

43
                static async Task<SymbolInformation> CreateSymbolInformation(INavigateToSearchResult result, bool keepThreadContext, CancellationToken cancellationToken)
44 45 46 47 48
                {
                    return new SymbolInformation
                    {
                        Name = result.Name,
                        Kind = ProtocolConversions.NavigateToKindToSymbolKind(result.Kind),
49
                        Location = await ProtocolConversions.TextSpanToLocationAsync(result.NavigableItem.Document, result.NavigableItem.SourceSpan, cancellationToken).ConfigureAwait(keepThreadContext),
50 51 52 53 54 55
                    };
                }
            }
        }
    }
}