diff --git a/src/EditorFeatures/Core/IInlineRenameSession.cs b/src/EditorFeatures/Core/IInlineRenameSession.cs index a7e52195f24dd..961e7dad4c7ef 100644 --- a/src/EditorFeatures/Core/IInlineRenameSession.cs +++ b/src/EditorFeatures/Core/IInlineRenameSession.cs @@ -54,5 +54,5 @@ internal interface IInlineRenameSession /// /// It will only be async when InlineRenameUIOptionsStorage.CommitRenameAsynchronously is set to true. /// - Task CommitAsync(bool previewChanges, IUIThreadOperationContext editorOperationContext = null); + Task CommitAsync(bool previewChanges, IUIThreadOperationContext editorOperationContext); } diff --git a/src/EditorFeatures/Core/InlineRename/CommandHandlers/AbstractRenameCommandHandler.cs b/src/EditorFeatures/Core/InlineRename/CommandHandlers/AbstractRenameCommandHandler.cs index 923c015b056ff..4972997778414 100644 --- a/src/EditorFeatures/Core/InlineRename/CommandHandlers/AbstractRenameCommandHandler.cs +++ b/src/EditorFeatures/Core/InlineRename/CommandHandlers/AbstractRenameCommandHandler.cs @@ -6,22 +6,18 @@ using System.Linq; using Microsoft.CodeAnalysis.Editor.Shared.Extensions; using Microsoft.CodeAnalysis.Editor.Shared.Utilities; -using Microsoft.CodeAnalysis.InlineRename; -using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.TestHooks; using Microsoft.VisualStudio.Commanding; using Microsoft.VisualStudio.Text; using Microsoft.VisualStudio.Text.Editor; using Microsoft.VisualStudio.Text.Editor.Commanding; using Microsoft.VisualStudio.Utilities; -using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Editor.Implementation.InlineRename; internal abstract partial class AbstractRenameCommandHandler( IThreadingContext threadingContext, InlineRenameService renameService, - IGlobalOptionService globalOptionService, IAsynchronousOperationListener listener) { public string DisplayName => EditorFeaturesResources.Rename; @@ -76,7 +72,7 @@ private void HandlePossibleTypingCommand(TArgs args, Action nextHandler, } else if (renameService.ActiveSession.IsInOpenTextBuffer(singleSpan.Start)) { - HandleTypingOutsideEditableSpan(args, operationContext); + CancelRenameSession(); nextHandler(); } else @@ -86,40 +82,9 @@ private void HandlePossibleTypingCommand(TArgs args, Action nextHandler, } } - private void HandleTypingOutsideEditableSpan(EditorCommandArgs args, IUIThreadOperationContext operationContext) - => CommitIfSynchronousOrCancelIfAsynchronous(args, operationContext, placeCaretAtTheEndOfIdentifier: true); - - private void CommitIfActive(EditorCommandArgs args, IUIThreadOperationContext operationContext, bool placeCaretAtTheEndOfIdentifier = true) - { - if (renameService.ActiveSession != null) - { - var selection = args.TextView.Selection.VirtualSelectedSpans.First(); - Commit(operationContext); - if (placeCaretAtTheEndOfIdentifier) - { - var translatedSelection = selection.TranslateTo(args.TextView.TextBuffer.CurrentSnapshot); - args.TextView.Selection.Select(translatedSelection.Start, translatedSelection.End); - args.TextView.Caret.MoveTo(translatedSelection.End); - } - } - } - - /// - /// Commit() will be called if rename commit is sync. Editor command would be executed after the rename operation complete and it is our legacy behavior. - /// Cancel() will be called if rename is async. It also matches the other editor's behavior (like VS LSP and VSCode). - /// - private void CommitIfSynchronousOrCancelIfAsynchronous(EditorCommandArgs args, IUIThreadOperationContext operationContext, bool placeCaretAtTheEndOfIdentifier) - { - if (globalOptionService.ShouldCommitAsynchronously()) - renameService.ActiveSession?.Cancel(); - else - CommitIfActive(args, operationContext, placeCaretAtTheEndOfIdentifier); - } - - private void Commit(IUIThreadOperationContext operationContext) + private void CancelRenameSession() { - RoslynDebug.AssertNotNull(renameService.ActiveSession); - renameService.ActiveSession.Commit(previewChanges: false, operationContext); + renameService.ActiveSession?.Cancel(); } private bool IsRenameCommitInProgress() diff --git a/src/EditorFeatures/Core/InlineRename/CommandHandlers/AbstractRenameCommandHandler_MoveSelectedLinesHandler.cs b/src/EditorFeatures/Core/InlineRename/CommandHandlers/AbstractRenameCommandHandler_MoveSelectedLinesHandler.cs index 48dda4380552b..e19ad16b8bf2c 100644 --- a/src/EditorFeatures/Core/InlineRename/CommandHandlers/AbstractRenameCommandHandler_MoveSelectedLinesHandler.cs +++ b/src/EditorFeatures/Core/InlineRename/CommandHandlers/AbstractRenameCommandHandler_MoveSelectedLinesHandler.cs @@ -15,21 +15,21 @@ public CommandState GetCommandState(MoveSelectedLinesUpCommandArgs args) => CommandState.Unspecified; public bool ExecuteCommand(MoveSelectedLinesUpCommandArgs args, CommandExecutionContext context) - => HandleMoveSelectLinesUpOrDownCommand(args, context); + => HandleMoveSelectLinesUpOrDownCommand(); public CommandState GetCommandState(MoveSelectedLinesDownCommandArgs args) => CommandState.Unspecified; public bool ExecuteCommand(MoveSelectedLinesDownCommandArgs args, CommandExecutionContext context) - => HandleMoveSelectLinesUpOrDownCommand(args, context); + => HandleMoveSelectLinesUpOrDownCommand(); - private bool HandleMoveSelectLinesUpOrDownCommand(EditorCommandArgs args, CommandExecutionContext context) + private bool HandleMoveSelectLinesUpOrDownCommand() { // When rename commit is in progress, swallow the command so it won't change the workspace if (IsRenameCommitInProgress()) return true; - CommitIfSynchronousOrCancelIfAsynchronous(args, context.OperationContext, placeCaretAtTheEndOfIdentifier: true); + CancelRenameSession(); return false; } } diff --git a/src/EditorFeatures/Core/InlineRename/CommandHandlers/AbstractRenameCommandHandler_OpenLineAboveHandler.cs b/src/EditorFeatures/Core/InlineRename/CommandHandlers/AbstractRenameCommandHandler_OpenLineAboveHandler.cs index e547a8cfe0a8e..91a28352839e6 100644 --- a/src/EditorFeatures/Core/InlineRename/CommandHandlers/AbstractRenameCommandHandler_OpenLineAboveHandler.cs +++ b/src/EditorFeatures/Core/InlineRename/CommandHandlers/AbstractRenameCommandHandler_OpenLineAboveHandler.cs @@ -18,7 +18,7 @@ public void ExecuteCommand(OpenLineAboveCommandArgs args, Action nextHandler, Co HandlePossibleTypingCommand(args, nextHandler, context.OperationContext, (activeSession, operationContext, span) => { // Caret would be moved to the new line when editor command is handled, so we don't need to move it. - CommitIfSynchronousOrCancelIfAsynchronous(args, operationContext, placeCaretAtTheEndOfIdentifier: false); + CancelRenameSession(); nextHandler(); }); } diff --git a/src/EditorFeatures/Core/InlineRename/CommandHandlers/AbstractRenameCommandHandler_OpenLineBelowHandler.cs b/src/EditorFeatures/Core/InlineRename/CommandHandlers/AbstractRenameCommandHandler_OpenLineBelowHandler.cs index 1682fd8673d75..c3884e7d41a1d 100644 --- a/src/EditorFeatures/Core/InlineRename/CommandHandlers/AbstractRenameCommandHandler_OpenLineBelowHandler.cs +++ b/src/EditorFeatures/Core/InlineRename/CommandHandlers/AbstractRenameCommandHandler_OpenLineBelowHandler.cs @@ -18,7 +18,7 @@ public void ExecuteCommand(OpenLineBelowCommandArgs args, Action nextHandler, Co HandlePossibleTypingCommand(args, nextHandler, context.OperationContext, (activeSession, operationContext, span) => { // Caret would be moved to the new line when editor command is handled, so we don't need to move it. - CommitIfSynchronousOrCancelIfAsynchronous(args, operationContext, placeCaretAtTheEndOfIdentifier: false); + CancelRenameSession(); nextHandler(); }); } diff --git a/src/EditorFeatures/Core/InlineRename/CommandHandlers/AbstractRenameCommandHandler_RefactoringWithCommandHandler.cs b/src/EditorFeatures/Core/InlineRename/CommandHandlers/AbstractRenameCommandHandler_RefactoringWithCommandHandler.cs index c578b382308c2..6f5b00bbcdede 100644 --- a/src/EditorFeatures/Core/InlineRename/CommandHandlers/AbstractRenameCommandHandler_RefactoringWithCommandHandler.cs +++ b/src/EditorFeatures/Core/InlineRename/CommandHandlers/AbstractRenameCommandHandler_RefactoringWithCommandHandler.cs @@ -18,32 +18,32 @@ public CommandState GetCommandState(ReorderParametersCommandArgs args) => CommandState.Unspecified; public bool ExecuteCommand(ReorderParametersCommandArgs args, CommandExecutionContext context) - => HandleRefactoringCommands(args, context); + => HandleRefactoringCommands(); public CommandState GetCommandState(RemoveParametersCommandArgs args) => CommandState.Unspecified; public bool ExecuteCommand(RemoveParametersCommandArgs args, CommandExecutionContext context) - => HandleRefactoringCommands(args, context); + => HandleRefactoringCommands(); public CommandState GetCommandState(ExtractInterfaceCommandArgs args) => CommandState.Unspecified; public bool ExecuteCommand(ExtractInterfaceCommandArgs args, CommandExecutionContext context) - => HandleRefactoringCommands(args, context); + => HandleRefactoringCommands(); public CommandState GetCommandState(EncapsulateFieldCommandArgs args) => CommandState.Unspecified; public bool ExecuteCommand(EncapsulateFieldCommandArgs args, CommandExecutionContext context) - => HandleRefactoringCommands(args, context); + => HandleRefactoringCommands(); - private bool HandleRefactoringCommands(EditorCommandArgs args, CommandExecutionContext context) + private bool HandleRefactoringCommands() { if (IsRenameCommitInProgress()) return true; - CommitIfSynchronousOrCancelIfAsynchronous(args, context.OperationContext, placeCaretAtTheEndOfIdentifier: true); + CancelRenameSession(); return false; } } diff --git a/src/EditorFeatures/Core/InlineRename/CommandHandlers/AbstractRenameCommandHandler_RenameHandler.cs b/src/EditorFeatures/Core/InlineRename/CommandHandlers/AbstractRenameCommandHandler_RenameHandler.cs index fbadb6588e48f..acd8908e0351d 100644 --- a/src/EditorFeatures/Core/InlineRename/CommandHandlers/AbstractRenameCommandHandler_RenameHandler.cs +++ b/src/EditorFeatures/Core/InlineRename/CommandHandlers/AbstractRenameCommandHandler_RenameHandler.cs @@ -44,11 +44,11 @@ public bool ExecuteCommand(RenameCommandArgs args, CommandExecutionContext conte } var token = listener.BeginAsyncOperation(nameof(ExecuteCommand)); - _ = ExecuteCommandAsync(args, context.OperationContext).CompletesAsyncOperation(token); + _ = ExecuteCommandAsync(args).CompletesAsyncOperation(token); return true; } - private async Task ExecuteCommandAsync(RenameCommandArgs args, IUIThreadOperationContext editorOperationContext) + private async Task ExecuteCommandAsync(RenameCommandArgs args) { threadingContext.ThrowIfNotOnUIThread(); @@ -81,9 +81,8 @@ private async Task ExecuteCommandAsync(RenameCommandArgs args, IUIThreadOperatio } else { - // Otherwise, commit or cancel the existing session and start a new one. - // Set placeCaretAtTheEndOfIdentifier to false because a new rename session will be created based on caret's location. - CommitIfSynchronousOrCancelIfAsynchronous(args, editorOperationContext, placeCaretAtTheEndOfIdentifier: false); + // Otherwise, cancel the existing session and start a new one. + CancelRenameSession(); } } diff --git a/src/EditorFeatures/Core/InlineRename/CommandHandlers/AbstractRenameCommandHandler_ReturnHandler.cs b/src/EditorFeatures/Core/InlineRename/CommandHandlers/AbstractRenameCommandHandler_ReturnHandler.cs index cd51267b3d521..5996b90a01f4f 100644 --- a/src/EditorFeatures/Core/InlineRename/CommandHandlers/AbstractRenameCommandHandler_ReturnHandler.cs +++ b/src/EditorFeatures/Core/InlineRename/CommandHandlers/AbstractRenameCommandHandler_ReturnHandler.cs @@ -2,9 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Runtime.Remoting.Contexts; +using Microsoft.CodeAnalysis.ErrorReporting; +using Microsoft.CodeAnalysis.Shared.TestHooks; using Microsoft.VisualStudio.Commanding; using Microsoft.VisualStudio.Text.Editor; using Microsoft.VisualStudio.Text.Editor.Commanding.Commands; +using Microsoft.VisualStudio.TextManager.Interop; using Microsoft.VisualStudio.Utilities; namespace Microsoft.CodeAnalysis.Editor.Implementation.InlineRename; @@ -27,7 +31,11 @@ public bool ExecuteCommand(ReturnKeyCommandArgs args, CommandExecutionContext co protected virtual void CommitAndSetFocus(InlineRenameSession activeSession, ITextView textView, IUIThreadOperationContext operationContext) { - activeSession.InitiateCommit(operationContext); + var token = listener.BeginAsyncOperation(nameof(ExecuteCommand)); + + // CommitAsync will display UI to the user while this asynchronous work is being done. + activeSession.CommitAsync(previewChanges: false, operationContext) + .ReportNonFatalErrorAsync().CompletesAsyncOperation(token); SetFocusToTextView(textView); } } diff --git a/src/EditorFeatures/Core/InlineRename/CommandHandlers/AbstractRenameCommandHandler_SaveHandler.cs b/src/EditorFeatures/Core/InlineRename/CommandHandlers/AbstractRenameCommandHandler_SaveHandler.cs index 0ea62864e63a3..53685bef61a13 100644 --- a/src/EditorFeatures/Core/InlineRename/CommandHandlers/AbstractRenameCommandHandler_SaveHandler.cs +++ b/src/EditorFeatures/Core/InlineRename/CommandHandlers/AbstractRenameCommandHandler_SaveHandler.cs @@ -17,12 +17,6 @@ public bool ExecuteCommand(SaveCommandArgs args, CommandExecutionContext context { // If commit is async, just let editor save the document. // If call async commit here, it could finish after the save command so the workspace would still be dirty. - if (renameService.ActiveSession != null && !globalOptionService.ShouldCommitAsynchronously()) - { - Commit(context.OperationContext); - SetFocusToTextView(args.TextView); - } - return false; } } diff --git a/src/EditorFeatures/Core/InlineRename/CommandHandlers/AbstractRenameCommandHandler_WordDeleteHandler.cs b/src/EditorFeatures/Core/InlineRename/CommandHandlers/AbstractRenameCommandHandler_WordDeleteHandler.cs index c04cfa53a2e09..4572997c93e17 100644 --- a/src/EditorFeatures/Core/InlineRename/CommandHandlers/AbstractRenameCommandHandler_WordDeleteHandler.cs +++ b/src/EditorFeatures/Core/InlineRename/CommandHandlers/AbstractRenameCommandHandler_WordDeleteHandler.cs @@ -23,12 +23,12 @@ public CommandState GetCommandState(WordDeleteToEndCommandArgs args) => GetCommandState(); public bool ExecuteCommand(WordDeleteToStartCommandArgs args, CommandExecutionContext context) - => HandleWordDeleteCommand(args, context, args.TextView, deleteToStart: true); + => HandleWordDeleteCommand(args, args.TextView, deleteToStart: true); public bool ExecuteCommand(WordDeleteToEndCommandArgs args, CommandExecutionContext context) - => HandleWordDeleteCommand(args, context, args.TextView, deleteToStart: false); + => HandleWordDeleteCommand(args, args.TextView, deleteToStart: false); - private bool HandleWordDeleteCommand(EditorCommandArgs args, CommandExecutionContext context, ITextView view, bool deleteToStart) + private bool HandleWordDeleteCommand(EditorCommandArgs args, ITextView view, bool deleteToStart) { var subjectBuffer = args.SubjectBuffer; if (renameService.ActiveSession == null) @@ -73,7 +73,7 @@ private bool HandleWordDeleteCommand(EditorCommandArgs args, CommandExecutionCon } else { - CommitIfSynchronousOrCancelIfAsynchronous(args, context.OperationContext, placeCaretAtTheEndOfIdentifier: true); + CancelRenameSession(); } } diff --git a/src/EditorFeatures/Core/InlineRename/CommandHandlers/RenameCommandHandler.cs b/src/EditorFeatures/Core/InlineRename/CommandHandlers/RenameCommandHandler.cs index 82b07c4211399..baa4e7fbe19fc 100644 --- a/src/EditorFeatures/Core/InlineRename/CommandHandlers/RenameCommandHandler.cs +++ b/src/EditorFeatures/Core/InlineRename/CommandHandlers/RenameCommandHandler.cs @@ -34,9 +34,8 @@ namespace Microsoft.CodeAnalysis.Editor.Implementation.InlineRename; internal sealed partial class RenameCommandHandler( IThreadingContext threadingContext, InlineRenameService renameService, - IGlobalOptionService globalOptionService, IAsynchronousOperationListenerProvider asynchronousOperationListenerProvider) - : AbstractRenameCommandHandler(threadingContext, renameService, globalOptionService, asynchronousOperationListenerProvider.GetListener(FeatureAttribute.Rename)) + : AbstractRenameCommandHandler(threadingContext, renameService, asynchronousOperationListenerProvider.GetListener(FeatureAttribute.Rename)) { protected override void SetFocusToTextView(ITextView textView) { diff --git a/src/EditorFeatures/Core/InlineRename/InlineRenameService.cs b/src/EditorFeatures/Core/InlineRename/InlineRenameService.cs index 112142313e2ae..0b07ccf887b54 100644 --- a/src/EditorFeatures/Core/InlineRename/InlineRenameService.cs +++ b/src/EditorFeatures/Core/InlineRename/InlineRenameService.cs @@ -29,20 +29,16 @@ namespace Microsoft.CodeAnalysis.Editor.Implementation.InlineRename; [method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] internal sealed class InlineRenameService( IThreadingContext threadingContext, - IUIThreadOperationExecutor uiThreadOperationExecutor, ITextBufferAssociatedViewService textBufferAssociatedViewService, ITextBufferFactoryService textBufferFactoryService, ITextBufferCloneService textBufferCloneService, IFeatureServiceFactory featureServiceFactory, IGlobalOptionService globalOptions, - [ImportMany] IEnumerable refactorNotifyServices, IAsynchronousOperationListenerProvider listenerProvider) : IInlineRenameService { private readonly IThreadingContext _threadingContext = threadingContext; - private readonly IUIThreadOperationExecutor _uiThreadOperationExecutor = uiThreadOperationExecutor; private readonly ITextBufferAssociatedViewService _textBufferAssociatedViewService = textBufferAssociatedViewService; private readonly IAsynchronousOperationListener _asyncListener = listenerProvider.GetListener(FeatureAttribute.Rename); - private readonly IEnumerable _refactorNotifyServices = refactorNotifyServices; private readonly ITextBufferFactoryService _textBufferFactoryService = textBufferFactoryService; private readonly ITextBufferCloneService _textBufferCloneService = textBufferCloneService; private readonly IFeatureServiceFactory _featureServiceFactory = featureServiceFactory; @@ -109,12 +105,10 @@ public async Task StartInlineSessionAsync( renameInfo, options, previewChanges, - _uiThreadOperationExecutor, _textBufferAssociatedViewService, _textBufferFactoryService, _textBufferCloneService, _featureServiceFactory, - _refactorNotifyServices, _asyncListener); return new InlineRenameSessionInfo(ActiveSession); diff --git a/src/EditorFeatures/Core/InlineRename/InlineRenameSession.cs b/src/EditorFeatures/Core/InlineRename/InlineRenameSession.cs index 8c1cdffb5808a..3c63e4c532b86 100644 --- a/src/EditorFeatures/Core/InlineRename/InlineRenameSession.cs +++ b/src/EditorFeatures/Core/InlineRename/InlineRenameSession.cs @@ -19,7 +19,6 @@ using Microsoft.CodeAnalysis.Editor.Undo; using Microsoft.CodeAnalysis.ErrorReporting; using Microsoft.CodeAnalysis.Host; -using Microsoft.CodeAnalysis.InlineRename; using Microsoft.CodeAnalysis.Internal.Log; using Microsoft.CodeAnalysis.Notification; using Microsoft.CodeAnalysis.Remote; @@ -37,15 +36,12 @@ namespace Microsoft.CodeAnalysis.Editor.Implementation.InlineRename; internal sealed partial class InlineRenameSession : IInlineRenameSession, IFeatureController { - private readonly IUIThreadOperationExecutor _uiThreadOperationExecutor; - private readonly ITextBufferAssociatedViewService _textBufferAssociatedViewService; private readonly ITextBufferFactoryService _textBufferFactoryService; private readonly ITextBufferCloneService _textBufferCloneService; private readonly IFeatureService _featureService; private readonly IFeatureDisableToken _completionDisabledToken; - private readonly IEnumerable _refactorNotifyServices; private readonly IAsynchronousOperationListener _asyncListener; private readonly Solution _baseSolution; private readonly ITextView _triggerView; @@ -141,12 +137,10 @@ public InlineRenameSession( IInlineRenameInfo renameInfo, SymbolRenameOptions options, bool previewChanges, - IUIThreadOperationExecutor uiThreadOperationExecutor, ITextBufferAssociatedViewService textBufferAssociatedViewService, ITextBufferFactoryService textBufferFactoryService, ITextBufferCloneService textBufferCloneService, IFeatureServiceFactory featureServiceFactory, - IEnumerable refactorNotifyServices, IAsynchronousOperationListener asyncListener) { // This should always be touching a symbol since we verified that upon invocation @@ -176,8 +170,6 @@ public InlineRenameSession( _featureService = featureServiceFactory.GlobalFeatureService; _completionDisabledToken = _featureService.Disable(PredefinedEditorFeatureNames.Completion, this); RenameService = renameService; - _uiThreadOperationExecutor = uiThreadOperationExecutor; - _refactorNotifyServices = refactorNotifyServices; _asyncListener = asyncListener; _triggerView = textBufferAssociatedViewService.GetAssociatedTextViews(triggerSpan.Snapshot.TextBuffer).FirstOrDefault(v => v.HasAggregateFocus) ?? textBufferAssociatedViewService.GetAssociatedTextViews(triggerSpan.Snapshot.TextBuffer).First(); @@ -733,54 +725,10 @@ void DismissUIAndRollbackEdits() } /// - /// Caller should pass in the IUIThreadOperationContext if it is called from editor so rename commit operation could set up the its own context correctly. + /// Caller should pass in the IUIThreadOperationContext if it is called from editor so rename commit operation could set up its own context correctly. + /// When the editorOperationContext is not null it will take ownership of the UI thread and try to create a BackgroundWorkIndicator /// - public void Commit(bool previewChanges = false, IUIThreadOperationContext editorOperationContext = null) - => CommitSynchronously(previewChanges, editorOperationContext); - - /// if the rename operation was committed, otherwise - private bool CommitSynchronously(bool previewChanges, IUIThreadOperationContext operationContext = null) - { - // We're going to synchronously block the UI thread here. So we can't use the background work indicator (as - // it needs the UI thread to update itself. This will force us to go through the Threaded-Wait-Dialog path - // which at least will allow the user to cancel the rename if they want. - // - // In the future we should remove this entrypoint and have all callers use CommitAsync instead. - return _threadingContext.JoinableTaskFactory.Run(() => CommitWorkerAsync(previewChanges, canUseBackgroundWorkIndicator: false, operationContext)); - } - - /// - /// Start to commit the rename session. - /// Session might be committed sync or async, depends on the value of InlineRenameUIOptionsStorage.CommitRenameAsynchronously. - /// If it is committed async, method will only kick off the task. - /// - /// - public void InitiateCommit(IUIThreadOperationContext editorOperationContext = null) - { - var token = _asyncListener.BeginAsyncOperation(nameof(InitiateCommit)); - _ = CommitAsync(previewChanges: false, editorOperationContext) - .ReportNonFatalErrorAsync().CompletesAsyncOperation(token); - } - - /// - /// Caller should pass in the IUIThreadOperationContext if it is called from editor so rename commit operation could set up the its own context correctly. - /// - public async Task CommitAsync(bool previewChanges, IUIThreadOperationContext editorOperationContext = null) - { - if (this.RenameService.GlobalOptions.ShouldCommitAsynchronously()) - { - await CommitWorkerAsync(previewChanges, canUseBackgroundWorkIndicator: true, editorOperationContext).ConfigureAwait(false); - } - else - { - CommitSynchronously(previewChanges, editorOperationContext); - } - } - - /// if the rename operation was committed, otherwise - private async Task CommitWorkerAsync(bool previewChanges, bool canUseBackgroundWorkIndicator, IUIThreadOperationContext editorUIOperationContext) + public async Task CommitAsync(bool previewChanges, IUIThreadOperationContext editorOperationContext) { await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(); VerifyNotDismissed(); @@ -798,22 +746,22 @@ private async Task CommitWorkerAsync(bool previewChanges, bool canUseBackg this.ReplacementText == _initialRenameText) { Cancel(); - return false; + return; } // Don't dup commit. if (this.IsCommitInProgress) { - return false; + return; } previewChanges = previewChanges || PreviewChanges; - if (editorUIOperationContext is not null) + if (editorOperationContext is not null) { // Prevent Editor's typing responsiveness auto canceling the rename operation. // InlineRenameSession will call IUIThreadOperationExecutor to sets up our own IUIThreadOperationContext - editorUIOperationContext.TakeOwnership(); + editorOperationContext.TakeOwnership(); } try @@ -822,40 +770,27 @@ private async Task CommitWorkerAsync(bool previewChanges, bool canUseBackg this.IsCommitInProgress = true; this.CommitStateChange?.Invoke(this, EventArgs.Empty); - if (canUseBackgroundWorkIndicator) - { - // We do not cancel on edit because as part of the rename system we have asynchronous work still - // occurring that itself may be asynchronously editing the buffer (for example, updating reference - // locations with the final renamed text). Ideally though, once we start comitting, we would cancel - // any of that work and then only have the work of rolling back to the original state of the world - // and applying the desired edits ourselves. - var factory = Workspace.Services.GetRequiredService(); - using var context = factory.Create( + // We do not cancel on edit because as part of the rename system we have asynchronous work still + // occurring that itself may be asynchronously editing the buffer (for example, updating reference + // locations with the final renamed text). Ideally though, once we start comitting, we would cancel + // any of that work and then only have the work of rolling back to the original state of the world + // and applying the desired edits ourselves. + var factory = Workspace.Services.GetRequiredService(); + using var context = factory.Create( _triggerView, TriggerSpan, EditorFeaturesResources.Computing_Rename_information, cancelOnEdit: false, cancelOnFocusLost: false); - await CommitCoreAsync(context, previewChanges).ConfigureAwait(true); - } - else - { - using var context = _uiThreadOperationExecutor.BeginExecute( - title: EditorFeaturesResources.Rename, - defaultDescription: EditorFeaturesResources.Computing_Rename_information, - allowCancellation: true, - showProgress: false); - - // .ConfigureAwait(true); so we can return to the UI thread to dispose the operation context. It - // has a non-JTF threading dependency on the main thread. So it can deadlock if you call it on a BG - // thread when in a blocking JTF call. - await CommitCoreAsync(context, previewChanges).ConfigureAwait(true); - } + // .ConfigureAwait(true); so we can return to the UI thread to dispose the operation context. It + // has a non-JTF threading dependency on the main thread. So it can deadlock if you call it on a BG + // thread when in a blocking JTF call. + await CommitCoreAsync(context, previewChanges).ConfigureAwait(true); } catch (OperationCanceledException) { // We've used CA(true) consistently in this method. So we should always be on the UI thread. DismissUIAndRollbackEditsAndEndRenameSession_MustBeCalledOnUIThread( RenameLogMessage.UserActionOutcome.Canceled | RenameLogMessage.UserActionOutcome.Committed, previewChanges); - return false; + return; } finally { @@ -863,7 +798,7 @@ private async Task CommitWorkerAsync(bool previewChanges, bool canUseBackg this.CommitStateChange?.Invoke(this, EventArgs.Empty); } - return true; + return; } private async Task CommitCoreAsync(IUIThreadOperationContext operationContext, bool previewChanges) @@ -1028,15 +963,4 @@ internal bool TryGetContainingEditableSpan(SnapshotPoint point, out SnapshotSpan internal bool IsInOpenTextBuffer(SnapshotPoint point) => _openTextBuffers.ContainsKey(point.Snapshot.TextBuffer); - - internal TestAccessor GetTestAccessor() - => new TestAccessor(this); - - public readonly struct TestAccessor(InlineRenameSession inlineRenameSession) - { - private readonly InlineRenameSession _inlineRenameSession = inlineRenameSession; - - public bool CommitWorker(bool previewChanges) - => _inlineRenameSession.CommitSynchronously(previewChanges); - } } diff --git a/src/EditorFeatures/Core/InlineRename/InlineRenameSessionOptionsStorage.cs b/src/EditorFeatures/Core/InlineRename/InlineRenameSessionOptionsStorage.cs index 63a6dfa25ae22..406d7871df0d1 100644 --- a/src/EditorFeatures/Core/InlineRename/InlineRenameSessionOptionsStorage.cs +++ b/src/EditorFeatures/Core/InlineRename/InlineRenameSessionOptionsStorage.cs @@ -13,9 +13,4 @@ internal static class InlineRenameSessionOptionsStorage public static readonly Option2 RenameInComments = new("dotnet_rename_in_comments", defaultValue: false); public static readonly Option2 RenameFile = new("dotnet_rename_file", defaultValue: true); public static readonly Option2 PreviewChanges = new("dotnet_preview_inline_rename_changes", defaultValue: false); - - public static readonly Option2 CommitRenameAsynchronously = new("dotnet_commit_rename_asynchronously", defaultValue: true); - - public static bool ShouldCommitAsynchronously(this IGlobalOptionService globalOptionService) - => globalOptionService.GetOption(CommitRenameAsynchronously); } diff --git a/src/EditorFeatures/Core/InlineRename/UI/Adornment/RenameFlyoutViewModel.cs b/src/EditorFeatures/Core/InlineRename/UI/Adornment/RenameFlyoutViewModel.cs index f0d2baf6d6704..367eeb23440c8 100644 --- a/src/EditorFeatures/Core/InlineRename/UI/Adornment/RenameFlyoutViewModel.cs +++ b/src/EditorFeatures/Core/InlineRename/UI/Adornment/RenameFlyoutViewModel.cs @@ -15,6 +15,7 @@ using Microsoft.CodeAnalysis.Editor.Shared.Extensions; using Microsoft.CodeAnalysis.Editor.Shared.Utilities; using Microsoft.CodeAnalysis.EditorFeatures.Lightup; +using Microsoft.CodeAnalysis.ErrorReporting; using Microsoft.CodeAnalysis.InlineRename; using Microsoft.CodeAnalysis.InlineRename.UI.SmartRename; using Microsoft.CodeAnalysis.Options; @@ -32,6 +33,7 @@ internal class RenameFlyoutViewModel : INotifyPropertyChanged, IDisposable { private readonly bool _registerOleComponent; private readonly IGlobalOptionService _globalOptionService; + private readonly IAsynchronousOperationListener _asyncListener; private OleComponent? _oleComponent; private bool _disposedValue; private bool _isReplacementTextValid = true; @@ -51,6 +53,7 @@ public RenameFlyoutViewModel( Session = session; _registerOleComponent = registerOleComponent; _globalOptionService = globalOptionService; + _asyncListener = listenerProvider.GetListener(FeatureAttribute.Rename); Session.ReplacementTextChanged += OnReplacementTextChanged; Session.ReplacementsComputed += OnReplacementsComputed; Session.ReferenceLocationsChanged += OnReferenceLocationsChanged; @@ -229,7 +232,12 @@ public bool Submit() } SmartRenameViewModel?.Commit(IdentifierText); - Session.InitiateCommit(); + + var token = _asyncListener.BeginAsyncOperation(nameof(Submit)); + + // CommitAsync will display UI to the user while this asynchronous work is being done. + Session.CommitAsync(previewChanges: false, editorOperationContext: null) + .ReportNonFatalErrorAsync().CompletesAsyncOperation(token); return true; } diff --git a/src/EditorFeatures/Test2/Rename/InlineRenameTests.vb b/src/EditorFeatures/Test2/Rename/InlineRenameTests.vb index 1b4286de6b95b..dd7188ab1b5d3 100644 --- a/src/EditorFeatures/Test2/Rename/InlineRenameTests.vb +++ b/src/EditorFeatures/Test2/Rename/InlineRenameTests.vb @@ -6,15 +6,12 @@ Imports System.Threading Imports Microsoft.CodeAnalysis.CodeActions Imports Microsoft.CodeAnalysis.CodeRefactorings Imports Microsoft.CodeAnalysis.Editor.Host -Imports Microsoft.CodeAnalysis.Editor.Implementation.InlineRename Imports Microsoft.CodeAnalysis.Editor.UnitTests.RenameTracking -Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces Imports Microsoft.CodeAnalysis.InlineRename Imports Microsoft.CodeAnalysis.IntroduceVariable Imports Microsoft.CodeAnalysis.Notification Imports Microsoft.CodeAnalysis.Options Imports Microsoft.CodeAnalysis.Rename -Imports Microsoft.CodeAnalysis.Shared.Utilities Imports Microsoft.VisualStudio.Text Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Rename @@ -52,7 +49,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Rename textBuffer.Insert(caretPosition, "Bar") - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) VerifyFileName(workspace, "BarTest1") @@ -80,7 +77,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Rename textBuffer.Insert(caretPosition, "renamed") - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) End Using @@ -135,7 +132,7 @@ class [|Test1$$|] ' User could use copy & paste to enter invalid character textBuffer.Insert(selectedSpan, "<>") - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) VerifyFileName(workspace, "Test1") End Using @@ -229,7 +226,7 @@ class Deconstructable Await VerifyTagsAreCorrect(workspace) - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) VerifyFileName(workspace, "BarTest1") @@ -262,7 +259,7 @@ class Deconstructable Await VerifyTagsAreCorrect(workspace) - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) @@ -785,7 +782,7 @@ End Class textBuffer.Insert(caretPosition, "goo") - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) End Using @@ -918,7 +915,7 @@ End Class Await VerifyTagsAreCorrect(workspace) Await VerifyNoRenameTrackingTags(renameTrackingTagger, workspace, document) - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) VerifyFileName(workspace, "BarTest1") End Using @@ -952,7 +949,7 @@ End Class Await VerifyTagsAreCorrect(workspace) Await VerifyNoRenameTrackingTags(renameTrackingTagger, workspace, document) - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) VerifyFileName(workspace, "BarTest1") End Using @@ -989,7 +986,7 @@ End Class Await WaitForRename(workspace) Await VerifyTagsAreCorrect(workspace) - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) Await VerifyNoRenameTrackingTags(renameTrackingTagger, workspace, document) VerifyFileName(workspace, "BarTest1") @@ -1064,7 +1061,7 @@ End Class Await WaitForRename(workspace) Await VerifyTagsAreCorrect(workspace) - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) Await VerifyNoRenameTrackingTags(renameTrackingTagger, workspace, document) VerifyFileName(workspace, "BarTest1") @@ -1103,7 +1100,7 @@ End Class textBuffer.Insert(caretPosition, "Bar") - session.Commit(previewChanges:=True) + Await session.CommitAsync(previewChanges:=True, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) Assert.True(previewService.Called) @@ -1137,7 +1134,7 @@ End Class Dim session = StartSession(workspace) session.ApplyReplacementText("BarGoo", propagateEditImmediately:=True) - session.Commit(previewChanges:=True) + Await session.CommitAsync(previewChanges:=True, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) Assert.True(previewService.Called) @@ -1147,7 +1144,7 @@ End Class previewService.ReturnsNull = False previewService.Called = False - session.Commit(previewChanges:=True) + Await session.CommitAsync(previewChanges:=True, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) Assert.True(previewService.Called) End Using @@ -1194,7 +1191,7 @@ End Class Await WaitForRename(workspace) Await VerifyTagsAreCorrect(workspace) - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) End Using End Function @@ -1239,7 +1236,7 @@ End Class Await WaitForRename(workspace) Await VerifyTagsAreCorrect(workspace) - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) End Using End Function @@ -1352,7 +1349,7 @@ class C Await WaitForRename(workspace) Await VerifyTagsAreCorrect(workspace) - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) End Using End Function @@ -1384,7 +1381,7 @@ class C Await WaitForRename(workspace) Await VerifyTagsAreCorrect(workspace) - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) End Using End Function @@ -1418,7 +1415,7 @@ class C Await WaitForRename(workspace) Await VerifyTagsAreCorrect(workspace) - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) End Using End Function @@ -1452,7 +1449,7 @@ class C Await WaitForRename(workspace) Await VerifyTagsAreCorrect(workspace) - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) End Using End Function @@ -1511,7 +1508,7 @@ End Module Dim textBuffer = workspace.Documents.Single().GetTextBuffer() textBuffer.Insert(caretPosition, "q") - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) End Using @@ -1541,7 +1538,7 @@ End Module textBuffer.Delete(New Span(caretPosition, 1)) textBuffer.Insert(caretPosition, "x") - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) End Using @@ -1585,7 +1582,7 @@ End Class textBuffer.Delete(New Span(caretPosition, 1)) textBuffer.Insert(caretPosition, "x") - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) End Using @@ -1594,7 +1591,7 @@ End Class - Public Sub VerifyVBRenameDoesNotCrashOnAsNewClause(host As RenameTestHost) + Public Async Function VerifyVBRenameDoesNotCrashOnAsNewClause(host As RenameTestHost) As Task Using workspace = CreateWorkspaceWithWaiter( @@ -1628,9 +1625,9 @@ End Class ' Ensure the rename doesn't crash textBuffer.Insert(caretPosition, "e") - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) End Using - End Sub + End Function @@ -1832,7 +1829,7 @@ End Class - Public Sub VerifyFileRenamesCorrectlyWhenCaseChanges(host As RenameTestHost) + Public Async Function VerifyFileRenamesCorrectlyWhenCaseChanges(host As RenameTestHost) As Task Using workspace = CreateWorkspaceWithWaiter( @@ -1853,10 +1850,12 @@ class [|$$Test1|] textBuffer.Delete(New Span(caretPosition, 1)) textBuffer.Insert(caretPosition, "t") - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) + Await VerifyTagsAreCorrect(workspace) + VerifyFileName(workspace, "test1") End Using - End Sub + End Function @@ -1885,8 +1884,7 @@ class [|$$Test1|] textBuffer.Insert(caretPosition, "Bar") textBuffer.Delete(New Span(caretPosition, "Bar".Length)) - Dim committed = session.GetTestAccessor().CommitWorker(previewChanges:=False) - Assert.False(committed) + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) End Using @@ -1970,7 +1968,7 @@ class [|C|] textBuffer.Insert(caretPosition, "Bar") - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) End Using @@ -2000,7 +1998,7 @@ class [|C|] textBuffer.Insert(caretPosition, "Bar") - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) End Using @@ -2030,7 +2028,7 @@ class [|C|] textBuffer.Insert(caretPosition, "Bar") - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) End Using @@ -2060,7 +2058,7 @@ class [|C|] textBuffer.Insert(caretPosition, "Bar") - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) End Using @@ -2090,7 +2088,7 @@ class [|C|] textBuffer.Insert(caretPosition, "Bar") - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) End Using @@ -2120,7 +2118,7 @@ class [|C|] textBuffer.Insert(caretPosition, "Bar") - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) End Using @@ -2150,7 +2148,7 @@ class [|C|] textBuffer.Insert(caretPosition, "Bar") - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) End Using @@ -2180,7 +2178,7 @@ class [|C|] textBuffer.Insert(caretPosition, "Bar") - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) End Using @@ -2210,7 +2208,7 @@ class [|C|] textBuffer.Insert(caretPosition, "Bar") - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) End Using @@ -2240,7 +2238,7 @@ class [|C|] textBuffer.Insert(caretPosition, "Bar") - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) End Using @@ -2270,7 +2268,7 @@ class [|C|] textBuffer.Insert(caretPosition, "Bar") - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) End Using @@ -2305,7 +2303,7 @@ class [|C|] textBuffer.Insert(caretPosition, "Bar") - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) End Using @@ -2336,7 +2334,7 @@ class [|C|] session.ApplyReplacementText("Example", True) session.RefreshRenameSessionWithOptionsChanged(New SymbolRenameOptions(RenameInComments:=True)) - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) End Using @@ -2377,7 +2375,7 @@ class [|C|] textBuffer.Insert(caretPosition, "Example") - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) Await VerifyTagsAreCorrect(workspace) End Using diff --git a/src/EditorFeatures/Test2/Rename/RenameCommandHandlerTests.vb b/src/EditorFeatures/Test2/Rename/RenameCommandHandlerTests.vb index 472194cbdf9f0..9217f878b0460 100644 --- a/src/EditorFeatures/Test2/Rename/RenameCommandHandlerTests.vb +++ b/src/EditorFeatures/Test2/Rename/RenameCommandHandlerTests.vb @@ -3,11 +3,8 @@ ' See the LICENSE file in the project root for more information. Imports Microsoft.CodeAnalysis.Editor.Implementation.InlineRename -Imports Microsoft.CodeAnalysis.Editor.InlineRename Imports Microsoft.CodeAnalysis.Editor.Shared.Extensions Imports Microsoft.CodeAnalysis.Editor.UnitTests.Extensions -Imports Microsoft.CodeAnalysis.InlineRename -Imports Microsoft.CodeAnalysis.Options Imports Microsoft.CodeAnalysis.Text.Shared.Extensions Imports Microsoft.VisualStudio.Commanding Imports Microsoft.VisualStudio.Text @@ -1000,9 +997,6 @@ partial class [|Program|] , host) - Dim globalOptions = workspace.GetService(Of IGlobalOptionService) - globalOptions.SetGlobalOption(InlineRenameSessionOptionsStorage.CommitRenameAsynchronously, False) - Dim view = workspace.Documents.Single().GetTextView() Dim commandHandler = CreateCommandHandler(workspace) @@ -1017,20 +1011,21 @@ partial class [|Program|] commandHandler.ExecuteCommand(New TypeCharCommandArgs(view, view.TextBuffer, "B"c), Sub() editorOperations.InsertText("B"), Utilities.TestCommandExecutionContext.Create()) - ' Now save the document, which should commit Rename + ' Now save the document commandHandler.ExecuteCommand(New SaveCommandArgs(view, view.TextBuffer), Sub() Exit Sub, Utilities.TestCommandExecutionContext.Create()) Await VerifyTagsAreCorrect(workspace) - ' Rename session was indeed committed and is no longer active - Assert.Null(workspace.GetService(Of IInlineRenameService).ActiveSession) + ' Rename session was not commited and is active + ' If we were to try and async rename it could finish after the save command so the workspace would still be dirty. + Assert.NotNull(workspace.GetService(Of IInlineRenameService).ActiveSession) End Using End Function Public Sub MoveSelectedLinesUpDuringRename(host As RenameTestHost) - VerifyCommandCommitsRenameSessionAndExecutesCommand( + VerifyCommandDoesNotCommitRenameSessionAndExecuteCommand( host, Sub(commandHandler As RenameCommandHandler, view As IWpfTextView, nextHandler As Action) commandHandler.ExecuteCommand(New MoveSelectedLinesUpCommandArgs(view, view.TextBuffer), nextHandler, Utilities.TestCommandExecutionContext.Create()) @@ -1040,7 +1035,7 @@ partial class [|Program|] Public Sub MoveSelectedLinesDownDuringRename(host As RenameTestHost) - VerifyCommandCommitsRenameSessionAndExecutesCommand( + VerifyCommandDoesNotCommitRenameSessionAndExecuteCommand( host, Sub(commandHandler As RenameCommandHandler, view As IWpfTextView, nextHandler As Action) commandHandler.ExecuteCommand(New MoveSelectedLinesDownCommandArgs(view, view.TextBuffer), nextHandler, Utilities.TestCommandExecutionContext.Create()) @@ -1050,7 +1045,7 @@ partial class [|Program|] Public Sub ReorderParametersDuringRename(host As RenameTestHost) - VerifyCommandCommitsRenameSessionAndExecutesCommand( + VerifyCommandDoesNotCommitRenameSessionAndExecuteCommand( host, Sub(commandHandler As RenameCommandHandler, view As IWpfTextView, nextHandler As Action) commandHandler.ExecuteCommand(New ReorderParametersCommandArgs(view, view.TextBuffer), nextHandler, Utilities.TestCommandExecutionContext.Create()) @@ -1060,7 +1055,7 @@ partial class [|Program|] Public Sub RemoveParametersDuringRename(host As RenameTestHost) - VerifyCommandCommitsRenameSessionAndExecutesCommand( + VerifyCommandDoesNotCommitRenameSessionAndExecuteCommand( host, Sub(commandHandler As RenameCommandHandler, view As IWpfTextView, nextHandler As Action) commandHandler.ExecuteCommand(New RemoveParametersCommandArgs(view, view.TextBuffer), nextHandler, Utilities.TestCommandExecutionContext.Create()) @@ -1070,7 +1065,7 @@ partial class [|Program|] Public Sub ExtractInterfaceDuringRename(host As RenameTestHost) - VerifyCommandCommitsRenameSessionAndExecutesCommand( + VerifyCommandDoesNotCommitRenameSessionAndExecuteCommand( host, Sub(commandHandler As RenameCommandHandler, view As IWpfTextView, nextHandler As Action) commandHandler.ExecuteCommand(New ExtractInterfaceCommandArgs(view, view.TextBuffer), nextHandler, Utilities.TestCommandExecutionContext.Create()) @@ -1080,7 +1075,7 @@ partial class [|Program|] Public Sub EncapsulateFieldDuringRename(host As RenameTestHost) - VerifyCommandCommitsRenameSessionAndExecutesCommand( + VerifyCommandDoesNotCommitRenameSessionAndExecuteCommand( host, Sub(commandHandler As RenameCommandHandler, view As IWpfTextView, nextHandler As Action) commandHandler.ExecuteCommand(New EncapsulateFieldCommandArgs(view, view.TextBuffer), nextHandler, Utilities.TestCommandExecutionContext.Create()) @@ -1110,7 +1105,7 @@ partial class [|Program|] Public Sub CutDuringRename_OutsideIdentifier(host As RenameTestHost) - VerifySessionCommittedAfterCutPasteOutsideIdentifier( + VerifySessionNotCommittedAfterCutPasteOutsideIdentifier( host, Sub(commandHandler As RenameCommandHandler, view As IWpfTextView, nextHandler As Action) commandHandler.ExecuteCommand(New CutCommandArgs(view, view.TextBuffer), nextHandler, Utilities.TestCommandExecutionContext.Create()) @@ -1120,17 +1115,16 @@ partial class [|Program|] Public Sub PasteDuringRename_OutsideIdentifier(host As RenameTestHost) - VerifySessionCommittedAfterCutPasteOutsideIdentifier( + VerifySessionNotCommittedAfterCutPasteOutsideIdentifier( host, Sub(commandHandler As RenameCommandHandler, view As IWpfTextView, nextHandler As Action) commandHandler.ExecuteCommand(New PasteCommandArgs(view, view.TextBuffer), nextHandler, Utilities.TestCommandExecutionContext.Create()) End Sub) End Sub - Private Shared Sub VerifyCommandCommitsRenameSessionAndExecutesCommand( + Private Shared Sub VerifyCommandDoesNotCommitRenameSessionAndExecuteCommand( host As RenameTestHost, - executeCommand As Action(Of RenameCommandHandler, IWpfTextView, Action), - Optional commitAsynchronously As Boolean = False) + executeCommand As Action(Of RenameCommandHandler, IWpfTextView, Action)) Using workspace = CreateWorkspaceWithWaiter( @@ -1144,9 +1138,6 @@ class [|C$$|] , host) - Dim globalOptions = workspace.GetService(Of IGlobalOptionService) - globalOptions.SetGlobalOption(InlineRenameSessionOptionsStorage.CommitRenameAsynchronously, commitAsynchronously) - Dim view = workspace.Documents.Single().GetTextView() view.Caret.MoveTo(New SnapshotPoint(view.TextBuffer.CurrentSnapshot, workspace.Documents.Single(Function(d) d.CursorPosition.HasValue).CursorPosition.Value)) @@ -1166,9 +1157,9 @@ class [|C$$|] Dim commandInvokedString = "/*Command Invoked*/" executeCommand(commandHandler, view, Sub() editorOperations.InsertText(commandInvokedString)) - ' Verify rename session was committed. + ' Verify rename session was not committed because the scenarios are not supported in async rename. Assert.Null(workspace.GetService(Of IInlineRenameService).ActiveSession) - Assert.Contains("D f", view.TextBuffer.CurrentSnapshot.GetText()) + Assert.Contains("C f", view.TextBuffer.CurrentSnapshot.GetText()) ' Verify the command was routed to the editor. Assert.Contains(commandInvokedString, view.TextBuffer.CurrentSnapshot.GetText()) @@ -1207,10 +1198,9 @@ class [|C$$|] End Using End Function - Private Shared Sub VerifySessionCommittedAfterCutPasteOutsideIdentifier( + Private Shared Sub VerifySessionNotCommittedAfterCutPasteOutsideIdentifier( host As RenameTestHost, - executeCommand As Action(Of RenameCommandHandler, IWpfTextView, Action), - Optional commitAsynchronously As Boolean = False) + executeCommand As Action(Of RenameCommandHandler, IWpfTextView, Action)) Using workspace = CreateWorkspaceWithWaiter( @@ -1224,9 +1214,6 @@ class [|C$$|] , host) - Dim globalOptions = workspace.GetService(Of IGlobalOptionService) - globalOptions.SetGlobalOption(InlineRenameSessionOptionsStorage.CommitRenameAsynchronously, commitAsynchronously) - Dim view = workspace.Documents.Single().GetTextView() view.Caret.MoveTo(New SnapshotPoint(view.TextBuffer.CurrentSnapshot, workspace.Documents.Single(Function(d) d.CursorPosition.HasValue).CursorPosition.Value)) @@ -1251,9 +1238,9 @@ class [|C$$|] executeCommand(commandHandler, view, Sub() editorOperations.InsertText(commandInvokedString)) - ' Verify rename session was committed + ' If a user cuts/pastes outside the identifier then that cancels the rename operation as it is not supported in async rename. Assert.Null(workspace.GetService(Of IInlineRenameService).ActiveSession) - Assert.Contains("D f", view.TextBuffer.CurrentSnapshot.GetText()) + Assert.Contains("C f", view.TextBuffer.CurrentSnapshot.GetText()) Assert.Contains(commandInvokedString, view.TextBuffer.CurrentSnapshot.GetText()) End Using End Sub diff --git a/src/EditorFeatures/Test2/Rename/RenameTagProducerTests.vb b/src/EditorFeatures/Test2/Rename/RenameTagProducerTests.vb index 2edfc36c53190..e9d042e4dadad 100644 --- a/src/EditorFeatures/Test2/Rename/RenameTagProducerTests.vb +++ b/src/EditorFeatures/Test2/Rename/RenameTagProducerTests.vb @@ -3,12 +3,10 @@ ' See the LICENSE file in the project root for more information. Imports System.Collections.ObjectModel -Imports System.Threading Imports Microsoft.CodeAnalysis.Collections Imports Microsoft.CodeAnalysis.Editor.Implementation.InlineRename Imports Microsoft.CodeAnalysis.Editor.Implementation.InlineRename.HighlightTags Imports Microsoft.CodeAnalysis.Editor.UnitTests.Extensions -Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces Imports Microsoft.CodeAnalysis.Rename Imports Microsoft.CodeAnalysis.Text.Shared.Extensions Imports Microsoft.VisualStudio.Text @@ -90,7 +88,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Rename session.Cancel() VerifyBufferContentsInWorkspace(actualWorkspace, actualWorkspace) ElseIf sessionCommit Then - Await session.CommitAsync(previewChanges:=False) + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) VerifyBufferContentsInWorkspace(actualWorkspace, resolvedConflictWorkspace) End If End If @@ -468,7 +466,7 @@ public class Class1 VerifyBufferContentsInWorkspace(workspace, resolvedConflictWorkspace) End Using - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) Using resolvedConflictWorkspace = CreateWorkspaceWithWaiter( @@ -1175,7 +1173,7 @@ End Class commandHandler.ExecuteCommand(New TypeCharCommandArgs(view, view.TextBuffer, "f"c), Sub() editorOperations.InsertText("f"), Utilities.TestCommandExecutionContext.Create()) commandHandler.ExecuteCommand(New TypeCharCommandArgs(view, view.TextBuffer, "g"c), Sub() editorOperations.InsertText("g"), Utilities.TestCommandExecutionContext.Create()) - session.Commit() + Await session.CommitAsync(previewChanges:=False, editorOperationContext:=Nothing) Dim selectionLength = view.Selection.End.Position - view.Selection.Start.Position Assert.Equal(0, selectionLength) End Using diff --git a/src/EditorFeatures/VisualBasicTest/LineCommit/CommitTestData.vb b/src/EditorFeatures/VisualBasicTest/LineCommit/CommitTestData.vb index a59c2e7eeffb4..0d5332c3ef00a 100644 --- a/src/EditorFeatures/VisualBasicTest/LineCommit/CommitTestData.vb +++ b/src/EditorFeatures/VisualBasicTest/LineCommit/CommitTestData.vb @@ -112,7 +112,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.LineCommit Throw New NotImplementedException() End Sub - Public Function CommitAsync(previewChanges As Boolean, Optional editorOperationContext As IUIThreadOperationContext = Nothing) As Task Implements IInlineRenameSession.CommitAsync + Public Function CommitAsync(previewChanges As Boolean, editorOperationContext As IUIThreadOperationContext) As Task Implements IInlineRenameSession.CommitAsync Throw New NotImplementedException() End Function End Class diff --git a/src/VisualStudio/Core/Def/Options/VisualStudioOptionStorage.cs b/src/VisualStudio/Core/Def/Options/VisualStudioOptionStorage.cs index 80950f0d3dd13..f3c391219fd97 100644 --- a/src/VisualStudio/Core/Def/Options/VisualStudioOptionStorage.cs +++ b/src/VisualStudio/Core/Def/Options/VisualStudioOptionStorage.cs @@ -340,7 +340,6 @@ public bool TryFetch(LocalUserRegistryOptionPersister persister, OptionKey2 opti {"dotnet_collapse_inline_rename_ui", new RoamingProfileStorage("TextEditor.CollapseRenameUI")}, {"dotnet_preview_inline_rename_changes", new RoamingProfileStorage("TextEditor.Specific.PreviewRename")}, {"dotnet_collapse_suggestions_in_inline_rename_ui", new RoamingProfileStorage("TextEditor.CollapseRenameSuggestionsUI")}, - {"dotnet_commit_rename_asynchronously", new LocalUserProfileStorage(@"Roslyn\Internal\OnOff\Features", "DotnetCommitRenameAsynchronously")}, {"dotnet_rename_get_suggestions_automatically", new FeatureFlagStorage(@"Editor.AutoSmartRenameSuggestions")}, // Option is deprecated, don't use the same RoamingProfileStorage key {"dotnet_rename_file", new RoamingProfileStorage("TextEditor.Specific.RenameFile")}, diff --git a/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpRename.cs b/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpRename.cs index 82901446adaa1..ea59d8437fe6b 100644 --- a/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpRename.cs +++ b/src/VisualStudio/IntegrationTest/New.IntegrationTests/CSharp/CSharpRename.cs @@ -35,7 +35,6 @@ public override async Task InitializeAsync() globalOptions.SetGlobalOption(InlineRenameSessionOptionsStorage.RenameOverloads, false); globalOptions.SetGlobalOption(InlineRenameSessionOptionsStorage.RenameFile, true); globalOptions.SetGlobalOption(InlineRenameSessionOptionsStorage.PreviewChanges, false); - globalOptions.SetGlobalOption(InlineRenameSessionOptionsStorage.CommitRenameAsynchronously, false); } [IdeFact] @@ -653,7 +652,7 @@ static void Main(string[] args) await TestServices.EditorVerifier.TextEqualsAsync( """ - class program$$ + class p$$rogram { static void Main(string[] args) { @@ -799,9 +798,6 @@ void Method() [IdeFact] public async Task VerifyAsyncRename() { - var globalOptions = await TestServices.Shell.GetComponentModelServiceAsync(HangMitigatingCancellationToken); - globalOptions.SetGlobalOption(InlineRenameSessionOptionsStorage.CommitRenameAsynchronously, true); - var markup = """ class Program {