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