-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[GH-135] - Detecting received like methods used in Received.InOrder
callback block
- Loading branch information
Showing
26 changed files
with
1,347 additions
and
1 deletion.
There are no files selected for viewing
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
22 changes: 22 additions & 0 deletions
22
...rks.Source.CSharp/DiagnosticsSources/ReceivedLikeUsedInReceivedInOrderDiagnosticSource.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,22 @@ | ||
using NSubstitute.Analyzers.Benchmarks.Source.CSharp.Models; | ||
|
||
namespace NSubstitute.Analyzers.Benchmarks.Source.CSharp.DiagnosticsSources | ||
{ | ||
public class ReceivedLikeUsedInReceivedInOrderDiagnosticSource | ||
{ | ||
public void NS5001_ReceivedLikeUsedInReceivedInOrderCallback() | ||
{ | ||
var substitute = Substitute.For<Foo>(); | ||
Received.InOrder(() => | ||
{ | ||
substitute.Received().ObjectReturningMethod(); | ||
_ = substitute.Received().InternalObjectReturningProperty; | ||
_ = substitute.Received()[0]; | ||
|
||
SubstituteExtensions.Received(substitute).ObjectReturningMethod(); | ||
_ = SubstituteExtensions.Received(substitute).InternalObjectReturningProperty; | ||
_ = SubstituteExtensions.Received(substitute)[0]; | ||
}); | ||
} | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
...ource.VisualBasic/DiagnosticsSources/ReceivedLikeUsedInReceivedInOrderDiagnosticSource.vb
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,18 @@ | ||
Imports NSubstitute.Analyzers.Benchmarks.Source.VisualBasic.Models | ||
|
||
Namespace DiagnosticsSources | ||
Public Class ReceivedLikeUsedInReceivedInOrderDiagnosticSource | ||
Public Sub NS5001_ReceivedLikeUsedInReceivedInOrderCallback() | ||
Dim substitute = NSubstitute.Substitute.[For](Of Foo)() | ||
NSubstitute.Received.InOrder(Function() | ||
substitute.Received().ObjectReturningMethod() | ||
Dim x = substitute.Received().InternalObjectReturningProperty | ||
Dim y = substitute.Received()(0) | ||
SubstituteExtensions.Received(substitute).ObjectReturningMethod() | ||
Dim a = SubstituteExtensions.Received(substitute).InternalObjectReturningProperty | ||
Dim b = SubstituteExtensions.Received(substitute)(0) | ||
Throw New System.Exception() | ||
End Function) | ||
End Sub | ||
End Class | ||
End Namespace |
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
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
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
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,83 @@ | ||
# NS5001 | ||
|
||
<table> | ||
<tr> | ||
<td>CheckId</td> | ||
<td>NS5001</td> | ||
</tr> | ||
<tr> | ||
<td>Category</td> | ||
<td>Usage</td> | ||
</tr> | ||
</table> | ||
|
||
## Cause | ||
|
||
Usage of received-like method in `Received.InOrder` callback. | ||
|
||
## Rule description | ||
|
||
A violation of this rule occurs when any of the following are used inside a `Received.InOrder` callback: | ||
|
||
- `Received()` | ||
- `ReceivedWithAnyArgs()` | ||
- `DidNotReceive()` | ||
- `DidNotReceiveWithAnyArgs()` | ||
|
||
Calls within `Received.InOrder` are already checked to ensure they were received in the expected order. Individual received-like assertions should be moved outside the `Received.InOrder` callback. | ||
|
||
## How to fix violations | ||
|
||
To fix a violation of this rule, remove received-like method calls from `Received.InOrder` callback. | ||
|
||
For example: | ||
|
||
````c# | ||
// Incorrect: | ||
Received.InOrder(() => | ||
{ | ||
sub.Received().Baz(); | ||
sub.Received().Bar(); | ||
}) | ||
|
||
// Correct: | ||
Received.InOrder(() => | ||
{ | ||
sub.Baz(); | ||
sub.Bar(); | ||
}) | ||
```` | ||
|
||
Alternatively, move any received-like methods outside of `Received.InOrder` block if ordering is not important: | ||
|
||
````c# | ||
// Incorrect: | ||
Received.InOrder(() => | ||
{ | ||
sub.Baz(); | ||
sub.Zap(); | ||
sub.DidNotReceive().Bar(); | ||
}) | ||
|
||
// Correct: | ||
Received.InOrder(() => | ||
{ | ||
sub.Baz(); | ||
sub.Zap(); | ||
}) | ||
sub.DidNotReceive().Bar(); | ||
```` | ||
|
||
## How to suppress violations | ||
|
||
This warning can be suppressed by disabling the warning in the **ruleset** file for the project. | ||
The warning can also be suppressed programmatically for an assembly: | ||
````c# | ||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "NS5001:Received-like method used in Received.InOrder block.", Justification = "Reviewed")] | ||
```` | ||
|
||
Or for a specific code block: | ||
````c# | ||
#pragma warning disable NS5001 // Received-like method used in Received.InOrder block. | ||
// the code which produces warning | ||
#pragma warning restore NS5001 // Received-like method used in Received.InOrder block. |
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
19 changes: 19 additions & 0 deletions
19
src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/ReceivedInReceivedInOrderAnalyzer.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,19 @@ | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.CSharp; | ||
using Microsoft.CodeAnalysis.CSharp.Syntax; | ||
using Microsoft.CodeAnalysis.Diagnostics; | ||
using NSubstitute.Analyzers.Shared.DiagnosticAnalyzers; | ||
|
||
namespace NSubstitute.Analyzers.CSharp.DiagnosticAnalyzers | ||
{ | ||
[DiagnosticAnalyzer(LanguageNames.CSharp)] | ||
internal sealed class ReceivedInReceivedInOrderAnalyzer : AbstractReceivedInReceivedInOrderAnalyzer<SyntaxKind, InvocationExpressionSyntax> | ||
{ | ||
public ReceivedInReceivedInOrderAnalyzer() | ||
: base(SubstitutionNodeFinder.Instance, CSharp.DiagnosticDescriptorsProvider.Instance) | ||
{ | ||
} | ||
|
||
protected override SyntaxKind InvocationExpressionKind { get; } = SyntaxKind.InvocationExpression; | ||
} | ||
} |
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
71 changes: 71 additions & 0 deletions
71
...stitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractReceivedInReceivedInOrderAnalyzer.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,71 @@ | ||
using System; | ||
using System.Collections.Immutable; | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.Diagnostics; | ||
using NSubstitute.Analyzers.Shared.Extensions; | ||
|
||
namespace NSubstitute.Analyzers.Shared.DiagnosticAnalyzers | ||
{ | ||
internal abstract class AbstractReceivedInReceivedInOrderAnalyzer<TSyntaxKind, TInvocationExpressionSyntax> : AbstractDiagnosticAnalyzer | ||
where TSyntaxKind : struct | ||
where TInvocationExpressionSyntax : SyntaxNode | ||
{ | ||
private readonly ISubstitutionNodeFinder<TInvocationExpressionSyntax> _substitutionNodeFinder; | ||
private readonly Action<SyntaxNodeAnalysisContext> _analyzeInvocationAction; | ||
|
||
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } | ||
|
||
protected AbstractReceivedInReceivedInOrderAnalyzer( | ||
ISubstitutionNodeFinder<TInvocationExpressionSyntax> substitutionNodeFinder, | ||
IDiagnosticDescriptorsProvider diagnosticDescriptorsProvider) | ||
: base(diagnosticDescriptorsProvider) | ||
{ | ||
_substitutionNodeFinder = substitutionNodeFinder; | ||
_analyzeInvocationAction = AnalyzeInvocation; | ||
SupportedDiagnostics = ImmutableArray.Create(diagnosticDescriptorsProvider.ReceivedUsedInReceivedInOrder); | ||
} | ||
|
||
protected abstract TSyntaxKind InvocationExpressionKind { get; } | ||
|
||
protected override void InitializeAnalyzer(AnalysisContext context) | ||
{ | ||
context.RegisterSyntaxNodeAction(_analyzeInvocationAction, InvocationExpressionKind); | ||
} | ||
|
||
private void AnalyzeInvocation(SyntaxNodeAnalysisContext syntaxNodeContext) | ||
{ | ||
var invocationExpression = (TInvocationExpressionSyntax)syntaxNodeContext.Node; | ||
var methodSymbolInfo = syntaxNodeContext.SemanticModel.GetSymbolInfo(invocationExpression); | ||
|
||
if (methodSymbolInfo.Symbol?.Kind != SymbolKind.Method) | ||
{ | ||
return; | ||
} | ||
|
||
if (methodSymbolInfo.Symbol.IsReceivedInOrderMethod() == false) | ||
{ | ||
return; | ||
} | ||
|
||
foreach (var syntaxNode in _substitutionNodeFinder.FindForReceivedInOrderExpression( | ||
syntaxNodeContext, | ||
invocationExpression, | ||
(IMethodSymbol)methodSymbolInfo.Symbol)) | ||
{ | ||
var symbolInfo = syntaxNodeContext.SemanticModel.GetSymbolInfo(syntaxNode); | ||
|
||
if (symbolInfo.Symbol.IsReceivedLikeMethod() == false) | ||
{ | ||
continue; | ||
} | ||
|
||
var diagnostic = Diagnostic.Create( | ||
DiagnosticDescriptorsProvider.ReceivedUsedInReceivedInOrder, | ||
syntaxNode.GetLocation(), | ||
symbolInfo.Symbol.Name); | ||
|
||
syntaxNodeContext.ReportDiagnostic(diagnostic); | ||
} | ||
} | ||
} | ||
} |
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
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
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
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
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
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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
Oops, something went wrong.