-
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-174 - analyzing usages of WithAnyArgs like methods
- Loading branch information
Showing
62 changed files
with
5,654 additions
and
47 deletions.
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
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
40 changes: 40 additions & 0 deletions
40
...ute.Analyzers.Benchmarks.Source.CSharp/DiagnosticsSources/WithAnyArgsDiagnosticsSource.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,40 @@ | ||
using NSubstitute.Analyzers.Benchmarks.Source.CSharp.Models; | ||
|
||
namespace NSubstitute.Analyzers.Benchmarks.Source.CSharp.DiagnosticsSources | ||
{ | ||
public class WithAnyArgsDiagnosticsSource | ||
{ | ||
public void NS5004_InvalidArgumentMatcherUsedWithAnyArgs() | ||
{ | ||
var substitute = Substitute.For<IFoo>(); | ||
|
||
_ = substitute.DidNotReceiveWithAnyArgs()[Arg.Is(1)]; | ||
_ = substitute.DidNotReceiveWithAnyArgs()[Arg.Do<int>(_ => { })]; | ||
substitute.DidNotReceiveWithAnyArgs().IntReturningProperty = Arg.Is(1); | ||
substitute.DidNotReceiveWithAnyArgs().IntReturningProperty = Arg.Do<int>(_ => { }); | ||
substitute.DidNotReceiveWithAnyArgs() | ||
.ObjectReturningMethodWithArguments(Arg.Is(1), Arg.Is(1), Arg.Do<int>(_ => { })); | ||
|
||
_ = substitute.DidNotReceiveWithAnyArgs()[Arg.Is(1)]; | ||
_ = substitute.DidNotReceiveWithAnyArgs()[Arg.Do<int>(_ => { })]; | ||
substitute.DidNotReceiveWithAnyArgs().IntReturningProperty = Arg.Is(1); | ||
substitute.DidNotReceiveWithAnyArgs().IntReturningProperty = Arg.Do<int>(_ => { }); | ||
substitute.DidNotReceiveWithAnyArgs() | ||
.ObjectReturningMethodWithArguments(Arg.Is(1), Arg.Is(1), Arg.Do<int>(_ => { })); | ||
|
||
_ = SubstituteExtensions.DidNotReceiveWithAnyArgs(substitute)[Arg.Is(1)]; | ||
_ = SubstituteExtensions.DidNotReceiveWithAnyArgs(substitute)[Arg.Do<int>(_ => { })]; | ||
SubstituteExtensions.DidNotReceiveWithAnyArgs(substitute).IntReturningProperty = Arg.Is(1); | ||
SubstituteExtensions.DidNotReceiveWithAnyArgs(substitute).IntReturningProperty = Arg.Do<int>(_ => { }); | ||
SubstituteExtensions.DidNotReceiveWithAnyArgs(substitute) | ||
.ObjectReturningMethodWithArguments(Arg.Is(1), Arg.Is(1), Arg.Do<int>(_ => { })); | ||
|
||
_ = SubstituteExtensions.DidNotReceiveWithAnyArgs(substitute)[Arg.Is(1)]; | ||
_ = SubstituteExtensions.DidNotReceiveWithAnyArgs(substitute)[Arg.Do<int>(_ => { })]; | ||
SubstituteExtensions.DidNotReceiveWithAnyArgs(substitute).IntReturningProperty = Arg.Is(1); | ||
SubstituteExtensions.DidNotReceiveWithAnyArgs(substitute).IntReturningProperty = Arg.Do<int>(_ => { }); | ||
SubstituteExtensions.DidNotReceiveWithAnyArgs(substitute) | ||
.ObjectReturningMethodWithArguments(Arg.Is(1), Arg.Is(1), Arg.Do<int>(_ => { })); | ||
} | ||
} | ||
} |
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
54 changes: 54 additions & 0 deletions
54
...nalyzers.Benchmarks.Source.VisualBasic/DiagnosticsSources/WithAnyArgsDiagnosticsSource.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,54 @@ | ||
Imports System | ||
Imports NSubstitute.Analyzers.Benchmarks.Source.VisualBasic.Models | ||
|
||
Namespace DiagnosticsSources | ||
Public Class WithAnyArgsDiagnosticsSource | ||
Public Sub NS5004_InvalidArgumentMatcherUsedWithAnyArgs() | ||
Dim substitute = NSubstitute.Substitute.[For](Of IFoo)() | ||
Dim fist = substitute.DidNotReceiveWithAnyArgs()(Arg.[Is](1)) | ||
Dim second = substitute.DidNotReceiveWithAnyArgs()(Arg.[Do](Of Integer)(Function(x) | ||
Throw New Exception | ||
End Function)) | ||
substitute.DidNotReceiveWithAnyArgs().IntReturningProperty = Arg.[Is](1) | ||
substitute.DidNotReceiveWithAnyArgs().IntReturningProperty = Arg.[Do](Of Integer)(Function(x) | ||
Throw New Exception | ||
End Function) | ||
substitute.DidNotReceiveWithAnyArgs().ObjectReturningMethodWithArguments(Arg.[Is](1), Arg.[Is](1), Arg.[Do](Of Integer)(Function(x) | ||
Throw New Exception | ||
End Function)) | ||
Dim third = substitute.DidNotReceiveWithAnyArgs()(Arg.[Is](1)) | ||
Dim fourth = substitute.DidNotReceiveWithAnyArgs()(Arg.[Do](Of Integer)(Function(x) | ||
Throw New Exception() | ||
End Function)) | ||
substitute.DidNotReceiveWithAnyArgs().IntReturningProperty = Arg.[Is](1) | ||
substitute.DidNotReceiveWithAnyArgs().IntReturningProperty = Arg.[Do](Of Integer)(Function(x) | ||
Throw New Exception() | ||
End Function) | ||
substitute.DidNotReceiveWithAnyArgs().ObjectReturningMethodWithArguments(Arg.[Is](1), Arg.[Is](1), Arg.[Do](Of Integer)(Function(x) | ||
Throw New Exception() | ||
End Function)) | ||
Dim fifth = SubstituteExtensions.DidNotReceiveWithAnyArgs(substitute)(Arg.[Is](1)) | ||
Dim sixth = SubstituteExtensions.DidNotReceiveWithAnyArgs(substitute)(Arg.[Do](Of Integer)(Function(x) | ||
Throw New Exception() | ||
End Function)) | ||
SubstituteExtensions.DidNotReceiveWithAnyArgs(substitute).IntReturningProperty = Arg.[Is](1) | ||
SubstituteExtensions.DidNotReceiveWithAnyArgs(substitute).IntReturningProperty = Arg.[Do](Of Integer)(Function(x) | ||
Throw New Exception() | ||
End Function) | ||
SubstituteExtensions.DidNotReceiveWithAnyArgs(substitute).ObjectReturningMethodWithArguments(Arg.[Is](1), Arg.[Is](1), Arg.[Do](Of Integer)(Function(x) | ||
Throw New Exception() | ||
End Function)) | ||
Dim seventh = SubstituteExtensions.DidNotReceiveWithAnyArgs(substitute)(Arg.[Is](1)) | ||
Dim eigth = SubstituteExtensions.DidNotReceiveWithAnyArgs(substitute)(Arg.[Do](Of Integer)(Function(x) | ||
Throw New Exception() | ||
End Function)) | ||
SubstituteExtensions.DidNotReceiveWithAnyArgs(substitute).IntReturningProperty = Arg.[Is](1) | ||
SubstituteExtensions.DidNotReceiveWithAnyArgs(substitute).IntReturningProperty = Arg.[Do](Of Integer)(Function(x) | ||
Throw New Exception() | ||
End Function) | ||
SubstituteExtensions.DidNotReceiveWithAnyArgs(substitute).ObjectReturningMethodWithArguments(Arg.[Is](1), Arg.[Is](1), Arg.[Do](Of Integer)(Function(x) | ||
Throw New 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
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,52 @@ | ||
# NS5004 | ||
|
||
<table> | ||
<tr> | ||
<td>CheckId</td> | ||
<td>NS5004</td> | ||
</tr> | ||
<tr> | ||
<td>Category</td> | ||
<td>Usage</td> | ||
</tr> | ||
</table> | ||
|
||
## Cause | ||
|
||
Argument matcher used with WithAnyArgs. This matcher may not be executed. | ||
|
||
## Rule description | ||
|
||
A violation of this rule occurs when `ReturnsForAnyArgs`,`ReturnsNullForAnyArgs`,`ThrowsForAnyArgs`,`ThrowsAsyncForAnyArgs`, `WhenForAnyArgs`, `DidNotReceiveWithAnyArgs` or `ReceivedWithAnyArgs` is used in combination with arg matchers other than `Arg.Any`. | ||
|
||
## How to fix violations | ||
|
||
To fix a violation of this rule, replace arg matchers used in aforementioned methods with `Arg.Any` | ||
|
||
For example: | ||
|
||
````c# | ||
// Incorrect: | ||
sub.DidNotReceiveWithAnyArgs().Bar(Arg.Is(1)); | ||
|
||
// Correct: | ||
sub.DidNotReceiveWithAnyArgs().Bar(Arg.Any<int>()); | ||
|
||
// The following are also correct. The exact arguments will not be checked due to *WithAnyArgs. | ||
sub.DidNotReceiveWithAnyArgs().Bar(default(int)); | ||
sub.DidNotReceiveWithAnyArgs().Bar(123); | ||
```` | ||
|
||
## 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", "NS5004:Argument matcher used with WithAnyArgs. This matcher may not be executed..", Justification = "Reviewed")] | ||
```` | ||
|
||
Or for a specific code block: | ||
````c# | ||
#pragma warning disable NS5004 // Argument matcher used with WithAnyArgs. This matcher may not be executed.. | ||
// the code which produces warning | ||
#pragma warning restore NS5004 // Argument matcher used with WithAnyArgs. This matcher may not be executed.. |
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
26 changes: 26 additions & 0 deletions
26
src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/WithAnyArgsArgumentMatcherAnalyzer.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,26 @@ | ||
using System.Collections.Immutable; | ||
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 WithAnyArgsArgumentMatcherAnalyzer : AbstractWithAnyArgsArgumentMatcherAnalyzer<SyntaxKind, InvocationExpressionSyntax> | ||
{ | ||
internal static ImmutableHashSet<int> MaybeAllowedAncestors { get; } = ImmutableHashSet.Create( | ||
(int)SyntaxKind.InvocationExpression, | ||
(int)SyntaxKind.ElementAccessExpression, | ||
(int)SyntaxKind.SimpleAssignmentExpression); | ||
|
||
public WithAnyArgsArgumentMatcherAnalyzer() | ||
: base(CSharp.DiagnosticDescriptorsProvider.Instance, SubstitutionNodeFinder.Instance) | ||
{ | ||
} | ||
|
||
protected override ImmutableHashSet<int> MaybeAllowedArgMatcherAncestors { get; } = MaybeAllowedAncestors; | ||
|
||
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
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.