private static AutoCompleteResponse MakeAutoCompleteResponse(ISymbol symbol, string completionText, bool isSuggestionMode, bool includeOptionalParams = true) { var displayNameGenerator = new SnippetGenerator(); displayNameGenerator.IncludeMarkers = false; displayNameGenerator.IncludeOptionalParameters = includeOptionalParams; var response = new AutoCompleteResponse(); response.CompletionText = completionText; // TODO: Do something more intelligent here response.DisplayText = displayNameGenerator.Generate(symbol); response.IsSuggestionMode = isSuggestionMode; //if (request.WantDocumentationForEveryCompletionResult) { response.Description = DocumentationConverter.ConvertDocumentation(symbol.GetDocumentationCommentXml(), "\r\n"); } //if (request.WantReturnType) { response.ReturnType = ReturnTypeFormatter.GetReturnType(symbol); } //if (request.WantKind) { response.Kind = symbol.GetKind(); } //if (request.WantSnippet) { var snippetGenerator = new SnippetGenerator(); snippetGenerator.IncludeMarkers = true; snippetGenerator.IncludeOptionalParameters = includeOptionalParams; response.Snippet = snippetGenerator.Generate(symbol); } //if (request.WantMethodHeader) { response.MethodHeader = displayNameGenerator.Generate(symbol); } return(response); }
public static async Task <List <CompletionItem> > Handle(CSharpContext context, string code, int line, int column) { var _document = context.WithText(code); var position = context.GetPosition(line, column); var service = Microsoft.CodeAnalysis.Completion.CompletionService.GetService(_document); var completionList = service.GetCompletionsAsync(_document, position).Result; var completions = new HashSet <AutoCompleteResponse>(); if (completionList != null) { // Only trigger on space if Roslyn has object creation items //if (request.TriggerCharacter == " " && !completionList.Items.Any(i => i.IsObjectCreationCompletionItem())) //{ // return completions; //} // get recommended symbols to match them up later with SymbolCompletionProvider var semanticModel = await _document.GetSemanticModelAsync(); var recommendedSymbols = await Microsoft.CodeAnalysis.Recommendations.Recommender.GetRecommendedSymbolsAtPositionAsync(semanticModel, position, context.Workspace); var isSuggestionMode = completionList.SuggestionModeItem != null; foreach (var item in completionList.Items) { var completionText = item.DisplayText; //if (completionText.IsValidCompletionFor(wordToComplete)) { var symbols = await item.GetCompletionSymbolsAsync(recommendedSymbols, _document); if (symbols.Any()) { foreach (var symbol in symbols) { if (context.Types != null && symbol.Kind != SymbolKind.Namespace) { var name = symbol.ContainingType != null ? symbol.ContainingType.ToDisplayString() : symbol.ToString(); var allowed = context.Types.Any(y => name.Like(y)); if (!allowed) { continue; } } if (item.UseDisplayTextAsCompletionText()) { completionText = item.DisplayText; } else if (item.TryGetInsertionText(out var insertionText)) { completionText = insertionText; } else { completionText = symbol.Name; } if (symbol != null) { //if (request.WantSnippet) //{ // foreach (var completion in MakeSnippetedResponses(request, symbol, completionText, isSuggestionMode)) // { // completions.Add(completion); // } //} //else { completions.Add(MakeAutoCompleteResponse(symbol, completionText, isSuggestionMode)); } } } // if we had any symbols from the completion, we can continue, otherwise it means // the completion didn't have an associated symbol so we'll add it manually continue; } // for other completions, i.e. keywords, create a simple AutoCompleteResponse // we'll just assume that the completion text is the same // as the display text. var response = new AutoCompleteResponse() { CompletionText = item.DisplayText, DisplayText = item.DisplayText, Snippet = item.DisplayText, Kind = item.Tags.First(), IsSuggestionMode = isSuggestionMode }; completions.Add(response); } } } var osr = completions // .OrderByDescending(c => c.CompletionText.IsValidCompletionStartsWithExactCase(wordToComplete)) // .ThenByDescending(c => c.CompletionText.IsValidCompletionStartsWithIgnoreCase(wordToComplete)) // .ThenByDescending(c => c.CompletionText.IsCamelCaseMatch(wordToComplete)) // .ThenByDescending(c => c.CompletionText.IsSubsequenceMatch(wordToComplete)) .OrderBy(c => c.DisplayText, StringComparer.OrdinalIgnoreCase) .ThenBy(c => c.CompletionText, StringComparer.OrdinalIgnoreCase); var completions2 = new Dictionary <string, List <CompletionItem> >(); foreach (var response in osr) { var completionItem = new CompletionItem { label = response.CompletionText, detail = !string.IsNullOrEmpty(response.ReturnType) ? response.DisplayText : $"{response.ReturnType} {response.DisplayText}", documentation = response.Description, kind = (int)GetCompletionItemKind(response.Kind), insertText = response.CompletionText, }; if (!completions2.ContainsKey(completionItem.label)) { completions2[completionItem.label] = new List <CompletionItem>(); } completions2[completionItem.label].Add(completionItem); } var result = new List <CompletionItem>(); foreach (var key in completions2.Keys) { var suggestion = completions2[key][0]; var overloadCount = completions2[key].Count - 1; if (overloadCount > 0) { // indicate that there is more suggestion.detail = $"{suggestion.detail} (+ {overloadCount} overload(s))"; } result.Add(suggestion); } return(result); }