IWordCompletionSession IWordCompletionSessionFactoryService.CreateWordCompletionSession(ITextView textView, SnapshotSpan wordSpan, IEnumerable <string> wordCollection, bool isForward)
        {
            var completionData = new CompletionData(
                wordSpan,
                new ReadOnlyCollection <string>(wordCollection.ToList()));

            textView.Properties[_completionDataKey] = completionData;
            try
            {
                // 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(new DismissedWordCompletionSession(textView));
                }

                // Now move the word completion set to the fron
                var wordCompletionSet = completionSession.CompletionSets.OfType <WordCompletionSet>().FirstOrDefault();
                if (wordCompletionSet == null)
                {
                    wordCompletionSet = new WordCompletionSet();
                }
                completionSession.SelectedCompletionSet = wordCompletionSet;

                var intellisenseSessionStack = _intellisenseSessionStackMapService.GetStackForTextView(textView);
                var wordTrackingSpan         = wordSpan.Snapshot.CreateTrackingSpan(wordSpan.Span, SpanTrackingMode.EdgeInclusive);
                var wordCompletionSession    = new WordCompletionSession(
                    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);

                RaiseCompleted(wordCompletionSession);

                return(wordCompletionSession);
            }
            finally
            {
                textView.Properties.RemoveProperty(_completionDataKey);
            }
        }
        IWordCompletionSession IWordCompletionSessionFactoryService.CreateWordCompletionSession(ITextView textView, SnapshotSpan wordSpan, IEnumerable<string> wordCollection, bool isForward)
        {
            var completionData = new CompletionData(
                wordSpan,
                new ReadOnlyCollection<string>(wordCollection.ToList()));
            textView.Properties[_completionDataKey] = completionData;
            try
            {
                // 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 new DismissedWordCompletionSession(textView);
                }

                // Now move the word completion set to the fron
                var wordCompletionSet = completionSession.CompletionSets.OfType<WordCompletionSet>().FirstOrDefault();
                if (wordCompletionSet == null)
                {
                    wordCompletionSet = new WordCompletionSet();
                }
                completionSession.SelectedCompletionSet = wordCompletionSet;

                var intellisenseSessionStack = _intellisenseSessionStackMapService.GetStackForTextView(textView);
                var wordTrackingSpan = wordSpan.Snapshot.CreateTrackingSpan(wordSpan.Span, SpanTrackingMode.EdgeInclusive);
                var wordCompletionSession = new WordCompletionSession(
                    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);

                return wordCompletionSession;
            }
            finally
            {
                textView.Properties.RemoveProperty(_completionDataKey);
            }
        }