Ejemplo n.º 1
0
        public async Task <LSP.CompletionItem> HandleRequestAsync(LSP.CompletionItem completionItem, RequestContext context, CancellationToken cancellationToken)
        {
            var document = context.Document;

            if (document == null)
            {
                return(completionItem);
            }

            var completionService = document.Project.LanguageServices.GetRequiredService <CompletionService>();
            var data = GetCompletionResolveData(completionItem);

            CompletionList?list = null;

            // See if we have a cache of the completion list we need
            if (data.ResultId.HasValue)
            {
                list = await _completionListCache.GetCachedCompletionListAsync(data.ResultId.Value, cancellationToken).ConfigureAwait(false);
            }

            if (list == null)
            {
                // We don't have a cache, so we need to recompute the list
                var position = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(data.Position), cancellationToken).ConfigureAwait(false);

                var completionOptions = await CompletionHandler.GetCompletionOptionsAsync(document, cancellationToken).ConfigureAwait(false);

                list = await completionService.GetCompletionsAsync(document, position, data.CompletionTrigger, options : completionOptions, cancellationToken : cancellationToken).ConfigureAwait(false);

                if (list == null)
                {
                    return(completionItem);
                }
            }

            // Find the matching completion item in the completion list
            var selectedItem = list.Items.FirstOrDefault(
                i => data.DisplayText == i.DisplayText &&
                completionItem.Label.StartsWith(i.DisplayTextPrefix) &&
                completionItem.Label.EndsWith(i.DisplayTextSuffix));

            if (selectedItem == null)
            {
                return(completionItem);
            }

            var description = await completionService.GetDescriptionAsync(document, selectedItem, cancellationToken).ConfigureAwait(false);

            if (completionItem is LSP.VSCompletionItem vsCompletionItem)
            {
                vsCompletionItem.Description = new ClassifiedTextElement(description.TaggedParts
                                                                         .Select(tp => new ClassifiedTextRun(tp.Tag.ToClassificationTypeName(), tp.Text)));
            }

            // We compute the TextEdit resolves for complex text edits (e.g. override and partial
            // method completions) here. Lazily resolving TextEdits is technically a violation of
            // the LSP spec, but is currently supported by the VS client anyway. Once the VS client
            // adheres to the spec, this logic will need to change and VS will need to provide
            // official support for TextEdit resolution in some form.
            if (selectedItem.IsComplexTextEdit)
            {
                Contract.ThrowIfTrue(completionItem.InsertText != null);
                Contract.ThrowIfTrue(completionItem.TextEdit != null);

                var snippetsSupported = context.ClientCapabilities.TextDocument?.Completion?.CompletionItem?.SnippetSupport ?? false;

                completionItem.TextEdit = await GenerateTextEditAsync(
                    document, completionService, selectedItem, snippetsSupported, cancellationToken).ConfigureAwait(false);
            }

            completionItem.Detail = description.TaggedParts.GetFullText();
            return(completionItem);
        }
Ejemplo n.º 2
0
        public async Task <LSP.CompletionItem> HandleRequestAsync(LSP.CompletionItem completionItem, RequestContext context, CancellationToken cancellationToken)
        {
            var document = context.Document;

            if (document == null)
            {
                return(completionItem);
            }

            var completionService = document.Project.LanguageServices.GetRequiredService <CompletionService>();
            var data = GetCompletionResolveData(completionItem);

            CompletionList?list = null;

            // See if we have a cache of the completion list we need
            if (data.ResultId.HasValue)
            {
                list = await _completionListCache.GetCachedCompletionListAsync(data.ResultId.Value, cancellationToken).ConfigureAwait(false);
            }

            if (list == null)
            {
                // We don't have a cache, so we need to recompute the list
                var position = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(data.Position), cancellationToken).ConfigureAwait(false);

                var completionOptions = await CompletionHandler.GetCompletionOptionsAsync(document, cancellationToken).ConfigureAwait(false);

                list = await completionService.GetCompletionsAsync(document, position, data.CompletionTrigger, options : completionOptions, cancellationToken : cancellationToken).ConfigureAwait(false);

                if (list == null)
                {
                    return(completionItem);
                }
            }

            var selectedItem = list.Items.FirstOrDefault(i => i.DisplayText == data.DisplayText);

            if (selectedItem == null)
            {
                return(completionItem);
            }

            var description = await completionService.GetDescriptionAsync(document, selectedItem, cancellationToken).ConfigureAwait(false);

            var lspVSClientCapability = context.ClientCapabilities?.HasVisualStudioLspCapability() == true;

            LSP.CompletionItem resolvedCompletionItem;
            if (lspVSClientCapability)
            {
                resolvedCompletionItem = CloneVSCompletionItem(completionItem);
                ((LSP.VSCompletionItem)resolvedCompletionItem).Description = new ClassifiedTextElement(description.TaggedParts
                                                                                                       .Select(tp => new ClassifiedTextRun(tp.Tag.ToClassificationTypeName(), tp.Text)));
            }
            else
            {
                resolvedCompletionItem = RoslynCompletionItem.From(completionItem);
                ((RoslynCompletionItem)resolvedCompletionItem).Description = description.TaggedParts.Select(
                    tp => new RoslynTaggedText {
                    Tag = tp.Tag, Text = tp.Text
                }).ToArray();
            }

            resolvedCompletionItem.Detail = description.TaggedParts.GetFullText();
            return(resolvedCompletionItem);
        }