public async Task <AggregatedCompletionContext> GetAggregatedCompletionContextAsync(ITextView textView, CompletionTrigger trigger, SnapshotPoint triggerLocation, CancellationToken token)
        {
            if (token.IsCancellationRequested || textView.IsClosed)
            {
                return(AggregatedCompletionContext.Empty);
            }

            var telemetryHost = GetOrCreateTelemetry(textView);
            var telemetry     = new CompletionSessionTelemetry(telemetryHost, headless: true);

            // ----- GetCompletionSources and GetRootSnapshot need to be run on the UI thread:
            await JoinableTaskContext.Factory.SwitchToMainThreadAsync();

            if (token.IsCancellationRequested || textView.IsClosed)
            {
                return(AggregatedCompletionContext.Empty);
            }

            var rootSnapshot = GetRootSnapshot(textView);

            GetCompletionSources(triggerLocation, GetItemSourceProviders, rootSnapshot, textView, textView.BufferGraph, trigger, telemetry, token,
                                 out var sourcesWithLocations, out var applicableToSpan);

            // ----- Go back to background thread to continue processing
            await TaskScheduler.Default;

            if (token.IsCancellationRequested || textView.IsClosed)
            {
                return(AggregatedCompletionContext.Empty);
            }

            // No source declared an appropriate ApplicableToSpan
            if (applicableToSpan == default)
            {
                return(AggregatedCompletionContext.Empty);
            }

            // No source wishes to participate
            if (!sourcesWithLocations.Any())
            {
                return(null);
            }

            var aggregatingSession = AsyncCompletionSession.CreateAggregatingSession(applicableToSpan, JoinableTaskContext, sourcesWithLocations, this, textView, telemetry, GuardedOperations);

            var completionData = await aggregatingSession.ConnectToCompletionSources(trigger, triggerLocation, rootSnapshot, token).ConfigureAwait(true);

            if (completionData.IsCanceled)
            {
                return(AggregatedCompletionContext.Empty);
            }

            var aggregateCompletionContext = new CompletionContext(
                completionData.InitialCompletionItems,
                completionData.RequestedSuggestionItemOptions,
                completionData.InitialSelectionHint);

            return(new AggregatedCompletionContext(aggregateCompletionContext, aggregatingSession));
        }
Пример #2
0
        public IAsyncCompletionSession TriggerCompletion(ITextView textView, CompletionTrigger trigger, SnapshotPoint triggerLocation, CancellationToken token)
        {
            var session = GetSession(textView);

            if (session != null)
            {
                return(session);
            }

            // This is a simple check that only queries the feature service.
            // If it succeeds, we will map triggerLocation to available buffers to discover MEF parts.
            // This is expensive but projected languages require it to discover parts in all available buffers.
            // To avoid doing this work, call IsCompletionSupported with appropriate IContentType prior to calling TriggerCompletion
            if (!CompletionAvailability.IsCurrentlyAvailable(textView))
            {
                return(null);
            }

            if (textView.IsClosed)
            {
                return(null);
            }

            if (!JoinableTaskContext.IsOnMainThread)
            {
                throw new InvalidOperationException($"This method must be callled on the UI thread.");
            }

            var telemetryHost = GetOrCreateTelemetry(textView);
            var telemetry     = new CompletionSessionTelemetry(telemetryHost);

            var rootSnapshot = GetRootSnapshot(textView);

            if (token.IsCancellationRequested || textView.IsClosed)
            {
                return(null);
            }

            // See if we can use more aggressive cancellation token for typing scenarios
            if (trigger.Reason == CompletionTriggerReason.Insertion)
            {
                token = CompletionUtilities.GetResponsiveToken(textView, token);
            }

            GetCompletionSources(triggerLocation, GetItemSourceProviders, rootSnapshot, textView, textView.BufferGraph, trigger, telemetry, token,
                                 out var sourcesWithLocations, out var applicableToSpan);

            if (token.IsCancellationRequested || textView.IsClosed)
            {
                return(null);
            }

            // No source declared an appropriate ApplicableToSpan
            if (applicableToSpan == default)
            {
                return(null);
            }

            // No source wishes to participate
            if (!sourcesWithLocations.Any())
            {
                return(null);
            }

            // Some of our extensions need to initialize the source providers before they initialize commit manager providers.
            // Therefore, it is important to invoke GetCommitManagerProviders after invoking GetItemSourceProviders.
            GetCommitManagersAndChars(triggerLocation, GetCommitManagerProviders, rootSnapshot, textView, telemetry,
                                      out var managersWithBuffers, out var potentialCommitChars);

            if (_contentTypeComparer == null)
            {
                _contentTypeComparer = new StableContentTypeComparer(ContentTypeRegistryService);
            }

            var itemManager       = GetItemManager(triggerLocation, GetItemManagerProviders, rootSnapshot, textView, _contentTypeComparer);
            var presenterProvider = GetPresenterProvider(triggerLocation, GetPresenters, rootSnapshot, textView.Roles, _contentTypeComparer);

            if (token.IsCancellationRequested || textView.IsClosed)
            {
                return(null);
            }

            session = new AsyncCompletionSession(applicableToSpan, potentialCommitChars, JoinableTaskContext, presenterProvider, sourcesWithLocations, managersWithBuffers, itemManager, this, textView, telemetry, GuardedOperations);
            textView.Properties.AddProperty(typeof(IAsyncCompletionSession), session);

            textView.Closed += DismissSessionOnViewClosed;
            EmulateLegacyCompletionTelemetry(textView);
            GuardedOperations.RaiseEvent(this, CompletionTriggered, new CompletionTriggeredEventArgs(session, textView));

            return(session);
        }