From 283ba6d0bcd5ddb80ea637dc30ea137f515aaf71 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 1 Mar 2022 14:28:37 -0800 Subject: [PATCH 1/3] Address layering of navigation action in code actions --- .../CodeActionEditHandlerService.cs | 38 +++++++++++-------- ...tion.cs => DocumentNavigationOperation.cs} | 20 +++------- 2 files changed, 28 insertions(+), 30 deletions(-) rename src/Features/Core/Portable/Common/{NavigationOperation.cs => DocumentNavigationOperation.cs} (63%) 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 63% rename from src/Features/Core/Portable/Common/NavigationOperation.cs rename to src/Features/Core/Portable/Common/DocumentNavigationOperation.cs index 23389de7a3005..a74c9b645596f 100644 --- a/src/Features/Core/Portable/Common/NavigationOperation.cs +++ b/src/Features/Core/Portable/Common/DocumentNavigationOperation.cs @@ -2,8 +2,6 @@ // 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; @@ -21,25 +19,17 @@ 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) + public DocumentNavigationOperation(DocumentId documentId!!, int position = 0) { - _documentId = documentId ?? throw new ArgumentNullException(nameof(documentId)); - _position = position; + DocumentId = 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)); - } } } } From 4dcfd49f20e5866ccb1d6812fcb97f9b8a34cd51 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 1 Mar 2022 17:35:47 -0800 Subject: [PATCH 2/3] Fix formatting warning --- .../Core/Portable/Common/DocumentNavigationOperation.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Features/Core/Portable/Common/DocumentNavigationOperation.cs b/src/Features/Core/Portable/Common/DocumentNavigationOperation.cs index a74c9b645596f..414c40da05c04 100644 --- a/src/Features/Core/Portable/Common/DocumentNavigationOperation.cs +++ b/src/Features/Core/Portable/Common/DocumentNavigationOperation.cs @@ -22,14 +22,15 @@ public class DocumentNavigationOperation : CodeActionOperation internal DocumentId DocumentId { get; } internal int Position { get; } - public DocumentNavigationOperation(DocumentId documentId!!, int position = 0) + public DocumentNavigationOperation(DocumentId documentId, int position = 0) { - DocumentId = documentId; + DocumentId = documentId ?? throw new ArgumentNullException(nameof(documentId)); Position = position; } public override void Apply(Workspace workspace, CancellationToken cancellationToken) { + // Intentionally empty. Handling of this operation is special cased in CodeActionEditHandlerService.cs } } } From eb56fe2031530b9a125aff8ae139505442e2c06d Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 1 Mar 2022 17:35:58 -0800 Subject: [PATCH 3/3] Simplify --- .../Core/Portable/Common/DocumentNavigationOperation.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Features/Core/Portable/Common/DocumentNavigationOperation.cs b/src/Features/Core/Portable/Common/DocumentNavigationOperation.cs index 414c40da05c04..ac2d0e7e599fd 100644 --- a/src/Features/Core/Portable/Common/DocumentNavigationOperation.cs +++ b/src/Features/Core/Portable/Common/DocumentNavigationOperation.cs @@ -4,8 +4,6 @@ using System; using System.Threading; -using Microsoft.CodeAnalysis.Navigation; -using Microsoft.CodeAnalysis.Shared.Utilities; namespace Microsoft.CodeAnalysis.CodeActions {