diff --git a/Raven.CodeAnalysis.Test/TaskCompletionSourceTests.cs b/Raven.CodeAnalysis.Test/TaskCompletionSourceTests.cs index 0acf155..72ee0e7 100644 --- a/Raven.CodeAnalysis.Test/TaskCompletionSourceTests.cs +++ b/Raven.CodeAnalysis.Test/TaskCompletionSourceTests.cs @@ -11,7 +11,7 @@ public class TaskCompletionSourceTests : CodeFixVerifier { //No diagnostics expected to show up [TestMethod] - public void TestMethod1() + public void Generic_with_RunContinuationsAsynchronously() { const string input = @" class C @@ -26,7 +26,7 @@ class C } [TestMethod] - public void TestMethod2() + public void Generic_without_RunContinuationsAsynchronously() { const string input = @" class C @@ -70,6 +70,68 @@ class C } }); } + + //No diagnostics expected to show up + [TestMethod] + public void NonGeneric_with_RunContinuationsAsynchronously() + { + const string input = @" +class C +{ + private void Method1() { var tcs = new TaskCompletionSource(TaskContinuationOptions.RunContinuationsAsynchronously); } + + private void Method2() { var tcs = new System.Threading.Tasks.TaskCompletionSource(null, System.Threading.Tasks.TaskContinuationOptions.RunContinuationsAsynchronously); } + + private void Method3() { var tcs = new TaskCompletionSource(TaskContinuationOptions.RunContinuationsAsynchronously | TaskContinuationOptions.AttachedToParent); } +}"; + VerifyCSharpDiagnostic(input); + } + + [TestMethod] + public void NonGeneric_without_RunContinuationsAsynchronously() + { + const string input = @" +class C +{ + private void Method1() { var tcs = new TaskCompletionSource(); } + + private void Method2() { var tcs = new System.Threading.Tasks.TaskCompletionSource(); } + + private void Method3() { var tcs = new TaskCompletionSource(TaskContinuationOptions.AttachedToParent); } +}"; + VerifyCSharpDiagnostic( + input, + new DiagnosticResult + { + Id = DiagnosticIds.TaskCompletionSourceMustHaveRunContinuationsAsynchronouslySet, + Message = "TaskCompletionSource must have TaskCreationOptions.RunContinuationsAsynchronously set", + Severity = DiagnosticSeverity.Error, + Locations = new[] + { + new DiagnosticResultLocation("Test0.cs", 4, 37) + } + }, + new DiagnosticResult + { + Id = DiagnosticIds.TaskCompletionSourceMustHaveRunContinuationsAsynchronouslySet, + Message = "TaskCompletionSource must have TaskCreationOptions.RunContinuationsAsynchronously set", + Severity = DiagnosticSeverity.Error, + Locations = new[] + { + new DiagnosticResultLocation("Test0.cs", 6, 40) + } + }, + new DiagnosticResult + { + Id = DiagnosticIds.TaskCompletionSourceMustHaveRunContinuationsAsynchronouslySet, + Message = "TaskCompletionSource must have TaskCreationOptions.RunContinuationsAsynchronously set", + Severity = DiagnosticSeverity.Error, + Locations = new[] + { + new DiagnosticResultLocation("Test0.cs", 8, 37) + } + }); + } protected override DiagnosticAnalyzer GetCSharpDiagnosticAnalyzer() { diff --git a/Raven.CodeAnalysis/TaskCompletionSource/TaskCompletionSourceMustHaveRunContinuationsAsynchronouslySetAnalyzer.cs b/Raven.CodeAnalysis/TaskCompletionSource/TaskCompletionSourceMustHaveRunContinuationsAsynchronouslySetAnalyzer.cs index 7fa6241..cb13db6 100644 --- a/Raven.CodeAnalysis/TaskCompletionSource/TaskCompletionSourceMustHaveRunContinuationsAsynchronouslySetAnalyzer.cs +++ b/Raven.CodeAnalysis/TaskCompletionSource/TaskCompletionSourceMustHaveRunContinuationsAsynchronouslySetAnalyzer.cs @@ -26,19 +26,9 @@ public override void Initialize(AnalysisContext context) private static void AnalyzeSyntax(SyntaxNodeAnalysisContext context) { var objectCreationExpressionSyntax = (ObjectCreationExpressionSyntax)context.Node; - var genericNameSyntax = objectCreationExpressionSyntax.Type as GenericNameSyntax; - if (genericNameSyntax == null) - { - var qualifiedNameSyntax = objectCreationExpressionSyntax.Type as QualifiedNameSyntax; - if (qualifiedNameSyntax == null) - return; - genericNameSyntax = qualifiedNameSyntax.Right as GenericNameSyntax; - if (genericNameSyntax == null) - return; - } - - if (string.Equals(genericNameSyntax.Identifier.Text, TaskCompletionSourceName) == false) + if (IsGenericTaskCompletionSourceCreation(objectCreationExpressionSyntax) == false && + IsNonGenericTaskCompletionSourceCreation(objectCreationExpressionSyntax) == false) return; var arguments = objectCreationExpressionSyntax.ArgumentList; @@ -51,6 +41,31 @@ private static void AnalyzeSyntax(SyntaxNodeAnalysisContext context) ReportDiagnostic(context, objectCreationExpressionSyntax); } + private static bool IsGenericTaskCompletionSourceCreation(ObjectCreationExpressionSyntax objectCreationExpressionSyntax) => + IsTaskCompletionSource(objectCreationExpressionSyntax); + + private static bool IsNonGenericTaskCompletionSourceCreation(ObjectCreationExpressionSyntax objectCreationExpressionSyntax) => + IsTaskCompletionSource(objectCreationExpressionSyntax); + + private static bool IsTaskCompletionSource(ObjectCreationExpressionSyntax objectCreationExpressionSyntax) + where TNameSyntax : SimpleNameSyntax + { + var nameSyntax = objectCreationExpressionSyntax.Type as TNameSyntax; + + if (nameSyntax == null) + { + var qualifiedNameSyntax = objectCreationExpressionSyntax.Type as QualifiedNameSyntax; + if (qualifiedNameSyntax == null) + return false; + + nameSyntax = qualifiedNameSyntax.Right as TNameSyntax; + if (nameSyntax == null) + return false; + } + + return string.Equals(nameSyntax.Identifier.Text, TaskCompletionSourceName); + } + private static bool IsRunContinuationsAsynchronously(ExpressionSyntax expression) { var memberAccessExpressionSyntax = expression as MemberAccessExpressionSyntax;