Example #1
0
        public async Task <QuickInfoItem> GetQuickInfoItemAsync(IAsyncQuickInfoSession session, CancellationToken cancellationToken)
        {
            if (DebuggingService.CurrentFrame == null)
            {
                return(null);
            }

            if (window != null)
            {
                await Runtime.RunInMainThread(DestroyWindow);
            }

            var view          = session.TextView;
            var textViewLines = view.TextViewLines;
            var snapshot      = textViewLines.FormattedSpan.Snapshot;
            var triggerPoint  = session.GetTriggerPoint(textBuffer);

            if (snapshot.TextBuffer != triggerPoint.TextBuffer)
            {
                return(null);
            }
            var point = triggerPoint.GetPoint(snapshot);

            foreach (var debugInfoProvider in provider.debugInfoProviders)
            {
                DataTipInfo debugInfo = default;

                if (!view.Selection.IsEmpty)
                {
                    foreach (var span in view.Selection.SelectedSpans)
                    {
                        if (span.Contains(point))
                        {
                            //debugInfo = new DataTipInfo (snapshot.CreateTrackingSpan (span, SpanTrackingMode.EdgeInclusive), snapshot.GetText (span));
                            debugInfo = await debugInfoProvider.Value.GetDebugInfoAsync(span, cancellationToken);

                            break;
                        }
                    }
                }
                else
                {
                    debugInfo = await debugInfoProvider.Value.GetDebugInfoAsync(point, cancellationToken);
                }

                if (!debugInfo.IsDefault)
                {
                    await EvaluateAndShowTooltipAsync(session, view, point, debugInfo, cancellationToken);

                    return(null);
                }
            }

            return(null);
        }
        private async Task EvaluateAndShowTooltipAsync(IAsyncQuickInfoSession session, ITextView view, SnapshotPoint point, DataTipInfo debugInfo, CancellationToken cancellationToken)
        {
            var options = DebuggingService.DebuggerSession.EvaluationOptions.Clone();

            options.AllowMethodEvaluation = true;
            options.AllowTargetInvoke     = true;

            var val = DebuggingService.CurrentFrame.GetExpressionValue(debugInfo.Text, options);

            if (val.IsEvaluating)
            {
                await WaitOneAsync(val.WaitHandle, cancellationToken);
            }

            if (cancellationToken.IsCancellationRequested)
            {
                return;
            }

            if (val == null || val.IsUnknown || val.IsNotSupported)
            {
                return;
            }

            if (!view.Properties.TryGetProperty(typeof(Gtk.Widget), out Gtk.Widget gtkParent))
            {
                return;
            }

            provider.textDocumentFactoryService.TryGetTextDocument(view.TextDataModel.DocumentBuffer, out var textDocument);

            // This is a bit hacky, since AsyncQuickInfo is designed to display multiple elements if multiple sources
            // return value, we don't want that for debugger value hovering, hence we dismiss AsyncQuickInfo
            // and do our own thing, notice VS does same thing
            await session.DismissAsync();

            await provider.joinableTaskContext.Factory.SwitchToMainThreadAsync();

            this.lastView = view;
            val.Name      = debugInfo.Text;
            window        = new DebugValueWindow((Gtk.Window)gtkParent.Toplevel, textDocument?.FilePath, textBuffer.CurrentSnapshot.GetLineNumberFromPosition(debugInfo.Span.GetStartPoint(textBuffer.CurrentSnapshot)), DebuggingService.CurrentFrame, val, null);
            Ide.IdeApp.CommandService.RegisterTopWindow(window);
            var bounds = view.TextViewLines.GetCharacterBounds(point);

            view.LayoutChanged += LayoutChanged;
#if CLOSE_ON_FOCUS_LOST
            view.LostAggregateFocus += View_LostAggregateFocus;
#endif
            RegisterForHiddenAsync(view).Ignore();
            window.LeaveNotifyEvent += LeaveNotifyEvent;
#if MAC
            var cocoaView = ((ICocoaTextView)view);
            var cgPoint   = cocoaView.VisualElement.ConvertPointToView(new CoreGraphics.CGPoint(bounds.Left - view.ViewportLeft, bounds.Top - view.ViewportTop), cocoaView.VisualElement.Superview);
            cgPoint.Y = cocoaView.VisualElement.Superview.Frame.Height - cgPoint.Y;
            window.ShowPopup(gtkParent, new Gdk.Rectangle((int)cgPoint.X, (int)cgPoint.Y, (int)bounds.Width, (int)bounds.Height), Components.PopupPosition.TopLeft);
#else
            throw new NotImplementedException();
#endif
        }
Example #3
0
        private async Task EvaluateAndShowTooltipAsync(IAsyncQuickInfoSession session, ITextView view, SnapshotPoint point, DataTipInfo debugInfo, CancellationToken cancellationToken)
        {
            var options = DebuggingService.DebuggerSession.EvaluationOptions.Clone();

            options.AllowMethodEvaluation = true;
            options.AllowTargetInvoke     = true;

            var val = DebuggingService.CurrentFrame.GetExpressionValue(debugInfo.Text, options);

            if (val.IsEvaluating)
            {
                await WaitOneAsync(val.WaitHandle, cancellationToken);
            }

            if (cancellationToken.IsCancellationRequested)
            {
                return;
            }

            if (val == null || val.IsUnknown || val.IsNotSupported)
            {
                return;
            }

            if (!view.Properties.TryGetProperty(typeof(Widget), out Widget gtkParent))
            {
                return;
            }

            provider.textDocumentFactoryService.TryGetTextDocument(view.TextDataModel.DocumentBuffer, out var textDocument);

            // This is a bit hacky, since AsyncQuickInfo is designed to display multiple elements if multiple sources
            // return value, we don't want that for debugger value hovering, hence we dismiss AsyncQuickInfo
            // and do our own thing, notice VS does same thing
            await session.DismissAsync();

            await provider.joinableTaskContext.Factory.SwitchToMainThreadAsync();

            lastView = view;

            val.Name = debugInfo.Text;

#if MAC
            var location = new PinnedWatchLocation(textDocument?.FilePath);
            var snapshot = view.TextDataModel.DocumentBuffer.CurrentSnapshot;
            int line, column;

            var start = debugInfo.Span.GetStartPoint(snapshot);
            snapshot.GetLineAndColumn(start, out line, out column);
            location.Column = column;
            location.Line   = line;

            var end = debugInfo.Span.GetEndPoint(snapshot);
            snapshot.GetLineAndColumn(end, out line, out column);
            location.EndColumn = column;
            location.EndLine   = line;

            window = new MacDebuggerTooltipWindow(location, DebuggingService.CurrentFrame, val, watch: null);

            view.LayoutChanged += LayoutChanged;
#if CLOSE_ON_FOCUS_LOST
            view.LostAggregateFocus += View_LostAggregateFocus;
#endif
            RegisterForHiddenAsync(view).Ignore();

            var cocoaView = (ICocoaTextView)view;
            var bounds    = view.TextViewLines.GetCharacterBounds(point);
            var rect      = new CoreGraphics.CGRect(bounds.Left - view.ViewportLeft, bounds.Top - view.ViewportTop, bounds.Width, bounds.Height);

            window.Show(rect, cocoaView.VisualElement, AppKit.NSRectEdge.MaxXEdge);
#else
            throw new NotImplementedException();
#endif
        }