Родитель
d1f6cbb7d0
Коммит
71e83fbfdd
|
@ -7,6 +7,7 @@ using System.Collections.Generic;
|
|||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.ExceptionServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -195,17 +196,18 @@ namespace Microsoft.CodeAnalysis.Testing
|
|||
/// <param name="verifier">The verifier to use for test assertions.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that the task will observe.</param>
|
||||
/// <returns>A <see cref="Project"/> with the changes from the <see cref="CodeAction"/>.</returns>
|
||||
protected async Task<Project> ApplyCodeActionAsync(Project project, CodeAction codeAction, IVerifier verifier, CancellationToken cancellationToken)
|
||||
protected async Task<(Project updatedProject, ExceptionDispatchInfo? validationError)> ApplyCodeActionAsync(Project project, CodeAction codeAction, IVerifier verifier, CancellationToken cancellationToken)
|
||||
{
|
||||
var operations = await codeAction.GetOperationsAsync(cancellationToken).ConfigureAwait(false);
|
||||
var solution = operations.OfType<ApplyChangesOperation>().Single().ChangedSolution;
|
||||
var changedProject = solution.GetProject(project.Id);
|
||||
ExceptionDispatchInfo? validationError = null;
|
||||
if (changedProject != project)
|
||||
{
|
||||
project = await RecreateProjectDocumentsAsync(changedProject, verifier, cancellationToken).ConfigureAwait(false);
|
||||
(project, validationError) = await RecreateProjectDocumentsAsync(changedProject, verifier, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return project;
|
||||
return (project, validationError);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -215,15 +217,16 @@ namespace Microsoft.CodeAnalysis.Testing
|
|||
/// <param name="verifier">The verifier to use for test assertions.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/>.</param>
|
||||
/// <returns>The updated <see cref="Project"/>.</returns>
|
||||
private async Task<Project> RecreateProjectDocumentsAsync(Project project, IVerifier verifier, CancellationToken cancellationToken)
|
||||
private async Task<(Project updatedProject, ExceptionDispatchInfo? validationError)> RecreateProjectDocumentsAsync(Project project, IVerifier verifier, CancellationToken cancellationToken)
|
||||
{
|
||||
ExceptionDispatchInfo? validationError = null;
|
||||
foreach (var documentId in project.DocumentIds)
|
||||
{
|
||||
var document = project.GetDocument(documentId);
|
||||
var initialTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);
|
||||
document = await RecreateDocumentAsync(document, cancellationToken).ConfigureAwait(false);
|
||||
var recreatedTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);
|
||||
if (CodeActionValidationMode != CodeActionValidationMode.None)
|
||||
if (CodeActionValidationMode != CodeActionValidationMode.None && validationError is null)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -236,23 +239,32 @@ namespace Microsoft.CodeAnalysis.Testing
|
|||
await initialTree.GetRootAsync(cancellationToken).ConfigureAwait(false),
|
||||
checkTrivia: CodeActionValidationMode == CodeActionValidationMode.Full);
|
||||
}
|
||||
catch
|
||||
catch (Exception genericError)
|
||||
{
|
||||
// Try to revalidate the tree with a better message
|
||||
var renderedInitialTree = TreeToString(await initialTree.GetRootAsync(cancellationToken).ConfigureAwait(false), CodeActionValidationMode);
|
||||
var renderedRecreatedTree = TreeToString(await recreatedTree.GetRootAsync(cancellationToken).ConfigureAwait(false), CodeActionValidationMode);
|
||||
verifier.EqualOrDiff(renderedRecreatedTree, renderedInitialTree);
|
||||
|
||||
// This is not expected to be hit, but it will be hit if the validation failure occurred in a
|
||||
// portion of the tree not captured by the rendered form from TreeToString.
|
||||
throw;
|
||||
try
|
||||
{
|
||||
verifier.EqualOrDiff(renderedRecreatedTree, renderedInitialTree);
|
||||
}
|
||||
catch (Exception specificError)
|
||||
{
|
||||
validationError = ExceptionDispatchInfo.Capture(specificError);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// This is not expected to be hit, but it will be hit if the validation failure occurred in
|
||||
// a portion of the tree not captured by the rendered form from TreeToString.
|
||||
validationError ??= ExceptionDispatchInfo.Capture(genericError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
project = document.Project;
|
||||
}
|
||||
|
||||
return project;
|
||||
return (project, validationError);
|
||||
}
|
||||
|
||||
private static async Task<Document> RecreateDocumentAsync(Document document, CancellationToken cancellationToken)
|
||||
|
|
|
@ -28,7 +28,7 @@ Microsoft.CodeAnalysis.Testing.AnalyzerTest<TVerifier>.XmlReferences.get -> Syst
|
|||
Microsoft.CodeAnalysis.Testing.AnalyzerVerifier<TAnalyzer, TTest, TVerifier>
|
||||
Microsoft.CodeAnalysis.Testing.AnalyzerVerifier<TAnalyzer, TTest, TVerifier>.AnalyzerVerifier() -> void
|
||||
Microsoft.CodeAnalysis.Testing.CodeActionTest<TVerifier>
|
||||
Microsoft.CodeAnalysis.Testing.CodeActionTest<TVerifier>.ApplyCodeActionAsync(Microsoft.CodeAnalysis.Project project, Microsoft.CodeAnalysis.CodeActions.CodeAction codeAction, Microsoft.CodeAnalysis.Testing.IVerifier verifier, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task<Microsoft.CodeAnalysis.Project>
|
||||
Microsoft.CodeAnalysis.Testing.CodeActionTest<TVerifier>.ApplyCodeActionAsync(Microsoft.CodeAnalysis.Project project, Microsoft.CodeAnalysis.CodeActions.CodeAction codeAction, Microsoft.CodeAnalysis.Testing.IVerifier verifier, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task<(Microsoft.CodeAnalysis.Project updatedProject, System.Runtime.ExceptionServices.ExceptionDispatchInfo validationError)>
|
||||
Microsoft.CodeAnalysis.Testing.CodeActionTest<TVerifier>.CodeActionEquivalenceKey.get -> string
|
||||
Microsoft.CodeAnalysis.Testing.CodeActionTest<TVerifier>.CodeActionEquivalenceKey.set -> void
|
||||
Microsoft.CodeAnalysis.Testing.CodeActionTest<TVerifier>.CodeActionIndex.get -> int?
|
||||
|
|
|
@ -535,6 +535,7 @@ namespace Microsoft.CodeAnalysis.Testing
|
|||
|
||||
var previousDiagnostics = ImmutableArray.Create<(Project project, Diagnostic diagnostic)>();
|
||||
|
||||
ExceptionDispatchInfo? firstValidationError = null;
|
||||
var currentIteration = -1;
|
||||
bool done;
|
||||
do
|
||||
|
@ -558,7 +559,7 @@ namespace Microsoft.CodeAnalysis.Testing
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return (project, ExceptionDispatchInfo.Capture(ex));
|
||||
return (project, firstValidationError ?? ExceptionDispatchInfo.Capture(ex));
|
||||
}
|
||||
|
||||
previousDiagnostics = analyzerDiagnostics;
|
||||
|
@ -600,7 +601,8 @@ namespace Microsoft.CodeAnalysis.Testing
|
|||
anyActions = true;
|
||||
|
||||
var originalProjectId = project.Id;
|
||||
var fixedProject = await ApplyCodeActionAsync(fixableDocument.Project, actionToApply, verifier, cancellationToken).ConfigureAwait(false);
|
||||
var (fixedProject, currentError) = await ApplyCodeActionAsync(fixableDocument.Project, actionToApply, verifier, cancellationToken).ConfigureAwait(false);
|
||||
firstValidationError ??= currentError;
|
||||
if (fixedProject != fixableDocument.Project)
|
||||
{
|
||||
done = false;
|
||||
|
@ -638,10 +640,10 @@ namespace Microsoft.CodeAnalysis.Testing
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return (project, ExceptionDispatchInfo.Capture(ex));
|
||||
return (project, firstValidationError ?? ExceptionDispatchInfo.Capture(ex));
|
||||
}
|
||||
|
||||
return (project, null);
|
||||
return (project, firstValidationError ?? null);
|
||||
}
|
||||
|
||||
private Task<(Project project, ExceptionDispatchInfo? iterationCountFailure)> FixAllAnalyzerDiagnosticsInDocumentAsync(ImmutableArray<DiagnosticAnalyzer> analyzers, ImmutableArray<CodeFixProvider> codeFixProviders, int? codeFixIndex, string? codeFixEquivalenceKey, Action<CodeAction, IVerifier>? codeActionVerifier, Project project, int numberOfIterations, IVerifier verifier, CancellationToken cancellationToken)
|
||||
|
@ -676,6 +678,7 @@ namespace Microsoft.CodeAnalysis.Testing
|
|||
|
||||
var previousDiagnostics = ImmutableArray.Create<(Project project, Diagnostic diagnostic)>();
|
||||
|
||||
ExceptionDispatchInfo? firstValidationError = null;
|
||||
var currentIteration = -1;
|
||||
bool done;
|
||||
do
|
||||
|
@ -699,7 +702,7 @@ namespace Microsoft.CodeAnalysis.Testing
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return (project, ExceptionDispatchInfo.Capture(ex));
|
||||
return (project, firstValidationError ?? ExceptionDispatchInfo.Capture(ex));
|
||||
}
|
||||
|
||||
var fixableDiagnostics = analyzerDiagnostics
|
||||
|
@ -772,7 +775,8 @@ namespace Microsoft.CodeAnalysis.Testing
|
|||
}
|
||||
|
||||
var originalProjectId = project.Id;
|
||||
var fixedProject = await ApplyCodeActionAsync(fixableDocument.Project, action, verifier, cancellationToken).ConfigureAwait(false);
|
||||
var (fixedProject, currentError) = await ApplyCodeActionAsync(fixableDocument.Project, action, verifier, cancellationToken).ConfigureAwait(false);
|
||||
firstValidationError ??= currentError;
|
||||
if (fixedProject != fixableDocument.Project)
|
||||
{
|
||||
done = false;
|
||||
|
@ -799,10 +803,10 @@ namespace Microsoft.CodeAnalysis.Testing
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return (project, ExceptionDispatchInfo.Capture(ex));
|
||||
return (project, firstValidationError ?? ExceptionDispatchInfo.Capture(ex));
|
||||
}
|
||||
|
||||
return (project, null);
|
||||
return (project, firstValidationError);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -227,6 +227,7 @@ namespace Microsoft.CodeAnalysis.Testing
|
|||
numberOfIterations = -numberOfIterations;
|
||||
}
|
||||
|
||||
ExceptionDispatchInfo? firstValidationError = null;
|
||||
var currentIteration = -1;
|
||||
bool done;
|
||||
do
|
||||
|
@ -239,7 +240,7 @@ namespace Microsoft.CodeAnalysis.Testing
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return (project, ExceptionDispatchInfo.Capture(ex));
|
||||
return (project, firstValidationError ?? ExceptionDispatchInfo.Capture(ex));
|
||||
}
|
||||
|
||||
done = true;
|
||||
|
@ -262,7 +263,8 @@ namespace Microsoft.CodeAnalysis.Testing
|
|||
anyActions = true;
|
||||
|
||||
var originalProjectId = project.Id;
|
||||
var fixedProject = await ApplyCodeActionAsync(triggerDocument.Project, actionToApply, verifier, cancellationToken).ConfigureAwait(false);
|
||||
var (fixedProject, currentError) = await ApplyCodeActionAsync(triggerDocument.Project, actionToApply, verifier, cancellationToken).ConfigureAwait(false);
|
||||
firstValidationError ??= currentError;
|
||||
if (fixedProject != triggerDocument.Project)
|
||||
{
|
||||
done = false;
|
||||
|
@ -294,10 +296,10 @@ namespace Microsoft.CodeAnalysis.Testing
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return (project, ExceptionDispatchInfo.Capture(ex));
|
||||
return (project, firstValidationError ?? ExceptionDispatchInfo.Capture(ex));
|
||||
}
|
||||
|
||||
return (project, null);
|
||||
return (project, firstValidationError);
|
||||
|
||||
async Task<Location> GetTriggerLocationAsync()
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче