Skip to content

Commit

Permalink
Merge pull request #59856 from CyrusNajmabadi/codeActionDocNav
Browse files Browse the repository at this point in the history
Address layering of navigation action in code actions
  • Loading branch information
CyrusNajmabadi authored Mar 2, 2022
2 parents bd36982 + 05c2090 commit 8212786
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,7 @@ public async Task<bool> 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))
{
Expand All @@ -185,7 +184,7 @@ public async Task<bool> ApplyAsync(

var updatedSolution = operations.OfType<ApplyChangesOperation>().FirstOrDefault()?.ChangedSolution ?? oldSolution;
await TryNavigateToLocationOrStartRenameSessionAsync(
workspace, oldSolution, updatedSolution, cancellationToken).ConfigureAwait(false);
workspace, operations, oldSolution, updatedSolution, cancellationToken).ConfigureAwait(false);
return applied;
}

Expand Down Expand Up @@ -289,41 +288,50 @@ private async Task<bool> ProcessOperationsAsync(
return applied;
}

private async Task TryNavigateToLocationOrStartRenameSessionAsync(Workspace workspace, Solution oldSolution, Solution newSolution, CancellationToken cancellationToken)
private async Task TryNavigateToLocationOrStartRenameSessionAsync(
Workspace workspace,
ImmutableArray<CodeActionOperation> operations,
Solution oldSolution,
Solution newSolution,
CancellationToken cancellationToken)
{
var navigationOperation = operations.OfType<DocumentNavigationOperation>().FirstOrDefault();
if (navigationOperation != null && workspace.CanOpenDocuments)
{
var navigationService = workspace.Services.GetRequiredService<IDocumentNavigationService>();
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<IDocumentNavigationService>();
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
// during ApplyChanges, such as in the Venus scenario where indentation and
// 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)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -21,25 +17,18 @@ namespace Microsoft.CodeAnalysis.CodeActions
/// </summary>
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<IDocumentNavigationService>();
var threadingService = workspace.Services.GetService<IWorkspaceThreadingServiceProvider>();

threadingService.Service.Run(
() => navigationService.TryNavigateToPositionAsync(workspace, _documentId, _position, cancellationToken));
}
// Intentionally empty. Handling of this operation is special cased in CodeActionEditHandlerService.cs
}
}
}

0 comments on commit 8212786

Please sign in to comment.