public void PresentItems( ITrackingSpan triggerSpan, IList <PresentationItem> completionItems, PresentationItem selectedItem, PresentationItem suggestionModeItem, bool suggestionMode, bool isSoftSelected, ImmutableArray <CompletionItemFilter> completionItemFilters, string filterText) { AssertIsForeground(); // check if this update is still relevant if (_textView.IsClosed || _isDismissed) { return; } if (triggerSpan != null) { _completionSet.SetTrackingSpan(triggerSpan); } _ignoreSelectionStatusChangedEvent = true; try { _completionSet.SetCompletionItems( completionItems, selectedItem, suggestionModeItem, suggestionMode, isSoftSelected, completionItemFilters, filterText); } finally { _ignoreSelectionStatusChangedEvent = false; } if (_editorSessionOpt == null) { // We're tracking the caret. Don't have the editor do it. // Map the span instead of a point to avoid affinity problems. _editorSessionOpt = _completionBroker.CreateCompletionSession( _textView, triggerSpan.GetStartTrackingPoint(PointTrackingMode.Negative), trackCaret: false); var debugTextView = _textView as IDebuggerTextView; if (debugTextView != null && !debugTextView.IsImmediateWindow) { debugTextView.HACK_StartCompletionSession(_editorSessionOpt); } _editorSessionOpt.Dismissed += (s, e) => OnEditorSessionDismissed(); // So here's the deal. We cannot create the editor session and give it the right // items (even though we know what they are). Instead, the session will call // back into the ICompletionSourceProvider (which is us) to get those values. It // will pass itself along with the calls back into ICompletionSourceProvider. // So, in order to make that connection work, we add properties to the session // so that we can call back into ourselves, get the items and add it to the // session. _editorSessionOpt.Properties.AddProperty(Key, this); _editorSessionOpt.Start(); } // Call so that the editor will refresh the completion text to embolden. _editorSessionOpt?.Match(); }