File: IntelliSense\QuickInfo\QuickInfoSourceProvider.QuickInfoSource.cs
Web Access
Project: src\src\EditorFeatures\Core\Microsoft.CodeAnalysis.EditorFeatures.csproj (Microsoft.CodeAnalysis.EditorFeatures)
// 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.
 
#nullable disable
 
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Classification;
using Microsoft.CodeAnalysis.Editor.Host;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.ErrorReporting;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.LanguageService;
using Microsoft.CodeAnalysis.QuickInfo;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.Text.Shared.Extensions;
using Microsoft.VisualStudio.Language.Intellisense;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Utilities;
using Roslyn.Utilities;
 
using IntellisenseQuickInfoItem = Microsoft.VisualStudio.Language.Intellisense.QuickInfoItem;
using Microsoft.CodeAnalysis.Editor.InlineRename;
 
namespace Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.QuickInfo;
 
internal partial class QuickInfoSourceProvider
{
    private sealed class QuickInfoSource(
        ITextBuffer subjectBuffer,
        IThreadingContext threadingContext,
        IUIThreadOperationExecutor operationExecutor,
        IAsynchronousOperationListener asyncListener,
        Lazy<IStreamingFindUsagesPresenter> streamingPresenter,
        EditorOptionsService editorOptionsService,
        IInlineRenameService inlineRenameService) : IAsyncQuickInfoSource
    {
        private readonly ITextBuffer _subjectBuffer = subjectBuffer;
        private readonly IThreadingContext _threadingContext = threadingContext;
        private readonly IUIThreadOperationExecutor _operationExecutor = operationExecutor;
        private readonly IAsynchronousOperationListener _asyncListener = asyncListener;
        private readonly Lazy<IStreamingFindUsagesPresenter> _streamingPresenter = streamingPresenter;
        private readonly EditorOptionsService _editorOptionsService = editorOptionsService;
        private readonly IInlineRenameService _inlineRenameService = inlineRenameService;
 
        public async Task<IntellisenseQuickInfoItem> GetQuickInfoItemAsync(IAsyncQuickInfoSession session, CancellationToken cancellationToken)
        {
            // Until https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1611398 is resolved we can't disable
            // quickinfo in InlineRename. Instead, we return no quickinfo information while the adornment
            // is being shown. This can be removed after IFeaturesService supports disabling quickinfo
            if (_editorOptionsService.GlobalOptions.GetOption(InlineRenameUIOptionsStorage.UseInlineAdornment) && _inlineRenameService.ActiveSession is not null)
                return null;
 
            var triggerPoint = session.GetTriggerPoint(_subjectBuffer.CurrentSnapshot);
            if (!triggerPoint.HasValue)
                return null;
 
            var snapshot = triggerPoint.Value.Snapshot;
            var document = snapshot.GetOpenDocumentInCurrentContextWithChanges();
            if (document == null)
                return null;
 
            var service = QuickInfoService.GetService(document);
            if (service == null)
                return null;
 
            try
            {
                using (Logger.LogBlock(FunctionId.Get_QuickInfo_Async, cancellationToken))
                {
                    cancellationToken.ThrowIfCancellationRequested();
 
                    var options = _editorOptionsService.GlobalOptions.GetSymbolDescriptionOptions(document.Project.Language);
                    var item = await service.GetQuickInfoAsync(document, triggerPoint.Value, options, cancellationToken).ConfigureAwait(false);
                    if (item != null)
                    {
                        var textVersion = snapshot.Version;
                        var trackingSpan = textVersion.CreateTrackingSpan(item.Span.ToSpan(), SpanTrackingMode.EdgeInclusive);
                        var classificationOptions = _editorOptionsService.GlobalOptions.GetClassificationOptions(document.Project.Language);
                        var lineFormattingOptions = snapshot.TextBuffer.GetLineFormattingOptions(_editorOptionsService, explicitFormat: false);
                        var navigationActionFactory = new NavigationActionFactory(document, _threadingContext, _operationExecutor, _asyncListener, _streamingPresenter);
 
                        return await IntellisenseQuickInfoBuilder
                            .BuildItemAsync(trackingSpan, item, document, classificationOptions, lineFormattingOptions, navigationActionFactory, cancellationToken)
                            .ConfigureAwait(false);
                    }
 
                    return null;
                }
            }
            catch (Exception e) when (FatalError.ReportAndPropagateUnlessCanceled(e, cancellationToken, ErrorSeverity.Critical))
            {
                throw ExceptionUtilities.Unreachable();
            }
        }
 
        public void Dispose()
        {
        }
    }
}