async Task <ICompletionDataList> InternalHandleCodeCompletion(CodeCompletionContext completionContext, CompletionTriggerInfo triggerInfo, int triggerWordLength, CancellationToken token, bool forceSymbolCompletion = false)
        {
            var analysisDocument = DocumentContext.AnalysisDocument;

            if (analysisDocument == null)
            {
                return(EmptyCompletionDataList);
            }


            var        cs = DocumentContext.RoslynWorkspace.Services.GetLanguageServices(LanguageNames.CSharp).GetService <CompletionService> ();
            SourceText sourceText;

            if (!analysisDocument.TryGetText(out sourceText))
            {
                return(EmptyCompletionDataList);
            }

            CompletionTriggerKind kind;

            switch (triggerInfo.CompletionTriggerReason)
            {
            case CompletionTriggerReason.CharTyped:
                kind = CompletionTriggerKind.Insertion;
                if (triggerInfo.TriggerCharacter == '{')
                {
                    return(EmptyCompletionDataList);
                }
                break;

            case CompletionTriggerReason.CompletionCommand:
                kind = CompletionTriggerKind.InvokeAndCommitIfUnique;
                break;

            case CompletionTriggerReason.BackspaceOrDeleteCommand:
                kind = CompletionTriggerKind.Deletion;
                break;

            case CompletionTriggerReason.RetriggerCommand:
                kind = CompletionTriggerKind.InvokeAndCommitIfUnique;
                break;

            default:
                kind = CompletionTriggerKind.Insertion;
                break;
            }
            var triggerSnapshot = Editor.GetPlatformTextBuffer().CurrentSnapshot;
            var trigger         = new CompletionTrigger(kind, triggerInfo.TriggerCharacter.HasValue ? triggerInfo.TriggerCharacter.Value : '\0');

            if (triggerInfo.CompletionTriggerReason == CompletionTriggerReason.CharTyped)
            {
                if (!cs.ShouldTriggerCompletion(sourceText, completionContext.TriggerOffset, trigger, null))
                {
                    return(EmptyCompletionDataList);
                }
            }

            completionContext.Trace("C#: Getting completions");
            var customOptions = DocumentContext.RoslynWorkspace.Options
                                .WithChangedOption(CompletionOptions.TriggerOnDeletion, LanguageNames.CSharp, true)
                                .WithChangedOption(CompletionOptions.HideAdvancedMembers, LanguageNames.CSharp, IdeApp.Preferences.CompletionOptionsHideAdvancedMembers)
                                // Roslyn's implementation of this feature doesn't work correctly in old editor
                                .WithChangedOption(CompletionOptions.ShowItemsFromUnimportedNamespaces, LanguageNames.CSharp, false);
            var completionList = await Task.Run(() => cs.GetCompletionsAsync(analysisDocument, Editor.CaretOffset, trigger, options: customOptions, cancellationToken: token)).ConfigureAwait(false);

            completionContext.Trace("C#: Got completions");

            if (completionList == null)
            {
                return(EmptyCompletionDataList);
            }

            var result = new CompletionDataList();

            result.TriggerWordLength = triggerWordLength;
            CSharpCompletionData defaultCompletionData = null;
            bool first = true, addProtocolCompletion = false;

            foreach (var item in completionList.Items)
            {
                if (string.IsNullOrEmpty(item.DisplayText))
                {
                    continue;
                }
                var data = new CSharpCompletionData(analysisDocument, triggerSnapshot, cs, item);
                if (first)
                {
                    first = false;
                    addProtocolCompletion = data.Provider is OverrideCompletionProvider;
                }
                result.Add(data);
                if (item.Rules.MatchPriority > 0)
                {
                    if (defaultCompletionData == null || defaultCompletionData.Rules.MatchPriority < item.Rules.MatchPriority)
                    {
                        defaultCompletionData = data;
                    }
                }
            }

            result.AutoCompleteUniqueMatch = (triggerInfo.CompletionTriggerReason == CompletionTriggerReason.CompletionCommand);

            var partialDoc = analysisDocument.WithFrozenPartialSemantics(token);
            var semanticModel = await partialDoc.GetSemanticModelAsync(token).ConfigureAwait(false);

            var syntaxContext = CSharpSyntaxContext.CreateContext(DocumentContext.RoslynWorkspace, semanticModel, completionContext.TriggerOffset, token);

            if (forceSymbolCompletion || IdeApp.Preferences.AddImportedItemsToCompletionList)
            {
                completionContext.Trace("C#: Adding import completion data");
                AddImportCompletionData(syntaxContext, result, semanticModel, completionContext.TriggerOffset, token);
                completionContext.Trace("C#: Added import completion data");
            }
            if (defaultCompletionData != null)
            {
                result.DefaultCompletionString = defaultCompletionData.DisplayText;
            }

            if (completionList.SuggestionModeItem != null)
            {
                if (completionList.Items.Contains(completionList.SuggestionModeItem))
                {
                    result.DefaultCompletionString = completionList.SuggestionModeItem.DisplayText;
                }
                // if a suggestion mode item is present autoselection is disabled
                // for example in the lambda case the suggestion mode item is '<lambda expression>' which is not part of the completion item list but taggs the completion list as auto select == false.
                result.AutoSelect = false;
            }
            if (triggerInfo.TriggerCharacter == '_' && triggerWordLength == 1)
            {
                result.AutoSelect = false;
            }
            if (triggerInfo.TriggerCharacter == ' ')
            {
                result.AutoCompleteEmptyMatch = true;
            }

            return(result);
        }