提交 58a811e5 编写于 作者: C CyrusNajmabadi

Ensure fix-all doesn't break code.

上级 068e0a7e
......@@ -396,6 +396,7 @@
<Compile Include="UseCollectionInitializer\UseCollectionInitializerTests.cs" />
<Compile Include="UseCoalesceExpression\UseCoalesceExpressionForNullableTests.cs" />
<Compile Include="UseCoalesceExpression\UseCoalesceExpressionTests.cs" />
<Compile Include="UseDefaultLiteral\UseDefaultLiteralTests.cs" />
<Compile Include="UseExplicitTupleName\UseExplicitTupleNameTests.cs" />
<Compile Include="UseExpressionBody\Refactoring\UseExpressionBodyForConstructorsRefactoringTests.cs" />
<Compile Include="UseExpressionBody\Refactoring\UseExpressionBodyForConversionOperatorsRefactoringTests.cs" />
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.UseDefaultLiteral
{
public class UseDefaultLiteralTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest
{
internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace)
=> (new CSharpUseThrowExpressionDiagnosticAnalyzer(), new UseThrowExpressionCodeFixProvider());
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseThrowExpression)]
public async Task WithoutBraces()
{
}
}
// 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.Generic;
using System.Collections.Immutable;
using System.Composition;
using System.Linq;
......@@ -8,6 +9,7 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editing;
......@@ -30,30 +32,51 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
return SpecializedTasks.EmptyTask;
}
protected override Task FixAllAsync(
protected override async Task FixAllAsync(
Document document, ImmutableArray<Diagnostic> diagnostics,
SyntaxEditor editor, CancellationToken cancellationToken)
{
foreach (var diagnostic in diagnostics)
// Fix-All for this feature is somewhat complicated. Each time we fix one case, it
// may make the next case unfixable. For example:
//
// 'var v = x ? default(string) : default(string)'.
var workspace = document.Project.Solution.Workspace;
var originalRoot = editor.OriginalRoot;
var originalNodes = diagnostics.SelectAsArray(
d => (DefaultExpressionSyntax)originalRoot.FindNode(d.Location.SourceSpan, getInnermostNodeForTie: true));
// We're going to be continually editing this tree. Track all the nodes we
// care about so we can find them across each edit.
document = document.WithSyntaxRoot(originalRoot.TrackNodes(originalNodes));
var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
var currentRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
foreach (var originalDefaultExpression in originalNodes)
{
cancellationToken.ThrowIfCancellationRequested();
AddEdits(editor, diagnostic, cancellationToken);
var defaultExpression = currentRoot.GetCurrentNode(originalDefaultExpression);
if (defaultExpression.CanReplaceWithDefaultLiteral(semanticModel, cancellationToken))
{
document = FixOne(document, currentRoot, defaultExpression);
semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
currentRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
}
}
return SpecializedTasks.EmptyTask;
editor.ReplaceNode(originalRoot, currentRoot);
}
private void AddEdits(
SyntaxEditor editor,
Diagnostic diagnostic,
CancellationToken cancellationToken)
private static Document FixOne(
Document document, SyntaxNode currentRoot, DefaultExpressionSyntax defaultExpression)
{
var defaultExpression = (DefaultExpressionSyntax)diagnostic.Location.FindNode(
getInnermostNodeForTie: true, cancellationToken: cancellationToken);
var replacement = SyntaxFactory.LiteralExpression(SyntaxKind.DefaultLiteralExpression)
.WithTriviaFrom(defaultExpression);
editor.ReplaceNode(defaultExpression, replacement);
var newRoot = currentRoot.ReplaceNode(defaultExpression, replacement);
return document.WithSyntaxRoot(newRoot);
}
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;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Text;
using System.Threading;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Utilities;
using Microsoft.CodeAnalysis.Diagnostics;
......@@ -17,7 +14,6 @@ namespace Microsoft.CodeAnalysis.CSharp.UseDefaultLiteral
[DiagnosticAnalyzer(LanguageNames.CSharp)]
internal class CSharpUseDefaultLiteralDiagnosticAnalyzer : AbstractCodeStyleDiagnosticAnalyzer
{
private static readonly LiteralExpressionSyntax s_defaultLiteralExpression = SyntaxFactory.LiteralExpression(SyntaxKind.DefaultLiteralExpression);
public CSharpUseDefaultLiteralDiagnosticAnalyzer()
: base(IDEDiagnosticIds.UseDefaultLiteralDiagnosticId,
......@@ -60,7 +56,7 @@ private void AnalyzeSyntax(SyntaxNodeAnalysisContext context)
}
var defaultExpression = (DefaultExpressionSyntax)context.Node;
if (!CanUseDefaultLiteral(defaultExpression, context.SemanticModel, cancellationToken))
if (!defaultExpression.CanReplaceWithDefaultLiteral(context.SemanticModel, cancellationToken))
{
return;
}
......@@ -70,19 +66,5 @@ private void AnalyzeSyntax(SyntaxNodeAnalysisContext context)
context.ReportDiagnostic(Diagnostic.Create(GetDescriptorWithSeverity(codeStyleOption.Notification.Value), defaultExpression.GetLocation()));
context.ReportDiagnostic(Diagnostic.Create(UnnecessaryWithoutSuggestionDescriptor, syntaxTree.GetLocation(fadeSpan)));
}
private bool CanUseDefaultLiteral(
DefaultExpressionSyntax defaultExpression,
SemanticModel semanticModel,
CancellationToken cancellationToken)
{
var speculationAnalyzer = new SpeculationAnalyzer(
defaultExpression, s_defaultLiteralExpression, semanticModel,
cancellationToken,
skipVerificationForReplacedNode: true,
failOnOverloadResolutionFailuresInOriginalCode: true);
return !speculationAnalyzer.ReplacementChangesSemantics();
}
}
}
\ No newline at end of file
......@@ -103,6 +103,7 @@
<Compile Include="Extensions\ArrowExpressionClauseSyntaxExtensions.cs" />
<Compile Include="Extensions\AssignmentExpressionSyntaxExtensions.cs" />
<Compile Include="Extensions\BlockSyntaxExtensions.cs" />
<Compile Include="Extensions\DefaultExpressionSyntaxExtensions.cs" />
<Compile Include="Extensions\SemanticModelExtensions.cs" />
<Compile Include="Formatting\CSharpFormattingOptions.Parsers.cs" />
<Compile Include="LanguageServices\CSharpCommandLineParserService.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.Threading;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.Extensions
{
internal static class DefaultExpressionSyntaxExtensions
{
private static readonly LiteralExpressionSyntax s_defaultLiteralExpression = SyntaxFactory.LiteralExpression(SyntaxKind.DefaultLiteralExpression);
public static bool CanReplaceWithDefaultLiteral(
this DefaultExpressionSyntax defaultExpression,
SemanticModel semanticModel,
CancellationToken cancellationToken)
{
var speculationAnalyzer = new SpeculationAnalyzer(
defaultExpression, s_defaultLiteralExpression, semanticModel,
cancellationToken,
skipVerificationForReplacedNode: true,
failOnOverloadResolutionFailuresInOriginalCode: true);
return !speculationAnalyzer.ReplacementChangesSemantics();
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册