public async Task HandleAsync(RequestHoverText command, KernelInvocationContext context)
        {
            using var _ = new GCPressure(1024 * 1024);

            var document = _workspace.UpdateWorkingDocument(command.Code);
            var text     = await document.GetTextAsync();

            var cursorPosition = text.Lines.GetPosition(command.LinePosition);
            var service        = QuickInfoService.GetService(document);
            var info           = await service.GetQuickInfoAsync(document, cursorPosition);

            if (info == null)
            {
                return;
            }

            var scriptSpanStart      = text.Lines.GetLinePosition(0);
            var linePosSpan          = text.Lines.GetLinePositionSpan(info.Span);
            var correctedLinePosSpan = linePosSpan.SubtractLineOffset(scriptSpanStart);

            context.Publish(
                new HoverTextProduced(
                    command,
                    new[]
            {
                new FormattedValue("text/markdown", info.ToMarkdownString())
            },
                    correctedLinePosSpan));
        }
Example #2
0
 QuickInfoState(QuickInfoService quickInfoService, Document document, SourceText sourceText, ITextSnapshot snapshot)
 {
     QuickInfoService = quickInfoService;
     Document         = document;
     SourceText       = sourceText;
     Snapshot         = snapshot;
 }
Example #3
0
        public async Task HandleAsync(RequestHoverText command, KernelInvocationContext context)
        {
            if (!command.DocumentIdentifier.TryDecodeDocumentFromDataUri(out var documentContents))
            {
                return;
            }

            var(document, offset) = GetDocumentWithOffsetFromCode(documentContents);
            var text = await document.GetTextAsync();

            var cursorPosition   = text.Lines.GetPosition(new LinePosition(command.Position.Line, command.Position.Character));
            var absolutePosition = cursorPosition + offset;
            var service          = QuickInfoService.GetService(document);
            var info             = await service.GetQuickInfoAsync(document, absolutePosition);

            if (info == null)
            {
                return;
            }

            var scriptSpanStart      = text.Lines.GetLinePosition(offset);
            var linePosSpan          = text.Lines.GetLinePositionSpan(info.Span);
            var correctedLinePosSpan = linePosSpan.SubtractLineOffset(scriptSpanStart);

            context.PublishHoverMarkdownResponse(command, info.ToMarkdownString(), correctedLinePosSpan);
        }
Example #4
0
        public void AugmentQuickInfoSession(IQuickInfoSession session, IList <object> quickInfoContent, out ITrackingSpan applicableToSpan)
        {
            if (_state == QuickInfoState.Disable)
            {
                applicableToSpan = default;
                return;
            }

            if (_state == QuickInfoState.Override)
            {
                quickInfoContent.Clear();
            }

            var triggerPoint = session.GetTriggerPoint(_textBuffer.CurrentSnapshot);

            if (!triggerPoint.HasValue)
            {
                applicableToSpan = default;
                return;
            }

            var quickInfo = QuickInfoService.GetQuickInfoAsync(_textBuffer, triggerPoint.Value, CancellationToken.None).Result;

            if (quickInfo is null || quickInfo.Descriptions.Length == 0)
            {
                applicableToSpan = default;
                return;
            }

            var trackingSpan = triggerPoint.Value.Snapshot.CreateTrackingSpan(quickInfo.GetSpan(), SpanTrackingMode.EdgeInclusive);

            var items = new List <UIElement>();

            foreach (var item in quickInfo.Descriptions)
            {
                var textBlock = ToTextBlock(item);
                if (item.Kind == SymbolDescriptionKind.Main)
                {
                    var panel = new WrapPanel();

                    var uiElements = TryGetImageElement(quickInfo.Image, out var image)
                        ? image.Enumerate().Concat(textBlock.Enumerate())
                        : textBlock.Enumerate();
                    Populate(panel, uiElements);

                    items.Insert(0, panel);
                }
                else
                {
                    items.Add(textBlock);
                }
            }

            var container = new StackPanel();

            Populate(container, items);
            quickInfoContent.Add(container);
            applicableToSpan = trackingSpan;
        }
            public async Task <IntellisenseQuickInfoItem> GetQuickInfoItemAsync(IAsyncQuickInfoSession session, CancellationToken cancellationToken)
            {
                var triggerPoint = session.GetTriggerPoint(_subjectBuffer.CurrentSnapshot);

                if (!triggerPoint.HasValue)
                {
                    return(null);
                }

                var snapshot = triggerPoint.Value.Snapshot;
                var document = snapshot.GetOpenDocumentInCurrentContextWithChanges();

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

                var service = QuickInfoService.GetService(document);

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

                try
                {
                    using (Logger.LogBlock(FunctionId.Get_QuickInfo_Async, cancellationToken))
                    {
                        cancellationToken.ThrowIfCancellationRequested();

                        var options = _globalOptions.GetSymbolDescriptionOptions(document.Project.Language);
                        var item    = await service.GetQuickInfoAsync(document, triggerPoint.Value, options, cancellationToken).ConfigureAwait(false);

                        if (item != null)
                        {
                            var textVersion           = snapshot.Version;
                            var trackingSpan          = textVersion.CreateTrackingSpan(item.Span.ToSpan(), SpanTrackingMode.EdgeInclusive);
                            var classificationOptions = _globalOptions.GetClassificationOptions(document.Project.Language);

                            return(await IntellisenseQuickInfoBuilder.BuildItemAsync(
                                       trackingSpan, item, document, classificationOptions,
                                       _threadingContext, _operationExecutor,
                                       _asyncListener, _streamingPresenter, cancellationToken).ConfigureAwait(false));
                        }

                        return(null);
                    }
                }
                catch (Exception e) when(FatalError.ReportAndPropagateUnlessCanceled(e, cancellationToken, ErrorSeverity.Critical))
                {
                    throw ExceptionUtilities.Unreachable;
                }
            }
            public async Task <IntellisenseQuickInfoItem> GetQuickInfoItemAsync(IAsyncQuickInfoSession session, CancellationToken cancellationToken)
            {
                var triggerPoint = session.GetTriggerPoint(_subjectBuffer.CurrentSnapshot);

                if (!triggerPoint.HasValue)
                {
                    return(null);
                }

                var snapshot = triggerPoint.Value.Snapshot;
                var document = snapshot.GetOpenDocumentInCurrentContextWithChanges();

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

                var service = QuickInfoService.GetService(document);

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

                try
                {
                    using (Internal.Log.Logger.LogBlock(FunctionId.Get_QuickInfo_Async, cancellationToken))
                    {
                        cancellationToken.ThrowIfCancellationRequested();

                        var item = await service.GetQuickInfoAsync(document, triggerPoint.Value, cancellationToken).ConfigureAwait(false);

                        if (item != null)
                        {
                            var textVersion  = snapshot.Version;
                            var trackingSpan = textVersion.CreateTrackingSpan(item.Span.ToSpan(), SpanTrackingMode.EdgeInclusive);
                            return(await IntellisenseQuickInfoBuilder.BuildItemAsync(trackingSpan, item, snapshot, document, _streamingPresenter, cancellationToken).ConfigureAwait(false));
                        }

                        return(null);
                    }
                }
                catch (Exception e) when(FatalError.ReportUnlessCanceled(e))
                {
                    throw ExceptionUtilities.Unreachable;
                }
            }
Example #7
0
        public async Task <MsQuickInfoItem> GetQuickInfoItemAsync(IAsyncQuickInfoSession session, CancellationToken cancellationToken)
        {
            // NOTE: returned null would be ignored by VS
            if (_state == QuickInfoState.Disable)
            {
                return(null);
            }

            var triggerPoint = session.GetTriggerPoint(_textBuffer.CurrentSnapshot);

            if (!triggerPoint.HasValue)
            {
                return(null);
            }

            var quickInfo = await QuickInfoService.GetQuickInfoAsync(_textBuffer, triggerPoint.Value, cancellationToken);

            if (quickInfo is null || quickInfo.Descriptions.Length == 0)
            {
                return(null);
            }

            var trackingSpan = triggerPoint.Value.Snapshot.CreateTrackingSpan(quickInfo.GetSpan(), SpanTrackingMode.EdgeInclusive);

            var items = new List <object>();

            foreach (var item in quickInfo.Descriptions)
            {
                if (item.Kind == SymbolDescriptionKind.Main)
                {
                    var containerItem = TryGetImageElement(quickInfo.Image, out var image)
                        ? new ContainerElement(ContainerElementStyle.Wrapped, image, ToClassifiedTextElement(item))
                        : new ContainerElement(ContainerElementStyle.Wrapped, ToClassifiedTextElement(item));

                    items.Insert(0, containerItem);
                }
                else
                {
                    items.Add(ToClassifiedTextElement(item));
                }
            }

            // NOTE: wrap element into a specified type to determine that the content element was created by CoCo or not
            return(_state == QuickInfoState.Override
                ? new MsQuickInfoItem(trackingSpan, new QuickInfoWrapper(new ContainerElement(ContainerElementStyle.Stacked, items)))
                : new MsQuickInfoItem(trackingSpan, new ContainerElement(ContainerElementStyle.Stacked, items)));
        }
Example #8
0
        public RoslynSession(
            SourceText sourceText,
            ProjectInfo projectInfo,
            MefHostServices hostServices,
            ImmutableArray <DiagnosticAnalyzer> analyzers,
            ImmutableDictionary <string, ImmutableArray <CodeFixProvider> > codeFixProviders,
            ImmutableArray <ISignatureHelpProviderWrapper> signatureHelpProviders
            )
        {
            _workspace         = new CustomWorkspace(hostServices);
            _sourceText        = sourceText;
            _document          = CreateProjectAndOpenNewDocument(_workspace, projectInfo, sourceText);
            QuickInfoService   = QuickInfoService.GetService(_document);
            _completionService = CompletionService.GetService(_document);

            Analyzers = analyzers;
            SignatureHelpProviders = signatureHelpProviders;
            CodeFixProviders       = codeFixProviders;
        }
Example #9
0
        public async Task <string> GetQuickInfo(Document document, CompletionItem completion)
        {
            var    infoService   = QuickInfoService.GetService(document);
            string text          = (await document.GetTextAsync()).ToString();
            string completedText = text.Substring(0, completion.Span.Start)
                                   + completion.DisplayText
                                   + (completion.Span.End == text.Length ? "" : text.Substring(completion.Span.End));
            var newDoc = document.WithText(SourceText.From(completedText));
            var info   = await infoService.GetQuickInfoAsync(newDoc, completedText.Length - 1);

            if (info == null || info.Sections.Length == 0)
            {
                return(null);
            }
            return(string.Join(
                       Environment.NewLine,
                       info.Sections.Select(section => section.Text)
                       ));
        }
Example #10
0
        public async Task HandleAsync(RequestHoverText command, KernelInvocationContext context)
        {
            var document = _workspace.ForkDocument(command.Code);
            var text     = await document.GetTextAsync();

            var cursorPosition = text.Lines.GetPosition(command.Position);
            var service        = QuickInfoService.GetService(document);
            var info           = await service.GetQuickInfoAsync(document, cursorPosition);

            if (info == null)
            {
                return;
            }

            var scriptSpanStart      = text.Lines.GetLinePosition(0);
            var linePosSpan          = text.Lines.GetLinePositionSpan(info.Span);
            var correctedLinePosSpan = linePosSpan.SubtractLineOffset(scriptSpanStart);

            context.PublishHoverTextMarkdownResponse(command, info.ToMarkdownString(), correctedLinePosSpan);
        }
Example #11
0
        public static QuickInfoState?Create(ITextSnapshot snapshot)
        {
            if (snapshot == null)
            {
                throw new ArgumentNullException(nameof(snapshot));
            }
            var sourceText = snapshot.AsText();
            var document   = sourceText.GetOpenDocumentInCurrentContextWithChanges();

            if (document == null)
            {
                return(null);
            }
            var quickInfoService = QuickInfoService.GetService(document);

            if (quickInfoService == null)
            {
                return(null);
            }
            return(new QuickInfoState(quickInfoService, document, sourceText, snapshot));
        }
Example #12
0
        public async Task <QuickInfoResponse> Handle(QuickInfoRequest request)
        {
            var document = _workspace.GetDocument(request.FileName);
            var response = new QuickInfoResponse();

            if (document is null)
            {
                return(response);
            }

            var quickInfoService = QuickInfoService.GetService(document);

            if (quickInfoService is null)
            {
                _logger?.LogWarning($"QuickInfo service was null for {document.FilePath}");
                return(response);
            }

            var sourceText = await document.GetTextAsync();

            var position = sourceText.Lines.GetPosition(new LinePosition(request.Line, request.Column));

            var quickInfo = await quickInfoService.GetQuickInfoAsync(document, position);

            if (quickInfo is null)
            {
                _logger?.LogTrace($"No QuickInfo found for {document.FilePath}:{request.Line},{request.Column}");
                return(response);
            }

            var finalTextBuilder   = new StringBuilder();
            var sectionTextBuilder = new StringBuilder();

            var description = quickInfo.Sections.FirstOrDefault(s => s.Kind == QuickInfoSectionKinds.Description);

            if (description is object)
            {
                appendSectionAsCsharp(description, finalTextBuilder, _formattingOptions, includeSpaceAtStart: false);
            }

            var summary = quickInfo.Sections.FirstOrDefault(s => s.Kind == QuickInfoSectionKinds.DocumentationComments);

            if (summary is object)
            {
                buildSectionAsMarkdown(summary, sectionTextBuilder, _formattingOptions, out _);
                appendBuiltSection(finalTextBuilder, sectionTextBuilder, _formattingOptions);
            }

            foreach (var section in quickInfo.Sections)
            {
                switch (section.Kind)
                {
                case QuickInfoSectionKinds.Description:
                case QuickInfoSectionKinds.DocumentationComments:
                    continue;

                case QuickInfoSectionKinds.TypeParameters:
                    appendSectionAsCsharp(section, finalTextBuilder, _formattingOptions);
                    break;

                case QuickInfoSectionKinds.AnonymousTypes:
                    // The first line is "Anonymous Types:"
                    buildSectionAsMarkdown(section, sectionTextBuilder, _formattingOptions, out int lastIndex, untilLineBreak: true);
                    appendBuiltSection(finalTextBuilder, sectionTextBuilder, _formattingOptions);

                    // Then we want all anonymous types to be C# highlighted
                    appendSectionAsCsharp(section, finalTextBuilder, _formattingOptions, lastIndex + 1);
                    break;

                case NullabilityAnalysis:
                    // Italicize the nullable analysis for emphasis.
                    buildSectionAsMarkdown(section, sectionTextBuilder, _formattingOptions, out _);
                    appendBuiltSection(finalTextBuilder, sectionTextBuilder, _formattingOptions, italicize: true);
                    break;

                default:
                    buildSectionAsMarkdown(section, sectionTextBuilder, _formattingOptions, out _);
                    appendBuiltSection(finalTextBuilder, sectionTextBuilder, _formattingOptions);
                    break;
                }
            }

            response.Markdown = finalTextBuilder.ToString().Trim();

            return(response);
Example #13
0
    public async Task <Section> GetTextAt(int pos16)
    {
        //using var p1 = perf.local();
        if (!CodeInfo.GetContextAndDocument(out var cd, pos16))
        {
            return(null);
        }

        //don't include <remarks>. Sometimes it takes too much space. Badly formatted if eg contains markdown.
        var opt1 = QuickInfoOptions.Default with {
            ShowRemarksInQuickInfo = false, IncludeNavigationHintsInQuickInfo = false
        };
        var opt2 = new Microsoft.CodeAnalysis.LanguageServices.SymbolDescriptionOptions(opt1, Microsoft.CodeAnalysis.Classification.ClassificationOptions.Default);

        var service = QuickInfoService.GetService(cd.document);
        var r       = await Task.Run(async() => await service.GetQuickInfoAsync(cd.document, pos16, opt2, default));

        //p1.Next();
        if (r == null)
        {
            return(null);
        }
        //this oveload is internal, but:
        //	- The public overload does not have an options parameter. Used to set options for workspace, but it stopped working.
        //	- Roslyn in Debug config asserts "don't use this function".

        //print.it(r.Span, r.RelatedSpans);
        //print.it(r.Tags);

        var a = r.Sections;

        if (a.Length == 0)
        {
            return(null);                       //when cursor is on }. //SHOULDDO: display block start code, like in VS.
        }
        //don't show some useless quickinfos, eg for literals
        if (r.Tags.Length == 2 && a.Length == 2 && a[1].Kind == QuickInfoSectionKinds.DocumentationComments)
        {
            //print.it(r.Tags[0], a[1].Kind, a[1].Text);
            var s = a[1].Text;
            if (s.Starts("Represents "))
            {
                switch (r.Tags[0])
                {
                case "Class":
                    if (s == "Represents text as a sequence of UTF-16 code units.")
                    {
                        return(null);
                    }
                    break;

                case "Structure":
                    if (s.RxIsMatch(@"^Represents a (\d+-bit u?n?signed integer|[\w+-]+ floating-point number)\.$"))
                    {
                        return(null);
                    }
                    break;
                }
            }
        }

        var x = new CiText();

        //bool hasDocComm = false;
        //QuickInfoSection descr = null;
        for (int i = 0; i < a.Length; i++)
        {
            var se = a[i];
            //print.it(se.Kind, se.Text);

            //if (se.Kind == QuickInfoSectionKinds.RemarksDocumentationComments) continue;

            x.StartParagraph();

            //if (se.Kind == QuickInfoSectionKinds.RemarksDocumentationComments) {
            //	x.Append("More info in Remarks (click and press F1)."); //no, because the DB does not contain Au and .NET remarks; would show this info only for others (local, XML files).
            //} else {
            if (i == 0)               //image
            {
                CiUtil.TagsToKindAndAccess(r.Tags, out var kind, out var access);
                if (kind != CiItemKind.None)
                {
                    if (access != default)
                    {
                        x.Image(access);
                    }
                    x.Image(kind);
                    x.Append(" ");
                }
            }

            var tp = se.TaggedParts;
            if (tp[0].Tag == TextTags.LineBreak)               //remove/replace some line breaks in returns and exceptions
            {
                int lessNewlines = se.Kind switch { QuickInfoSectionKinds.ReturnsDocumentationComments => 1, QuickInfoSectionKinds.Exception => 2, _ => 0 };
                var k            = new List <TaggedText>(tp.Length - 1);
                for (int j = 1; j < tp.Length; j++)
                {
                    var v = tp[j];
                    if (lessNewlines > 0 && j > 1)
                    {
                        if (v.Tag == TextTags.LineBreak)
                        {
                            if (j == 2)
                            {
                                continue;                                     //remove line break after "Returns:" etc
                            }
                            if (lessNewlines == 2)                            //in list of exceptions replace "\n  " with ", "
                            {
                                if (++j == tp.Length || tp[j].Tag != TextTags.Space)
                                {
                                    j--; continue;
                                }
                                v = new(TextTags.Text, ", ");
                            }
                        }
                    }
                    k.Add(v);
                }
                x.AppendTaggedParts(k, false);
            }
            else
            {
                x.AppendTaggedParts(tp);
            }
            //}

            x.EndParagraph();
        }

        return(x.Result);
    }
}
        public async Task <QuickInfoResponse> Handle(QuickInfoRequest request, Document document)
        {
            var response = new QuickInfoResponse();

            if (document is null)
            {
                return(response);
            }

            var quickInfoService = QuickInfoService.GetService(document);

            if (quickInfoService is null)
            {
                _logger?.LogWarning($"QuickInfo service was null for {document.FilePath}");
                return(response);
            }

            var sourceText = await document.GetTextAsync();

            var position = sourceText.GetTextPosition(request);

            var quickInfo = await quickInfoService.GetQuickInfoAsync(document, position);

            if (quickInfo is null)
            {
                _logger?.LogTrace($"No QuickInfo found for {document.FilePath}:{request.Line},{request.Column}");
                return(response);
            }

            var finalTextBuilder = new StringBuilder();

            bool lastSectionHadLineBreak = true;
            var  description             = quickInfo.Sections.FirstOrDefault(s => s.Kind == QuickInfoSectionKinds.Description);

            if (description is object)
            {
                appendSection(description, MarkdownFormat.AllTextAsCSharp);
            }

            var summary = quickInfo.Sections.FirstOrDefault(s => s.Kind == QuickInfoSectionKinds.DocumentationComments);

            if (summary is object)
            {
                appendSection(summary, MarkdownFormat.Default);
            }

            foreach (var section in quickInfo.Sections)
            {
                switch (section.Kind)
                {
                case QuickInfoSectionKinds.Description:
                case QuickInfoSectionKinds.DocumentationComments:
                    continue;

                case QuickInfoSectionKinds.TypeParameters:
                    appendSection(section, MarkdownFormat.AllTextAsCSharp);
                    break;

                case QuickInfoSectionKinds.AnonymousTypes:
                    // The first line is "Anonymous Types:"
                    // Then we want all anonymous types to be C# highlighted
                    appendSection(section, MarkdownFormat.FirstLineDefaultRestCSharp);
                    break;

                case NullabilityAnalysis:
                    // Italicize the nullable analysis for emphasis.
                    appendSection(section, MarkdownFormat.Italicize);
                    break;

                default:
                    appendSection(section, MarkdownFormat.Default);
                    break;
                }
            }

            response.Markdown = finalTextBuilder.ToString().Trim();

            return(response);

            void appendSection(QuickInfoSection section, MarkdownFormat format)
            {
                if (!lastSectionHadLineBreak && !section.TaggedParts.StartsWithNewline())
                {
                    finalTextBuilder.Append(_formattingOptions.NewLine);
                    finalTextBuilder.Append(_formattingOptions.NewLine);
                }
                MarkdownHelpers.TaggedTextToMarkdown(section.TaggedParts, finalTextBuilder, _formattingOptions, format, out lastSectionHadLineBreak);
            }
        }