From f90c4a2bcd49f5aa86fec383358964e546bafb60 Mon Sep 17 00:00:00 2001 From: tpodolak Date: Fri, 27 Aug 2021 23:34:24 +0200 Subject: [PATCH] GH-163 - better argument matcher enclosing expression detection --- ...tcherSuppressDiagnosticsCodeFixProvider.cs | 2 +- ...stitutableMemberArgumentMatcherAnalyzer.cs | 54 ++++--------------- ...tcherSuppressDiagnosticsCodeFixProvider.cs | 11 ++-- ...stitutableMemberArgumentMatcherAnalyzer.cs | 26 ++++----- ...tcherSuppressDiagnosticsCodeFixProvider.cs | 2 +- ...stitutableMemberArgumentMatcherAnalyzer.cs | 47 +++------------- ...MemberArgumentMatcherDiagnosticVerifier.cs | 16 +++--- ...SubstitutableMemberArgumentMatcherTests.cs | 17 ++++-- ...MemberArgumentMatcherDiagnosticVerifier.cs | 4 ++ ...SubstitutableMemberArgumentMatcherTests.cs | 19 +++++-- 10 files changed, 84 insertions(+), 114 deletions(-) diff --git a/src/NSubstitute.Analyzers.CSharp/CodeFixProviders/NonSubstitutableMemberArgumentMatcherSuppressDiagnosticsCodeFixProvider.cs b/src/NSubstitute.Analyzers.CSharp/CodeFixProviders/NonSubstitutableMemberArgumentMatcherSuppressDiagnosticsCodeFixProvider.cs index b32da786..fa7ad592 100644 --- a/src/NSubstitute.Analyzers.CSharp/CodeFixProviders/NonSubstitutableMemberArgumentMatcherSuppressDiagnosticsCodeFixProvider.cs +++ b/src/NSubstitute.Analyzers.CSharp/CodeFixProviders/NonSubstitutableMemberArgumentMatcherSuppressDiagnosticsCodeFixProvider.cs @@ -10,6 +10,6 @@ namespace NSubstitute.Analyzers.CSharp.CodeFixProviders internal sealed class NonSubstitutableMemberArgumentMatcherSuppressDiagnosticsCodeFixProvider : AbstractNonSubstitutableMemberArgumentMatcherSuppressDiagnosticsCodeFixProvider { - protected override ImmutableArray> AllowedAncestorPaths { get; } = NonSubstitutableMemberArgumentMatcherAnalyzer.AllowedPaths; + protected override ImmutableHashSet MaybeAllowedArgMatcherAncestors { get; } = NonSubstitutableMemberArgumentMatcherAnalyzer.MaybeAllowedAncestors; } } \ No newline at end of file diff --git a/src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/NonSubstitutableMemberArgumentMatcherAnalyzer.cs b/src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/NonSubstitutableMemberArgumentMatcherAnalyzer.cs index 427341cd..54d1e049 100644 --- a/src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/NonSubstitutableMemberArgumentMatcherAnalyzer.cs +++ b/src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/NonSubstitutableMemberArgumentMatcherAnalyzer.cs @@ -10,58 +10,24 @@ namespace NSubstitute.Analyzers.CSharp.DiagnosticAnalyzers [DiagnosticAnalyzer(LanguageNames.CSharp)] internal sealed class NonSubstitutableMemberArgumentMatcherAnalyzer : AbstractNonSubstitutableMemberArgumentMatcherAnalyzer { - internal static ImmutableArray> AllowedPaths { get; } = ImmutableArray.Create( - ImmutableArray.Create( - (int)SyntaxKind.Argument, - (int)SyntaxKind.ArgumentList, - (int)SyntaxKind.InvocationExpression), - ImmutableArray.Create( - (int)SyntaxKind.Argument, - (int)SyntaxKind.BracketedArgumentList, - (int)SyntaxKind.ElementAccessExpression), - ImmutableArray.Create( - (int)SyntaxKind.CastExpression, - (int)SyntaxKind.Argument, - (int)SyntaxKind.ArgumentList, - (int)SyntaxKind.InvocationExpression), - ImmutableArray.Create( - (int)SyntaxKind.AsExpression, - (int)SyntaxKind.Argument, - (int)SyntaxKind.ArgumentList, - (int)SyntaxKind.InvocationExpression), - ImmutableArray.Create( - (int)SyntaxKind.CastExpression, - (int)SyntaxKind.Argument, - (int)SyntaxKind.BracketedArgumentList, - (int)SyntaxKind.ElementAccessExpression), - ImmutableArray.Create( - (int)SyntaxKind.AsExpression, - (int)SyntaxKind.Argument, - (int)SyntaxKind.BracketedArgumentList, - (int)SyntaxKind.ElementAccessExpression), - ImmutableArray.Create((int)SyntaxKind.AddAssignmentExpression)); + internal static ImmutableHashSet MaybeAllowedAncestors { get; } = ImmutableHashSet.Create( + (int)SyntaxKind.InvocationExpression, + (int)SyntaxKind.ElementAccessExpression, + (int)SyntaxKind.AddAssignmentExpression, + (int)SyntaxKind.ObjectCreationExpression); - private static ImmutableArray> IgnoredPaths { get; } = ImmutableArray.Create( - ImmutableArray.Create( - (int)SyntaxKind.EqualsValueClause, - (int)SyntaxKind.VariableDeclarator), - ImmutableArray.Create( - (int)SyntaxKind.CastExpression, - (int)SyntaxKind.EqualsValueClause, - (int)SyntaxKind.VariableDeclarator), - ImmutableArray.Create( - (int)SyntaxKind.AsExpression, - (int)SyntaxKind.EqualsValueClause, - (int)SyntaxKind.VariableDeclarator)); + private static ImmutableHashSet IgnoredAncestors { get; } = + ImmutableHashSet.Create( + (int)SyntaxKind.VariableDeclarator); public NonSubstitutableMemberArgumentMatcherAnalyzer() : base(NonSubstitutableMemberAnalysis.Instance, NSubstitute.Analyzers.CSharp.DiagnosticDescriptorsProvider.Instance) { } - protected override ImmutableArray> AllowedAncestorPaths { get; } = AllowedPaths; + protected override ImmutableHashSet MaybeAllowedArgMatcherAncestors { get; } = MaybeAllowedAncestors; - protected override ImmutableArray> IgnoredAncestorPaths { get; } = IgnoredPaths; + protected override ImmutableHashSet IgnoredArgMatcherAncestors { get; } = IgnoredAncestors; protected override SyntaxKind InvocationExpressionKind { get; } = SyntaxKind.InvocationExpression; } diff --git a/src/NSubstitute.Analyzers.Shared/CodeFixProviders/AbstractNonSubstitutableMemberArgumentMatcherSuppressDiagnosticsCodeFixProvider.cs b/src/NSubstitute.Analyzers.Shared/CodeFixProviders/AbstractNonSubstitutableMemberArgumentMatcherSuppressDiagnosticsCodeFixProvider.cs index 36cdef35..854b01c4 100644 --- a/src/NSubstitute.Analyzers.Shared/CodeFixProviders/AbstractNonSubstitutableMemberArgumentMatcherSuppressDiagnosticsCodeFixProvider.cs +++ b/src/NSubstitute.Analyzers.Shared/CodeFixProviders/AbstractNonSubstitutableMemberArgumentMatcherSuppressDiagnosticsCodeFixProvider.cs @@ -2,7 +2,6 @@ using System.Collections.Immutable; using System.Linq; using Microsoft.CodeAnalysis; -using NSubstitute.Analyzers.Shared.Extensions; namespace NSubstitute.Analyzers.Shared.CodeFixProviders { @@ -10,17 +9,23 @@ internal abstract class AbstractNonSubstitutableMemberArgumentMatcherSuppressDia { public override ImmutableArray FixableDiagnosticIds { get; } = ImmutableArray.Create(DiagnosticIdentifiers.NonSubstitutableMemberArgumentMatcherUsage); - protected abstract ImmutableArray> AllowedAncestorPaths { get; } + protected abstract ImmutableHashSet MaybeAllowedArgMatcherAncestors { get; } protected override IEnumerable GetSuppressibleSymbol(SemanticModel model, SyntaxNode syntaxNode, ISymbol symbol) { - var ancestorNode = syntaxNode.GetAncestorNode(AllowedAncestorPaths); + var ancestorNode = syntaxNode.Ancestors() + .FirstOrDefault(ancestor => MaybeAllowedArgMatcherAncestors.Contains(ancestor.RawKind)); if (ancestorNode == null) { return Enumerable.Empty(); } + if (model.GetSymbolInfo(ancestorNode).Symbol is IMethodSymbol methodSymbol && methodSymbol.MethodKind == MethodKind.Constructor) + { + return Enumerable.Empty(); + } + return base.GetSuppressibleSymbol(model, ancestorNode, model.GetSymbolInfo(ancestorNode).Symbol); } } diff --git a/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractNonSubstitutableMemberArgumentMatcherAnalyzer.cs b/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractNonSubstitutableMemberArgumentMatcherAnalyzer.cs index fc552a82..e383e1f9 100644 --- a/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractNonSubstitutableMemberArgumentMatcherAnalyzer.cs +++ b/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractNonSubstitutableMemberArgumentMatcherAnalyzer.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Immutable; +using System.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; using NSubstitute.Analyzers.Shared.Extensions; @@ -14,9 +15,9 @@ internal abstract class AbstractNonSubstitutableMemberArgumentMatcherAnalyzer> AllowedAncestorPaths { get; } + protected abstract ImmutableHashSet MaybeAllowedArgMatcherAncestors { get; } - protected abstract ImmutableArray> IgnoredAncestorPaths { get; } + protected abstract ImmutableHashSet IgnoredArgMatcherAncestors { get; } protected abstract TSyntaxKind InvocationExpressionKind { get; } @@ -59,16 +60,15 @@ private void AnalyzeInvocation(SyntaxNodeAnalysisContext syntaxNodeContext) private void AnalyzeArgLikeMethod(SyntaxNodeAnalysisContext syntaxNodeContext, TInvocationExpressionSyntax argInvocationExpression) { - // find allowed enclosing expression - var enclosingExpression = FindAllowedEnclosingExpression(argInvocationExpression); + var enclosingExpression = FindMaybeAllowedEnclosingExpression(argInvocationExpression); // if Arg is used with not allowed expression, find if it is used in ignored ones eg. var x = Arg.Any // as variable might be used later on if (enclosingExpression == null) { - var maybeIgnoredEnclosingExpression = FindMaybeIgnoredEnclosingExpression(argInvocationExpression); + var ignoredEnclosingExpression = FindIgnoredEnclosingExpression(argInvocationExpression); - if (maybeIgnoredEnclosingExpression == null) + if (ignoredEnclosingExpression == null) { var diagnostic = Diagnostic.Create( DiagnosticDescriptorsProvider.NonSubstitutableMemberArgumentMatcherUsage, @@ -108,14 +108,16 @@ private void AnalyzeArgLikeMethod(SyntaxNodeAnalysisContext syntaxNodeContext, T } } - private SyntaxNode FindAllowedEnclosingExpression(TInvocationExpressionSyntax invocationExpression) - { - return invocationExpression.GetAncestorNode(AllowedAncestorPaths); - } + private SyntaxNode FindMaybeAllowedEnclosingExpression(TInvocationExpressionSyntax invocationExpression) => + FindEnclosingExpression(invocationExpression, MaybeAllowedArgMatcherAncestors); + + private SyntaxNode FindIgnoredEnclosingExpression(TInvocationExpressionSyntax invocationExpressionSyntax) => + FindEnclosingExpression(invocationExpressionSyntax, IgnoredArgMatcherAncestors); - private SyntaxNode FindMaybeIgnoredEnclosingExpression(TInvocationExpressionSyntax invocationExpressionSyntax) + private static SyntaxNode FindEnclosingExpression(TInvocationExpressionSyntax invocationExpression, ImmutableHashSet ancestors) { - return invocationExpressionSyntax.GetAncestorNode(IgnoredAncestorPaths); + return invocationExpression.Ancestors() + .FirstOrDefault(ancestor => ancestors.Contains(ancestor.RawKind)); } } } \ No newline at end of file diff --git a/src/NSubstitute.Analyzers.VisualBasic/CodeFixProviders/NonSubstitutableMemberArgumentMatcherSuppressDiagnosticsCodeFixProvider.cs b/src/NSubstitute.Analyzers.VisualBasic/CodeFixProviders/NonSubstitutableMemberArgumentMatcherSuppressDiagnosticsCodeFixProvider.cs index 7a4741de..33b84318 100644 --- a/src/NSubstitute.Analyzers.VisualBasic/CodeFixProviders/NonSubstitutableMemberArgumentMatcherSuppressDiagnosticsCodeFixProvider.cs +++ b/src/NSubstitute.Analyzers.VisualBasic/CodeFixProviders/NonSubstitutableMemberArgumentMatcherSuppressDiagnosticsCodeFixProvider.cs @@ -9,6 +9,6 @@ namespace NSubstitute.Analyzers.VisualBasic.CodeFixProviders [ExportCodeFixProvider(LanguageNames.VisualBasic)] internal sealed class NonSubstitutableMemberArgumentMatcherSuppressDiagnosticsCodeFixProvider : AbstractNonSubstitutableMemberArgumentMatcherSuppressDiagnosticsCodeFixProvider { - protected override ImmutableArray> AllowedAncestorPaths { get; } = NonSubstitutableMemberArgumentMatcherAnalyzer.AllowedPaths; + protected override ImmutableHashSet MaybeAllowedArgMatcherAncestors { get; } = NonSubstitutableMemberArgumentMatcherAnalyzer.MaybeAllowedAncestors; } } \ No newline at end of file diff --git a/src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/NonSubstitutableMemberArgumentMatcherAnalyzer.cs b/src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/NonSubstitutableMemberArgumentMatcherAnalyzer.cs index 28b15282..eaf6fcb4 100644 --- a/src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/NonSubstitutableMemberArgumentMatcherAnalyzer.cs +++ b/src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/NonSubstitutableMemberArgumentMatcherAnalyzer.cs @@ -10,53 +10,22 @@ namespace NSubstitute.Analyzers.VisualBasic.DiagnosticAnalyzers [DiagnosticAnalyzer(LanguageNames.VisualBasic)] internal sealed class NonSubstitutableMemberArgumentMatcherAnalyzer : AbstractNonSubstitutableMemberArgumentMatcherAnalyzer { - internal static ImmutableArray> AllowedPaths { get; } = ImmutableArray.Create( - ImmutableArray.Create( - (int)SyntaxKind.SimpleArgument, - (int)SyntaxKind.ArgumentList, - (int)SyntaxKind.InvocationExpression), - ImmutableArray.Create( - (int)SyntaxKind.TryCastExpression, - (int)SyntaxKind.SimpleArgument, - (int)SyntaxKind.ArgumentList, - (int)SyntaxKind.InvocationExpression), - ImmutableArray.Create( - (int)SyntaxKind.DirectCastExpression, - (int)SyntaxKind.SimpleArgument, - (int)SyntaxKind.ArgumentList, - (int)SyntaxKind.InvocationExpression), - ImmutableArray.Create( - (int)SyntaxKind.CTypeExpression, - (int)SyntaxKind.SimpleArgument, - (int)SyntaxKind.ArgumentList, - (int)SyntaxKind.InvocationExpression), - ImmutableArray.Create((int)SyntaxKind.AddHandlerStatement)); + internal static ImmutableHashSet MaybeAllowedAncestors { get; } = ImmutableHashSet.Create( + (int)SyntaxKind.InvocationExpression, + (int)SyntaxKind.AddHandlerStatement, + (int)SyntaxKind.ObjectCreationExpression); - private static ImmutableArray> IgnoredPaths { get; } = ImmutableArray.Create( - ImmutableArray.Create( - (int)SyntaxKind.EqualsValue, - (int)SyntaxKind.VariableDeclarator), - ImmutableArray.Create( - (int)SyntaxKind.TryCastExpression, - (int)SyntaxKind.EqualsValue, - (int)SyntaxKind.VariableDeclarator), - ImmutableArray.Create( - (int)SyntaxKind.DirectCastExpression, - (int)SyntaxKind.EqualsValue, - (int)SyntaxKind.VariableDeclarator), - ImmutableArray.Create( - (int)SyntaxKind.CTypeExpression, - (int)SyntaxKind.EqualsValue, - (int)SyntaxKind.VariableDeclarator)); + private static ImmutableHashSet IgnoredAncestors { get; } = ImmutableHashSet.Create( + (int)SyntaxKind.VariableDeclarator); public NonSubstitutableMemberArgumentMatcherAnalyzer() : base(NonSubstitutableMemberAnalysis.Instance, NSubstitute.Analyzers.VisualBasic.DiagnosticDescriptorsProvider.Instance) { } - protected override ImmutableArray> AllowedAncestorPaths { get; } = AllowedPaths; + protected override ImmutableHashSet MaybeAllowedArgMatcherAncestors { get; } = MaybeAllowedAncestors; - protected override ImmutableArray> IgnoredAncestorPaths { get; } = IgnoredPaths; + protected override ImmutableHashSet IgnoredArgMatcherAncestors { get; } = IgnoredAncestors; protected override SyntaxKind InvocationExpressionKind { get; } = SyntaxKind.InvocationExpression; } diff --git a/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/NonSubstitutableMemberArgumentMatcherAnalyzerTests/NonSubstitutableMemberArgumentMatcherDiagnosticVerifier.cs b/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/NonSubstitutableMemberArgumentMatcherAnalyzerTests/NonSubstitutableMemberArgumentMatcherDiagnosticVerifier.cs index b9c462fd..a870c20c 100644 --- a/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/NonSubstitutableMemberArgumentMatcherAnalyzerTests/NonSubstitutableMemberArgumentMatcherDiagnosticVerifier.cs +++ b/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/NonSubstitutableMemberArgumentMatcherAnalyzerTests/NonSubstitutableMemberArgumentMatcherDiagnosticVerifier.cs @@ -125,8 +125,8 @@ public static IEnumerable MisusedArgTestCases yield return new object[] { "[|Arg.Compat.Is(1)|]" }; yield return new object[] { "(int)[|Arg.Compat.Is(1)|]" }; yield return new object[] { "[|Arg.Compat.Is(1)|] as int?" }; - yield return new object[] { "[|Arg.Do(_ => {})|]" }; - yield return new object[] { "[|Arg.Compat.Do(_ => {})|]" }; + yield return new object[] { "[|Arg.Do(__ => {})|]" }; + yield return new object[] { "[|Arg.Compat.Do(__ => {})|]" }; yield return new object[] { "[|Arg.Invoke()|]" }; yield return new object[] { "[|Arg.Compat.Invoke()|]" }; yield return new object[] { "[|Arg.InvokeDelegate()|]" }; @@ -147,11 +147,15 @@ public static IEnumerable CorrectlyUsedArgTestCases yield return new object[] { "Arg.Is(1)" }; yield return new object[] { "(int)Arg.Is(1)" }; yield return new object[] { "Arg.Is(1) as int?" }; + yield return new object[] { "Arg.Is((int x) => x > 0)" }; + yield return new object[] { "true ? Arg.Is((int x) => x > 0) : 0" }; yield return new object[] { "Arg.Compat.Is(1)" }; yield return new object[] { "(int)Arg.Compat.Is(1)" }; yield return new object[] { "Arg.Compat.Is(1) as int?" }; - yield return new object[] { "Arg.Do(_ => {})" }; - yield return new object[] { "Arg.Compat.Do(_ => {})" }; + yield return new object[] { "Arg.Compat.Is((int x) => x > 0) " }; + yield return new object[] { "true ? Arg.Compat.Is((int x) => x > 0) : 0" }; + yield return new object[] { "Arg.Do(__ => {})" }; + yield return new object[] { "Arg.Compat.Do(__ => {})" }; yield return new object[] { "Arg.Invoke()" }; yield return new object[] { "Arg.Compat.Invoke()" }; yield return new object[] { "Arg.InvokeDelegate()" }; @@ -171,8 +175,8 @@ public static IEnumerable CorrectlyUsedArgTestCasesWithoutCasts yield return new object[] { "Arg.Compat.Any()" }; yield return new object[] { "Arg.Is(1)" }; yield return new object[] { "Arg.Compat.Is(1)" }; - yield return new object[] { "Arg.Do(_ => {})" }; - yield return new object[] { "Arg.Compat.Do(_ => {})" }; + yield return new object[] { "Arg.Do(__ => {})" }; + yield return new object[] { "Arg.Compat.Do(__ => {})" }; yield return new object[] { "Arg.Invoke()" }; yield return new object[] { "Arg.Compat.Invoke()" }; yield return new object[] { "Arg.InvokeDelegate()" }; diff --git a/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/NonSubstitutableMemberArgumentMatcherAnalyzerTests/NonSubstitutableMemberArgumentMatcherTests.cs b/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/NonSubstitutableMemberArgumentMatcherAnalyzerTests/NonSubstitutableMemberArgumentMatcherTests.cs index 86365e12..f5665900 100644 --- a/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/NonSubstitutableMemberArgumentMatcherAnalyzerTests/NonSubstitutableMemberArgumentMatcherTests.cs +++ b/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/NonSubstitutableMemberArgumentMatcherAnalyzerTests/NonSubstitutableMemberArgumentMatcherTests.cs @@ -299,7 +299,7 @@ public class FooTests public void Test() {{ var substitute = NSubstitute.Substitute.For(); - var x = substitute[{arg}]; + var _ = substitute[{arg}]; }} }} }}"; @@ -325,7 +325,7 @@ public class FooTests public void Test() {{ var substitute = NSubstitute.Substitute.For(); - var x = substitute[{arg}]; + var _ = substitute[{arg}]; }} }} }}"; @@ -362,6 +362,7 @@ public void Test() public override async Task ReportsNoDiagnostics_WhenUsingUnfortunatelyNamedMethod(string arg) { var source = $@"using System; +using System.Linq.Expressions; using NSubstitute; namespace MyNamespace @@ -391,6 +392,11 @@ public static T Is(T value) return default(T); }} + public static T Is(Expression> predicate) + {{ + return default(T); + }} + public static Action Invoke() {{ return default(Action); @@ -418,6 +424,11 @@ public static T Is(T value) return default(T); }} + public static T Is(Expression> predicate) + {{ + return default(T); + }} + public static Action Invoke() {{ return default(Action); @@ -575,7 +586,7 @@ public class FooTests public void Test() {{ var substitute = NSubstitute.Substitute.For(); - var x = substitute.FooBar({arg}); + var _ = substitute.FooBar({arg}); }} }} }}"; diff --git a/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/NonSubstitutableMemberArgumentMatcherAnalyzerTests/NonSubstitutableMemberArgumentMatcherDiagnosticVerifier.cs b/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/NonSubstitutableMemberArgumentMatcherAnalyzerTests/NonSubstitutableMemberArgumentMatcherDiagnosticVerifier.cs index 0ab05ed9..af7e8c7e 100644 --- a/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/NonSubstitutableMemberArgumentMatcherAnalyzerTests/NonSubstitutableMemberArgumentMatcherDiagnosticVerifier.cs +++ b/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/NonSubstitutableMemberArgumentMatcherAnalyzerTests/NonSubstitutableMemberArgumentMatcherDiagnosticVerifier.cs @@ -145,10 +145,14 @@ public static IEnumerable CorrectlyUsedArgTestCases yield return new object[] { "TryCast(Arg.Is(1), Object)" }; yield return new object[] { "CType(Arg.Is(1), Integer)" }; yield return new object[] { "DirectCast(Arg.Is(1), Integer)" }; + yield return new object[] { "Arg.Is(Function(ByVal x As Integer) x > 0)" }; + yield return new object[] { "If(True, Arg.Is(Function(ByVal x As Integer) x > 0), 0)" }; yield return new object[] { "Arg.Compat.Is(1)" }; yield return new object[] { "TryCast(Arg.Compat.Is(1), Object)" }; yield return new object[] { "CType(Arg.Compat.Is(1), Integer)" }; yield return new object[] { "DirectCast(Arg.Compat.Is(1), Integer)" }; + yield return new object[] { "Arg.Compat.Is(Function(ByVal x As Integer) x > 0)" }; + yield return new object[] { "If(True, Arg.Compat.Is(Function(ByVal x As Integer) x > 0), 0)" }; yield return new object[] { "Arg.Invoke()" }; yield return new object[] { "Arg.Compat.Invoke()" }; yield return new object[] { "Arg.InvokeDelegate(Of Integer)()" }; diff --git a/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/NonSubstitutableMemberArgumentMatcherAnalyzerTests/NonSubstitutableMemberArgumentMatcherTests.cs b/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/NonSubstitutableMemberArgumentMatcherAnalyzerTests/NonSubstitutableMemberArgumentMatcherTests.cs index 91d8964f..f54b6878 100644 --- a/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/NonSubstitutableMemberArgumentMatcherAnalyzerTests/NonSubstitutableMemberArgumentMatcherTests.cs +++ b/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/NonSubstitutableMemberArgumentMatcherAnalyzerTests/NonSubstitutableMemberArgumentMatcherTests.cs @@ -150,7 +150,7 @@ Namespace MyNamespace Public Class FooTests Public Sub Test() Dim substitute = NSubstitute.Substitute.[For](Of Func(Of {delegateArgType}, Integer))() - Dim x = substitute({arg}) + Dim __ = substitute({arg}) End Sub End Class End Namespace @@ -301,7 +301,7 @@ End Interface Public Class FooTests Public Sub Test() Dim substitute = NSubstitute.Substitute.[For](Of IFoo)() - Dim x = substitute({arg}) + Dim __ = substitute({arg}) End Sub End Class End Namespace @@ -332,7 +332,7 @@ End Class Public Class FooTests Public Sub Test() Dim substitute = NSubstitute.Substitute.[For](Of Foo)() - Dim x = substitute({arg}) + Dim __ = substitute({arg}) End Sub End Class End Namespace @@ -383,6 +383,7 @@ public override async Task ReportsNoDiagnostics_WhenUsingUnfortunatelyNamedMetho { var source = $@"Imports System Imports NSubstitute +Imports System.Linq.Expressions Imports System.Runtime.CompilerServices Namespace MyNamespace @@ -405,6 +406,10 @@ Public Shared Function [Is](Of T)(ByVal value As T) As T Return Nothing End Function + Public Shared Function [Is](Of T)(ByVal predicate As Expression(Of Predicate(Of T))) As T + Return Nothing + End Function + Public Shared Function Invoke() As Action Return Nothing End Function @@ -426,6 +431,10 @@ Public Shared Function [Is](Of T)(ByVal value As T) As T Return Nothing End Function + Public Shared Function [Is](Of T)(ByVal predicate As Expression(Of Predicate(Of T))) As T + Return Nothing + End Function + Public Shared Function Invoke() As Action Return Nothing End Function @@ -459,7 +468,7 @@ Imports NSubstitute Namespace MyNamespace Public Class FooTests Public Sub Test() - Dim x = {arg} + Dim __ = {arg} End Sub End Class End Namespace @@ -565,7 +574,7 @@ End Class Public Class FooTests Public Sub Test() Dim substitute = NSubstitute.Substitute.[For](Of Foo)() - Dim x = substitute.FooBar({arg}) + Dim __ = substitute.FooBar({arg}) End Sub End Class End Namespace