diff --git a/.github/workflows/github-actions-release.yml b/.github/workflows/github-actions-release.yml
index 4086a24..2b9cec9 100644
--- a/.github/workflows/github-actions-release.yml
+++ b/.github/workflows/github-actions-release.yml
@@ -7,7 +7,7 @@ on:
type: string
description: The version of the library
required: true
- default: 1.9.1
+ default: 1.9.2
VersionSuffix:
type: string
description: The version suffix of the library (for example rc.1)
diff --git a/src/Moq.Analyzers/Moq.Analyzers.csproj b/src/Moq.Analyzers/Moq.Analyzers.csproj
index 74558d2..241b850 100644
--- a/src/Moq.Analyzers/Moq.Analyzers.csproj
+++ b/src/Moq.Analyzers/Moq.Analyzers.csproj
@@ -17,6 +17,10 @@
https://github.com/PosInformatique/PosInformatique.Moq.Analyzers
README.md
+ 1.9.2
+ - Fix the PosInfoMoq1003 to raise warnings when using InSequence() method.
+ - Fix the PosInfoMoq2003 to raise errors when using InSequence() method.
+
1.9.1
- Add new rules:
- PosInfoMoq2009: Mock.Of<T> method must be used only to mock non-sealed class
diff --git a/src/Moq.Analyzers/MoqSymbols.cs b/src/Moq.Analyzers/MoqSymbols.cs
index b5ed98c..315e399 100644
--- a/src/Moq.Analyzers/MoqSymbols.cs
+++ b/src/Moq.Analyzers/MoqSymbols.cs
@@ -44,12 +44,15 @@ internal sealed class MoqSymbols
private MoqSymbols(INamedTypeSymbol mockGenericClass, Compilation compilation)
{
this.mockGenericClass = mockGenericClass;
+
+ var setupConditionResultInterface = new Lazy(() => compilation.GetTypeByMetadataName("Moq.Language.ISetupConditionResult`1")!);
+
this.mockBehaviorEnum = new Lazy(() => compilation.GetTypeByMetadataName("Moq.MockBehavior")!);
this.isAnyTypeClass = new Lazy(() => compilation.GetTypeByMetadataName("Moq.It+IsAnyType")!);
this.isAnyMethod = new Lazy(() => compilation.GetTypeByMetadataName("Moq.It")!.GetMembers("IsAny").Single());
this.verifiesInterface = new Lazy(() => compilation.GetTypeByMetadataName("Moq.Language.IVerifies")!);
- this.setupMethods = new Lazy>(() => mockGenericClass.GetMembers("Setup").OfType().ToArray());
+ this.setupMethods = new Lazy>(() => mockGenericClass.GetMembers("Setup").Concat(setupConditionResultInterface.Value.GetMembers("Setup")).OfType().ToArray());
this.mockBehaviorStrictField = new Lazy(() => this.mockBehaviorEnum.Value.GetMembers("Strict").First());
this.setupProtectedMethods = new Lazy>(() => compilation.GetTypeByMetadataName("Moq.Protected.IProtectedMock`1")!.GetMembers("Setup").OfType().ToArray());
this.asMethod = new Lazy(() => mockGenericClass.GetMembers("As").Single());
diff --git a/tests/Moq.Analyzers.Tests/Analyzers/CallBackDelegateMustMatchMockedMethodAnalyzerTest.cs b/tests/Moq.Analyzers.Tests/Analyzers/CallBackDelegateMustMatchMockedMethodAnalyzerTest.cs
index f1a79e3..e57bf06 100644
--- a/tests/Moq.Analyzers.Tests/Analyzers/CallBackDelegateMustMatchMockedMethodAnalyzerTest.cs
+++ b/tests/Moq.Analyzers.Tests/Analyzers/CallBackDelegateMustMatchMockedMethodAnalyzerTest.cs
@@ -10,8 +10,10 @@ namespace PosInformatique.Moq.Analyzers.Tests
public class CallBackDelegateMustMatchMockedMethodAnalyzerTest
{
- [Fact]
- public async Task CallBackSignatureMatch_NoDiagnosticReported()
+ [Theory]
+ [InlineData("")]
+ [InlineData(".InSequence(sequence)")]
+ public async Task CallBackSignatureMatch_NoDiagnosticReported(string sequence)
{
var source = @"
namespace ConsoleApplication1
@@ -23,31 +25,33 @@ public class TestClass
{
public void TestMethod()
{
+ var sequence = new MockSequence();
+
var mock1 = new Mock();
- mock1.Setup(m => m.TestMethod())
+ mock1" + sequence + @".Setup(m => m.TestMethod())
.Callback(() => { })
.Throws(new Exception());
- mock1.Setup(m => m.TestMethod(default))
+ mock1" + sequence + @".Setup(m => m.TestMethod(default))
.Callback((string x) => { })
.Throws(new Exception());
- mock1.Setup(m => m.TestMethod(default, default))
+ mock1" + sequence + @".Setup(m => m.TestMethod(default, default))
.Callback((string x, int y) => { })
.Throws(new Exception());
- mock1.Setup(m => m.TestGenericMethod(1234))
+ mock1" + sequence + @".Setup(m => m.TestGenericMethod(1234))
.Callback((int x) => { })
.Throws(new Exception());
- mock1.Setup(m => m.TestGenericMethod(It.IsAny()))
+ mock1" + sequence + @".Setup(m => m.TestGenericMethod(It.IsAny()))
.Callback((object x) => { })
.Throws(new Exception());
- mock1.Setup(m => m.TestMethodReturn())
+ mock1" + sequence + @".Setup(m => m.TestMethodReturn())
.Callback(() => { })
.Returns(1234);
- mock1.Setup(m => m.TestMethodReturn(default))
+ mock1" + sequence + @".Setup(m => m.TestMethodReturn(default))
.Callback((string x) => { })
.Returns(1234);
- mock1.Setup(m => m.TestMethodReturn(default, default))
+ mock1" + sequence + @".Setup(m => m.TestMethodReturn(default, default))
.Callback((string x, int y) => { })
.Returns(1234);
@@ -80,8 +84,10 @@ public interface I
await Verifier.VerifyAnalyzerAsync(source);
}
- [Fact]
- public async Task CallBackSignatureNotMatch_DiagnosticReported()
+ [Theory]
+ [InlineData("")]
+ [InlineData(".InSequence(sequence)")]
+ public async Task CallBackSignatureNotMatch_DiagnosticReported(string sequence)
{
var source = @"
namespace ConsoleApplication1
@@ -93,37 +99,39 @@ public class TestClass
{
public void TestMethod()
{
+ var sequence = new MockSequence();
+
var mock1 = new Mock();
- mock1.Setup(m => m.TestMethod())
+ mock1" + sequence + @".Setup(m => m.TestMethod())
.Callback([|(int too, int much, int parameters)|] => { })
.Throws(new Exception());
- mock1.Setup(m => m.TestMethod(default))
+ mock1" + sequence + @".Setup(m => m.TestMethod(default))
.Callback([|()|] => { })
.Throws(new Exception());
- mock1.Setup(m => m.TestMethod(default))
+ mock1" + sequence + @".Setup(m => m.TestMethod(default))
.Callback(([|int otherType|]) => { })
.Throws(new Exception());
- mock1.Setup(m => m.TestMethod(default))
+ mock1" + sequence + @".Setup(m => m.TestMethod(default))
.Callback([|(int too, int much, int parameters)|] => { })
.Throws(new Exception());
- mock1.Setup(m => m.TestGenericMethod(1234))
+ mock1" + sequence + @".Setup(m => m.TestGenericMethod(1234))
.Callback(([|string x|]) => { })
.Throws(new Exception());
- mock1.Setup(m => m.TestGenericMethod(It.IsAny()))
+ mock1" + sequence + @".Setup(m => m.TestGenericMethod(It.IsAny()))
.Callback(([|string x|]) => { })
.Throws(new Exception());
- mock1.Setup(m => m.TestMethodReturn())
+ mock1" + sequence + @".Setup(m => m.TestMethodReturn())
.Callback([|(int too, int much, int parameters)|] => { })
.Returns(1234);
- mock1.Setup(m => m.TestMethodReturn(default))
+ mock1" + sequence + @".Setup(m => m.TestMethodReturn(default))
.Callback([|()|] => { })
.Returns(1234);
- mock1.Setup(m => m.TestMethodReturn(default))
+ mock1" + sequence + @".Setup(m => m.TestMethodReturn(default))
.Callback(([|int otherType|]) => { })
.Returns(1234);
- mock1.Setup(m => m.TestMethodReturn(default))
+ mock1" + sequence + @".Setup(m => m.TestMethodReturn(default))
.Callback([|(int too, int much, int parameters)|] => { })
.Returns(1234);
}
diff --git a/tests/Moq.Analyzers.Tests/Analyzers/CallBackDelegateShouldBeUsedWithItIsAnyParametersAnalyzerTest.cs b/tests/Moq.Analyzers.Tests/Analyzers/CallBackDelegateShouldBeUsedWithItIsAnyParametersAnalyzerTest.cs
index 1cc7ddb..73806a0 100644
--- a/tests/Moq.Analyzers.Tests/Analyzers/CallBackDelegateShouldBeUsedWithItIsAnyParametersAnalyzerTest.cs
+++ b/tests/Moq.Analyzers.Tests/Analyzers/CallBackDelegateShouldBeUsedWithItIsAnyParametersAnalyzerTest.cs
@@ -57,7 +57,7 @@ await Verifier.VerifyAnalyzerAsync(
}
[Fact]
- public async Task Callback_NoDiagnosticReported()
+ public async Task NoCallback_DiagnosticReported_WithSequence()
{
var source = @"
namespace ConsoleApplication1
@@ -69,21 +69,72 @@ public class TestClass
{
public void TestMethod()
{
+ var sequence = new MockSequence();
+
+ var mock1 = new Mock();
+ mock1.InSequence(sequence).Setup(m => m.TestMethod({|#0:It.IsAny()|#0}, {|#1:It.IsAny()|#1}));
+ mock1.InSequence(sequence).Setup(m => m.TestMethod(""Ignored"", {|#2:It.IsAny()|#2}));
+ mock1.InSequence(sequence).Setup(m => m.TestMethod({|#3:It.IsAny()|#3}, 1234));
+ mock1.InSequence(sequence).Setup(m => m.TestMethod({|#4:It.IsAny()|#4}));
+ }
+ }
+
+ public interface I
+ {
+ void TestMethod(string a);
+
+ void TestMethod(string a, int b);
+ }
+ }";
+
+ await Verifier.VerifyAnalyzerAsync(
+ source,
+ [
+ new DiagnosticResult(CallBackDelegateShouldBeUsedWithItIsAnyParametersAnalyzer.Rule)
+ .WithSpan(14, 80, 14, 98).WithArguments("a"),
+ new DiagnosticResult(CallBackDelegateShouldBeUsedWithItIsAnyParametersAnalyzer.Rule)
+ .WithSpan(14, 100, 14, 115).WithArguments("b"),
+ new DiagnosticResult(CallBackDelegateShouldBeUsedWithItIsAnyParametersAnalyzer.Rule)
+ .WithSpan(15, 91, 15, 106).WithArguments("b"),
+ new DiagnosticResult(CallBackDelegateShouldBeUsedWithItIsAnyParametersAnalyzer.Rule)
+ .WithSpan(16, 80, 16, 98).WithArguments("a"),
+ new DiagnosticResult(CallBackDelegateShouldBeUsedWithItIsAnyParametersAnalyzer.Rule)
+ .WithSpan(17, 80, 17, 98).WithArguments("a"),
+ ]);
+ }
+
+ [Theory]
+ [InlineData("")]
+ [InlineData(".InSequence(sequence)")]
+ public async Task Callback_NoDiagnosticReported(string sequence)
+ {
+ var source = @"
+ namespace ConsoleApplication1
+ {
+ using Moq;
+ using System;
+
+ public class TestClass
+ {
+ public void TestMethod()
+ {
+ var sequence = new MockSequence();
+
var mock1 = new Mock();
- mock1.Setup(m => m.TestMethod(It.IsAny()))
+ mock1" + sequence + @".Setup(m => m.TestMethod(It.IsAny()))
.Callback(() => { });
- mock1.Setup(m => m.TestMethod(It.IsAny(), It.IsAny()))
+ mock1" + sequence + @".Setup(m => m.TestMethod(It.IsAny(), It.IsAny()))
.Callback(() => { });
- mock1.Setup(m => m.TestMethod(""OK"", It.IsAny()))
+ mock1" + sequence + @".Setup(m => m.TestMethod(""OK"", It.IsAny()))
.Callback(() => { });
- mock1.Setup(m => m.TestMethod(It.IsAny(), 1234))
+ mock1" + sequence + @".Setup(m => m.TestMethod(It.IsAny(), 1234))
.Callback(() => { });
var mock2 = new Mock();
- mock2.Setup(m => m.TestMethod());
+ mock2" + sequence + @".Setup(m => m.TestMethod());
var mock3 = new Mock();
- mock3.Setup(m => m.TestMethod(""OK"", 1234));
+ mock3" + sequence + @".Setup(m => m.TestMethod(""OK"", 1234));
var o = new object();
o.ToString(); // Ignored
diff --git a/tests/Moq.Analyzers.Tests/Analyzers/ConstructorArgumentsMustMatchAnalyzerTest.cs b/tests/Moq.Analyzers.Tests/Analyzers/ConstructorArgumentsMustMatchAnalyzerTest.cs
index 8def3be..b053a46 100644
--- a/tests/Moq.Analyzers.Tests/Analyzers/ConstructorArgumentsMustMatchAnalyzerTest.cs
+++ b/tests/Moq.Analyzers.Tests/Analyzers/ConstructorArgumentsMustMatchAnalyzerTest.cs
@@ -208,7 +208,6 @@ private C(int a, object b, int c, System.IDisposable d)
await Verifier.VerifyAnalyzerAsync(source);
}
-
[Theory]
[InlineData("class")]
[InlineData("abstract class")]