Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make change signature more async and remove UI dialogs from the service #47768

Merged
merged 21 commits into from
Dec 18, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ internal ChangeSignatureResult ChangeSignature(Document document, int position,
switch (context)
{
case ChangeSignatureAnalysisSucceededContext changeSignatureAnalyzedSucceedContext:
return ChangeSignatureWithContext(changeSignatureAnalyzedSucceedContext, cancellationToken);
return ChangeSignatureWithContextAsync(changeSignatureAnalyzedSucceedContext, cancellationToken).WaitAndGetResult_CanCallOnBackground(cancellationToken);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the next commit, I make this async as well and move the wait up to the command handler

case CannotChangeSignatureAnalyzedContext cannotChangeSignatureAnalyzedContext:
switch (cannotChangeSignatureAnalyzedContext.CannotChangeSignatureReason)
{
Expand Down Expand Up @@ -200,21 +200,21 @@ internal async Task<ChangeSignatureAnalyzedContext> GetContextAsync(
declarationDocument, positionForTypeBinding, symbol, parameterConfiguration);
}

private ChangeSignatureResult ChangeSignatureWithContext(ChangeSignatureAnalysisSucceededContext context, CancellationToken cancellationToken)
private Task<ChangeSignatureResult> ChangeSignatureWithContextAsync(ChangeSignatureAnalysisSucceededContext context, CancellationToken cancellationToken)
{
var options = GetChangeSignatureOptions(context);
if (options == null)
{
return new ChangeSignatureResult(succeeded: false);
return Task.FromResult(new ChangeSignatureResult(succeeded: false));
}

return ChangeSignatureWithContext(context, options, cancellationToken);
return ChangeSignatureWithContextAsync(context, options, cancellationToken);
}

internal ChangeSignatureResult ChangeSignatureWithContext(ChangeSignatureAnalysisSucceededContext context, ChangeSignatureOptionsResult options, CancellationToken cancellationToken)
internal async Task<ChangeSignatureResult> ChangeSignatureWithContextAsync(ChangeSignatureAnalysisSucceededContext context, ChangeSignatureOptionsResult options, CancellationToken cancellationToken)
{
var succeeded = TryCreateUpdatedSolution(context, options, cancellationToken, out var updatedSolution);
return new ChangeSignatureResult(succeeded, updatedSolution, context.Symbol.ToDisplayString(), context.Symbol.GetGlyph(), options.PreviewChanges);
var updatedSolution = await TryCreateUpdatedSolutionAsync(context, options, cancellationToken).ConfigureAwait(false);
return new ChangeSignatureResult(updatedSolution != null, updatedSolution, context.Symbol.ToDisplayString(), context.Symbol.GetGlyph(), options.PreviewChanges);
}

/// <returns>Returns <c>null</c> if the operation is cancelled.</returns>
Expand Down Expand Up @@ -250,13 +250,11 @@ private static async Task<ImmutableArray<ReferencedSymbol>> FindChangeSignatureR

#nullable enable
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there anything left in this file that isn't #nullable enabled or isn't easily updated?


private bool TryCreateUpdatedSolution(
ChangeSignatureAnalysisSucceededContext context, ChangeSignatureOptionsResult options, CancellationToken cancellationToken, [NotNullWhen(true)] out Solution? updatedSolution)
private async Task<Solution?> TryCreateUpdatedSolutionAsync(
ChangeSignatureAnalysisSucceededContext context, ChangeSignatureOptionsResult options, CancellationToken cancellationToken)
{
var telemetryTimer = Stopwatch.StartNew();

updatedSolution = null;

var currentSolution = context.Solution;
var declaredSymbol = context.Symbol;

Expand All @@ -265,8 +263,8 @@ private bool TryCreateUpdatedSolution(

var hasLocationsInMetadata = false;

var symbols = FindChangeSignatureReferencesAsync(
declaredSymbol, context.Solution, cancellationToken).WaitAndGetResult(cancellationToken);
var symbols = await FindChangeSignatureReferencesAsync(
declaredSymbol, context.Solution, cancellationToken).ConfigureAwait(false);

var declaredSymbolParametersCount = declaredSymbol.GetParameters().Length;

Expand Down Expand Up @@ -387,7 +385,7 @@ private bool TryCreateUpdatedSolution(
var notificationService = context.Solution.Workspace.Services.GetRequiredService<INotificationService>();
if (!notificationService.ConfirmMessageBox(FeaturesResources.This_symbol_has_related_definitions_or_references_in_metadata_Changing_its_signature_may_result_in_build_errors_Do_you_want_to_continue, severity: NotificationSeverity.Warning))
Copy link
Member Author

@dibarbet dibarbet Sep 16, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is moved in the next commit to the proper locations

{
return false;
return null;
}
}
dibarbet marked this conversation as resolved.
Show resolved Hide resolved

Expand All @@ -397,7 +395,7 @@ private bool TryCreateUpdatedSolution(
{
var doc = currentSolution.GetRequiredDocument(docId);
var updater = doc.Project.LanguageServices.GetRequiredService<AbstractChangeSignatureService>();
var root = doc.GetSyntaxRootSynchronously(CancellationToken.None);
var root = await doc.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
if (root is null)
{
throw new NotSupportedException(WorkspacesResources.Document_does_not_support_syntax_trees);
Expand All @@ -422,7 +420,7 @@ private bool TryCreateUpdatedSolution(
newRoot,
changeSignatureFormattingAnnotation,
doc.Project.Solution.Workspace,
options: doc.GetOptionsAsync(cancellationToken).WaitAndGetResult(cancellationToken),
options: await doc.GetOptionsAsync(cancellationToken).ConfigureAwait(false),
rules: GetFormattingRules(doc),
cancellationToken: CancellationToken.None);

Expand All @@ -433,18 +431,17 @@ private bool TryCreateUpdatedSolution(
foreach (var docId in nodesToUpdate.Keys)
{
var updatedDoc = currentSolution.GetRequiredDocument(docId).WithSyntaxRoot(updatedRoots[docId]);
var docWithImports = ImportAdder.AddImportsFromSymbolAnnotationAsync(updatedDoc, cancellationToken: cancellationToken).WaitAndGetResult(cancellationToken);
var reducedDoc = Simplifier.ReduceAsync(docWithImports, Simplifier.Annotation, cancellationToken: cancellationToken).WaitAndGetResult(cancellationToken);
var formattedDoc = Formatter.FormatAsync(reducedDoc, SyntaxAnnotation.ElasticAnnotation, cancellationToken: cancellationToken).WaitAndGetResult(cancellationToken);
var docWithImports = await ImportAdder.AddImportsFromSymbolAnnotationAsync(updatedDoc, cancellationToken: cancellationToken).ConfigureAwait(false);
var reducedDoc = await Simplifier.ReduceAsync(docWithImports, Simplifier.Annotation, cancellationToken: cancellationToken).ConfigureAwait(false);
var formattedDoc = await Formatter.FormatAsync(reducedDoc, SyntaxAnnotation.ElasticAnnotation, cancellationToken: cancellationToken).ConfigureAwait(false);

currentSolution = currentSolution.WithDocumentSyntaxRoot(docId, formattedDoc.GetSyntaxRootSynchronously(cancellationToken)!);
currentSolution = currentSolution.WithDocumentSyntaxRoot(docId, (await formattedDoc.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false))!);
}

telemetryTimer.Stop();
ChangeSignatureLogger.LogCommitInformation(telemetryNumberOfDeclarationsToUpdate, telemetryNumberOfReferencesToUpdate, (int)telemetryTimer.ElapsedMilliseconds);

updatedSolution = currentSolution;
return true;
return currentSolution;
}

#nullable restore
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,19 @@ public ChangeSignatureCodeAction(AbstractChangeSignatureService changeSignatureS
public override object? GetOptions(CancellationToken cancellationToken)
=> AbstractChangeSignatureService.GetChangeSignatureOptions(_context);

protected override Task<IEnumerable<CodeActionOperation>> ComputeOperationsAsync(object options, CancellationToken cancellationToken)
protected override async Task<IEnumerable<CodeActionOperation>> ComputeOperationsAsync(object options, CancellationToken cancellationToken)
{
if (options is ChangeSignatureOptionsResult changeSignatureOptions && changeSignatureOptions != null)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (options is ChangeSignatureOptionsResult changeSignatureOptions && changeSignatureOptions != null)
if (options is ChangeSignatureOptionsResult changeSignatureOptions)

If the first test is true, it can't be null.

{
var changeSignatureResult = _changeSignatureService.ChangeSignatureWithContext(_context, changeSignatureOptions, cancellationToken);
var changeSignatureResult = await _changeSignatureService.ChangeSignatureWithContextAsync(_context, changeSignatureOptions, cancellationToken).ConfigureAwait(false);

if (changeSignatureResult.Succeeded)
{
return Task.FromResult(SpecializedCollections.SingletonEnumerable<CodeActionOperation>(new ApplyChangesOperation(changeSignatureResult.UpdatedSolution!)));
return SpecializedCollections.SingletonEnumerable<CodeActionOperation>(new ApplyChangesOperation(changeSignatureResult.UpdatedSolution!));
}
}

return SpecializedTasks.EmptyEnumerable<CodeActionOperation>();
return SpecializedCollections.EmptyEnumerable<CodeActionOperation>();
}
}
}