public override async Task <QuickInfoItem?> GetQuickInfoAsync(Document document, int position, CancellationToken cancellationToken)
        {
            var extensionManager = _services.WorkspaceServices.GetRequiredService <IExtensionManager>();
            var options          = SymbolDescriptionOptions.From(document.Project);

            // returns the first non-empty quick info found (based on provider order)
            foreach (var provider in GetProviders())
            {
                try
                {
                    if (!extensionManager.IsDisabled(provider))
                    {
                        var context = new QuickInfoContext(document, position, options, cancellationToken);

                        var info = await provider.GetQuickInfoAsync(context).ConfigureAwait(false);

                        if (info != null)
                        {
                            return(info);
                        }
                    }
                }
                catch (OperationCanceledException)
                {
                    throw;
                }
                catch (Exception e) when(extensionManager.CanHandleException(provider, e))
                {
                    extensionManager.HandleException(provider, e);
                }
            }

            return(null);
        }
        public static async Task <CompletionDescription> GetDescriptionAsync(
            CompletionItem item, Document document, SymbolDescriptionOptions options, CancellationToken cancellationToken)
        {
            var symbols = await GetSymbolsAsync(item, document, cancellationToken).ConfigureAwait(false);

            return(await GetDescriptionForSymbolsAsync(item, document, symbols, options, cancellationToken).ConfigureAwait(false));
        }
        internal sealed override async Task <CompletionDescription> GetDescriptionWorkerAsync(
            Document document, CompletionItem item, CompletionOptions options, SymbolDescriptionOptions displayOptions, CancellationToken cancellationToken)
        {
            var description = await GetDescriptionAsync(item, document, displayOptions, cancellationToken).ConfigureAwait(false);

            return(UpdateDescription(description));
        }
        protected override async Task AssertContentIsAsync(
            TestWorkspace workspace,
            Document document,
            int position,
            string expectedContent,
            string expectedDocumentationComment = null)
        {
            var provider = CreateProvider();
            var options  = SymbolDescriptionOptions.From(document.Project);
            var info     = await provider.GetQuickInfoAsync(new QuickInfoContext(document, position, options, CancellationToken.None));

            Assert.NotNull(info);
            Assert.NotEqual(0, info.RelatedSpans.Length);

            var trackingSpan       = new Mock <ITrackingSpan>(MockBehavior.Strict);
            var threadingContext   = workspace.ExportProvider.GetExportedValue <IThreadingContext>();
            var operationExecutor  = workspace.ExportProvider.GetExportedValue <IUIThreadOperationExecutor>();
            var streamingPresenter = workspace.ExportProvider.GetExport <IStreamingFindUsagesPresenter>();
            var quickInfoItem      = await IntellisenseQuickInfoBuilder.BuildItemAsync(
                trackingSpan.Object, info, document,
                threadingContext, operationExecutor,
                AsynchronousOperationListenerProvider.NullListener,
                streamingPresenter, CancellationToken.None);

            var containerElement = quickInfoItem.Item as ContainerElement;

            var textElements = containerElement.Elements.OfType <ClassifiedTextElement>();

            Assert.NotEmpty(textElements);

            var textElement = textElements.First();
            var actualText  = string.Concat(textElement.Runs.Select(r => r.Text));

            Assert.Equal(expectedContent, actualText);
        }
        internal override async Task <CompletionDescription> GetDescriptionWorkerAsync(
            Document document, CompletionItem item, CompletionOptions options, SymbolDescriptionOptions displayOptions, CancellationToken cancellationToken)
        {
            var position = SymbolCompletionItem.GetContextPosition(item);

            // What EditorBrowsable settings were we previously passed in (if it mattered)?
            if (item.Properties.TryGetValue(HideAdvancedMembers, out var hideAdvancedMembersString) &&
                bool.TryParse(hideAdvancedMembersString, out var hideAdvancedMembers))
            {
                options = options with {
                    HideAdvancedMembers = hideAdvancedMembers
                };
            }

            var(token, semanticModel, symbols) = await GetSymbolsAsync(document, position, options, cancellationToken).ConfigureAwait(false);

            if (symbols.Length == 0)
            {
                return(CompletionDescription.Empty);
            }

            Contract.ThrowIfNull(semanticModel);

            var name        = SymbolCompletionItem.GetSymbolName(item);
            var kind        = SymbolCompletionItem.GetKind(item);
            var bestSymbols = symbols.WhereAsArray(s => s.Kind == kind && s.Name == name);

            return(await SymbolCompletionItem.GetDescriptionAsync(item, bestSymbols, document, semanticModel, displayOptions, cancellationToken).ConfigureAwait(false));
        }
 internal virtual Task <QuickInfoItem?> GetQuickInfoAsync(
     Document document,
     int position,
     SymbolDescriptionOptions options,
     CancellationToken cancellationToken)
 {
     return(SpecializedTasks.Null <QuickInfoItem>());
 }
Beispiel #7
0
 public static Func <CancellationToken, Task <CompletionDescription> > CreateDescriptionFactory(
     HostSolutionServices workspaceServices,
     SemanticModel semanticModel,
     int position,
     ISymbol symbol,
     SymbolDescriptionOptions options)
 {
     return(CreateDescriptionFactory(workspaceServices, semanticModel, position, options, new[] { symbol }));
 }
Beispiel #8
0
 public SymbolDescriptionBuilder(
     SemanticModel semanticModel,
     int position,
     HostWorkspaceServices workspaceServices,
     IStructuralTypeDisplayService structuralTypeDisplayService,
     SymbolDescriptionOptions options,
     CancellationToken cancellationToken)
     : base(semanticModel, position, workspaceServices, structuralTypeDisplayService, options, cancellationToken)
 {
 }
        protected override async Task AssertNoContentAsync(
            TestWorkspace workspace,
            Document document,
            int position)
        {
            var provider = CreateProvider();
            var options  = SymbolDescriptionOptions.From(document.Project);

            Assert.Null(await provider.GetQuickInfoAsync(new QuickInfoContext(document, position, options, CancellationToken.None)));
        }
Beispiel #10
0
 /// <summary>
 /// Creates a <see cref="QuickInfoContext"/> instance.
 /// </summary>
 public QuickInfoContext(
     Document document,
     int position,
     SymbolDescriptionOptions options,
     CancellationToken cancellationToken)
 {
     Document          = document ?? throw new ArgumentNullException(nameof(document));
     Position          = position;
     Options           = options;
     CancellationToken = cancellationToken;
 }
Beispiel #11
0
 public CommonQuickInfoContext(
     HostWorkspaceServices services,
     SemanticModel semanticModel,
     int position,
     SymbolDescriptionOptions options,
     CancellationToken cancellationToken)
 {
     Services          = services;
     SemanticModel     = semanticModel;
     Position          = position;
     Options           = options;
     CancellationToken = cancellationToken;
 }
Beispiel #12
0
        public static async Task <IEnumerable <TaggedText> > GetDescriptionAsync(this ISymbol symbol, TextDocument document, CancellationToken cancellationToken)
        {
            if (symbol == null)
            {
                return(Enumerable.Empty <TaggedText>());
            }

            var codeProject = document.GetCodeProject();
            var formatter   = codeProject.LanguageServices.GetService <IDocumentationCommentFormattingService>();

            if (formatter == null)
            {
                return(Enumerable.Empty <TaggedText>());
            }

            var symbolDisplayService = codeProject.LanguageServices.GetService <ISymbolDisplayService>();

            if (symbolDisplayService == null)
            {
                return(Enumerable.Empty <TaggedText>());
            }

            // Any code document will do
            var codeDocument = codeProject.Documents.FirstOrDefault();

            if (codeDocument == null)
            {
                return(Enumerable.Empty <TaggedText>());
            }

            var semanticModel = await codeDocument.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            if (semanticModel == null)
            {
                return(Enumerable.Empty <TaggedText>());
            }

            var services  = codeProject.Solution.Workspace.Services;
            var options   = SymbolDescriptionOptions.From(document.Project);
            var quickInfo = await QuickInfoUtilities.CreateQuickInfoItemAsync(services, semanticModel, span : default, ImmutableArray.Create(symbol), options, cancellationToken).ConfigureAwait(false);
Beispiel #13
0
        internal static async Task <Hover?> GetHoverAsync(
            SemanticModel semanticModel,
            int position,
            SymbolDescriptionOptions options,
            HostLanguageServices languageServices,
            CancellationToken cancellationToken)
        {
            Debug.Assert(semanticModel.Language is LanguageNames.CSharp or LanguageNames.VisualBasic);

            // Get the quick info service to compute quick info.
            // This code path is only invoked for C# and VB, so we can directly cast to QuickInfoServiceWithProviders.
            var quickInfoService = (QuickInfoServiceWithProviders)languageServices.GetRequiredService <QuickInfoService>();
            var info             = await quickInfoService.GetQuickInfoAsync(semanticModel, position, options, cancellationToken).ConfigureAwait(false);

            if (info == null)
            {
                return(null);
            }

            var text = await semanticModel.SyntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false);

            return(await GetHoverAsync(info, text, semanticModel.Language, document : null, classificationOptions : null, clientCapabilities : null, cancellationToken).ConfigureAwait(false));
        }
        public static async Task <QuickInfoItem> CreateQuickInfoItemAsync(
            HostSolutionServices services,
            SemanticModel semanticModel,
            TextSpan span,
            ImmutableArray <ISymbol> symbols,
            SupportedPlatformData?supportedPlatforms,
            bool showAwaitReturn,
            NullableFlowState flowState,
            SymbolDescriptionOptions options,
            CancellationToken cancellationToken)
        {
            var descriptionService = services.GetRequiredLanguageService <ISymbolDisplayService>(semanticModel.Language);
            var groups             = await descriptionService.ToDescriptionGroupsAsync(semanticModel, span.Start, symbols, options, cancellationToken).ConfigureAwait(false);

            using var _1 = ArrayBuilder <QuickInfoSection> .GetInstance(out var sections);

            var symbol = symbols.First();

            if (showAwaitReturn)
            {
                // We show a special message if the Task being awaited has no return
                if (symbol is INamedTypeSymbol {
                    SpecialType : SpecialType.System_Void
                })
 public static Task <CompletionDescription> GetDescriptionAsync(CompletionItem item, Document document, SymbolDescriptionOptions displayOptions, CancellationToken cancellationToken)
 => SymbolCompletionItem.HasSymbols(item)
     ? SymbolCompletionItem.GetDescriptionAsync(item, document, displayOptions, cancellationToken)
     : Task.FromResult(CommonCompletionItem.GetDescription(item));
        public static async Task <CompletionDescription> GetDescriptionAsync(
            CompletionItem item, IReadOnlyList <ISymbol> symbols, Document document, SemanticModel semanticModel, SymbolDescriptionOptions options, CancellationToken cancellationToken)
        {
            var position           = GetDescriptionPosition(item);
            var supportedPlatforms = GetSupportedPlatforms(item, document.Project.Solution);

            if (symbols.Count != 0)
            {
                return(await CommonCompletionUtilities.CreateDescriptionAsync(document.Project.Solution.Services, semanticModel, position, symbols, options, supportedPlatforms, cancellationToken).ConfigureAwait(false));
            }
            else
            {
                return(CompletionDescription.Empty);
            }
        }
        public static async Task <CompletionDescription> GetDescriptionForSymbolsAsync(
            CompletionItem item, Document document, ImmutableArray <ISymbol> symbols, SymbolDescriptionOptions options, CancellationToken cancellationToken)
        {
            if (symbols.Length == 0)
            {
                return(CompletionDescription.Empty);
            }

            var position = GetDescriptionPosition(item);

            if (position == -1)
            {
                position = item.Span.Start;
            }

            var supportedPlatforms = GetSupportedPlatforms(item, document.Project.Solution);
            var contextDocument    = FindAppropriateDocumentForDescriptionContext(document, supportedPlatforms);
            var semanticModel      = await contextDocument.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            var services = document.Project.Solution.Services;

            return(await CommonCompletionUtilities.CreateDescriptionAsync(services, semanticModel, position, symbols, options, supportedPlatforms, cancellationToken).ConfigureAwait(false));
        }
 internal override Task <CompletionDescription?> GetDescriptionAsync(Document document, CompletionItem item, CompletionOptions options, SymbolDescriptionOptions displayOptions, CancellationToken cancellationToken)
 => GetLanguage(item).CompletionProvider.GetDescriptionAsync(document, item, cancellationToken);
Beispiel #19
0
        public async Task <LSP.CompletionItem> HandleRequestAsync(LSP.CompletionItem completionItem, RequestContext context, CancellationToken cancellationToken)
        {
            var document = context.Document;

            Contract.ThrowIfNull(document);

            var completionService = document.Project.LanguageServices.GetRequiredService <CompletionService>();
            var cacheEntry        = GetCompletionListCacheEntry(completionItem);

            if (cacheEntry == null)
            {
                // Don't have a cache associated with this completion item, cannot resolve.
                context.TraceInformation("No cache entry found for the provided completion item at resolve time.");
                return(completionItem);
            }

            var list = cacheEntry.CompletionList;

            // Find the matching completion item in the completion list
            var selectedItem = list.Items.FirstOrDefault(cachedCompletionItem => MatchesLSPCompletionItem(completionItem, cachedCompletionItem));

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

            var options        = CompletionOptions.From(document.Project);
            var displayOptions = SymbolDescriptionOptions.From(document.Project);
            var description    = await completionService.GetDescriptionAsync(document, selectedItem, options, displayOptions, cancellationToken).ConfigureAwait(false) !;

            if (description != null)
            {
                var supportsVSExtensions = context.ClientCapabilities.HasVisualStudioLspCapability();
                if (supportsVSExtensions)
                {
                    var vsCompletionItem = (LSP.VSInternalCompletionItem)completionItem;
                    vsCompletionItem.Description = new ClassifiedTextElement(description.TaggedParts
                                                                             .Select(tp => new ClassifiedTextRun(tp.Tag.ToClassificationTypeName(), tp.Text)));
                }
                else
                {
                    var clientSupportsMarkdown = context.ClientCapabilities.TextDocument?.Completion?.CompletionItem?.DocumentationFormat.Contains(LSP.MarkupKind.Markdown) == true;
                    completionItem.Documentation = ProtocolConversions.GetDocumentationMarkupContent(description.TaggedParts, document, clientSupportsMarkdown);
                }
            }

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

            return(completionItem);
        }
Beispiel #20
0
 public static Func <CancellationToken, Task <CompletionDescription> > CreateDescriptionFactory(
     HostSolutionServices workspaceServices, SemanticModel semanticModel, int position, SymbolDescriptionOptions options, IReadOnlyList <ISymbol> symbols)
 {
     return(c => CreateDescriptionAsync(workspaceServices, semanticModel, position, symbols, options, supportedPlatforms: null, cancellationToken: c));
 }
Beispiel #21
0
        public static Task <CompletionDescription> CreateDescriptionAsync(
            HostSolutionServices workspaceServices, SemanticModel semanticModel, int position, IReadOnlyList <ISymbol> symbols, SymbolDescriptionOptions options, SupportedPlatformData?supportedPlatforms, CancellationToken cancellationToken)
        {
            // Lets try to find the first non-obsolete symbol (overload) and fall-back
            // to the first symbol if all are obsolete.
            var symbol = symbols.FirstOrDefault(s => !s.IsObsolete()) ?? symbols[0];

            return(CreateDescriptionAsync(workspaceServices, semanticModel, position, symbol, overloadCount: symbols.Count - 1, options, supportedPlatforms, cancellationToken));
        }
Beispiel #22
0
        public static async Task <CompletionDescription> CreateDescriptionAsync(
            HostSolutionServices workspaceServices, SemanticModel semanticModel, int position, ISymbol symbol, int overloadCount, SymbolDescriptionOptions options, SupportedPlatformData?supportedPlatforms, CancellationToken cancellationToken)
        {
            var symbolDisplayService = workspaceServices.GetRequiredLanguageService <ISymbolDisplayService>(semanticModel.Language);
            var formatter            = workspaceServices.GetRequiredLanguageService <IDocumentationCommentFormattingService>(semanticModel.Language);

            // TODO(cyrusn): Figure out a way to cancel this.
            var sections = await symbolDisplayService.ToDescriptionGroupsAsync(semanticModel, position, ImmutableArray.Create(symbol), options, cancellationToken).ConfigureAwait(false);

            if (!sections.ContainsKey(SymbolDescriptionGroups.MainDescription))
            {
                return(CompletionDescription.Empty);
            }

            var textContentBuilder = new List <TaggedText>();

            textContentBuilder.AddRange(sections[SymbolDescriptionGroups.MainDescription]);

            switch (symbol.Kind)
            {
            case SymbolKind.Method:
            case SymbolKind.Property:
            case SymbolKind.NamedType:
                if (overloadCount > 0)
                {
                    var isGeneric = symbol.GetArity() > 0;

                    textContentBuilder.AddSpace();
                    textContentBuilder.AddPunctuation("(");
                    textContentBuilder.AddPunctuation("+");
                    textContentBuilder.AddText(NonBreakingSpaceString + overloadCount.ToString());

                    AddOverloadPart(textContentBuilder, overloadCount, isGeneric);

                    textContentBuilder.AddPunctuation(")");
                }

                break;
            }

            AddDocumentationPart(textContentBuilder, symbol, semanticModel, position, formatter, cancellationToken);

            if (sections.TryGetValue(SymbolDescriptionGroups.AwaitableUsageText, out var parts))
            {
                textContentBuilder.AddRange(parts);
            }

            if (sections.TryGetValue(SymbolDescriptionGroups.StructuralTypes, out parts))
            {
                if (!parts.IsDefaultOrEmpty)
                {
                    textContentBuilder.AddLineBreak();
                    textContentBuilder.AddLineBreak();
                    textContentBuilder.AddRange(parts);
                }
            }

            if (supportedPlatforms != null)
            {
                textContentBuilder.AddLineBreak();
                textContentBuilder.AddRange(supportedPlatforms.ToDisplayParts().ToTaggedText());
            }

            return(CompletionDescription.Create(textContentBuilder.AsImmutable()));
        }
Beispiel #23
0
        public async Task <ImmutableArray <InlineHint> > GetInlineHintsAsync(
            Document document, TextSpan textSpan, InlineTypeHintsOptions options, SymbolDescriptionOptions displayOptions, CancellationToken cancellationToken)
        {
            // TODO: https://github.com/dotnet/roslyn/issues/57283
            var globalOptions      = document.Project.Solution.Workspace.Services.GetRequiredService <ILegacyGlobalOptionsWorkspaceService>();
            var displayAllOverride = globalOptions.InlineHintsOptionsDisplayAllOverride;

            var enabledForTypes = options.EnabledForTypes;

            if (!enabledForTypes && !displayAllOverride)
            {
                return(ImmutableArray <InlineHint> .Empty);
            }

            var forImplicitVariableTypes  = enabledForTypes && options.ForImplicitVariableTypes;
            var forLambdaParameterTypes   = enabledForTypes && options.ForLambdaParameterTypes;
            var forImplicitObjectCreation = enabledForTypes && options.ForImplicitObjectCreation;

            if (!forImplicitVariableTypes && !forLambdaParameterTypes && !forImplicitObjectCreation && !displayAllOverride)
            {
                return(ImmutableArray <InlineHint> .Empty);
            }

            var anonymousTypeService = document.GetRequiredLanguageService <IStructuralTypeDisplayService>();
            var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            using var _1 = ArrayBuilder <InlineHint> .GetInstance(out var result);

            foreach (var node in root.DescendantNodes(n => n.Span.IntersectsWith(textSpan)))
            {
                var hintOpt = TryGetTypeHint(
                    semanticModel, node,
                    displayAllOverride,
                    forImplicitVariableTypes,
                    forLambdaParameterTypes,
                    forImplicitObjectCreation,
                    cancellationToken);
                if (hintOpt == null)
                {
                    continue;
                }

                var(type, span, textChange, prefix, suffix) = hintOpt.Value;

                using var _2 = ArrayBuilder <SymbolDisplayPart> .GetInstance(out var finalParts);

                finalParts.AddRange(prefix);

                var parts = type.ToDisplayParts(s_minimalTypeStyle);
                AddParts(anonymousTypeService, finalParts, parts, semanticModel, span.Start);

                // If we have nothing to show, then don't bother adding this hint.
                if (finalParts.All(p => string.IsNullOrWhiteSpace(p.ToString())))
                {
                    continue;
                }

                finalParts.AddRange(suffix);
                var taggedText = finalParts.ToTaggedText();

                result.Add(new InlineHint(
                               span, taggedText, textChange,
                               InlineHintHelpers.GetDescriptionFunction(span.Start, type.GetSymbolKey(cancellationToken: cancellationToken), displayOptions)));
            }

            return(result.ToImmutable());
        }
        internal async Task <QuickInfoItem?> GetQuickInfoAsync(SemanticModel semanticModel, int position, SymbolDescriptionOptions options, CancellationToken cancellationToken)
        {
            var extensionManager = _services.WorkspaceServices.GetRequiredService <IExtensionManager>();

            // returns the first non-empty quick info found (based on provider order)
            foreach (var provider in GetProviders().OfType <CommonQuickInfoProvider>())
            {
                try
                {
                    if (!extensionManager.IsDisabled(provider))
                    {
                        var context = new CommonQuickInfoContext(_services.WorkspaceServices.SolutionServices, semanticModel, position, options, cancellationToken);

                        var info = await provider.GetQuickInfoAsync(context).ConfigureAwait(false);

                        if (info != null)
                        {
                            return(info);
                        }
                    }
                }
                catch (OperationCanceledException)
                {
                    throw;
                }
                catch (Exception e) when(extensionManager.CanHandleException(provider, e))
                {
                    extensionManager.HandleException(provider, e);
                }
            }

            return(null);
        }
 public static Task <CompletionDescription> GetDescriptionAsync(CompletionItem item, Document document, SymbolDescriptionOptions displayOptions, CancellationToken cancellationToken)
 => SymbolCompletionItem.GetDescriptionAsync(item, document, displayOptions, cancellationToken);
        private static async Task <CompletionDescription?> GetConversionDescriptionAsync(Document document, CompletionItem item, SymbolDescriptionOptions displayOptions, CancellationToken cancellationToken)
        {
            var conversion = await TryRehydrateAsync(document, item, cancellationToken).ConfigureAwait(false);

            if (conversion == null)
            {
                return(null);
            }

            return(await SymbolCompletionItem.GetDescriptionForSymbolsAsync(
                       item, document, ImmutableArray.Create(conversion), displayOptions, cancellationToken).ConfigureAwait(false));
        }
 private static Task <CompletionDescription> GetIndexerDescriptionAsync(Document document, CompletionItem item, SymbolDescriptionOptions options, CancellationToken cancellationToken)
 => SymbolCompletionItem.GetDescriptionAsync(item, document, options, cancellationToken);
 internal override Task <CompletionDescription> GetDescriptionAsync(Document document, CodeAnalysis.Completion.CompletionItem item, CodeAnalysis.Completion.CompletionOptions options, SymbolDescriptionOptions displayOptions, CancellationToken cancellationToken = default)
 => Task.FromResult(CompletionDescription.Empty);
 internal override Task <CompletionDescription> GetDescriptionWorkerAsync(Document document, CompletionItem item, CompletionOptions options, SymbolDescriptionOptions displayOptions, CancellationToken cancellationToken)
 => ImportCompletionItem.GetCompletionDescriptionAsync(document, item, displayOptions, cancellationToken);
 /// <summary>
 /// Gets the description of the item.
 /// </summary>
 /// <param name="document">This will be the  original document that
 /// <paramref name="item"/> was created against.</param>
 /// <param name="item">The item to get the description for.</param>
 /// <param name="options">Completion options</param>
 /// <param name="displayOptions">Display options</param>
 /// <param name="cancellationToken"></param>
 internal abstract Task <CompletionDescription?> GetDescriptionAsync(Document document, CompletionItem item, CompletionOptions options, SymbolDescriptionOptions displayOptions, CancellationToken cancellationToken = default);