提交 a0f4c9a2 编写于 作者: C CyrusNajmabadi

Extract out common FixAll code. It will be used for other diagnostic analyzers we have.

上级 142d9116
......@@ -9,6 +9,7 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeFixes.FixAllOccurrences;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
......@@ -31,7 +32,7 @@ internal partial class InvokeDelegateWithConditionalAccessCodeFixProvider : Code
/// By taking control ourselves, we can simply make all the tree edits and not have to
/// try to back-infer textual changes which then may or may not merge properly.
/// </summary>
private class InvokeDelegateWithConditionalAccessFixAllProvider : BatchFixAllProvider
private class InvokeDelegateWithConditionalAccessFixAllProvider : DocumentBasedFixAllProvider
{
private readonly InvokeDelegateWithConditionalAccessCodeFixProvider _provider;
......@@ -40,32 +41,8 @@ public InvokeDelegateWithConditionalAccessFixAllProvider(InvokeDelegateWithCondi
_provider = provider;
}
internal override async Task<CodeAction> GetFixAsync(
ImmutableDictionary<Document, ImmutableArray<Diagnostic>> documentsAndDiagnosticsToFixMap,
FixAllState fixAllState,
CancellationToken cancellationToken)
{
// Process all documents in parallel.
var updatedDocumentTasks = documentsAndDiagnosticsToFixMap.Select(
kvp => FixAsync(fixAllState, kvp.Key, kvp.Value, cancellationToken));
await Task.WhenAll(updatedDocumentTasks).ConfigureAwait(false);
var currentSolution = fixAllState.Solution;
foreach (var task in updatedDocumentTasks)
{
var updatedDocument = await task.ConfigureAwait(false);
currentSolution = currentSolution.WithDocumentSyntaxRoot(
updatedDocument.Id,
await updatedDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false));
}
var title = GetFixAllTitle(fixAllState);
return new CodeAction.SolutionChangeAction(title, _ => Task.FromResult(currentSolution));
}
private Task<Document> FixAsync(
FixAllState fixAllState, Document document, ImmutableArray<Diagnostic> diagnostics, CancellationToken cancellationToken)
protected override Task<Document> FixDocumentAsync(
Document document, ImmutableArray<Diagnostic> diagnostics, CancellationToken cancellationToken)
{
// Filter out the diagnostics we created for the faded out code. We don't want
// to try to fix those as well as the normal diagnostics we created.
......@@ -78,4 +55,4 @@ public InvokeDelegateWithConditionalAccessFixAllProvider(InvokeDelegateWithCondi
}
}
}
}
}
\ No newline at end of file
......@@ -209,36 +209,7 @@ public override async Task<CodeAction> GetFixAsync(FixAllContext fixAllContext)
public virtual string GetFixAllTitle(FixAllState fixAllState)
{
var diagnosticIds = fixAllState.DiagnosticIds;
string diagnosticId;
if (diagnosticIds.Count() == 1)
{
diagnosticId = diagnosticIds.Single();
}
else
{
diagnosticId = string.Join(",", diagnosticIds.ToArray());
}
switch (fixAllState.Scope)
{
case FixAllScope.Custom:
return string.Format(WorkspacesResources.Fix_all_0, diagnosticId);
case FixAllScope.Document:
var document = fixAllState.Document;
return string.Format(WorkspacesResources.Fix_all_0_in_1, diagnosticId, document.Name);
case FixAllScope.Project:
var project = fixAllState.Project;
return string.Format(WorkspacesResources.Fix_all_0_in_1, diagnosticId, project.Name);
case FixAllScope.Solution:
return string.Format(WorkspacesResources.Fix_all_0_in_Solution, diagnosticId);
default:
throw ExceptionUtilities.Unreachable;
}
return FixAllProvider.GetFixAllTitle(fixAllState);
}
public virtual async Task<Solution> TryMergeFixesAsync(
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
namespace Microsoft.CodeAnalysis.CodeFixes.FixAllOccurrences
{
/// <summary>
/// A simple implementation of <see cref="FixAllProvider"/> that takes care of collecting
/// all the diagnostics and fixes all documents in parallel. The only functionality a
/// subclass needs to provide is how each document will apply all the fixes to all the
/// diagnostics in that document.
/// </summary>
internal abstract class DocumentBasedFixAllProvider : FixAllProvider
{
public sealed override async Task<CodeAction> GetFixAsync(FixAllContext fixAllContext)
{
var documentsAndDiagnosticsToFixMap = await fixAllContext.GetDocumentDiagnosticsToFixAsync().ConfigureAwait(false);
return await GetFixAsync(documentsAndDiagnosticsToFixMap, fixAllContext.State, fixAllContext.CancellationToken).ConfigureAwait(false);
}
internal sealed override async Task<CodeAction> GetFixAsync(
ImmutableDictionary<Document, ImmutableArray<Diagnostic>> documentsAndDiagnosticsToFixMap,
FixAllState fixAllState,
CancellationToken cancellationToken)
{
// Process all documents in parallel.
var updatedDocumentTasks = documentsAndDiagnosticsToFixMap.Select(
kvp => FixDocumentAsync(kvp.Key, kvp.Value, cancellationToken));
await Task.WhenAll(updatedDocumentTasks).ConfigureAwait(false);
var currentSolution = fixAllState.Solution;
foreach (var task in updatedDocumentTasks)
{
var updatedDocument = await task.ConfigureAwait(false);
currentSolution = currentSolution.WithDocumentSyntaxRoot(
updatedDocument.Id,
await updatedDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false));
}
var title = GetFixAllTitle(fixAllState);
return new CodeAction.SolutionChangeAction(title, _ => Task.FromResult(currentSolution));
}
protected abstract Task<Document> FixDocumentAsync(
Document document, ImmutableArray<Diagnostic> diagnostics, CancellationToken cancellationToken);
}
}
......@@ -2,9 +2,11 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CodeFixes
{
......@@ -54,5 +56,39 @@ public virtual IEnumerable<string> GetSupportedFixAllDiagnosticIds(CodeFixProvid
{
return Task.FromResult<CodeAction>(null);
}
internal static string GetFixAllTitle(FixAllState fixAllState)
{
var diagnosticIds = fixAllState.DiagnosticIds;
string diagnosticId;
if (diagnosticIds.Count() == 1)
{
diagnosticId = diagnosticIds.Single();
}
else
{
diagnosticId = string.Join(",", diagnosticIds.ToArray());
}
switch (fixAllState.Scope)
{
case FixAllScope.Custom:
return string.Format(WorkspacesResources.Fix_all_0, diagnosticId);
case FixAllScope.Document:
var document = fixAllState.Document;
return string.Format(WorkspacesResources.Fix_all_0_in_1, diagnosticId, document.Name);
case FixAllScope.Project:
var project = fixAllState.Project;
return string.Format(WorkspacesResources.Fix_all_0_in_1, diagnosticId, project.Name);
case FixAllScope.Solution:
return string.Format(WorkspacesResources.Fix_all_0_in_Solution, diagnosticId);
default:
throw ExceptionUtilities.Unreachable;
}
}
}
}
\ No newline at end of file
......@@ -329,6 +329,7 @@
<Compile Include="CodeCleanup\Providers\SimplificationCodeCleanupProvider.cs" />
<Compile Include="CodeFixes\CodeFixContext.cs" />
<Compile Include="CodeFixes\FixAllOccurrences\BatchSimplificationFixAllProvider.cs" />
<Compile Include="CodeFixes\FixAllOccurrences\DocumentBasedFixAllProvider.cs" />
<Compile Include="CodeFixes\FixAllOccurrences\FixAllState.FixAllDiagnosticProvider.cs" />
<Compile Include="CodeFixes\FixAllOccurrences\FixAllProviderInfo.cs" />
<Compile Include="CodeFixes\FixAllOccurrences\FixAllState.FixMultipleDiagnosticProvider.cs" />
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册