Skip to content

Commit

Permalink
Merge pull request #875 from sharwell/first-iteration
Browse files Browse the repository at this point in the history
Only require code fix for first iteration
  • Loading branch information
sharwell authored Jun 23, 2021
2 parents db69a5b + b5e8451 commit 70dbc0e
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -110,16 +110,22 @@ protected static bool HasAnyChange(ProjectState oldState, ProjectState newState,
return false;
}

protected static CodeAction? TryGetCodeActionToApply(ImmutableArray<CodeAction> actions, int? codeActionIndex, string? codeActionEquivalenceKey, Action<CodeAction, IVerifier>? codeActionVerifier, IVerifier verifier)
protected static CodeAction? TryGetCodeActionToApply(int iteration, ImmutableArray<CodeAction> actions, int? codeActionIndex, string? codeActionEquivalenceKey, Action<CodeAction, IVerifier>? codeActionVerifier, IVerifier verifier)
{
CodeAction? result;
if (codeActionIndex.HasValue && codeActionEquivalenceKey != null)
{
if (actions.Length <= codeActionIndex)
var expectedAction = actions.FirstOrDefault(action => action.EquivalenceKey == codeActionEquivalenceKey);
if (expectedAction is null && iteration > 0)
{
// No matching code action was found. This is acceptable if this is not the first iteration.
return null;
}

verifier.True(
actions.Length > codeActionIndex,
$"Expected to find a code action at index '{codeActionIndex}', but only '{actions.Length}' code actions were found.");

verifier.Equal(
codeActionEquivalenceKey,
actions[codeActionIndex.Value].EquivalenceKey,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ static Microsoft.CodeAnalysis.Testing.AnalyzerVerifier<TAnalyzer, TTest, TVerifi
static Microsoft.CodeAnalysis.Testing.AnalyzerVerifier<TAnalyzer, TTest, TVerifier>.VerifyAnalyzerAsync(string source, params Microsoft.CodeAnalysis.Testing.DiagnosticResult[] expected) -> System.Threading.Tasks.Task
static Microsoft.CodeAnalysis.Testing.CodeActionTest<TVerifier>.CodeActionExpected(Microsoft.CodeAnalysis.Testing.SolutionState state) -> bool
static Microsoft.CodeAnalysis.Testing.CodeActionTest<TVerifier>.HasAnyChange(Microsoft.CodeAnalysis.Testing.ProjectState oldState, Microsoft.CodeAnalysis.Testing.ProjectState newState, bool recursive) -> bool
static Microsoft.CodeAnalysis.Testing.CodeActionTest<TVerifier>.TryGetCodeActionToApply(System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.CodeActions.CodeAction> actions, int? codeActionIndex, string codeActionEquivalenceKey, System.Action<Microsoft.CodeAnalysis.CodeActions.CodeAction, Microsoft.CodeAnalysis.Testing.IVerifier> codeActionVerifier, Microsoft.CodeAnalysis.Testing.IVerifier verifier) -> Microsoft.CodeAnalysis.CodeActions.CodeAction
static Microsoft.CodeAnalysis.Testing.CodeActionTest<TVerifier>.TryGetCodeActionToApply(int iteration, System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.CodeActions.CodeAction> actions, int? codeActionIndex, string codeActionEquivalenceKey, System.Action<Microsoft.CodeAnalysis.CodeActions.CodeAction, Microsoft.CodeAnalysis.Testing.IVerifier> codeActionVerifier, Microsoft.CodeAnalysis.Testing.IVerifier verifier) -> Microsoft.CodeAnalysis.CodeActions.CodeAction
static Microsoft.CodeAnalysis.Testing.DiagnosticResult.CompilerError(string identifier) -> Microsoft.CodeAnalysis.Testing.DiagnosticResult
static Microsoft.CodeAnalysis.Testing.DiagnosticResult.CompilerWarning(string identifier) -> Microsoft.CodeAnalysis.Testing.DiagnosticResult
static Microsoft.CodeAnalysis.Testing.IVerifierExtensions.EqualOrDiff(this Microsoft.CodeAnalysis.Testing.IVerifier verifier, string expected, string actual, string message = null) -> void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -534,9 +534,12 @@ private async Task VerifyProjectAsync(ProjectState newState, Project project, IV

var previousDiagnostics = ImmutableArray.Create<(Project project, Diagnostic diagnostic)>();

var currentIteration = -1;
bool done;
do
{
currentIteration++;

var analyzerDiagnostics = await GetSortedDiagnosticsAsync(project.Solution, analyzers, additionalDiagnostics: ImmutableArray<(Project project, Diagnostic diagnostic)>.Empty, CompilerDiagnostics, verifier, cancellationToken).ConfigureAwait(false);
if (analyzerDiagnostics.Length == 0)
{
Expand Down Expand Up @@ -590,7 +593,7 @@ private async Task VerifyProjectAsync(ProjectState newState, Project project, IV
}

var filteredActions = FilterCodeActions(actions.ToImmutable());
var actionToApply = TryGetCodeActionToApply(filteredActions, codeFixIndex, codeFixEquivalenceKey, codeActionVerifier, verifier);
var actionToApply = TryGetCodeActionToApply(currentIteration, filteredActions, codeFixIndex, codeFixEquivalenceKey, codeActionVerifier, verifier);
if (actionToApply != null)
{
anyActions = true;
Expand Down Expand Up @@ -672,9 +675,12 @@ private async Task VerifyProjectAsync(ProjectState newState, Project project, IV

var previousDiagnostics = ImmutableArray.Create<(Project project, Diagnostic diagnostic)>();

var currentIteration = -1;
bool done;
do
{
currentIteration++;

var analyzerDiagnostics = await GetSortedDiagnosticsAsync(project.Solution, analyzers, additionalDiagnostics: ImmutableArray<(Project project, Diagnostic diagnostic)>.Empty, CompilerDiagnostics, verifier, cancellationToken).ConfigureAwait(false);
if (analyzerDiagnostics.Length == 0)
{
Expand Down Expand Up @@ -728,7 +734,7 @@ private async Task VerifyProjectAsync(ProjectState newState, Project project, IV
actions.AddRange(FilterCodeActions(actionsBuilder.ToImmutable()).Select(action => (action, codeFixProvider)));
}

var actionToApply = TryGetCodeActionToApply(actions.Select(a => a.Item1).ToImmutableArray(), codeFixIndex, codeFixEquivalenceKey, codeActionVerifier, verifier);
var actionToApply = TryGetCodeActionToApply(currentIteration, actions.Select(a => a.Item1).ToImmutableArray(), codeFixIndex, codeFixEquivalenceKey, codeActionVerifier, verifier);
if (actionToApply != null)
{
firstDiagnostic = diagnostic;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,9 +227,12 @@ private async Task VerifyProjectAsync(ProjectState newState, Project project, IV
numberOfIterations = -numberOfIterations;
}

var currentIteration = -1;
bool done;
do
{
currentIteration++;

try
{
verifier.True(--numberOfIterations >= -1, "The upper limit for the number of code fix iterations was exceeded");
Expand All @@ -253,7 +256,7 @@ private async Task VerifyProjectAsync(ProjectState newState, Project project, IV
}

var filteredActions = FilterCodeActions(actions.ToImmutable());
var actionToApply = TryGetCodeActionToApply(filteredActions, codeActionIndex, codeActionEquivalenceKey, codeActionVerifier, verifier);
var actionToApply = TryGetCodeActionToApply(currentIteration, filteredActions, codeActionIndex, codeActionEquivalenceKey, codeActionVerifier, verifier);
if (actionToApply != null)
{
anyActions = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,67 @@ class TestClass2 {
Assert.Equal($"Context: {context}{Environment.NewLine}Expected '2' iterations but found '1' iterations.", exception.Message);
}

[Fact]
[WorkItem(874, "https://github.com/dotnet/roslyn-sdk/issues/874")]
public async Task TestTwoIterationsRequiredButOneApplied()
{
var testCode = @"
class TestClass {
int field = [|3|];
}
";
var fixedCode = @"
class TestClass {
int field = [|4|];
}
";

await new CSharpTest
{
TestCode = testCode,
FixedState =
{
Sources = { fixedCode },
MarkupHandling = MarkupMode.Allow,
},
CodeActionEquivalenceKey = "IncrementFix:4",
CodeActionIndex = 0,
}.RunAsync();
}

[Fact]
[WorkItem(874, "https://github.com/dotnet/roslyn-sdk/issues/874")]
public async Task TestTwoIterationsRequiredButNoneApplied()
{
var testCode = @"
class TestClass {
int field = [|3|];
}
";
var fixedCode = @"
class TestClass {
int field = [|4|];
}
";

var exception = await Assert.ThrowsAsync<InvalidOperationException>(async () =>
{
await new CSharpTest
{
TestCode = testCode,
FixedState =
{
Sources = { fixedCode },
MarkupHandling = MarkupMode.Allow,
},
CodeActionEquivalenceKey = "IncrementFix:3",
CodeActionIndex = 0,
}.RunAsync();
});

new DefaultVerifier().EqualOrDiff($"Context: Iterative code fix application{Environment.NewLine}The code action equivalence key and index must be consistent when both are specified.", exception.Message);
}

private class CSharpTest : CSharpCodeFixTest<LiteralUnderFiveAnalyzer, IncrementFix>
{
public int DiagnosticIndexToFix { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ namespace Microsoft.CodeAnalysis.Testing.TestAnalyzers
[DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)]
public class LiteralUnderFiveAnalyzer : DiagnosticAnalyzer
{
internal const string CurrentValueProperty = nameof(CurrentValueProperty);

internal static readonly DiagnosticDescriptor Descriptor =
new DiagnosticDescriptor("LiteralUnderFive", "title", "message", "category", DiagnosticSeverity.Warning, isEnabledByDefault: true);

Expand All @@ -34,7 +36,9 @@ private void HandleLiteralOperation(OperationAnalysisContext context)
&& operation.ConstantValue.Value is int value
&& value < 5)
{
context.ReportDiagnostic(Diagnostic.Create(Descriptor, operation.Syntax.GetLocation()));
var properties = ImmutableDictionary<string, string?>.Empty
.Add(CurrentValueProperty, value.ToString());
context.ReportDiagnostic(Diagnostic.Create(Descriptor, operation.Syntax.GetLocation(), properties));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
CodeAction.Create(
"LiteralUnderFive",
cancellationToken => CreateChangedDocument(context.Document, diagnostic.Location.SourceSpan, cancellationToken),
nameof(IncrementFix)),
$"{nameof(IncrementFix)}:{int.Parse(diagnostic.Properties[LiteralUnderFiveAnalyzer.CurrentValueProperty]!) + 1}"),
diagnostic);
}

Expand Down

0 comments on commit 70dbc0e

Please sign in to comment.