提交 12476e8e 编写于 作者: C CyrusNajmabadi

Pull common FixAll logic into some helper base types that we can use across...

Pull common FixAll logic into some helper base types that we can use across many of our code style fixes.
上级 59c220df
......@@ -76,17 +76,13 @@
<Compile Include="UseExpressionBody\Operators\UseExpressionBodyForOperatorsDiagnosticAnalyzer.cs" />
<Compile Include="UseExpressionBody\Constructors\UseExpressionBodyForConstructorsCodeFixProvider.cs" />
<Compile Include="UseExpressionBody\Operators\UseExpressionBodyForOperatorsCodeFixProvider.cs" />
<Compile Include="UseExpressionBody\AbstractUseExpressionBodyCodeFixProvider.FixAllProvider.cs" />
<Compile Include="AddBraces\CSharpAddBracesCodeFixProvider.cs" />
<Compile Include="AddBraces\CSharpAddBracesDiagnosticAnalyzer.cs" />
<Compile Include="UseCollectionInitializer\CSharpUseCollectionInitializerCodeFixProvider.cs" />
<Compile Include="UseCollectionInitializer\CSharpUseCollectionInitializerDiagnosticAnalyzer.cs" />
<Compile Include="UseNullPropagation\CSharpUseNullPropagationCodeFixProvider.cs" />
<Compile Include="UseNullPropagation\CSharpUseNullPropagationDiagnosticAnalyzer.cs" />
<Compile Include="UsePatternMatching\CSharpIsAndCastCheckCodeFixProvider.InlineTypeCheckFixAllProvider.cs" />
<Compile Include="UsePatternMatching\CSharpIsAndCastCheckCodeFixProvider.cs" />
<Compile Include="UsePatternMatching\CSharpAsAndNullCheckCodeFixProvider.InlineTypeCheckFixAllProvider.cs" />
<Compile Include="InlineDeclaration\CSharpInlineDeclarationCodeFixProvider.InlineDeclarationFixAllProvider.cs" />
<Compile Include="UsePatternMatching\CSharpIsAndCastCheckDiagnosticAnalyzer.cs" />
<Compile Include="UsePatternMatching\CSharpAsAndNullCheckDiagnosticAnalyzer.cs" />
<Compile Include="UsePatternMatching\CSharpAsAndNullCheckCodeFixProvider.cs" />
......@@ -352,7 +348,6 @@
<Compile Include="IntroduceVariable\CSharpIntroduceVariableService_IntroduceLocal.cs" />
<Compile Include="IntroduceVariable\CSharpIntroduceVariableService_IntroduceQueryLocal.cs" />
<Compile Include="InvokeDelegateWithConditionalAccess\InvokeDelegateWithConditionalAccessAnalyzer.cs" />
<Compile Include="InvokeDelegateWithConditionalAccess\InvokeDelegateWithConditionalAccessCodeFixProvider.FixAllProvider.cs" />
<Compile Include="InvokeDelegateWithConditionalAccess\InvokeDelegateWithConditionalAccessCodeFixProvider.cs" />
<Compile Include="LanguageServices\CSharpAnonymousTypeDisplayService.cs" />
<Compile Include="LanguageServices\CSharpSymbolDisplayService.cs" />
......
// 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.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeFixes.FixAllOccurrences;
namespace Microsoft.CodeAnalysis.CSharp.InlineDeclaration
{
internal partial class CSharpInlineDeclarationCodeFixProvider : CodeFixProvider
{
private class InlineDeclarationFixAllProvider : DocumentBasedFixAllProvider
{
private readonly CSharpInlineDeclarationCodeFixProvider _provider;
public InlineDeclarationFixAllProvider(CSharpInlineDeclarationCodeFixProvider provider)
{
_provider = provider;
}
protected override Task<Document> FixDocumentAsync(
Document document,
ImmutableArray<Diagnostic> diagnostics,
CancellationToken cancellationToken)
{
return _provider.FixAllAsync(document, diagnostics, cancellationToken);
}
}
}
}
\ No newline at end of file
......@@ -24,13 +24,11 @@
namespace Microsoft.CodeAnalysis.CSharp.InlineDeclaration
{
[ExportCodeFixProvider(LanguageNames.CSharp), Shared]
internal partial class CSharpInlineDeclarationCodeFixProvider : CodeFixProvider
internal partial class CSharpInlineDeclarationCodeFixProvider : SyntaxEditorBasedCodeFixProvider
{
public override ImmutableArray<string> FixableDiagnosticIds
=> ImmutableArray.Create(IDEDiagnosticIds.InlineDeclarationDiagnosticId);
public override FixAllProvider GetFixAllProvider() => new InlineDeclarationFixAllProvider(this);
public override Task RegisterCodeFixesAsync(CodeFixContext context)
{
context.RegisterCodeFix(new MyCodeAction(
......@@ -39,20 +37,11 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
return SpecializedTasks.EmptyTask;
}
private Task<Document> FixAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken)
=> FixAllAsync(document, ImmutableArray.Create(diagnostic), cancellationToken);
private async Task<Document> FixAllAsync(
Document document, ImmutableArray<Diagnostic> diagnostics, CancellationToken cancellationToken)
protected override async Task FixAllAsync(
Document document, ImmutableArray<Diagnostic> diagnostics,
SyntaxEditor editor, CancellationToken cancellationToken)
{
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
// Create an editor to do all the transformations. This allows us to fix all
// the diagnostics in a clean manner. If we used the normal batch fix provider
// then it might fail to apply all the individual text changes as many of the
// changes produced by the diff might end up overlapping others.
var editor = new SyntaxEditor(root, document.Project.Solution.Workspace);
var options = document.Project.Solution.Workspace.Options;
var options = document.Project.Solution.Options;
// Attempt to use an out-var declaration if that's the style the user prefers.
// Note: if using 'var' would cause a problem, we will use the actual type
......@@ -68,9 +57,6 @@ private Task<Document> FixAsync(Document document, Diagnostic diagnostic, Cancel
useVarWhenDeclaringLocals, useImplicitTypeForIntrinsicTypes,
cancellationToken).ConfigureAwait(false);
}
var newRoot = editor.GetChangedRoot();
return document.WithSyntaxRoot(newRoot);
}
private async Task AddEditsAsync(
......
// 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.CodeFixes;
using Microsoft.CodeAnalysis.CodeFixes.FixAllOccurrences;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.InvokeDelegateWithConditionalAccess
{
internal partial class InvokeDelegateWithConditionalAccessCodeFixProvider : CodeFixProvider
{
/// <summary>
/// We use a specialized <see cref="FixAllProvider"/> so that we can make many edits to
/// the syntax tree which would otherwise be in close proximity. Close-proximity
/// edits can fail in the normal <see cref="BatchFixAllProvider" />. That's because
/// each individual edit will be diffed in the syntax tree. The diff is purely textual
/// and may result in a value that doesn't actually correspond to the syntax edit
/// made. As such, the individual textual edits wll overlap and won't merge properly.
///
/// 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 : DocumentBasedFixAllProvider
{
private readonly InvokeDelegateWithConditionalAccessCodeFixProvider _provider;
public InvokeDelegateWithConditionalAccessFixAllProvider(InvokeDelegateWithConditionalAccessCodeFixProvider provider)
{
_provider = provider;
}
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.
var filteredDiagnostics = diagnostics.WhereAsArray(
d => !d.Descriptor.CustomTags.Contains(WellKnownDiagnosticTags.Unnecessary));
// Defer to the actual SimplifyNullCheckCodeFixProvider to process htis
// document. It can process all the diagnostics and apply them properly.
return _provider.FixAllAsync(document, filteredDiagnostics, cancellationToken);
}
}
}
}
\ No newline at end of file
......@@ -20,12 +20,14 @@
namespace Microsoft.CodeAnalysis.CSharp.InvokeDelegateWithConditionalAccess
{
[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(InvokeDelegateWithConditionalAccessCodeFixProvider)), Shared]
internal partial class InvokeDelegateWithConditionalAccessCodeFixProvider : CodeFixProvider
internal partial class InvokeDelegateWithConditionalAccessCodeFixProvider : SyntaxEditorBasedCodeFixProvider
{
public override ImmutableArray<string> FixableDiagnosticIds { get; } = ImmutableArray.Create(IDEDiagnosticIds.InvokeDelegateWithConditionalAccessId);
public override FixAllProvider GetFixAllProvider()
=> new InvokeDelegateWithConditionalAccessFixAllProvider(this);
// 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.
protected override bool IncludeDiagnosticDuringFixAll(Diagnostic diagnostic)
=> !diagnostic.Descriptor.CustomTags.Contains(WellKnownDiagnosticTags.Unnecessary);
public override Task RegisterCodeFixesAsync(CodeFixContext context)
{
......@@ -35,49 +37,40 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
return SpecializedTasks.EmptyTask;
}
private Task<Document> FixAsync(
Document document, Diagnostic diagnostic, CancellationToken cancellationToken)
protected override Task FixAllAsync(
Document document, ImmutableArray<Diagnostic> diagnostics,
SyntaxEditor editor, CancellationToken cancellationToken)
{
return FixAllAsync(document, ImmutableArray.Create(diagnostic), cancellationToken);
}
private async Task<Document> FixAllAsync(
Document document, ImmutableArray<Diagnostic> diagnostics, CancellationToken cancellationToken)
{
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var editor = new SyntaxEditor(root, document.Project.Solution.Workspace);
foreach (var diagnostic in diagnostics)
{
cancellationToken.ThrowIfCancellationRequested();
AddEdits(root, editor, diagnostic, cancellationToken);
AddEdits(editor, diagnostic, cancellationToken);
}
var newRoot = editor.GetChangedRoot();
return document.WithSyntaxRoot(newRoot);
return SpecializedTasks.EmptyTask;
}
private void AddEdits(
SyntaxNode root, SyntaxEditor editor, Diagnostic diagnostic, CancellationToken cancellationToken)
SyntaxEditor editor, Diagnostic diagnostic, CancellationToken cancellationToken)
{
if (diagnostic.Properties[Constants.Kind] == Constants.VariableAndIfStatementForm)
{
HandleVariableAndIfStatementForm(root, editor, diagnostic, cancellationToken);
HandleVariableAndIfStatementForm(editor, diagnostic, cancellationToken);
}
else
{
Debug.Assert(diagnostic.Properties[Constants.Kind] == Constants.SingleIfStatementForm);
HandleSingleIfStatementForm(root, editor, diagnostic, cancellationToken);
HandleSingleIfStatementForm(editor, diagnostic, cancellationToken);
}
}
private void HandleSingleIfStatementForm(
SyntaxNode root,
SyntaxEditor editor,
Diagnostic diagnostic,
CancellationToken cancellationToken)
{
var root = editor.OriginalRoot;
var ifStatementLocation = diagnostic.AdditionalLocations[0];
var expressionStatementLocation = diagnostic.AdditionalLocations[1];
......@@ -109,8 +102,10 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
}
private static void HandleVariableAndIfStatementForm(
SyntaxNode root, SyntaxEditor editor, Diagnostic diagnostic, CancellationToken cancellationToken)
SyntaxEditor editor, Diagnostic diagnostic, CancellationToken cancellationToken)
{
var root = editor.OriginalRoot;
var localDeclarationLocation = diagnostic.AdditionalLocations[0];
var ifStatementLocation = diagnostic.AdditionalLocations[1];
var expressionStatementLocation = diagnostic.AdditionalLocations[2];
......
// 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.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeFixes.FixAllOccurrences;
namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody
{
internal partial class AbstractUseExpressionBodyCodeFixProvider<TDeclaration> : CodeFixProvider
where TDeclaration : SyntaxNode
{
private class UseExpressionBodyFixAllProvider : DocumentBasedFixAllProvider
{
private readonly AbstractUseExpressionBodyCodeFixProvider<TDeclaration> _provider;
public UseExpressionBodyFixAllProvider(AbstractUseExpressionBodyCodeFixProvider<TDeclaration> provider)
{
_provider = provider;
}
protected override Task<Document> FixDocumentAsync(Document document, ImmutableArray<Diagnostic> diagnostics, CancellationToken cancellationToken)
=> _provider.FixAllAsync(document, diagnostics, cancellationToken);
}
}
}
\ No newline at end of file
......@@ -19,7 +19,8 @@
namespace Microsoft.CodeAnalysis.CSharp.UseExpressionBody
{
internal abstract partial class AbstractUseExpressionBodyCodeFixProvider<TDeclaration> : CodeFixProvider
internal abstract partial class AbstractUseExpressionBodyCodeFixProvider<TDeclaration> :
SyntaxEditorBasedCodeFixProvider
where TDeclaration : SyntaxNode
{
private readonly Option<CodeStyleOption<bool>> _option;
......@@ -40,8 +41,6 @@ internal abstract partial class AbstractUseExpressionBodyCodeFixProvider<TDeclar
_useBlockBodyTitle = useBlockBodyTitle;
}
public sealed override FixAllProvider GetFixAllProvider() => new UseExpressionBodyFixAllProvider(this);
public sealed override Task RegisterCodeFixesAsync(CodeFixContext context)
{
var diagnostic = context.Diagnostics.First();
......@@ -57,34 +56,26 @@ public sealed override Task RegisterCodeFixesAsync(CodeFixContext context)
return SpecializedTasks.EmptyTask;
}
private Task<Document> FixAsync(
Document document, Diagnostic diagnostic, CancellationToken cancellationToken)
{
return FixAllAsync(document, ImmutableArray.Create(diagnostic), cancellationToken);
}
private async Task<Document> FixAllAsync(
Document document, ImmutableArray<Diagnostic> diagnostics, CancellationToken cancellationToken)
protected override Task FixAllAsync(
Document document, ImmutableArray<Diagnostic> diagnostics,
SyntaxEditor editor, CancellationToken cancellationToken)
{
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var editor = new SyntaxEditor(root, document.Project.Solution.Workspace);
var options = document.Project.Solution.Workspace.Options;
var preferExpressionBody = document.Project.Solution.Workspace.Options.GetOption(_option).Value;
var options = document.Project.Solution.Options;
var preferExpressionBody = options.GetOption(_option).Value;
foreach (var diagnostic in diagnostics)
{
cancellationToken.ThrowIfCancellationRequested();
AddEdits(root, editor, diagnostic, options, preferExpressionBody, cancellationToken);
AddEdits(editor, diagnostic, options, preferExpressionBody, cancellationToken);
}
var newRoot = editor.GetChangedRoot();
return document.WithSyntaxRoot(newRoot);
return SpecializedTasks.EmptyTask;
}
private void AddEdits(
SyntaxNode root, SyntaxEditor editor, Diagnostic diagnostic,
OptionSet options, bool preferExpressionBody, CancellationToken cancellationToken)
SyntaxEditor editor, Diagnostic diagnostic,
OptionSet options, bool preferExpressionBody,
CancellationToken cancellationToken)
{
var declarationLocation = diagnostic.AdditionalLocations[0];
var declaration = (TDeclaration)declarationLocation.FindNode(cancellationToken);
......
// 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.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeFixes.FixAllOccurrences;
namespace Microsoft.CodeAnalysis.CSharp.UsePatternMatching
{
internal partial class CSharpAsAndNullCheckCodeFixProvider : CodeFixProvider
{
private class InlineTypeCheckFixAllProvider : DocumentBasedFixAllProvider
{
private readonly CSharpAsAndNullCheckCodeFixProvider _provider;
public InlineTypeCheckFixAllProvider(CSharpAsAndNullCheckCodeFixProvider provider)
{
_provider = provider;
}
protected override Task<Document> FixDocumentAsync(
Document document, ImmutableArray<Diagnostic> diagnostics, CancellationToken cancellationToken)
{
return _provider.FixAllAsync(document, diagnostics, cancellationToken);
}
}
}
}
\ No newline at end of file
......@@ -19,13 +19,11 @@
namespace Microsoft.CodeAnalysis.CSharp.UsePatternMatching
{
[ExportCodeFixProvider(LanguageNames.CSharp), Shared]
internal partial class CSharpAsAndNullCheckCodeFixProvider : CodeFixProvider
internal partial class CSharpAsAndNullCheckCodeFixProvider : SyntaxEditorBasedCodeFixProvider
{
public override ImmutableArray<string> FixableDiagnosticIds
=> ImmutableArray.Create(IDEDiagnosticIds.InlineAsTypeCheckId);
public override FixAllProvider GetFixAllProvider() => new InlineTypeCheckFixAllProvider(this);
public override Task RegisterCodeFixesAsync(CodeFixContext context)
{
context.RegisterCodeFix(new MyCodeAction(
......@@ -34,31 +32,20 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
return SpecializedTasks.EmptyTask;
}
private Task<Document> FixAsync(
Document document, Diagnostic diagnostic, CancellationToken cancellationToken)
{
return FixAllAsync(document, ImmutableArray.Create(diagnostic), cancellationToken);
}
private async Task<Document> FixAllAsync(
Document document, ImmutableArray<Diagnostic> diagnostics, CancellationToken cancellationToken)
protected override Task FixAllAsync(
Document document, ImmutableArray<Diagnostic> diagnostics,
SyntaxEditor editor, CancellationToken cancellationToken)
{
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var editor = new SyntaxEditor(root, document.Project.Solution.Workspace);
foreach (var diagnostic in diagnostics)
{
cancellationToken.ThrowIfCancellationRequested();
AddEdits(root, editor, diagnostic, cancellationToken);
AddEdits(editor, diagnostic, cancellationToken);
}
var newRoot = editor.GetChangedRoot();
return document.WithSyntaxRoot(newRoot);
return SpecializedTasks.EmptyTask;
}
private void AddEdits(
SyntaxNode root,
SyntaxEditor editor,
Diagnostic diagnostic,
CancellationToken cancellationToken)
......
// 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.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeFixes.FixAllOccurrences;
namespace Microsoft.CodeAnalysis.CSharp.UsePatternMatching
{
internal partial class CSharpIsAndCastCheckCodeFixProvider : CodeFixProvider
{
private class InlineTypeCheckFixAllProvider : DocumentBasedFixAllProvider
{
private readonly CSharpIsAndCastCheckCodeFixProvider _provider;
public InlineTypeCheckFixAllProvider(CSharpIsAndCastCheckCodeFixProvider provider)
{
_provider = provider;
}
protected override Task<Document> FixDocumentAsync(
Document document, ImmutableArray<Diagnostic> diagnostics, CancellationToken cancellationToken)
{
return _provider.FixAllAsync(document, diagnostics, cancellationToken);
}
}
}
}
\ No newline at end of file
......@@ -19,13 +19,11 @@
namespace Microsoft.CodeAnalysis.CSharp.UsePatternMatching
{
[ExportCodeFixProvider(LanguageNames.CSharp), Shared]
internal partial class CSharpIsAndCastCheckCodeFixProvider : CodeFixProvider
internal partial class CSharpIsAndCastCheckCodeFixProvider : SyntaxEditorBasedCodeFixProvider
{
public override ImmutableArray<string> FixableDiagnosticIds
=> ImmutableArray.Create(IDEDiagnosticIds.InlineIsTypeCheckId);
public override FixAllProvider GetFixAllProvider() => new InlineTypeCheckFixAllProvider(this);
public override Task RegisterCodeFixesAsync(CodeFixContext context)
{
context.RegisterCodeFix(new MyCodeAction(
......@@ -34,31 +32,20 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
return SpecializedTasks.EmptyTask;
}
private Task<Document> FixAsync(
Document document, Diagnostic diagnostic, CancellationToken cancellationToken)
{
return FixAllAsync(document, ImmutableArray.Create(diagnostic), cancellationToken);
}
private async Task<Document> FixAllAsync(
Document document, ImmutableArray<Diagnostic> diagnostics, CancellationToken cancellationToken)
protected override Task FixAllAsync(
Document document, ImmutableArray<Diagnostic> diagnostics,
SyntaxEditor editor, CancellationToken cancellationToken)
{
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var editor = new SyntaxEditor(root, document.Project.Solution.Workspace);
foreach (var diagnostic in diagnostics)
{
cancellationToken.ThrowIfCancellationRequested();
AddEdits(root, editor, diagnostic, cancellationToken);
AddEdits(editor, diagnostic, cancellationToken);
}
var newRoot = editor.GetChangedRoot();
return document.WithSyntaxRoot(newRoot);
return SpecializedTasks.EmptyTask;
}
private void AddEdits(
SyntaxNode root,
SyntaxEditor editor,
Diagnostic diagnostic,
CancellationToken cancellationToken)
......
......@@ -144,7 +144,6 @@
<Compile Include="UseNullPropagation\AbstractUseNullPropagationDiagnosticAnalyzer.cs" />
<Compile Include="UseThrowExpression\AbstractUseThrowExpressionDiagnosticAnalyzer.cs" />
<Compile Include="UseThrowExpression\UseThrowExpressionCodeFixProvider.cs" />
<Compile Include="UseThrowExpression\UseThrowExpressionCodeFixProvider.FixAllProvider.cs" />
<Compile Include="Structure\BlockTypes.cs" />
<Compile Include="CodeLens\CodeLensReferencesServiceFactory.cs" />
<Compile Include="Structure\Syntax\BlockStructureExtensions.cs" />
......
......@@ -8,7 +8,6 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeFixes.FixAllOccurrences;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.LanguageServices;
......@@ -18,12 +17,13 @@
namespace Microsoft.CodeAnalysis.UseCoalesceExpression
{
[ExportCodeFixProvider(LanguageNames.CSharp, LanguageNames.VisualBasic), Shared]
internal class UseCoalesceExpressionCodeFixProvider : CodeFixProvider
internal class UseCoalesceExpressionCodeFixProvider : SyntaxEditorBasedCodeFixProvider
{
public override ImmutableArray<string> FixableDiagnosticIds
=> ImmutableArray.Create(IDEDiagnosticIds.UseCoalesceExpressionDiagnosticId);
public override FixAllProvider GetFixAllProvider() => new UseCoalesceExpressionFixAllProvider(this);
protected override bool IncludeDiagnosticDuringFixAll(Diagnostic diagnostic)
=> !diagnostic.Descriptor.CustomTags.Contains(WellKnownDiagnosticTags.Unnecessary);
public override Task RegisterCodeFixesAsync(CodeFixContext context)
{
......@@ -33,24 +33,13 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
return SpecializedTasks.EmptyTask;
}
private Task<Document> FixAsync(
Document document,
Diagnostic diagnostic,
CancellationToken cancellationToken)
{
return FixAllAsync(document, ImmutableArray.Create(diagnostic), cancellationToken);
}
private async Task<Document> FixAllAsync(
Document document,
ImmutableArray<Diagnostic> diagnostics,
CancellationToken cancellationToken)
protected override Task FixAllAsync(
Document document, ImmutableArray<Diagnostic> diagnostics,
SyntaxEditor editor, CancellationToken cancellationToken)
{
var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>();
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var editor = new SyntaxEditor(root, document.Project.Solution.Workspace);
var generator = editor.Generator;
var root = editor.OriginalRoot;
foreach (var diagnostic in diagnostics)
{
......@@ -75,26 +64,7 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
});
}
var newRoot = editor.GetChangedRoot();
return document.WithSyntaxRoot(newRoot);
}
private class UseCoalesceExpressionFixAllProvider : DocumentBasedFixAllProvider
{
private readonly UseCoalesceExpressionCodeFixProvider _provider;
public UseCoalesceExpressionFixAllProvider(UseCoalesceExpressionCodeFixProvider provider)
{
_provider = provider;
}
protected override Task<Document> FixDocumentAsync(
Document document, ImmutableArray<Diagnostic> diagnostics, CancellationToken cancellationToken)
{
var filteredDiagnostics = diagnostics.WhereAsArray(
d => !d.Descriptor.CustomTags.Contains(WellKnownDiagnosticTags.Unnecessary));
return _provider.FixAllAsync(document, filteredDiagnostics, cancellationToken);
}
return SpecializedTasks.EmptyTask;
}
private class MyCodeAction : CodeAction.DocumentChangeAction
......
......@@ -8,7 +8,6 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeFixes.FixAllOccurrences;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.LanguageServices;
......@@ -18,12 +17,13 @@
namespace Microsoft.CodeAnalysis.UseCoalesceExpression
{
[ExportCodeFixProvider(LanguageNames.CSharp, LanguageNames.VisualBasic), Shared]
internal class UseCoalesceExpressionForNullableCodeFixProvider : CodeFixProvider
internal class UseCoalesceExpressionForNullableCodeFixProvider : SyntaxEditorBasedCodeFixProvider
{
public override ImmutableArray<string> FixableDiagnosticIds
=> ImmutableArray.Create(IDEDiagnosticIds.UseCoalesceExpressionForNullableDiagnosticId);
public override FixAllProvider GetFixAllProvider() => new UseCoalesceExpressionForNullableFixAllProvider(this);
protected override bool IncludeDiagnosticDuringFixAll(Diagnostic diagnostic)
=> !diagnostic.Descriptor.CustomTags.Contains(WellKnownDiagnosticTags.Unnecessary);
public override Task RegisterCodeFixesAsync(CodeFixContext context)
{
......@@ -33,40 +33,26 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
return SpecializedTasks.EmptyTask;
}
private Task<Document> FixAsync(
Document document,
Diagnostic diagnostic,
CancellationToken cancellationToken)
{
return FixAllAsync(document, ImmutableArray.Create(diagnostic), cancellationToken);
}
private async Task<Document> FixAllAsync(
Document document,
ImmutableArray<Diagnostic> diagnostics,
CancellationToken cancellationToken)
protected override Task FixAllAsync(
Document document, ImmutableArray<Diagnostic> diagnostics,
SyntaxEditor editor, CancellationToken cancellationToken)
{
var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>();
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var editor = new SyntaxEditor(root, document.Project.Solution.Workspace);
var generator = editor.Generator;
var root = editor.OriginalRoot;
foreach (var diagnostic in diagnostics)
{
var conditionalExpression = root.FindNode(diagnostic.AdditionalLocations[0].SourceSpan, getInnermostNodeForTie: true);
var conditionExpression = root.FindNode(diagnostic.AdditionalLocations[1].SourceSpan);
var whenPart = root.FindNode(diagnostic.AdditionalLocations[2].SourceSpan);
SyntaxNode condition, whenTrue, whenFalse;
syntaxFacts.GetPartsOfConditionalExpression(
conditionalExpression, out condition, out whenTrue, out whenFalse);
conditionalExpression, out var condition, out var whenTrue, out var whenFalse);
editor.ReplaceNode(conditionalExpression,
(c, g) => {
SyntaxNode currentCondition, currentWhenTrue, currentWhenFalse;
syntaxFacts.GetPartsOfConditionalExpression(
c, out currentCondition, out currentWhenTrue, out currentWhenFalse);
c, out var currentCondition, out var currentWhenTrue, out var currentWhenFalse);
return whenPart == whenTrue
? g.CoalesceExpression(conditionExpression, syntaxFacts.WalkDownParentheses(currentWhenTrue))
......@@ -74,26 +60,7 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
});
}
var newRoot = editor.GetChangedRoot();
return document.WithSyntaxRoot(newRoot);
}
private class UseCoalesceExpressionForNullableFixAllProvider : DocumentBasedFixAllProvider
{
private readonly UseCoalesceExpressionForNullableCodeFixProvider _provider;
public UseCoalesceExpressionForNullableFixAllProvider(UseCoalesceExpressionForNullableCodeFixProvider provider)
{
_provider = provider;
}
protected override Task<Document> FixDocumentAsync(
Document document, ImmutableArray<Diagnostic> diagnostics, CancellationToken cancellationToken)
{
var filteredDiagnostics = diagnostics.WhereAsArray(
d => !d.Descriptor.CustomTags.Contains(WellKnownDiagnosticTags.Unnecessary));
return _provider.FixAllAsync(document, filteredDiagnostics, cancellationToken);
}
return SpecializedTasks.EmptyTask;
}
private class MyCodeAction : CodeAction.DocumentChangeAction
......
......@@ -9,7 +9,6 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeFixes.FixAllOccurrences;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.LanguageServices;
......@@ -26,7 +25,7 @@ internal abstract class AbstractUseNullPropagationCodeFixProvider<
TInvocationExpression,
TMemberAccessExpression,
TConditionalAccessExpression,
TElementAccessExpression> : CodeFixProvider
TElementAccessExpression> : SyntaxEditorBasedCodeFixProvider
where TSyntaxKind : struct
where TExpressionSyntax : SyntaxNode
where TConditionalExpressionSyntax : TExpressionSyntax
......@@ -39,7 +38,8 @@ internal abstract class AbstractUseNullPropagationCodeFixProvider<
public override ImmutableArray<string> FixableDiagnosticIds
=> ImmutableArray.Create(IDEDiagnosticIds.UseNullPropagationDiagnosticId);
public override FixAllProvider GetFixAllProvider() => new UseNullPropagationFixAllProvider(this);
protected override bool IncludeDiagnosticDuringFixAll(Diagnostic diagnostic)
=> !diagnostic.Descriptor.CustomTags.Contains(WellKnownDiagnosticTags.Unnecessary);
public override Task RegisterCodeFixesAsync(CodeFixContext context)
{
......@@ -49,24 +49,13 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
return SpecializedTasks.EmptyTask;
}
private Task<Document> FixAsync(
Document document,
Diagnostic diagnostic,
CancellationToken cancellationToken)
{
return FixAllAsync(document, ImmutableArray.Create(diagnostic), cancellationToken);
}
private async Task<Document> FixAllAsync(
Document document,
ImmutableArray<Diagnostic> diagnostics,
CancellationToken cancellationToken)
protected override Task FixAllAsync(
Document document, ImmutableArray<Diagnostic> diagnostics,
SyntaxEditor editor, CancellationToken cancellationToken)
{
var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>();
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var editor = new SyntaxEditor(root, document.Project.Solution.Workspace);
var generator = editor.Generator;
var root = editor.OriginalRoot;
foreach (var diagnostic in diagnostics)
{
......@@ -103,8 +92,7 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
});
}
var newRoot = editor.GetChangedRoot();
return document.WithSyntaxRoot(newRoot);
return SpecializedTasks.EmptyTask;
}
private SyntaxNode CreateConditionalAccessExpression(
......@@ -134,30 +122,6 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
return currentConditional;
}
private class UseNullPropagationFixAllProvider : DocumentBasedFixAllProvider
{
private readonly AbstractUseNullPropagationCodeFixProvider<
TSyntaxKind, TExpressionSyntax, TConditionalExpressionSyntax,
TBinaryExpressionSyntax, TInvocationExpression, TMemberAccessExpression,
TConditionalAccessExpression, TElementAccessExpression> _provider;
public UseNullPropagationFixAllProvider(AbstractUseNullPropagationCodeFixProvider<
TSyntaxKind, TExpressionSyntax, TConditionalExpressionSyntax,
TBinaryExpressionSyntax, TInvocationExpression, TMemberAccessExpression,
TConditionalAccessExpression, TElementAccessExpression> provider)
{
_provider = provider;
}
protected override Task<Document> FixDocumentAsync(
Document document, ImmutableArray<Diagnostic> diagnostics, CancellationToken cancellationToken)
{
var filteredDiagnostics = diagnostics.WhereAsArray(
d => !d.Descriptor.CustomTags.Contains(WellKnownDiagnosticTags.Unnecessary));
return _provider.FixAllAsync(document, filteredDiagnostics, cancellationToken);
}
}
private class MyCodeAction : CodeAction.DocumentChangeAction
{
public MyCodeAction(Func<CancellationToken, Task<Document>> createChangedDocument)
......
// 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;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeFixes.FixAllOccurrences;
namespace Microsoft.CodeAnalysis.UseThrowExpression
{
internal partial class UseThrowExpressionCodeFixProvider
{
/// <summary>
/// A specialized <see cref="FixAllProvider"/> for this CodeFixProvider.
/// SimplifyNullCheck needs a specialized <see cref="FixAllProvider"/> because
/// the normal <see cref="BatchFixAllProvider"/> is insufficient for our needs.
/// Specifically, when doing a bulk fix-all, it's very common for many edits to
/// be near each other. The simplest example of this is just the following code:
///
/// <code>
/// if (s == null) throw ...
/// if (t == null) throw ...
/// _s = s;
/// _t = t;
/// </code>
///
/// If we use the normal batch-fixer then the underlying merge algorithm gets
/// throw off by hte sequence of edits. specifically, the removal of
/// "if (s == null) throw ..." actually gets seen by it as the removal of
/// "(s == null) throw ... \r\n if". That text change then intersects the
/// removal of "if (t == null) throw ...". because of the intersection, one
/// of the edits is ignored.
///
/// This FixAllProvider avoids this entirely by not doing any textual merging.
/// Instead, we just take all the fixes to apply in the document, as we use
/// the core <see cref="UseThrowExpressionCodeFixProvider.FixAllAsync"/> to do
/// all the editing at once on the SyntaxTree. Because we're doing real tree
/// edits with actual nodes, there is no issue with anything getting messed up.
/// </summary>
private class UseThrowExpressionFixAllProvider : DocumentBasedFixAllProvider
{
private readonly UseThrowExpressionCodeFixProvider _provider;
public UseThrowExpressionFixAllProvider(UseThrowExpressionCodeFixProvider provider)
{
_provider = provider;
}
protected override Task<Document> FixDocumentAsync(
Document document, ImmutableArray<Diagnostic> diagnostics, CancellationToken cancellationToken)
{
var filteredDiagnostics = diagnostics.WhereAsArray(
d => !d.Descriptor.CustomTags.Contains(WellKnownDiagnosticTags.Unnecessary));
return _provider.FixAllAsync(document, filteredDiagnostics, cancellationToken);
}
}
}
}
\ No newline at end of file
......@@ -17,13 +17,13 @@ namespace Microsoft.CodeAnalysis.UseThrowExpression
{
[ExportCodeFixProvider(LanguageNames.CSharp,
Name = PredefinedCodeFixProviderNames.UseThrowExpression), Shared]
internal partial class UseThrowExpressionCodeFixProvider : CodeFixProvider
internal partial class UseThrowExpressionCodeFixProvider : SyntaxEditorBasedCodeFixProvider
{
public override ImmutableArray<string> FixableDiagnosticIds
=> ImmutableArray.Create(IDEDiagnosticIds.UseThrowExpressionDiagnosticId);
public override FixAllProvider GetFixAllProvider()
=> new UseThrowExpressionFixAllProvider(this);
protected override bool IncludeDiagnosticDuringFixAll(Diagnostic diagnostic)
=> !diagnostic.Descriptor.CustomTags.Contains(WellKnownDiagnosticTags.Unnecessary);
public override Task RegisterCodeFixesAsync(CodeFixContext context)
{
......@@ -35,23 +35,12 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
return SpecializedTasks.EmptyTask;
}
private Task<Document> FixAsync(
Document document,
Diagnostic diagnostic,
CancellationToken cancellationToken)
protected override Task FixAllAsync(
Document document, ImmutableArray<Diagnostic> diagnostics,
SyntaxEditor editor, CancellationToken cancellationToken)
{
return FixAllAsync(document, ImmutableArray.Create(diagnostic), cancellationToken);
}
private async Task<Document> FixAllAsync(
Document document,
ImmutableArray<Diagnostic> diagnostics,
CancellationToken cancellationToken)
{
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var editor = new SyntaxEditor(root, document.Project.Solution.Workspace);
var generator = editor.Generator;
var root = editor.OriginalRoot;
foreach (var diagnostic in diagnostics)
{
......@@ -68,8 +57,7 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
generator.ThrowExpression(throwStatementExpression)));
}
var newRoot = editor.GetChangedRoot();
return document.WithSyntaxRoot(newRoot);
return SpecializedTasks.EmptyTask;
}
private class MyCodeAction : CodeAction.DocumentChangeAction
......
// 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)
{
// 'await' the tasks so that if any completed in a cancelled manner then we'll
// throw the right exception here. Calling .Result on the tasks might end up
// with AggregateExceptions being thrown instead.
var updatedDocument = await task.ConfigureAwait(false);
currentSolution = currentSolution.WithDocumentSyntaxRoot(
updatedDocument.Id,
await updatedDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false));
}
var title = fixAllState.GetDefaultFixAllTitle();
return new CodeAction.SolutionChangeAction(title, _ => Task.FromResult(currentSolution));
}
protected abstract Task<Document> FixDocumentAsync(
Document document, ImmutableArray<Diagnostic> diagnostics, CancellationToken cancellationToken);
}
}
// 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;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
namespace Microsoft.CodeAnalysis.CodeFixes
{
internal partial class SyntaxEditorBasedCodeFixProvider : CodeFixProvider
{
/// <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 sealed class SyntaxEditorBasedFixAllProvider : FixAllProvider
{
private readonly SyntaxEditorBasedCodeFixProvider _codeFixProvider;
public SyntaxEditorBasedFixAllProvider(SyntaxEditorBasedCodeFixProvider codeFixProvider)
{
_codeFixProvider = codeFixProvider;
}
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)
{
// 'await' the tasks so that if any completed in a cancelled manner then we'll
// throw the right exception here. Calling .Result on the tasks might end up
// with AggregateExceptions being thrown instead.
var updatedDocument = await task.ConfigureAwait(false);
currentSolution = currentSolution.WithDocumentSyntaxRoot(
updatedDocument.Id,
await updatedDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false));
}
var title = fixAllState.GetDefaultFixAllTitle();
return new CodeAction.SolutionChangeAction(title, _ => Task.FromResult(currentSolution));
}
private Task<Document> FixDocumentAsync(
Document document, ImmutableArray<Diagnostic> diagnostics, CancellationToken cancellationToken)
{
var filteredDiagnostics = diagnostics.WhereAsArray(_codeFixProvider.IncludeDiagnosticDuringFixAll);
return _codeFixProvider.FixAllAsync(document, filteredDiagnostics, cancellationToken);
}
}
}
}
\ No newline at end of file
// 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.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Editing;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CodeFixes
{
internal abstract partial class SyntaxEditorBasedCodeFixProvider : CodeFixProvider
{
public sealed override FixAllProvider GetFixAllProvider()
=> new SyntaxEditorBasedFixAllProvider(this);
protected Task<Document> FixAsync(
Document document, Diagnostic diagnostic, CancellationToken cancellationToken)
{
return FixAllAsync(document, ImmutableArray.Create(diagnostic), cancellationToken);
}
private async Task<Document> FixAllAsync(Document document, ImmutableArray<Diagnostic> diagnostics, CancellationToken cancellationToken)
{
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var editor = new SyntaxEditor(root, document.Project.Solution.Workspace);
await FixAllAsync(document, diagnostics, editor, cancellationToken).ConfigureAwait(false);
var newRoot = editor.GetChangedRoot();
return document.WithSyntaxRoot(root);
}
protected abstract Task FixAllAsync(
Document document, ImmutableArray<Diagnostic> diagnostics, SyntaxEditor editor, CancellationToken cancellationToken);
/// <summary>
/// Whether or not this diagnostic should be included when performing a FixAll. This is useful
/// for providers that create multiple diagnostics for the same issue (For example, one main
/// diagnostic and multiple 'faded out code' diagnostics). FixAll can be invoked from any of
/// those, but we'll only want perform an edit for only one diagnostic for each of those sets
/// of diagnostics.
/// </summary>
protected virtual bool IncludeDiagnosticDuringFixAll(Diagnostic diagnostic) => true;
}
}
\ No newline at end of file
......@@ -12,7 +12,6 @@ namespace Microsoft.CodeAnalysis.Editing
public class SyntaxEditor
{
private readonly SyntaxGenerator _generator;
private readonly SyntaxNode _root;
private readonly List<Change> _changes;
/// <summary>
......@@ -25,7 +24,7 @@ public SyntaxEditor(SyntaxNode root, Workspace workspace)
throw new ArgumentNullException(nameof(workspace));
}
_root = root ?? throw new ArgumentNullException(nameof(root));
OriginalRoot = root ?? throw new ArgumentNullException(nameof(root));
_generator = SyntaxGenerator.GetGenerator(workspace, root.Language);
_changes = new List<Change>();
}
......@@ -33,10 +32,7 @@ public SyntaxEditor(SyntaxNode root, Workspace workspace)
/// <summary>
/// The <see cref="SyntaxNode"/> that was specified when the <see cref="SyntaxEditor"/> was constructed.
/// </summary>
public SyntaxNode OriginalRoot
{
get { return _root; }
}
public SyntaxNode OriginalRoot { get; }
/// <summary>
/// A <see cref="SyntaxGenerator"/> to use to create and change <see cref="SyntaxNode"/>'s.
......@@ -52,7 +48,7 @@ public SyntaxGenerator Generator
public SyntaxNode GetChangedRoot()
{
var nodes = Enumerable.Distinct(_changes.Select(c => c.Node));
var newRoot = _root.TrackNodes(nodes);
var newRoot = OriginalRoot.TrackNodes(nodes);
foreach (var change in _changes)
{
......@@ -171,7 +167,7 @@ public void InsertAfter(SyntaxNode node, SyntaxNode newNode)
private void CheckNodeInTree(SyntaxNode node)
{
if (!_root.Contains(node))
if (!OriginalRoot.Contains(node))
{
throw new ArgumentException(Microsoft.CodeAnalysis.WorkspacesResources.The_node_is_not_part_of_the_tree, nameof(node));
}
......
......@@ -315,7 +315,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\SyntaxEditorBasedCodeFixProvider.cs" />
<Compile Include="CodeFixes\FixAllOccurrences\FixAllState.FixAllDiagnosticProvider.cs" />
<Compile Include="CodeFixes\FixAllOccurrences\FixAllProviderInfo.cs" />
<Compile Include="CodeFixes\FixAllOccurrences\FixAllState.FixMultipleDiagnosticProvider.cs" />
......@@ -329,6 +329,7 @@
<Compile Include="CodeFixes\FixAllOccurrences\FixAllScope.cs" />
<Compile Include="CodeFixes\FixAllOccurrences\FixAllProvider.cs" />
<Compile Include="CodeFixes\CodeFix.cs" />
<Compile Include="CodeFixes\SyntaxEditorBasedCodeFixProvider.FixAllProvider.cs" />
<Compile Include="CodeGeneration\AbstractCodeGenerationService.cs" />
<Compile Include="CodeGeneration\AbstractCodeGenerationService_FindDeclaration.cs" />
<Compile Include="CodeGeneration\AbstractFlagsEnumGenerator.cs" />
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册