diff --git a/src/EditorFeatures/Core/Implementation/CodeActions/CodeActionEditHandlerService.cs b/src/EditorFeatures/Core/Implementation/CodeActions/CodeActionEditHandlerService.cs index 10e8485fdd503..5b6f65af970b6 100644 --- a/src/EditorFeatures/Core/Implementation/CodeActions/CodeActionEditHandlerService.cs +++ b/src/EditorFeatures/Core/Implementation/CodeActions/CodeActionEditHandlerService.cs @@ -172,8 +172,7 @@ public async Task ApplyAsync( { // Come back to the UI thread after processing the operations so we can commit the transaction applied = await ProcessOperationsAsync( - workspace, operations, progressTracker, - cancellationToken).ConfigureAwait(true); + workspace, operations, progressTracker, cancellationToken).ConfigureAwait(true); } catch (Exception ex) when (FatalError.ReportAndPropagateUnlessCanceled(ex, cancellationToken)) { @@ -185,7 +184,7 @@ public async Task ApplyAsync( var updatedSolution = operations.OfType().FirstOrDefault()?.ChangedSolution ?? oldSolution; await TryNavigateToLocationOrStartRenameSessionAsync( - workspace, oldSolution, updatedSolution, cancellationToken).ConfigureAwait(false); + workspace, operations, oldSolution, updatedSolution, cancellationToken).ConfigureAwait(false); return applied; } @@ -289,33 +288,42 @@ private async Task ProcessOperationsAsync( return applied; } - private async Task TryNavigateToLocationOrStartRenameSessionAsync(Workspace workspace, Solution oldSolution, Solution newSolution, CancellationToken cancellationToken) + private async Task TryNavigateToLocationOrStartRenameSessionAsync( + Workspace workspace, + ImmutableArray operations, + Solution oldSolution, + Solution newSolution, + CancellationToken cancellationToken) { + var navigationOperation = operations.OfType().FirstOrDefault(); + if (navigationOperation != null && workspace.CanOpenDocuments) + { + var navigationService = workspace.Services.GetRequiredService(); + await navigationService.TryNavigateToPositionAsync( + workspace, navigationOperation.DocumentId, navigationOperation.Position, cancellationToken).ConfigureAwait(false); + return; + } + var changedDocuments = newSolution.GetChangedDocuments(oldSolution); foreach (var documentId in changedDocuments) { var document = newSolution.GetRequiredDocument(documentId); if (!document.SupportsSyntaxTree) - { continue; - } var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); - var navigationTokenOpt = root.GetAnnotatedTokens(NavigationAnnotation.Kind) - .FirstOrNull(); - if (navigationTokenOpt.HasValue) + var navigationToken = root.GetAnnotatedTokens(NavigationAnnotation.Kind).FirstOrNull(); + if (navigationToken.HasValue) { var navigationService = workspace.Services.GetRequiredService(); await navigationService.TryNavigateToPositionAsync( - workspace, documentId, navigationTokenOpt.Value.SpanStart, cancellationToken).ConfigureAwait(false); + workspace, documentId, navigationToken.Value.SpanStart, cancellationToken).ConfigureAwait(false); return; } - var renameTokenOpt = root.GetAnnotatedTokens(RenameAnnotation.Kind) - .FirstOrNull(); - - if (renameTokenOpt.HasValue) + var renameToken = root.GetAnnotatedTokens(RenameAnnotation.Kind).FirstOrNull(); + if (renameToken.HasValue) { // It's possible that the workspace's current solution is not the same as // newSolution. This can happen if the workspace host performs other edits @@ -323,7 +331,7 @@ await navigationService.TryNavigateToPositionAsync( // formatting can happen. To work around this, we create a SyntaxPath to the // rename token in the newSolution and resolve it to the current solution. - var pathToRenameToken = new SyntaxPath(renameTokenOpt.Value); + var pathToRenameToken = new SyntaxPath(renameToken.Value); var latestDocument = workspace.CurrentSolution.GetDocument(documentId); if (latestDocument != null) { diff --git a/src/Features/Core/Portable/Common/NavigationOperation.cs b/src/Features/Core/Portable/Common/DocumentNavigationOperation.cs similarity index 60% rename from src/Features/Core/Portable/Common/NavigationOperation.cs rename to src/Features/Core/Portable/Common/DocumentNavigationOperation.cs index 23389de7a3005..ac2d0e7e599fd 100644 --- a/src/Features/Core/Portable/Common/NavigationOperation.cs +++ b/src/Features/Core/Portable/Common/DocumentNavigationOperation.cs @@ -2,12 +2,8 @@ // 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.Threading; -using Microsoft.CodeAnalysis.Navigation; -using Microsoft.CodeAnalysis.Shared.Utilities; namespace Microsoft.CodeAnalysis.CodeActions { @@ -21,25 +17,18 @@ namespace Microsoft.CodeAnalysis.CodeActions /// public class DocumentNavigationOperation : CodeActionOperation { - private readonly DocumentId _documentId; - private readonly int _position; + internal DocumentId DocumentId { get; } + internal int Position { get; } public DocumentNavigationOperation(DocumentId documentId, int position = 0) { - _documentId = documentId ?? throw new ArgumentNullException(nameof(documentId)); - _position = position; + DocumentId = documentId ?? throw new ArgumentNullException(nameof(documentId)); + Position = position; } public override void Apply(Workspace workspace, CancellationToken cancellationToken) { - if (workspace.CanOpenDocuments) - { - var navigationService = workspace.Services.GetService(); - var threadingService = workspace.Services.GetService(); - - threadingService.Service.Run( - () => navigationService.TryNavigateToPositionAsync(workspace, _documentId, _position, cancellationToken)); - } + // Intentionally empty. Handling of this operation is special cased in CodeActionEditHandlerService.cs } } }