From edb6496f7947f332b994756c2e715926c79c0865 Mon Sep 17 00:00:00 2001 From: tpodolak Date: Fri, 21 Aug 2020 00:40:19 +0200 Subject: [PATCH] [GH-108] - async method support --- ...stitutableMemberReceivedInOrderAnalyzer.cs | 7 +++ .../AbstractNonSubstitutableSetupAnalyzer.cs | 2 +- ...stitutableMemberReceivedInOrderAnalyzer.cs | 27 ++++---- ...MemberReceivedInOrderDiagnosticVerifier.cs | 63 ++++++++++++++++--- ...MemberReceivedInOrderDiagnosticVerifier.cs | 49 +++++++++++++-- 5 files changed, 119 insertions(+), 29 deletions(-) diff --git a/src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/NonSubstitutableMemberReceivedInOrderAnalyzer.cs b/src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/NonSubstitutableMemberReceivedInOrderAnalyzer.cs index 864673ce..eb8ad9b3 100644 --- a/src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/NonSubstitutableMemberReceivedInOrderAnalyzer.cs +++ b/src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/NonSubstitutableMemberReceivedInOrderAnalyzer.cs @@ -13,6 +13,9 @@ internal sealed class NonSubstitutableMemberReceivedInOrderAnalyzer : AbstractNo private static ImmutableArray> IgnoredPaths { get; } = ImmutableArray.Create( ImmutableArray.Create( (int)SyntaxKind.Argument), + ImmutableArray.Create( + (int)SyntaxKind.AwaitExpression, + (int)SyntaxKind.Argument), ImmutableArray.Create( (int)SyntaxKind.CastExpression, (int)SyntaxKind.Argument), @@ -22,6 +25,10 @@ internal sealed class NonSubstitutableMemberReceivedInOrderAnalyzer : AbstractNo ImmutableArray.Create( (int)SyntaxKind.EqualsValueClause, (int)SyntaxKind.VariableDeclarator), + ImmutableArray.Create( + (int)SyntaxKind.AwaitExpression, + (int)SyntaxKind.EqualsValueClause, + (int)SyntaxKind.VariableDeclarator), ImmutableArray.Create( (int)SyntaxKind.AsExpression, (int)SyntaxKind.EqualsValueClause, diff --git a/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractNonSubstitutableSetupAnalyzer.cs b/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractNonSubstitutableSetupAnalyzer.cs index f9d9970d..05fa20e8 100644 --- a/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractNonSubstitutableSetupAnalyzer.cs +++ b/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractNonSubstitutableSetupAnalyzer.cs @@ -27,7 +27,7 @@ protected void Analyze(SyntaxNodeAnalysisContext syntaxNodeAnalysisContext, Synt if (analysisResult.CanBeSubstituted == false) { - ReportDiagnostics(syntaxNodeAnalysisContext, analysisResult); + ReportDiagnostics(syntaxNodeAnalysisContext, in analysisResult); } } diff --git a/src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/NonSubstitutableMemberReceivedInOrderAnalyzer.cs b/src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/NonSubstitutableMemberReceivedInOrderAnalyzer.cs index 59c2173b..4356d691 100644 --- a/src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/NonSubstitutableMemberReceivedInOrderAnalyzer.cs +++ b/src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/NonSubstitutableMemberReceivedInOrderAnalyzer.cs @@ -12,30 +12,27 @@ internal sealed class NonSubstitutableMemberReceivedInOrderAnalyzer : AbstractNo { private static ImmutableArray> IgnoredPaths { get; } = ImmutableArray.Create( ImmutableArray.Create( - (int)SyntaxKind.SimpleArgument, - (int)SyntaxKind.ArgumentList, - (int)SyntaxKind.InvocationExpression), + (int)SyntaxKind.SimpleArgument), + ImmutableArray.Create( + (int)SyntaxKind.AwaitExpression, + (int)SyntaxKind.SimpleArgument), ImmutableArray.Create( (int)SyntaxKind.TryCastExpression, - (int)SyntaxKind.SimpleArgument, - (int)SyntaxKind.ArgumentList, - (int)SyntaxKind.InvocationExpression), + (int)SyntaxKind.SimpleArgument), ImmutableArray.Create( (int)SyntaxKind.PredefinedCastExpression, - (int)SyntaxKind.SimpleArgument, - (int)SyntaxKind.ArgumentList, - (int)SyntaxKind.InvocationExpression), + (int)SyntaxKind.SimpleArgument), ImmutableArray.Create( (int)SyntaxKind.DirectCastExpression, - (int)SyntaxKind.SimpleArgument, - (int)SyntaxKind.ArgumentList, - (int)SyntaxKind.InvocationExpression), + (int)SyntaxKind.SimpleArgument), ImmutableArray.Create( (int)SyntaxKind.CTypeExpression, - (int)SyntaxKind.SimpleArgument, - (int)SyntaxKind.ArgumentList, - (int)SyntaxKind.InvocationExpression), + (int)SyntaxKind.SimpleArgument), + ImmutableArray.Create( + (int)SyntaxKind.EqualsValue, + (int)SyntaxKind.VariableDeclarator), ImmutableArray.Create( + (int)SyntaxKind.AwaitExpression, (int)SyntaxKind.EqualsValue, (int)SyntaxKind.VariableDeclarator), ImmutableArray.Create( diff --git a/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/NonSubstitutableMemberReceivedInOrderAnalyzerTests/NonSubstitutableMemberReceivedInOrderDiagnosticVerifier.cs b/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/NonSubstitutableMemberReceivedInOrderAnalyzerTests/NonSubstitutableMemberReceivedInOrderDiagnosticVerifier.cs index 9cdfb8ab..d38ae266 100644 --- a/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/NonSubstitutableMemberReceivedInOrderAnalyzerTests/NonSubstitutableMemberReceivedInOrderDiagnosticVerifier.cs +++ b/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/NonSubstitutableMemberReceivedInOrderAnalyzerTests/NonSubstitutableMemberReceivedInOrderDiagnosticVerifier.cs @@ -29,7 +29,7 @@ public class NonSubstitutableMemberReceivedInOrderDiagnosticVerifier : CSharpDia public async Task ReportsDiagnostics_WhenInvokingNonVirtualMethodWithoutAssignment() { var source = @"using NSubstitute; - +using System.Threading.Tasks; namespace MyNamespace { public class Foo @@ -40,17 +40,22 @@ public int Bar() } } + public class FooBar + { + public Task Bar() + { + return Task.CompletedTask; + } + } + public class FooTests { public void Test() { var substitute = NSubstitute.Substitute.For(); - Received.InOrder(() => - { - [|substitute.Bar()|]; - }); - + var otherSubstitute = NSubstitute.Substitute.For(); Received.InOrder(() => [|substitute.Bar()|]); + Received.InOrder(async () => await [|otherSubstitute.Bar()|]); } } }"; @@ -61,7 +66,7 @@ public void Test() public async Task ReportsDiagnostics_WhenInvokingNonVirtualMethodWithNonUsedAssignment() { var source = @"using NSubstitute; - +using System.Threading.Tasks; namespace MyNamespace { public class Foo @@ -77,11 +82,20 @@ public Foo Bar(int x) } } + public class FooBar + { + public Task Bar() + { + return Task.FromResult(1); + } + } + public class FooTests { public void Test() { var substitute = NSubstitute.Substitute.For(); + var otherSubstitute = NSubstitute.Substitute.For(); Received.InOrder(() => { [|substitute.Bar()|]; @@ -90,6 +104,10 @@ public void Test() var z = (int)[|substitute.Bar()|]; var zz = [|substitute.Bar()|] as object; }); + Received.InOrder(async () => + { + var x = await [|otherSubstitute.Bar()|]; + }); } } }"; @@ -208,7 +226,7 @@ public void Test() public async Task ReportsNoDiagnostics_WhenInvokingNonVirtualMethodWithUsedAssignment() { var source = @"using NSubstitute; - +using System.Threading.Tasks; namespace MyNamespace { public class Foo @@ -219,11 +237,20 @@ public int Bar() } } + public class FooBar + { + public Task Bar() + { + return Task.FromResult(1); + } + } + public class FooTests { public void Test() { var substitute = NSubstitute.Substitute.For(); + var otherSubstitute = NSubstitute.Substitute.For(); Received.InOrder(() => { var a = substitute.Bar(); @@ -233,6 +260,11 @@ public void Test() var bb = b; var cc = c; }); + Received.InOrder(async () => + { + var a = await otherSubstitute.Bar(); + var aa = a; + }); } } }"; @@ -299,7 +331,7 @@ public void Test() public async Task ReportsNoDiagnostics_WhenNonVirtualMethodIsCalledAsArgument() { var source = @"using NSubstitute; - +using System.Threading.Tasks; namespace MyNamespace { public class Foo @@ -315,11 +347,20 @@ public int FooBar() } } + public class FooBar + { + public Task Bar() + { + return Task.FromResult(1); + } + } + public class FooTests { public void Test() { var substitute = NSubstitute.Substitute.For(); + var otherSubstitute = NSubstitute.Substitute.For(); Received.InOrder(() => { var local = 1; @@ -330,6 +371,10 @@ public void Test() substitute.Bar(local); substitute.Bar(1); }); + Received.InOrder(async () => + { + substitute.Bar(await otherSubstitute.Bar()); + }); } } }"; diff --git a/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/NonSubstitutableMemberReceivedInOrderAnalyzerTests/NonSubstitutableMemberReceivedInOrderDiagnosticVerifier.cs b/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/NonSubstitutableMemberReceivedInOrderAnalyzerTests/NonSubstitutableMemberReceivedInOrderDiagnosticVerifier.cs index af02c22a..d22e01e1 100644 --- a/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/NonSubstitutableMemberReceivedInOrderAnalyzerTests/NonSubstitutableMemberReceivedInOrderDiagnosticVerifier.cs +++ b/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/NonSubstitutableMemberReceivedInOrderAnalyzerTests/NonSubstitutableMemberReceivedInOrderDiagnosticVerifier.cs @@ -29,7 +29,7 @@ public class NonSubstitutableMemberReceivedInOrderDiagnosticVerifier : VisualBas public async Task ReportsDiagnostics_WhenInvokingNonVirtualMethodWithoutAssignment() { var source = @"Imports NSubstitute - +Imports System.Threading.Tasks Namespace MyNamespace Public Class Foo Public Function Bar() As Integer @@ -37,14 +37,23 @@ Return 2 End Function End Class + Public Class FooBar + Public Function Bar() As Task(Of Integer) + Return Task.FromResult(1) + End Function + End Class + Public Class FooTests Public Sub Test() Dim substitute = NSubstitute.Substitute.[For](Of Foo)() + Dim otherSubstitute = NSubstitute.Substitute.[For](Of FooBar)() NSubstitute.Received.InOrder(Function() [|substitute.Bar()|] End Function) NSubstitute.Received.InOrder(Function() [|substitute.Bar()|]) + NSubstitute.Received.InOrder(Async Function() Await [|otherSubstitute.Bar()|]) NSubstitute.Received.InOrder(Sub() [|substitute.Bar()|]) + NSubstitute.Received.InOrder(Async Sub() Await [|otherSubstitute.Bar()|]) End Sub End Class End Namespace @@ -56,7 +65,7 @@ End Namespace public async Task ReportsDiagnostics_WhenInvokingNonVirtualMethodWithNonUsedAssignment() { var source = @"Imports NSubstitute - +Imports System.Threading.Tasks Namespace MyNamespace Public Class Foo Public Function Bar() As Integer @@ -68,15 +77,26 @@ Return Nothing End Function End Class + Public Class FooBar + Public Function Bar() As Task(Of Integer) + Return Task.FromResult(1) + End Function + End Class + Public Class FooTests Public Sub Test() Dim substitute = NSubstitute.Substitute.[For](Of Foo)() + Dim otherSubstitute = NSubstitute.Substitute.[For](Of FooBar)() NSubstitute.Received.InOrder(Function() [|substitute.Bar()|] Dim y = [|substitute.Bar()|] Dim z = CInt([|substitute.Bar()|]) Dim zz = TryCast([|substitute.Bar()|], Object) End Function) + NSubstitute.Received.InOrder(Async Function() + Await [|otherSubstitute.Bar()|] + Dim y = Await [|otherSubstitute.Bar()|] + End Function) End Sub End Class End Namespace"; @@ -188,7 +208,7 @@ End Namespace public async Task ReportsNoDiagnostics_WhenInvokingNonVirtualMethodWithUsedAssignment() { var source = @"Imports NSubstitute - +Imports System.Threading.Tasks Namespace MyNamespace Public Class Foo Public Function Bar() As Integer @@ -196,13 +216,24 @@ Return 2 End Function End Class + Public Class FooBar + Public Function Bar() As Task(Of Integer) + Return Task.FromResult(1) + End Function + End Class + Public Class FooTests Public Sub Test() Dim substitute = NSubstitute.Substitute.[For](Of Foo)() + Dim otherSubstitute = NSubstitute.Substitute.[For](Of FooBar)() NSubstitute.Received.InOrder(Function() Dim x = substitute.Bar() Dim y = x End Function) + NSubstitute.Received.InOrder(Async Function() + Dim x = Await otherSubstitute.Bar() + Dim y = x + End Function) End Sub End Class End Namespace @@ -274,7 +305,7 @@ End Namespace public async Task ReportsNoDiagnostics_WhenNonVirtualMethodIsCalledAsArgument() { var source = @"Imports NSubstitute - +Imports System.Threading.Tasks Namespace MyNamespace Public Class Foo Public Overridable Function Bar(ByVal x As Object) As Integer @@ -286,9 +317,16 @@ Return 1 End Function End Class + Public Class FooBar + Public Function Bar() As Task(Of Integer) + Return Task.FromResult(1) + End Function + End Class + Public Class FooTests Public Sub Test() Dim substitute = NSubstitute.Substitute.[For](Of Foo)() + Dim otherSubstitute = NSubstitute.Substitute.[For](Of FooBar)() NSubstitute.Received.InOrder(Function() Dim local = 1 Dim x = substitute.Bar(substitute.FooBar()) @@ -300,6 +338,9 @@ Public Sub Test() substitute.Bar(local) substitute.Bar(1) End Function) + NSubstitute.Received.InOrder(Async Function() + Dim x = substitute.Bar(Await otherSubstitute.Bar()) + End Function) End Sub End Class End Namespace