/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/VisualStudio/Core/Def/DebuggerIntelliSense/DebuggerTextView.cs
446 строк
12 KB
Cyrus Najmabadi
Merge remote-tracking branch 'upstream/main' into actuallyUseAutoProps
01 апр 2025, 20:18
01 апр 2025, 20:18
95bbf74
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #nullable disable using System; using System.Windows; using System.Windows.Media; using Microsoft.CodeAnalysis.Editor; using Microsoft.VisualStudio.Text; using Microsoft.VisualStudio.Text.Editor; using Microsoft.VisualStudio.Text.Formatting; using Microsoft.VisualStudio.Text.Projection; using Microsoft.VisualStudio.TextManager.Interop; using Microsoft.VisualStudio.Utilities; namespace Microsoft.VisualStudio.LanguageServices.Implementation.DebuggerIntelliSense; internal sealed partial class DebuggerTextView : IWpfTextView, IDebuggerTextView2, ITextView2 { /// <summary> /// The actual debugger view of the watch or immediate window that we're wrapping /// </summary> private readonly IWpfTextView _innerTextView; private readonly IVsTextLines _debuggerTextLinesOpt; // This name "CompletionRoot" is specified on the Editor side. // Roslyn must match the name. // The const should be removed with resolution of https://github.com/dotnet/roslyn/issues/31189 public const string CompletionRoot = nameof(CompletionRoot); public DebuggerTextView( IWpfTextView innerTextView, IBufferGraph bufferGraph, IVsTextLines debuggerTextLinesOpt, bool isImmediateWindow) { _innerTextView = innerTextView; _debuggerTextLinesOpt = debuggerTextLinesOpt; BufferGraph = bufferGraph; IsImmediateWindow = isImmediateWindow; // The editor requires the current top buffer. // TODO it seems to be a hack. It should be removed. // Here is an issue to track: https://github.com/dotnet/roslyn/issues/31189 // Starting debugging for the second time, we already have the property set. _innerTextView.Properties[CompletionRoot] = bufferGraph.TopBuffer; } /// <summary> /// We basically replace the innerTextView's BufferGraph with our own custom projection graph /// that projects the immediate window contents into a context buffer: /// /// (1) /// (2) (5) /// (3) (6) /// (4) /// (1) Top level projection buffer - the subject buffer used by intellisense /// (2/3) Currently a double projection buffer combo that elides away the ? in the immediate window, and may add some /// boilerplate code to force an expression context. /// (4) innerTextView.TextBuffer, what the user actually sees in the watch/immediate windows /// (5) A read-only projection of (6) /// (6) The context buffer which is typically a source file /// /// </summary> public IBufferGraph BufferGraph { get; } public bool IsImmediateWindow { get; } public uint StartBufferUpdate() { // null in unit tests if (_debuggerTextLinesOpt == null) { return 0; } _debuggerTextLinesOpt.GetStateFlags(out var bufferFlags); _debuggerTextLinesOpt.SetStateFlags((uint)((BUFFERSTATEFLAGS)bufferFlags & ~BUFFERSTATEFLAGS.BSF_USER_READONLY)); return bufferFlags; } public void EndBufferUpdate(uint cookie) { // null in unit tests _debuggerTextLinesOpt?.SetStateFlags(cookie); } public ITextCaret Caret { get { return _innerTextView.Caret; } } public bool HasAggregateFocus { get { return _innerTextView.HasAggregateFocus; } } public bool InLayout { get { return _innerTextView.InLayout; } } public bool IsClosed { get { return _innerTextView.IsClosed; } } public bool IsMouseOverViewOrAdornments { get { return _innerTextView.IsMouseOverViewOrAdornments; } } public double LineHeight { get { return _innerTextView.LineHeight; } } public double MaxTextRightCoordinate { get { return _innerTextView.MaxTextRightCoordinate; } } public IEditorOptions Options { get { return _innerTextView.Options; } } public PropertyCollection Properties { get { return _innerTextView.Properties; } } public ITrackingSpan ProvisionalTextHighlight { get { return _innerTextView.ProvisionalTextHighlight; } set { _innerTextView.ProvisionalTextHighlight = value; } } public ITextViewRoleSet Roles { get { return _innerTextView.Roles; } } public ITextSelection Selection { get { return _innerTextView.Selection; } } public ITextViewLineCollection TextViewLines { get { return _innerTextView.TextViewLines; } } public ITextViewModel TextViewModel { get { return _innerTextView.TextViewModel; } } public IViewScroller ViewScroller { get { return _innerTextView.ViewScroller; } } public double ViewportBottom { get { return _innerTextView.ViewportBottom; } } public double ViewportHeight { get { return _innerTextView.ViewportHeight; } } public double ViewportLeft { get { return _innerTextView.ViewportLeft; } set { _innerTextView.ViewportLeft = value; } } public double ViewportRight { get { return _innerTextView.ViewportRight; } } public double ViewportTop { get { return _innerTextView.ViewportTop; } } public double ViewportWidth { get { return _innerTextView.ViewportWidth; } } public ITextSnapshot VisualSnapshot { get { return _innerTextView.VisualSnapshot; } } public ITextDataModel TextDataModel { get { return _innerTextView.TextDataModel; } } public ITextBuffer TextBuffer { get { return _innerTextView.TextBuffer; } } public ITextSnapshot TextSnapshot { get { return _innerTextView.TextSnapshot; } } public FrameworkElement VisualElement { get { return _innerTextView.VisualElement; } } public Brush Background { get { return _innerTextView.Background; } set { _innerTextView.Background = value; } } IWpfTextViewLineCollection IWpfTextView.TextViewLines { get { return _innerTextView.TextViewLines; } } public IFormattedLineSource FormattedLineSource { get { return _innerTextView.FormattedLineSource; } } public ILineTransformSource LineTransformSource { get { return _innerTextView.LineTransformSource; } } public double ZoomLevel { get { return _innerTextView.ZoomLevel; } set { _innerTextView.ZoomLevel = value; } } public bool InOuterLayout => throw new NotImplementedException(); public IMultiSelectionBroker MultiSelectionBroker { get { field ??= _innerTextView.GetMultiSelectionBroker(); return field; } } public void Close() => throw new NotSupportedException(); public void DisplayTextLineContainingBufferPosition(SnapshotPoint bufferPosition, double verticalDistance, ViewRelativePosition relativeTo, double? viewportWidthOverride, double? viewportHeightOverride) => throw new NotSupportedException(); public void DisplayTextLineContainingBufferPosition(SnapshotPoint bufferPosition, double verticalDistance, ViewRelativePosition relativeTo) => throw new NotSupportedException(); public SnapshotSpan GetTextElementSpan(SnapshotPoint point) => throw new NotSupportedException(); public ITextViewLine GetTextViewLineContainingBufferPosition(SnapshotPoint bufferPosition) => _innerTextView.GetTextViewLineContainingBufferPosition(bufferPosition); public void QueueSpaceReservationStackRefresh() => throw new NotSupportedException(); public IAdornmentLayer GetAdornmentLayer(string name) => _innerTextView.GetAdornmentLayer(name); public ISpaceReservationManager GetSpaceReservationManager(string name) => _innerTextView.GetSpaceReservationManager(name); IWpfTextViewLine IWpfTextView.GetTextViewLineContainingBufferPosition(SnapshotPoint bufferPosition) => _innerTextView.GetTextViewLineContainingBufferPosition(bufferPosition); public void Cleanup() { // The innerTextView of the immediate window never closes, but we want // our completion subscribers to unsubscribe from events when this // DebuggerTextView is no longer in use. if (this.IsImmediateWindow) { this.ClosedInternal?.Invoke(this, EventArgs.Empty); } _innerTextView.Properties.RemoveProperty(CompletionRoot); } public void QueuePostLayoutAction(Action action) => _innerTextView.QueuePostLayoutAction(action); public bool TryGetTextViewLines(out ITextViewLineCollection textViewLines) => _innerTextView.TryGetTextViewLines(out textViewLines); public bool TryGetTextViewLineContainingBufferPosition(SnapshotPoint bufferPosition, out ITextViewLine textViewLine) => _innerTextView.TryGetTextViewLineContainingBufferPosition(bufferPosition, out textViewLine); private event EventHandler ClosedInternal; #pragma warning disable 67 public event EventHandler MaxTextRightCoordinateChanged; #pragma warning restore 67 public event EventHandler Closed { add { if (this.IsImmediateWindow) { this.ClosedInternal += value; } else { _innerTextView.Closed += value; } } remove { if (this.IsImmediateWindow) { this.ClosedInternal -= value; } else { _innerTextView.Closed -= value; } } } public event EventHandler GotAggregateFocus { add { _innerTextView.GotAggregateFocus += value; } remove { _innerTextView.GotAggregateFocus -= value; } } public event EventHandler<TextViewLayoutChangedEventArgs> LayoutChanged { add { _innerTextView.LayoutChanged += value; } remove { _innerTextView.LayoutChanged -= value; } } public event EventHandler LostAggregateFocus { add { _innerTextView.LostAggregateFocus += value; } remove { _innerTextView.LostAggregateFocus -= value; } } public event EventHandler<MouseHoverEventArgs> MouseHover { add { _innerTextView.MouseHover += value; } remove { _innerTextView.MouseHover -= value; } } public event EventHandler ViewportHeightChanged { add { _innerTextView.ViewportHeightChanged += value; } remove { _innerTextView.ViewportHeightChanged -= value; } } public event EventHandler ViewportLeftChanged { add { _innerTextView.ViewportLeftChanged += value; } remove { _innerTextView.ViewportLeftChanged -= value; } } public event EventHandler ViewportWidthChanged { add { _innerTextView.ViewportWidthChanged += value; } remove { _innerTextView.ViewportWidthChanged -= value; } } public event EventHandler<BackgroundBrushChangedEventArgs> BackgroundBrushChanged { add { _innerTextView.BackgroundBrushChanged += value; } remove { _innerTextView.BackgroundBrushChanged -= value; } } public event EventHandler<ZoomLevelChangedEventArgs> ZoomLevelChanged { add { _innerTextView.ZoomLevelChanged += value; } remove { _innerTextView.ZoomLevelChanged -= value; } } }