public int GetDataTipText(TextSpan[] pSpan, out string pbstrText) { if (!_wpfTextView.TextBuffer.ContentType.IsOfType(PythonCoreConstants.ContentType)) { pbstrText = null; return(VSConstants.E_NOTIMPL); } if (pSpan.Length != 1) { throw new ArgumentException("Array parameter should contain exactly one TextSpan", "pSpan"); } // Adjust the span to expression boundaries. var snapshot = _wpfTextView.TextSnapshot; var start = LineAndColumnNumberToSnapshotPoint(snapshot, pSpan[0].iStartLine, pSpan[0].iStartIndex); var end = LineAndColumnNumberToSnapshotPoint(snapshot, pSpan[0].iEndLine, pSpan[0].iEndIndex); // If this is a zero-length span (which it usually is, unless there's selection), adjust it // to cover one char to the right, since an empty span at the beginning of the expression does // not count as belonging to that expression; if (start == end && start.Position != snapshot.Length) { end += 1; } var snapshotSpan = new SnapshotSpan(start, end); var trackingSpan = snapshot.CreateTrackingSpan(snapshotSpan.Span, SpanTrackingMode.EdgeExclusive); var rep = new ReverseExpressionParser(snapshot, _wpfTextView.TextBuffer, trackingSpan); var exprSpan = rep.GetExpressionRange(forCompletion: false); string expr = null; if (exprSpan != null) { SnapshotPointToLineAndColumnNumber(exprSpan.Value.Start, out pSpan[0].iStartLine, out pSpan[0].iStartIndex); SnapshotPointToLineAndColumnNumber(exprSpan.Value.End, out pSpan[0].iEndLine, out pSpan[0].iEndIndex); expr = VsProjectAnalyzer.ExpressionForDataTipAsync( _serviceProvider, _wpfTextView, exprSpan.Value, TimeSpan.FromSeconds(1.0) ).WaitAndUnwrapExceptions(Dispatcher.CurrentDispatcher); } else { // If it's not an expression, suppress the tip. pbstrText = null; return(VSConstants.E_FAIL); } return(_debugger.GetDataTipValue(_vsTextLines, pSpan, expr, out pbstrText)); }