<commit_before>﻿// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Immutable;
using System.Composition;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.NavigateTo;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.VisualStudio.LanguageServer.Protocol;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis.LanguageServer.Handler
{
    /// <summary>
    /// TODO - This must be moved to the MS.CA.LanguageServer.Protocol project once
    /// we no longer reference VS icon types.
    /// </summary>
    [ExportRoslynLanguagesLspRequestHandlerProvider, Shared]
    [ProvidesMethod(Methods.WorkspaceSymbolName)]
    internal class WorkspaceSymbolsHandler : AbstractStatelessRequestHandler<WorkspaceSymbolParams, SymbolInformation[]?>
    {
        private static readonly IImmutableSet<string> s_supportedKinds =
            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);

        private readonly IAsynchronousOperationListener _asyncListener;
        private readonly IThreadingContext _threadingContext;

        [ImportingConstructor]
        [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
        public WorkspaceSymbolsHandler(
            IAsynchronousOperationListenerProvider listenerProvider,
            IThreadingContext threadingContext)
        {
            _asyncListener = listenerProvider.GetListener(FeatureAttribute.NavigateTo);
            _threadingContext = threadingContext;
        }

        public override string Method => Methods.WorkspaceSymbolName;

        public override bool MutatesSolutionState => false;
        public override bool RequiresLSPSolution => true;

        public override TextDocumentIdentifier? GetTextDocumentIdentifier(WorkspaceSymbolParams request) => null;

        public override async Task<SymbolInformation[]?> HandleRequestAsync(WorkspaceSymbolParams request, RequestContext context, CancellationToken cancellationToken)
        {
            Contract.ThrowIfNull(context.Solution);

            var solution = context.Solution;

            using var progress = BufferedProgress.Create(request.PartialResultToken);
            var searcher = NavigateToSearcher.Create(
                solution,
                _asyncListener,
                new LSPNavigateToCallback(context, progress),
                request.Query,
                searchCurrentDocument: false,
                s_supportedKinds,
                _threadingContext.DisposalToken);

            await searcher.SearchAsync(cancellationToken).ConfigureAwait(false);
            return progress.GetValues();
        }

        private class LSPNavigateToCallback : INavigateToSearchCallback
        {
            private readonly RequestContext _context;
            private readonly BufferedProgress<SymbolInformation> _progress;

            public LSPNavigateToCallback(
                RequestContext context,
                BufferedProgress<SymbolInformation> progress)
            {
                _context = context;
                _progress = progress;
            }

            public async Task AddItemAsync(Project project, INavigateToSearchResult result, CancellationToken cancellationToken)
            {
                var location = await ProtocolConversions.TextSpanToLocationAsync(
                    result.NavigableItem.Document, result.NavigableItem.SourceSpan, result.NavigableItem.IsStale, _context, cancellationToken).ConfigureAwait(false);
                if (location == null)
                    return;

                Contract.ThrowIfNull(location);
                _progress.Report(new VSSymbolInformation
                {
                    Name = result.Name,
                    ContainerName = result.AdditionalInformation,
                    Kind = ProtocolConversions.NavigateToKindToSymbolKind(result.Kind),
                    Location = location,
                    Icon = ProtocolConversions.GetImageIdFromGlyph(result.NavigableItem.Glyph)
                });
            }

            public void Done(bool isFullyLoaded)
            {
                // do nothing, we already await the SearchAsync method which calls this in a finally right before returning.<commit_msg>Fix the broken test when resolving conflict<commit_after>﻿// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Immutable;
using System.Composition;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.NavigateTo;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.VisualStudio.LanguageServer.Protocol;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis.LanguageServer.Handler
{
    /// <summary>
    /// TODO - This must be moved to the MS.CA.LanguageServer.Protocol project once
    /// we no longer reference VS icon types.
    /// </summary>
    [ExportRoslynLanguagesLspRequestHandlerProvider, Shared]
    [ProvidesMethod(Methods.WorkspaceSymbolName)]
    internal class WorkspaceSymbolsHandler : AbstractStatelessRequestHandler<WorkspaceSymbolParams, SymbolInformation[]?>
    {
        private static readonly IImmutableSet<string> s_supportedKinds =
            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);

        private readonly IAsynchronousOperationListener _asyncListener;
        private readonly IThreadingContext _threadingContext;

        [ImportingConstructor]
        [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
        public WorkspaceSymbolsHandler(
            IAsynchronousOperationListenerProvider listenerProvider,
            IThreadingContext threadingContext)
        {
            _asyncListener = listenerProvider.GetListener(FeatureAttribute.NavigateTo);
            _threadingContext = threadingContext;
        }

        public override string Method => Methods.WorkspaceSymbolName;

        public override bool MutatesSolutionState => false;
        public override bool RequiresLSPSolution => true;

        public override TextDocumentIdentifier? GetTextDocumentIdentifier(WorkspaceSymbolParams request) => null;

        public override async Task<SymbolInformation[]?> HandleRequestAsync(WorkspaceSymbolParams request, RequestContext context, CancellationToken cancellationToken)
        {
            Contract.ThrowIfNull(context.Solution);

            var solution = context.Solution;

            using var progress = BufferedProgress.Create(request.PartialResultToken);
            var searcher = NavigateToSearcher.Create(
                solution,
                _asyncListener,
                new LSPNavigateToCallback(context, progress),
                request.Query,
                searchCurrentDocument: false,
                s_supportedKinds,
                _threadingContext.DisposalToken);

            await searcher.SearchAsync(cancellationToken).ConfigureAwait(false);
            return progress.GetValues();
        }

        private class LSPNavigateToCallback : INavigateToSearchCallback
        {
            private readonly RequestContext _context;
            private readonly BufferedProgress<SymbolInformation> _progress;

            public LSPNavigateToCallback(
                RequestContext context,
                BufferedProgress<SymbolInformation> progress)
            {
                _context = context;
                _progress = progress;
            }

            public async Task AddItemAsync(Project project, INavigateToSearchResult result, CancellationToken cancellationToken)
            {
                var location = await ProtocolConversions.TextSpanToLocationAsync(
                    result.NavigableItem.Document, result.NavigableItem.SourceSpan, result.NavigableItem.IsStale, _context, cancellationToken).ConfigureAwait(false);
                if (location == null)
                    return;

                Contract.ThrowIfNull(location);
                _progress.Report(new VSSymbolInformation
                {
                    Name = result.Name,
                    ContainerName = result.AdditionalInformation,
                    Kind = ProtocolConversions.NavigateToKindToSymbolKind(result.Kind),
                    Location = location,
                    Icon = VSLspExtensionConversions.GetImageIdFromGlyph(result.NavigableItem.Glyph)
                });
            }

            public void Done(bool isFullyLoaded)
            {
                // do nothing, we already await the SearchAsync method which calls this in a finally right before returning.
{'fraction_non_alphanumeric': 0.058846918489065606, 'fraction_numerical': 0.0, 'mean_word_length': 2.4373078237102836, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4337911', 'n_tokens_mistral': 2326, 'n_tokens_neox': 2240, 'n_words': 523}