Skip to content

Commit

Permalink
Merge branch 'asyncNavigation4' into asyncNavigation5
Browse files Browse the repository at this point in the history
  • Loading branch information
CyrusNajmabadi committed Mar 2, 2022
2 parents c3d108d + 5e32a95 commit 13cd975
Show file tree
Hide file tree
Showing 11 changed files with 90 additions and 106 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,6 @@ public CSharpOperationFactory(SemanticModel semanticModel)
case BoundKind.TupleLiteral:
case BoundKind.ConvertedTupleLiteral:
return CreateBoundTupleOperation((BoundTupleExpression)boundNode);
case BoundKind.UnconvertedInterpolatedString:
throw ExceptionUtilities.Unreachable;
case BoundKind.InterpolatedString:
return CreateBoundInterpolatedStringExpressionOperation((BoundInterpolatedString)boundNode);
case BoundKind.StringInsert:
Expand All @@ -218,8 +216,6 @@ public CSharpOperationFactory(SemanticModel semanticModel)
return CreateBoundLocalFunctionStatementOperation((BoundLocalFunctionStatement)boundNode);
case BoundKind.AnonymousObjectCreationExpression:
return CreateBoundAnonymousObjectCreationExpressionOperation((BoundAnonymousObjectCreationExpression)boundNode);
case BoundKind.AnonymousPropertyDeclaration:
throw ExceptionUtilities.Unreachable;
case BoundKind.ConstantPattern:
return CreateBoundConstantPatternOperation((BoundConstantPattern)boundNode);
case BoundKind.DeclarationPattern:
Expand Down Expand Up @@ -268,10 +264,6 @@ public CSharpOperationFactory(SemanticModel semanticModel)
return CreateRangeExpressionOperation((BoundRangeExpression)boundNode);
case BoundKind.SwitchSection:
return CreateBoundSwitchSectionOperation((BoundSwitchSection)boundNode);
case BoundKind.UnconvertedConditionalOperator:
throw ExceptionUtilities.Unreachable;
case BoundKind.UnconvertedSwitchExpression:
throw ExceptionUtilities.Unreachable;
case BoundKind.ConvertedSwitchExpression:
return CreateBoundSwitchExpressionOperation((BoundConvertedSwitchExpression)boundNode);
case BoundKind.SwitchExpressionArm:
Expand Down Expand Up @@ -326,6 +318,10 @@ public CSharpOperationFactory(SemanticModel semanticModel)
_ => null
};
return new NoneOperation(children, _semanticModel, boundNode.Syntax, type: type, constantValue, isImplicit: isImplicit);
case BoundKind.UnconvertedInterpolatedString:
case BoundKind.UnconvertedConditionalOperator:
case BoundKind.UnconvertedSwitchExpression:
case BoundKind.AnonymousPropertyDeclaration:
default:
// If you're hitting this because the IOperation test hook has failed, see
// <roslyn-root>/docs/Compilers/IOperation Test Hook.md for instructions on how to fix.
Expand Down Expand Up @@ -849,7 +845,7 @@ private IOperation CreateBoundObjectInitializerMemberOperation(BoundObjectInitia

return new PropertyReferenceOperation(property.GetPublicSymbol(), arguments, createReceiver(), _semanticModel, syntax, type, isImplicit);
default:
throw ExceptionUtilities.Unreachable;
throw ExceptionUtilities.UnexpectedValue(memberSymbol.Kind);
}

IOperation? createReceiver() => memberSymbol?.IsStatic == true ?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,8 @@ public InteractiveDocumentNavigationService(IThreadingContext threadingContext)
_threadingContext = threadingContext;
}

public Task<bool> CanNavigateToSpanAsync(Workspace workspace, DocumentId documentId, TextSpan textSpan, CancellationToken cancellationToken)
{
return SpecializedTasks.True;
}
public Task<bool> CanNavigateToSpanAsync(Workspace workspace, DocumentId documentId, TextSpan textSpan, bool allowInvalidSpan, CancellationToken cancellationToken)
=> SpecializedTasks.True;

public Task<bool> CanNavigateToLineAndOffsetAsync(Workspace workspace, DocumentId documentId, int lineNumber, int offset, CancellationToken cancellationToken)
=> SpecializedTasks.False;
Expand Down Expand Up @@ -90,9 +88,9 @@ public Task<bool> CanNavigateToPositionAsync(Workspace workspace, DocumentId doc
}

public Task<INavigableLocation?> GetLocationForLineAndOffsetAsync(Workspace workspace, DocumentId documentId, int lineNumber, int offset, NavigationOptions options, CancellationToken cancellationToken)
=> throw new NotSupportedException();
=> SpecializedTasks.Null<INavigableLocation>();

public Task<INavigableLocation?> GetLocationForPositionAsync(Workspace workspace, DocumentId documentId, int position, int virtualSpace, NavigationOptions options, CancellationToken cancellationToken)
=> throw new NotSupportedException();
=> SpecializedTasks.Null<INavigableLocation>();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,13 @@ protected async Task NavigateToSymbolItemAsync(
protected async Task NavigateToPositionAsync(Workspace workspace, DocumentId documentId, int position, int virtualSpace, CancellationToken cancellationToken)
{
var navigationService = workspace.Services.GetRequiredService<IDocumentNavigationService>();
if (await navigationService.CanNavigateToPositionAsync(workspace, documentId, position, virtualSpace, cancellationToken).ConfigureAwait(false))
var location = await navigationService.GetLocationForPositionAsync(
workspace, documentId, position, virtualSpace, NavigationOptions.Default, cancellationToken).ConfigureAwait(false);

if (location != null)
{
var location = await navigationService.GetLocationForPositionAsync(
workspace, documentId, position, virtualSpace, NavigationOptions.Default, cancellationToken).ConfigureAwait(false);
if (location != null)
await location.NavigateToAsync(cancellationToken).ConfigureAwait(false);
await location.NavigateToAsync(cancellationToken).ConfigureAwait(false);
return;
}
else
{
Expand Down
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,43 +288,54 @@ 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>();
var location = await navigationService.GetLocationForPositionAsync(
workspace, navigationOperation.DocumentId, navigationOperation.Position, cancellationToken).ConfigureAwait(false);
if (location != null)
await location.NavigateToAsync(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>();
var location = await navigationService.GetLocationForPositionAsync(
workspace, documentId, navigationTokenOpt.Value.SpanStart, cancellationToken).ConfigureAwait(false);
workspace, documentId, navigationToken.Value.SpanStart, cancellationToken).ConfigureAwait(false);
if (location != null)
await location.NavigateToAsync(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 @@ -36,7 +36,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Utilities.GoToHelpers
Return If(_canNavigateToPosition, SpecializedTasks.True, SpecializedTasks.False)
End Function

Public Function CanNavigateToSpanAsync(workspace As Workspace, documentId As DocumentId, textSpan As TextSpan, cancellationToken As CancellationToken) As Task(Of Boolean) Implements IDocumentNavigationService.CanNavigateToSpanAsync
Public Function CanNavigateToSpanAsync(workspace As Workspace, documentId As DocumentId, textSpan As TextSpan, allowInvalidSpan As Boolean, cancellationToken As CancellationToken) As Task(Of Boolean) Implements IDocumentNavigationService.CanNavigateToSpanAsync
Return If(_canNavigateToSpan, SpecializedTasks.True, SpecializedTasks.False)
End Function

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Utilities
Return If(CanNavigateToPositionReturnValue, SpecializedTasks.True, SpecializedTasks.False)
End Function

Public Function CanNavigateToSpanAsync(workspace As Workspace, documentId As DocumentId, textSpan As TextSpan, cancellationToken As CancellationToken) As Task(Of Boolean) Implements IDocumentNavigationService.CanNavigateToSpanAsync
Public Function CanNavigateToSpanAsync(workspace As Workspace, documentId As DocumentId, textSpan As TextSpan, allowInvalidSpan As Boolean, cancellationToken As CancellationToken) As Task(Of Boolean) Implements IDocumentNavigationService.CanNavigateToSpanAsync
Me.ProvidedDocumentId = documentId
Me.ProvidedTextSpan = textSpan

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,30 +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(async () =>
{
var location = await navigationService.GetLocationForPositionAsync(
workspace, _documentId, _position, cancellationToken).ConfigureAwait(false);
return location != null &&
await location.NavigateToAsync(cancellationToken).ConfigureAwait(false);
});
}
// Intentionally empty. Handling of this operation is special cased in CodeActionEditHandlerService.cs
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace Microsoft.CodeAnalysis.Navigation
{
internal sealed class DefaultDocumentNavigationService : IDocumentNavigationService
{
public Task<bool> CanNavigateToSpanAsync(Workspace workspace, DocumentId documentId, TextSpan textSpan, CancellationToken cancellationToken)
public Task<bool> CanNavigateToSpanAsync(Workspace workspace, DocumentId documentId, TextSpan textSpan, bool allowInvalidSpan, CancellationToken cancellationToken)
=> SpecializedTasks.False;

public Task<bool> CanNavigateToLineAndOffsetAsync(Workspace workspace, DocumentId documentId, int lineNumber, int offset, CancellationToken cancellationToken)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ internal interface IDocumentNavigationService : IWorkspaceService
/// Determines whether it is possible to navigate to the given position in the specified document.
/// </summary>
/// <remarks>Legal to call from any thread.</remarks>
Task<bool> CanNavigateToSpanAsync(Workspace workspace, DocumentId documentId, TextSpan textSpan, CancellationToken cancellationToken);
Task<bool> CanNavigateToSpanAsync(Workspace workspace, DocumentId documentId, TextSpan textSpan, bool allowInvalidSpan, CancellationToken cancellationToken);

/// <summary>
/// Determines whether it is possible to navigate to the given line/offset in the specified document.
Expand All @@ -34,6 +34,9 @@ internal interface IDocumentNavigationService : IWorkspaceService

internal static class IDocumentNavigationServiceExtensions
{
public static Task<bool> CanNavigateToSpanAsync(this IDocumentNavigationService service, Workspace workspace, DocumentId documentId, TextSpan textSpan, CancellationToken cancellationToken)
=> service.CanNavigateToSpanAsync(workspace, documentId, textSpan, allowInvalidSpan: false, cancellationToken);

public static Task<bool> CanNavigateToPositionAsync(this IDocumentNavigationService service, Workspace workspace, DocumentId documentId, int position, CancellationToken cancellationToken)
=> service.CanNavigateToPositionAsync(workspace, documentId, position, virtualSpace: 0, cancellationToken);

Expand Down
Loading

0 comments on commit 13cd975

Please sign in to comment.