internal FSharpOption <IWordCompletionSession> CreateWordCompletionSession(ITextView textView, SnapshotSpan wordSpan, IEnumerable <string> wordCollection, bool isForward) { // Dismiss any active ICompletionSession instances. It's possible and possibly common for // normal intellisense to be active when the user invokes word completion. We want only word // completion displayed at this point _asyncCompletionBroker.GetSession(textView)?.Dismiss(); // Store the WordCompletionData inside the ITextView. The IAsyncCompletionSource implementation will // asked to provide data for the creation of the IAsyncCompletionSession. Hence we must share through // ITextView var wordCompletionData = new VimWordCompletionData( wordSpan, new ReadOnlyCollection <string>(wordCollection.ToList())); textView.SetWordCompletionData(wordCompletionData); // Create a completion session at the start of the word. The actual session information will // take care of mapping it to a specific span var completionTrigger = new CompletionTrigger(CompletionTriggerReason.Insertion, wordSpan.Snapshot); var asyncCompletionSession = _asyncCompletionBroker.TriggerCompletion( textView, completionTrigger, wordSpan.Start, CancellationToken.None); // It's possible for the Start method to dismiss the ICompletionSession. This happens when there // is an initialization error such as being unable to find a CompletionSet. If this occurs we // just return the equivalent IWordCompletionSession (one which is dismissed) if (asyncCompletionSession.IsDismissed) { return(FSharpOption <IWordCompletionSession> .None); } asyncCompletionSession.OpenOrUpdate(completionTrigger, wordSpan.Start, CancellationToken.None); #if VS_SPECIFIC_2019 return(new WordAsyncCompletionSession(asyncCompletionSession, _vsEditorAdaptersFactoryService)); #elif VS_SPECIFIC_MAC return(new WordAsyncCompletionSession(asyncCompletionSession)); #endif }
internal FSharpOption <IWordCompletionSession> CreateWordCompletionSession(ITextView textView, SnapshotSpan wordSpan, IEnumerable <string> wordCollection, bool isForward) { var completionData = new VimWordCompletionData( wordSpan, new ReadOnlyCollection <string>(wordCollection.ToList())); textView.SetWordCompletionData(completionData); // Dismiss any active ICompletionSession instances. It's possible and possibly common for // normal intellisense to be active when the user invokes word completion. We want only word // completion displayed at this point foreach (var existingCompletionSession in _completionBroker.GetSessions(textView)) { existingCompletionSession.Dismiss(); } // Create a completion session at the start of the word. The actual session information will // take care of mapping it to a specific span var trackingPoint = textView.TextSnapshot.CreateTrackingPoint(wordSpan.Start, PointTrackingMode.Positive); var completionSession = _completionBroker.CreateCompletionSession(textView, trackingPoint, true); completionSession.Properties[WordCompletionSessionKey] = WordCompletionSessionKey; // Start the completion. This will cause it to get populated at which point we can go about // filtering the data completionSession.Start(); // It's possible for the Start method to dismiss the ICompletionSession. This happens when there // is an initialization error such as being unable to find a CompletionSet. If this occurs we // just return the equivalent IWordCompletionSession (one which is dismissed) if (completionSession.IsDismissed) { return(FSharpOption <IWordCompletionSession> .None); } // Now move the word completion set to the fron var wordCompletionSet = completionSession.CompletionSets.OfType <WordLegacyCompletionSet>().FirstOrDefault(); if (wordCompletionSet == null) { wordCompletionSet = new WordLegacyCompletionSet(); } completionSession.SelectedCompletionSet = wordCompletionSet; var intellisenseSessionStack = _intellisenseSessionStackMapService.GetStackForTextView(textView); var wordTrackingSpan = wordSpan.Snapshot.CreateTrackingSpan(wordSpan.Span, SpanTrackingMode.EdgeInclusive); var wordCompletionSession = new WordLegacyCompletionSession( wordTrackingSpan, intellisenseSessionStack, completionSession, wordCompletionSet); // Ensure the correct item is selected and committed to the ITextBuffer. If this is a forward completion // then we select the first item, else the last. Sending the command will go ahead and insert the // completion in the given span var command = isForward ? IntellisenseKeyboardCommand.TopLine : IntellisenseKeyboardCommand.BottomLine; wordCompletionSession.SendCommand(command); // For reasons I don't understand, if the command is 'bottom // line', it doesn't seem to take effect on the first try. wordCompletionSession.SendCommand(command); return(FSharpOption <IWordCompletionSession> .Some(wordCompletionSession)); }