diff --git a/ReleaseNotes.md b/ReleaseNotes.md index 45329b27..4c2ae357 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -1,3 +1,11 @@ +### 1.0.6 (21 February 2019) + + - [#71](https://github.com/nsubstitute/NSubstitute.Analyzers/issues/71) - Incorrect NS4000 when using typeof expression + +### 1.0.5 (09 February 2019) + + - [#61](https://github.com/nsubstitute/NSubstitute.Analyzers/issues/61) - CallInfo analysis for AndDoes method + ### 1.0.4 (03 January 2019) - [#57](https://github.com/nsubstitute/NSubstitute.Analyzers/issues/57) - Incorrect NS3004 for derived types diff --git a/src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/ReEntrantCallFinder.cs b/src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/ReEntrantCallFinder.cs index fb66af38..e3c008b4 100644 --- a/src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/ReEntrantCallFinder.cs +++ b/src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/ReEntrantCallFinder.cs @@ -47,6 +47,14 @@ public override void VisitInvocationExpression(InvocationExpressionSyntax node) base.VisitInvocationExpression(node); } + public override void VisitClassDeclaration(ClassDeclarationSyntax node) + { + } + + public override void VisitStructDeclaration(StructDeclarationSyntax node) + { + } + public override void DefaultVisit(SyntaxNode node) { VisitRelatedSymbols(node); diff --git a/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractNonSubstitutableMemberReceivedAnalyzer.cs b/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractNonSubstitutableMemberReceivedAnalyzer.cs index a3b20e81..0514ff1f 100644 --- a/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractNonSubstitutableMemberReceivedAnalyzer.cs +++ b/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractNonSubstitutableMemberReceivedAnalyzer.cs @@ -76,7 +76,7 @@ private void AnalyzeInvocation(SyntaxNodeAnalysisContext syntaxNodeContext) { var diagnostic = Diagnostic.Create( DiagnosticDescriptorsProvider.NonVirtualReceivedSetupSpecification, - invocationExpression.GetLocation(), + GetSymbolLocation(parentNode, symbolInfo.Symbol), symbolInfo.Symbol.Name); syntaxNodeContext.ReportDiagnostic(diagnostic); @@ -86,7 +86,7 @@ private void AnalyzeInvocation(SyntaxNodeAnalysisContext syntaxNodeContext) { var diagnostic = Diagnostic.Create( DiagnosticDescriptorsProvider.InternalSetupSpecification, - invocationExpression.GetLocation(), + GetSymbolLocation(parentNode, symbolInfo.Symbol), symbolInfo.Symbol.Name); syntaxNodeContext.ReportDiagnostic(diagnostic); @@ -117,5 +117,12 @@ private SyntaxNode GetKnownParent(SyntaxNode receivedSyntaxNode) return null; } + + private Location GetSymbolLocation(SyntaxNode syntaxNode, ISymbol symbol) + { + var actualNode = symbol is IMethodSymbol _ ? syntaxNode.Parent : syntaxNode; + + return actualNode.GetLocation(); + } } } \ No newline at end of file diff --git a/src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/ReEntrantCallFinder.cs b/src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/ReEntrantCallFinder.cs index 360216d8..78b04767 100644 --- a/src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/ReEntrantCallFinder.cs +++ b/src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/ReEntrantCallFinder.cs @@ -46,6 +46,14 @@ public override void VisitInvocationExpression(InvocationExpressionSyntax node) base.VisitInvocationExpression(node); } + public override void VisitClassBlock(ClassBlockSyntax node) + { + } + + public override void VisitStructureBlock(StructureBlockSyntax node) + { + } + public override void DefaultVisit(SyntaxNode node) { VisitRelatedSymbols(node); diff --git a/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/NonSubstitutableMemberReceivedAnalyzerTests/ReceivedAsExtensionMethodTests.cs b/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/NonSubstitutableMemberReceivedAnalyzerTests/ReceivedAsExtensionMethodTests.cs index 895b1757..8c18c491 100644 --- a/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/NonSubstitutableMemberReceivedAnalyzerTests/ReceivedAsExtensionMethodTests.cs +++ b/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/NonSubstitutableMemberReceivedAnalyzerTests/ReceivedAsExtensionMethodTests.cs @@ -25,7 +25,7 @@ public class FooTests public void Test() {{ var substitute = NSubstitute.Substitute.For(); - [|substitute.{method}()|].Bar(); + [|substitute.{method}().Bar()|]; }} }} }}"; @@ -138,7 +138,7 @@ public class FooTests public void Test() {{ var substitute = NSubstitute.Substitute.For(); - [|substitute.{method}()|].Bar(); + [|substitute.{method}().Bar()|]; }} }} }}"; @@ -327,7 +327,7 @@ public class FooTests public void Test() {{ var substitute = NSubstitute.Substitute.For(); - var x = [|substitute.{method}()|].Bar; + var x = [|substitute.{method}().Bar|]; }} }} }}"; @@ -374,7 +374,7 @@ public class FooTests public void Test() {{ var substitute = NSubstitute.Substitute.For(); - var x = [|substitute.{method}()|][1]; + var x = [|substitute.{method}()[1]|]; }} }} }}"; @@ -457,7 +457,7 @@ public class FooTests public void Test() {{ var substitute = NSubstitute.Substitute.For(); - var x = [|substitute.{method}()|]{call}; + var x = [|substitute.{method}(){call}|]; }} }} }}"; @@ -531,7 +531,7 @@ public class FooTests public void Test() {{ var substitute = NSubstitute.Substitute.For(); - var x = [|substitute.{method}()|]{call}; + var x = [|substitute.{method}(){call}|]; }} }} }}"; diff --git a/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/NonSubstitutableMemberReceivedAnalyzerTests/ReceivedAsOrdinaryMethodTests.cs b/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/NonSubstitutableMemberReceivedAnalyzerTests/ReceivedAsOrdinaryMethodTests.cs index 5987ce70..23d731af 100644 --- a/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/NonSubstitutableMemberReceivedAnalyzerTests/ReceivedAsOrdinaryMethodTests.cs +++ b/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/NonSubstitutableMemberReceivedAnalyzerTests/ReceivedAsOrdinaryMethodTests.cs @@ -33,7 +33,7 @@ public class FooTests public void Test() {{ var substitute = NSubstitute.Substitute.For(); - [|{method}(substitute)|].Bar(); + [|{method}(substitute).Bar()|]; }} }} }}"; @@ -154,7 +154,7 @@ public class FooTests public void Test() {{ var substitute = NSubstitute.Substitute.For(); - [|{method}(substitute)|].Bar(); + [|{method}(substitute).Bar()|]; }} }} }}"; @@ -351,7 +351,7 @@ public class FooTests public void Test() {{ var substitute = NSubstitute.Substitute.For(); - var x = [|{method}(substitute)|].Bar; + var x = [|{method}(substitute).Bar|]; }} }} }}"; @@ -398,7 +398,7 @@ public class FooTests public void Test() {{ var substitute = NSubstitute.Substitute.For(); - var x = [|{method}(substitute)|][1]; + var x = [|{method}(substitute)[1]|]; }} }} }}"; @@ -481,7 +481,7 @@ public class FooTests public void Test() {{ var substitute = NSubstitute.Substitute.For(); - var x = [|{method}(substitute)|]{call}; + var x = [|{method}(substitute){call}|]; }} }} }}"; @@ -555,7 +555,7 @@ public class FooTests public void Test() {{ var substitute = NSubstitute.Substitute.For(); - var x = [|{method}(substitute)|]{call}; + var x = [|{method}(substitute){call}|]; }} }} }}"; diff --git a/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/ReEntrantReturnsSetupAnalyzerTests/ReEntrantReturnsSetupDiagnosticVerifier.cs b/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/ReEntrantReturnsSetupAnalyzerTests/ReEntrantReturnsSetupDiagnosticVerifier.cs index 7e113b2a..40b79e19 100644 --- a/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/ReEntrantReturnsSetupAnalyzerTests/ReEntrantReturnsSetupDiagnosticVerifier.cs +++ b/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/ReEntrantReturnsSetupAnalyzerTests/ReEntrantReturnsSetupDiagnosticVerifier.cs @@ -99,6 +99,11 @@ public abstract class ReEntrantReturnsSetupDiagnosticVerifier : CSharpDiagnostic [InlineData] public abstract Task ReportsDiagnostic_WhenUsingReEntrantReturns_AcrossMultipleFiles(string method); + [CombinatoryTheory] + [InlineData("Foo")] + [InlineData("FooBar")] + public abstract Task ReportsNoDiagnostic_WhenUsed_WithTypeofExpression(string method, string type); + protected override DiagnosticAnalyzer GetDiagnosticAnalyzer() { return new ReEntrantSetupAnalyzer(); diff --git a/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/ReEntrantReturnsSetupAnalyzerTests/ReturnsAsExtensionMethodTests.cs b/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/ReEntrantReturnsSetupAnalyzerTests/ReturnsAsExtensionMethodTests.cs index 848a6a76..f7b356a2 100644 --- a/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/ReEntrantReturnsSetupAnalyzerTests/ReturnsAsExtensionMethodTests.cs +++ b/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/ReEntrantReturnsSetupAnalyzerTests/ReturnsAsExtensionMethodTests.cs @@ -530,5 +530,49 @@ public static int ReturnThis() await VerifyDiagnostics(new[] { source, secondSource }, Descriptor, $"{plainMethodName}() is set with a method that itself calls {plainMethodName}. This can cause problems with NSubstitute. Consider replacing with a lambda: {plainMethodName}(x => FooBar.ReturnThis())."); } + + [CombinatoryData("Returns", "Returns", "ReturnsForAnyArgs", "ReturnsForAnyArgs")] + public override async Task ReportsNoDiagnostic_WhenUsed_WithTypeofExpression(string method, string type) + { + var source = $@"using NSubstitute; + +namespace MyNamespace +{{ + public class Foo + {{ + public object FooBar() + {{ + return null; + }} + + public object Bar() + {{ + var sub = Substitute.For(); + sub.FooBar().Returns(1); + return null; + }} + }} + + public struct FooBar + {{ + public object Bar() + {{ + var sub = Substitute.For(); + sub.FooBar().Returns(1); + return null; + }} + }} + + public class FooTests + {{ + public void Test() + {{ + var substitute = NSubstitute.Substitute.For(); + substitute.FooBar().{method}(typeof({type})); + }} + }} +}}"; + await VerifyNoDiagnostic(source); + } } } \ No newline at end of file diff --git a/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/ReEntrantReturnsSetupAnalyzerTests/ReturnsAsOrdinaryMethodTests.cs b/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/ReEntrantReturnsSetupAnalyzerTests/ReturnsAsOrdinaryMethodTests.cs index 17ff0a56..2f15f81e 100644 --- a/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/ReEntrantReturnsSetupAnalyzerTests/ReturnsAsOrdinaryMethodTests.cs +++ b/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/ReEntrantReturnsSetupAnalyzerTests/ReturnsAsOrdinaryMethodTests.cs @@ -529,5 +529,49 @@ public static int ReturnThis() await VerifyDiagnostics(new[] { source, secondSource }, Descriptor, $"{plainMethodName}() is set with a method that itself calls {plainMethodName}. This can cause problems with NSubstitute. Consider replacing with a lambda: {plainMethodName}(x => FooBar.ReturnThis())."); } + + [CombinatoryData("SubstituteExtensions.Returns", "SubstituteExtensions.Returns", "SubstituteExtensions.ReturnsForAnyArgs", "SubstituteExtensions.ReturnsForAnyArgs")] + public override async Task ReportsNoDiagnostic_WhenUsed_WithTypeofExpression(string method, string type) + { + var source = $@"using NSubstitute; + +namespace MyNamespace +{{ + public class Foo + {{ + public object FooBar() + {{ + return null; + }} + + public object Bar() + {{ + var sub = Substitute.For(); + sub.FooBar().Returns(1); + return null; + }} + }} + + public struct FooBar + {{ + public object Bar() + {{ + var sub = Substitute.For(); + sub.FooBar().Returns(1); + return null; + }} + }} + + public class FooTests + {{ + public void Test() + {{ + var substitute = NSubstitute.Substitute.For(); + {method}(substitute.FooBar(), typeof({type})); + }} + }} +}}"; + await VerifyNoDiagnostic(source); + } } } \ No newline at end of file diff --git a/tests/NSubstitute.Analyzers.Tests.Shared/DiagnosticAnalyzers/IReEntrantReturnsSetupDiagnosticVerifier.cs b/tests/NSubstitute.Analyzers.Tests.Shared/DiagnosticAnalyzers/IReEntrantReturnsSetupDiagnosticVerifier.cs index 0c137ded..4f7c7707 100644 --- a/tests/NSubstitute.Analyzers.Tests.Shared/DiagnosticAnalyzers/IReEntrantReturnsSetupDiagnosticVerifier.cs +++ b/tests/NSubstitute.Analyzers.Tests.Shared/DiagnosticAnalyzers/IReEntrantReturnsSetupDiagnosticVerifier.cs @@ -23,5 +23,7 @@ public interface IReEntrantReturnsSetupDiagnosticVerifier Task ReportsNoDiagnostic_WhenReEntrantSubstituteNotUsed(string method, string firstReturn, string secondReturn); Task ReportsDiagnostic_WhenUsingReEntrantReturns_AcrossMultipleFiles(string method); + + Task ReportsNoDiagnostic_WhenUsed_WithTypeofExpression(string method, string type); } } \ No newline at end of file diff --git a/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/NonSubstitutableMemberReceivedAnalyzerTests/ReceivedAsExtensionMethodTests.cs b/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/NonSubstitutableMemberReceivedAnalyzerTests/ReceivedAsExtensionMethodTests.cs index dc4b6afb..a8de5b1e 100644 --- a/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/NonSubstitutableMemberReceivedAnalyzerTests/ReceivedAsExtensionMethodTests.cs +++ b/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/NonSubstitutableMemberReceivedAnalyzerTests/ReceivedAsExtensionMethodTests.cs @@ -23,7 +23,7 @@ Public Class FooTests Public Sub Test() Dim substitute = NSubstitute.Substitute.[For](Of Foo)() - [|substitute.{method}()|].Bar() + [|substitute.{method}().Bar()|] End Sub End Class End Namespace @@ -133,7 +133,7 @@ Public Class FooTests Public Sub Test() Dim substitute = NSubstitute.Substitute.[For](Of Foo2)() - [|substitute.{method}()|].Bar() + [|substitute.{method}().Bar()|] End Sub End Class End Namespace @@ -324,7 +324,7 @@ Public Class FooTests Public Sub Test() Dim substitute = NSubstitute.Substitute.For(Of Foo) - Dim x As Integer = [|substitute.{method}()|].Bar + Dim x As Integer = [|substitute.{method}().Bar|] End Sub End Class End Namespace"; @@ -383,7 +383,7 @@ Public Class FooTests Public Sub Test() Dim substitute = NSubstitute.Substitute.For(Of Foo) - Dim x As Integer = [|substitute.{method}()|](1) + Dim x As Integer = [|substitute.{method}()(1)|] End Sub End Class End Namespace"; @@ -457,7 +457,7 @@ End Class Public Class FooTests Public Sub Test() Dim substitute = NSubstitute.Substitute.[For](Of Foo)() - Dim x = [|substitute.{method}()|]{call} + Dim x = [|substitute.{method}(){call}|] End Sub End Class End Namespace"; @@ -523,7 +523,7 @@ End Class Public Class FooTests Public Sub Test() Dim substitute = NSubstitute.Substitute.[For](Of Foo)() - Dim x = [|substitute.{method}()|]{call} + Dim x = [|substitute.{method}(){call}|] End Sub End Class End Namespace"; diff --git a/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/NonSubstitutableMemberReceivedAnalyzerTests/ReceivedAsOrdinaryMethodTests.cs b/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/NonSubstitutableMemberReceivedAnalyzerTests/ReceivedAsOrdinaryMethodTests.cs index 93a4d772..a15e1c63 100644 --- a/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/NonSubstitutableMemberReceivedAnalyzerTests/ReceivedAsOrdinaryMethodTests.cs +++ b/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/NonSubstitutableMemberReceivedAnalyzerTests/ReceivedAsOrdinaryMethodTests.cs @@ -31,7 +31,7 @@ Public Class FooTests Public Sub Test() Dim substitute = NSubstitute.Substitute.[For](Of Foo)() - [|{method}(substitute)|].Bar() + [|{method}(substitute).Bar()|] End Sub End Class End Namespace @@ -153,7 +153,7 @@ Public Class FooTests Public Sub Test() Dim substitute = NSubstitute.Substitute.[For](Of Foo)() - [|{method}(substitute)|].Bar() + [|{method}(substitute).Bar()|] End Sub End Class End Namespace @@ -353,7 +353,7 @@ Public Class FooTests Public Sub Test() Dim substitute = NSubstitute.Substitute.For(Of Foo) - Dim x As Integer = [|{method}(substitute)|].Bar + Dim x As Integer = [|{method}(substitute).Bar|] End Sub End Class End Namespace"; @@ -412,7 +412,7 @@ Public Class FooTests Public Sub Test() Dim substitute = NSubstitute.Substitute.For(Of Foo) - Dim x As Integer = [|{method}(substitute)|](1) + Dim x As Integer = [|{method}(substitute)(1)|] End Sub End Class End Namespace"; @@ -486,7 +486,7 @@ End Class Public Class FooTests Public Sub Test() Dim substitute = NSubstitute.Substitute.[For](Of Foo)() - Dim x = [|{method}(substitute)|]{call} + Dim x = [|{method}(substitute){call}|] End Sub End Class End Namespace"; @@ -552,7 +552,7 @@ End Class Public Class FooTests Public Sub Test() Dim substitute = NSubstitute.Substitute.[For](Of Foo)() - Dim x = [|{method}(substitute)|]{call} + Dim x = [|{method}(substitute){call}|] End Sub End Class End Namespace"; diff --git a/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/ReEntrantReturnsSetupAnalyzerTests/ReEntrantReturnsSetupDiagnosticVerifier.cs b/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/ReEntrantReturnsSetupAnalyzerTests/ReEntrantReturnsSetupDiagnosticVerifier.cs index 4266ec64..f8353a9a 100644 --- a/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/ReEntrantReturnsSetupAnalyzerTests/ReEntrantReturnsSetupDiagnosticVerifier.cs +++ b/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/ReEntrantReturnsSetupAnalyzerTests/ReEntrantReturnsSetupDiagnosticVerifier.cs @@ -89,6 +89,11 @@ Dim barr As IBar [InlineData] public abstract Task ReportsDiagnostic_WhenUsingReEntrantReturns_AcrossMultipleFiles(string method); + [CombinatoryTheory] + [InlineData("Foo")] + [InlineData("FooBar")] + public abstract Task ReportsNoDiagnostic_WhenUsed_WithTypeofExpression(string method, string type); + protected override DiagnosticAnalyzer GetDiagnosticAnalyzer() { return new ReEntrantSetupAnalyzer(); diff --git a/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/ReEntrantReturnsSetupAnalyzerTests/ReturnsAsExtensionMethodTests.cs b/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/ReEntrantReturnsSetupAnalyzerTests/ReturnsAsExtensionMethodTests.cs index b7dc53e8..623c0803 100644 --- a/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/ReEntrantReturnsSetupAnalyzerTests/ReturnsAsExtensionMethodTests.cs +++ b/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/ReEntrantReturnsSetupAnalyzerTests/ReturnsAsExtensionMethodTests.cs @@ -450,5 +450,41 @@ End Namespace await VerifyDiagnostics(new[] { source, secondSource }, Descriptor, $"{method}() is set with a method that itself calls {method}. This can cause problems with NSubstitute. Consider replacing with a lambda: {method}(Function(x) FooBar.ReturnThis())."); } + + public override async Task ReportsNoDiagnostic_WhenUsed_WithTypeofExpression(string method, string type) + { + var source = $@"Imports NSubstitute +Imports System +Namespace MyNamespace + Public Class Foo + Public Function FooBar() As Type + Return Nothing + End Function + + Public Function Bar() As Type + Dim [sub] = Substitute.[For](Of Foo)() + [sub].FooBar().Returns(GetType(Object)) + Return Nothing + End Function + End Class + + Public Structure FooBar + Public Function Bar() As Type + Dim [sub] = Substitute.[For](Of Foo)() + [sub].FooBar().Returns(GetType(Object)) + Return Nothing + End Function + End Structure + + Public Class FooTests + Public Sub Test() + Dim substitute = NSubstitute.Substitute.[For](Of Foo)() + substitute.FooBar().{method}(GetType([{type}])) + End Sub + End Class +End Namespace"; + + await VerifyNoDiagnostic(source); + } } } \ No newline at end of file diff --git a/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/ReEntrantReturnsSetupAnalyzerTests/ReturnsAsOrdinaryMethodTests.cs b/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/ReEntrantReturnsSetupAnalyzerTests/ReturnsAsOrdinaryMethodTests.cs index 98a846cd..20749ac7 100644 --- a/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/ReEntrantReturnsSetupAnalyzerTests/ReturnsAsOrdinaryMethodTests.cs +++ b/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/ReEntrantReturnsSetupAnalyzerTests/ReturnsAsOrdinaryMethodTests.cs @@ -458,5 +458,42 @@ End Namespace await VerifyDiagnostics(new[] { source, secondSource }, Descriptor, $"{plainMethodName}() is set with a method that itself calls {plainMethodName}. This can cause problems with NSubstitute. Consider replacing with a lambda: {plainMethodName}(Function(x) FooBar.ReturnThis())."); } + + [CombinatoryData("SubstituteExtensions.Returns", "SubstituteExtensions.Returns(Of Object)", "SubstituteExtensions.ReturnsForAnyArgs", "SubstituteExtensions.ReturnsForAnyArgs(Of Object)")] + public override async Task ReportsNoDiagnostic_WhenUsed_WithTypeofExpression(string method, string type) + { + var source = $@"Imports NSubstitute +Imports System +Namespace MyNamespace + Public Class Foo + Public Function FooBar() As Type + Return Nothing + End Function + + Public Function Bar() As Type + Dim [sub] = Substitute.[For](Of Foo)() + [sub].FooBar().Returns(GetType(Object)) + Return Nothing + End Function + End Class + + Public Structure FooBar + Public Function Bar() As Type + Dim [sub] = Substitute.[For](Of Foo)() + [sub].FooBar().Returns(GetType(Object)) + Return Nothing + End Function + End Structure + + Public Class FooTests + Public Sub Test() + Dim substitute = NSubstitute.Substitute.[For](Of Foo)() + {method}(substitute.FooBar(), GetType([{type}])) + End Sub + End Class +End Namespace"; + + await VerifyNoDiagnostic(source); + } } } \ No newline at end of file