Skip to content

Commit d96f68a

Browse files
authored
Merge pull request #2741 from vweijsters/fix-2740
Fixed SA1129 code fix for CancellationToken as default parameter
2 parents 0a204c8 + fc6a3d1 commit d96f68a

2 files changed

Lines changed: 65 additions & 1 deletion

File tree

StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/ReadabilityRules/SA1129CodeFixProvider.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,14 @@ private static SyntaxNode GetReplacementNode(SyntaxNode node, SemanticModel sema
7070

7171
if (IsType<CancellationToken>(namedTypeSymbol))
7272
{
73-
replacement = ConstructMemberAccessSyntax(newExpression.Type, nameof(CancellationToken.None));
73+
if (IsDefaultParameterValue(newExpression))
74+
{
75+
replacement = SyntaxFactory.DefaultExpression(newExpression.Type);
76+
}
77+
else
78+
{
79+
replacement = ConstructMemberAccessSyntax(newExpression.Type, nameof(CancellationToken.None));
80+
}
7481
}
7582
else if (IsEnumWithDefaultMember(namedTypeSymbol, out memberName))
7683
{
@@ -117,6 +124,16 @@ private static bool IsType<T>(INamedTypeSymbol namedTypeSymbol)
117124
return true;
118125
}
119126

127+
private static bool IsDefaultParameterValue(ObjectCreationExpressionSyntax expression)
128+
{
129+
if (expression.Parent.Parent is ParameterSyntax parameterSyntax)
130+
{
131+
return parameterSyntax.Parent.Parent is BaseMethodDeclarationSyntax;
132+
}
133+
134+
return false;
135+
}
136+
120137
/// <summary>
121138
/// Determines whether a given enumeration symbol contains a member with value <c>0</c>.
122139
/// </summary>

StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1129UnitTests.cs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,53 @@ private enum MyEnum {{ {declarationBody} }}
526526
await this.VerifyCSharpFixAsync(testCode, fixedTestCode).ConfigureAwait(false);
527527
}
528528

529+
/// <summary>
530+
/// Verifies that <c>new CancellationToken()</c> is replaced by <c>default(CancellationToken)</c> when its used for a default parameter.
531+
/// </summary>
532+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
533+
[Fact]
534+
[WorkItem(2740, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2740")]
535+
public async Task VerifyCancellationTokenDefaultParameterAsync()
536+
{
537+
var testCode = @"using System.Threading;
538+
539+
public class TestClass
540+
{
541+
public TestClass(CancellationToken cancellationToken = new CancellationToken())
542+
{
543+
}
544+
545+
public void TestMethod(CancellationToken cancellationToken = new CancellationToken())
546+
{
547+
}
548+
}
549+
";
550+
551+
var fixedTestCode = @"using System.Threading;
552+
553+
public class TestClass
554+
{
555+
public TestClass(CancellationToken cancellationToken = default(CancellationToken))
556+
{
557+
}
558+
559+
public void TestMethod(CancellationToken cancellationToken = default(CancellationToken))
560+
{
561+
}
562+
}
563+
";
564+
565+
DiagnosticResult[] expected =
566+
{
567+
this.CSharpDiagnostic().WithLocation(5, 60),
568+
this.CSharpDiagnostic().WithLocation(9, 66),
569+
};
570+
571+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
572+
await this.VerifyCSharpDiagnosticAsync(fixedTestCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
573+
await this.VerifyCSharpFixAsync(testCode, fixedTestCode).ConfigureAwait(false);
574+
}
575+
529576
/// <inheritdoc/>
530577
protected override IEnumerable<DiagnosticAnalyzer> GetCSharpDiagnosticAnalyzers()
531578
{

0 commit comments

Comments
 (0)