-
Notifications
You must be signed in to change notification settings - Fork 465
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2873 from goyzhang/master
Add a fixer for CA2200
- Loading branch information
Showing
2 changed files
with
153 additions
and
0 deletions.
There are no files selected for viewing
58 changes: 58 additions & 0 deletions
58
...osoft.CodeQuality.Analyzers/Core/QualityGuidelines/RethrowToPreserveStackDetails.Fixer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
using System.Collections.Immutable; | ||
using System.Composition; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.CodeActions; | ||
using Microsoft.CodeAnalysis.CodeFixes; | ||
using Microsoft.CodeAnalysis.Editing; | ||
using Microsoft.CodeAnalysis.Formatting; | ||
|
||
namespace Microsoft.CodeQuality.Analyzers.QualityGuidelines | ||
{ | ||
/// <summary> | ||
/// CA2200: Rethrow to preserve stack details | ||
/// </summary> | ||
[ExportCodeFixProvider(LanguageNames.CSharp, LanguageNames.VisualBasic, Name = RethrowToPreserveStackDetailsAnalyzer.RuleId), Shared] | ||
public sealed class RethrowToPreserveStackDetailsFixer : CodeFixProvider | ||
{ | ||
public sealed override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(RethrowToPreserveStackDetailsAnalyzer.RuleId); | ||
|
||
public sealed override FixAllProvider GetFixAllProvider() | ||
{ | ||
// See https://github.com/dotnet/roslyn/blob/master/docs/analyzers/FixAllProvider.md for more information on Fix All Providers' | ||
return WellKnownFixAllProviders.BatchFixer; | ||
} | ||
public async sealed override Task RegisterCodeFixesAsync(CodeFixContext context) | ||
{ | ||
var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); | ||
var diagnostics = context.Diagnostics; | ||
|
||
var nodeToReplace = root.FindNode(context.Span); | ||
if (nodeToReplace == null) | ||
{ | ||
return; | ||
} | ||
// Register a code action that will invoke the fix. | ||
context.RegisterCodeFix( | ||
CodeAction.Create( | ||
title: MicrosoftCodeQualityAnalyzersResources.RethrowToPreserveStackDetailsTitle, | ||
createChangedDocument: c => MakeThrowAsync(context.Document, nodeToReplace, c), | ||
equivalenceKey: nameof(RethrowToPreserveStackDetailsFixer)), | ||
diagnostics); | ||
} | ||
|
||
private async Task<Document> MakeThrowAsync(Document document, SyntaxNode nodeToReplace, CancellationToken cancellationToken) | ||
{ | ||
var formattednewLocal = SyntaxGenerator.GetGenerator(document).ThrowStatement() | ||
.WithLeadingTrivia(nodeToReplace.GetLeadingTrivia()) | ||
.WithTrailingTrivia(nodeToReplace.GetTrailingTrivia()) | ||
.WithAdditionalAnnotations(Formatter.Annotation); | ||
|
||
var oldRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); | ||
var newRoot = oldRoot.ReplaceNode(nodeToReplace, formattednewLocal); | ||
|
||
return document.WithSyntaxRoot(newRoot); | ||
} | ||
} | ||
} |
95 changes: 95 additions & 0 deletions
95
...Quality.Analyzers/UnitTests/QualityGuidelines/RethrowToPreserveStackDetailsTests.Fixer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
using System.Threading.Tasks; | ||
using Microsoft.CodeAnalysis.Testing; | ||
using Xunit; | ||
using VerifyCS = Test.Utilities.CSharpCodeFixVerifier< | ||
Microsoft.CodeQuality.CSharp.Analyzers.QualityGuidelines.CSharpRethrowToPreserveStackDetailsAnalyzer, | ||
Microsoft.CodeQuality.Analyzers.QualityGuidelines.RethrowToPreserveStackDetailsFixer>; | ||
using VerifyVB = Test.Utilities.VisualBasicCodeFixVerifier< | ||
Microsoft.CodeQuality.VisualBasic.Analyzers.QualityGuidelines.BasicRethrowToPreserveStackDetailsAnalyzer, | ||
Microsoft.CodeQuality.Analyzers.QualityGuidelines.RethrowToPreserveStackDetailsFixer>; | ||
|
||
namespace Microsoft.CodeQuality.Analyzers.UnitTests.QualityGuidelines | ||
{ | ||
public class RethrowToPreserveStackDetailsTests | ||
{ | ||
[Fact] | ||
public async Task TestCSharp_RethrowExplicitlyToThrowImplicitly() | ||
{ | ||
await VerifyCS.VerifyCodeFixAsync(@" | ||
using System; | ||
class Program | ||
{ | ||
void CatchAndRethrowExplicitly() | ||
{ | ||
try | ||
{ | ||
ThrowException(); | ||
} | ||
catch (ArithmeticException e) | ||
{ | ||
throw e; //Some comments | ||
} | ||
} | ||
void ThrowException() | ||
{ | ||
throw new ArithmeticException(); | ||
} | ||
}", new DiagnosticResult(CSharp.Analyzers.QualityGuidelines.CSharpRethrowToPreserveStackDetailsAnalyzer.Rule).WithLocation(14, 13), | ||
@" | ||
using System; | ||
class Program | ||
{ | ||
void CatchAndRethrowExplicitly() | ||
{ | ||
try | ||
{ | ||
ThrowException(); | ||
} | ||
catch (ArithmeticException e) | ||
{ | ||
throw; //Some comments | ||
} | ||
} | ||
void ThrowException() | ||
{ | ||
throw new ArithmeticException(); | ||
} | ||
}"); | ||
} | ||
[Fact] | ||
public async Task TestBasic_RethrowExplicitlyToThrowImplicitly() | ||
{ | ||
await VerifyVB.VerifyCodeFixAsync(@" | ||
Imports System | ||
Class Program | ||
Sub CatchAndRethrowExplicitly() | ||
Try | ||
Throw New ArithmeticException() | ||
Catch e As ArithmeticException | ||
Throw e 'Some comment | ||
End Try | ||
End Sub | ||
End Class | ||
", new DiagnosticResult(VisualBasic.Analyzers.QualityGuidelines.BasicRethrowToPreserveStackDetailsAnalyzer.Rule).WithLocation(8, 13), | ||
@" | ||
Imports System | ||
Class Program | ||
Sub CatchAndRethrowExplicitly() | ||
Try | ||
Throw New ArithmeticException() | ||
Catch e As ArithmeticException | ||
Throw 'Some comment | ||
End Try | ||
End Sub | ||
End Class | ||
" | ||
); | ||
} | ||
} | ||
} | ||
|
||
|