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)); }
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); }