File: NavigateTo\NavigateToItemProvider.Callback.cs
Web Access
Project: src\src\EditorFeatures\Core.Wpf\Microsoft.CodeAnalysis.EditorFeatures.Wpf_vhjqpc1t_wpftmp.csproj (Microsoft.CodeAnalysis.EditorFeatures.Wpf)
// 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.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.ErrorReporting;
using Microsoft.CodeAnalysis.NavigateTo;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text.Shared.Extensions;
using Microsoft.VisualStudio.Language.NavigateTo.Interfaces;
using Microsoft.VisualStudio.Text.PatternMatching;
using Roslyn.Utilities;
 
namespace Microsoft.CodeAnalysis.Editor.Implementation.NavigateTo
{
    internal partial class NavigateToItemProvider
    {
        private class NavigateToItemProviderCallback : INavigateToSearchCallback
        {
            private readonly Solution _solution;
            private readonly INavigateToItemDisplayFactory _displayFactory;
            private readonly INavigateToCallback _callback;
 
            public NavigateToItemProviderCallback(Solution solution, INavigateToItemDisplayFactory displayFactory, INavigateToCallback callback)
            {
                _solution = solution;
                _displayFactory = displayFactory;
                _callback = callback;
            }
 
            public void Done(bool isFullyLoaded)
            {
                if (!isFullyLoaded && _callback is INavigateToCallback2 callback2)
                {
                    callback2.Done(IncompleteReason.SolutionLoading);
                }
                else
                {
                    _callback.Done();
                }
            }
 
            public Task AddResultsAsync(ImmutableArray<INavigateToSearchResult> results, CancellationToken cancellationToken)
            {
                foreach (var result in results)
                {
                    var matchedSpans = result.NameMatchSpans.SelectAsArray(t => t.ToSpan());
 
                    var patternMatch = new PatternMatch(
                        GetPatternMatchKind(result.MatchKind),
                        punctuationStripped: false,
                        result.IsCaseSensitive,
                        matchedSpans);
 
                    var project = _solution.GetRequiredProject(result.NavigableItem.Document.Project.Id);
                    var navigateToItem = new NavigateToItem(
                        result.Name,
                        result.Kind,
                        GetNavigateToLanguage(project.Language),
                        result.SecondarySort,
                        result,
                        patternMatch,
                        _displayFactory);
 
                    try
                    {
                        _callback.AddItem(navigateToItem);
                    }
                    catch (InvalidOperationException ex) when (FatalError.ReportAndCatch(ex, ErrorSeverity.Critical))
                    {
                        // Mitigation for race condition in platform https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1534364
                        //
                        // Catch this so that don't tear down OOP, but still report the exception so that we ensure this issue
                        // gets attention and is fixed.
                    }
                }
 
                return Task.CompletedTask;
            }
 
            public void ReportProgress(int current, int maximum)
            {
                _callback.ReportProgress(current, maximum);
            }
 
            public void ReportIncomplete()
            {
            }
 
            private static PatternMatchKind GetPatternMatchKind(NavigateToMatchKind matchKind)
                => matchKind switch
                {
                    NavigateToMatchKind.Exact => PatternMatchKind.Exact,
                    NavigateToMatchKind.Prefix => PatternMatchKind.Prefix,
                    NavigateToMatchKind.Substring => PatternMatchKind.Substring,
                    NavigateToMatchKind.Regular => PatternMatchKind.Fuzzy,
                    NavigateToMatchKind.None => PatternMatchKind.Fuzzy,
                    NavigateToMatchKind.CamelCaseExact => PatternMatchKind.CamelCaseExact,
                    NavigateToMatchKind.CamelCasePrefix => PatternMatchKind.CamelCasePrefix,
                    NavigateToMatchKind.CamelCaseNonContiguousPrefix => PatternMatchKind.CamelCaseNonContiguousPrefix,
                    NavigateToMatchKind.CamelCaseSubstring => PatternMatchKind.CamelCaseSubstring,
                    NavigateToMatchKind.CamelCaseNonContiguousSubstring => PatternMatchKind.CamelCaseNonContiguousSubstring,
                    NavigateToMatchKind.Fuzzy => PatternMatchKind.Fuzzy,
                    _ => throw ExceptionUtilities.UnexpectedValue(matchKind),
                };
 
            /// <summary>
            /// Returns the name for the language used by the old Navigate To providers.
            /// </summary>
            /// <remarks> It turns out this string is used for sorting and for some SQM data, so it's best
            /// to keep it unchanged.</remarks>
            private static string GetNavigateToLanguage(string languageName)
                => languageName switch
                {
                    LanguageNames.CSharp => "csharp",
                    LanguageNames.VisualBasic => "vb",
                    _ => languageName,
                };
        }
    }
}