diff --git a/src/EditorFeatures/Core/IDebuggerTextView.cs b/src/EditorFeatures/Core/IDebuggerTextView.cs index 3900669411817f277802b020304e63611c7d1035..ccf21ec87a92e24dc186c5b015cedf781be67eea 100644 --- a/src/EditorFeatures/Core/IDebuggerTextView.cs +++ b/src/EditorFeatures/Core/IDebuggerTextView.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using Microsoft.VisualStudio.Language.Intellisense; namespace Microsoft.CodeAnalysis.Editor @@ -9,5 +10,8 @@ internal interface IDebuggerTextView bool IsImmediateWindow { get; } void HACK_StartCompletionSession(IIntellisenseSession editorSessionOpt); + + uint StartBufferUpdate(); + void EndBufferUpdate(uint cookie); } } diff --git a/src/EditorFeatures/Core/Implementation/IntelliSense/Completion/Controller_Commit.cs b/src/EditorFeatures/Core/Implementation/IntelliSense/Completion/Controller_Commit.cs index 2335f8dc8bd36ddfe6466315efd9a649f4f3c82a..ea8dc00abaf6c59de67e08991acb96a75f3e1924 100644 --- a/src/EditorFeatures/Core/Implementation/IntelliSense/Completion/Controller_Commit.cs +++ b/src/EditorFeatures/Core/Implementation/IntelliSense/Completion/Controller_Commit.cs @@ -114,6 +114,16 @@ private CompletionProvider GetCompletionProvider(CompletionItem item) var adjustedNewText = AdjustForVirtualSpace(textChange); var editOptions = GetEditOptions(mappedSpan, adjustedNewText); + // The immediate window is always marked read-only and the language service is + // responsible for asking the buffer to make itself writable. We'll have to do that for + // commit, so we need to drag the IVsTextLines around, too. + // We have to ask the buffer to make itself writable, if it isn't already + uint immediateWindowBufferUpdateCookie = 0; + if (_isImmediateWindow) + { + immediateWindowBufferUpdateCookie = ((IDebuggerTextView)TextView).StartBufferUpdate(); + } + // Now actually make the text change to the document. using (var textEdit = this.SubjectBuffer.CreateEdit(editOptions, reiteratedVersionNumber: null, editTag: null)) { @@ -121,6 +131,11 @@ private CompletionProvider GetCompletionProvider(CompletionItem item) textEdit.ApplyAndLogExceptions(); } + if (_isImmediateWindow) + { + ((IDebuggerTextView)TextView).EndBufferUpdate(immediateWindowBufferUpdateCookie); + } + // If the completion change requested a new position for the caret to go, // then set the caret to go directly to that point. if (completionChange.NewPosition.HasValue) diff --git a/src/VisualStudio/Core/Def/Implementation/DebuggerIntelliSense/AbstractDebuggerIntelliSenseContext.cs b/src/VisualStudio/Core/Def/Implementation/DebuggerIntelliSense/AbstractDebuggerIntelliSenseContext.cs index 1c06b6e7667f4d880102046c0f34abcbc4df7fb1..7aa942b194d5e92e2477a83841f06ef73152977d 100644 --- a/src/VisualStudio/Core/Def/Implementation/DebuggerIntelliSense/AbstractDebuggerIntelliSenseContext.cs +++ b/src/VisualStudio/Core/Def/Implementation/DebuggerIntelliSense/AbstractDebuggerIntelliSenseContext.cs @@ -195,7 +195,7 @@ internal bool TryInitialize() var bufferGraph = _bufferGraphFactoryService.CreateBufferGraph(_projectionBuffer); - _debuggerTextView = new DebuggerTextView(_textView, bufferGraph, this.InImmediateWindow); + _debuggerTextView = new DebuggerTextView(_textView, bufferGraph, _debuggerTextLines, InImmediateWindow); return true; } diff --git a/src/VisualStudio/Core/Def/Implementation/DebuggerIntelliSense/DebuggerTextView.cs b/src/VisualStudio/Core/Def/Implementation/DebuggerIntelliSense/DebuggerTextView.cs index ad298b361745773e488605e5b4fa50971638e453..bcc748128eaba6da57e0b943158d29abdb595d4d 100644 --- a/src/VisualStudio/Core/Def/Implementation/DebuggerIntelliSense/DebuggerTextView.cs +++ b/src/VisualStudio/Core/Def/Implementation/DebuggerIntelliSense/DebuggerTextView.cs @@ -12,6 +12,7 @@ using Microsoft.VisualStudio.Text.Formatting; using Microsoft.VisualStudio.Text.Outlining; using Microsoft.VisualStudio.Text.Projection; +using Microsoft.VisualStudio.TextManager.Interop; using Microsoft.VisualStudio.Utilities; using Roslyn.Utilities; @@ -23,15 +24,18 @@ internal partial class DebuggerTextView : IWpfTextView, IDebuggerTextView /// The actual debugger view of the watch or immediate window that we're wrapping /// private readonly IWpfTextView _innerTextView; + private readonly IVsTextLines _debuggerTextLines; public DebuggerTextView( IWpfTextView innerTextView, IBufferGraph bufferGraph, + IVsTextLines debuggerTextLines, bool isImmediateWindow) { _innerTextView = innerTextView; - this.BufferGraph = bufferGraph; - this.IsImmediateWindow = isImmediateWindow; + _debuggerTextLines = debuggerTextLines; + BufferGraph = bufferGraph; + IsImmediateWindow = isImmediateWindow; } /// @@ -60,6 +64,19 @@ public bool IsImmediateWindow get; } + public uint StartBufferUpdate() + { + _debuggerTextLines.GetStateFlags(out var bufferFlags); + _debuggerTextLines.SetStateFlags((uint)((BUFFERSTATEFLAGS)bufferFlags & ~BUFFERSTATEFLAGS.BSF_USER_READONLY)); + + return bufferFlags; + } + + public void EndBufferUpdate(uint cookie) + { + _debuggerTextLines.SetStateFlags(cookie); + } + public ITextCaret Caret { get { return _innerTextView.Caret; }