From 4f0ccff46f2728f82511d78b12a2059efc83cda5 Mon Sep 17 00:00:00 2001 From: Marcono1234 Date: Sat, 27 Jul 2024 16:24:00 +0200 Subject: [PATCH] Add Mockito-ArgumentMatchers-parameterized-call.ql --- ...ito-ArgumentMatchers-parameterized-call.ql | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 codeql-custom-queries-java/queries/unit-tests/Mockito-ArgumentMatchers-parameterized-call.ql diff --git a/codeql-custom-queries-java/queries/unit-tests/Mockito-ArgumentMatchers-parameterized-call.ql b/codeql-custom-queries-java/queries/unit-tests/Mockito-ArgumentMatchers-parameterized-call.ql new file mode 100644 index 0000000..51aeaac --- /dev/null +++ b/codeql-custom-queries-java/queries/unit-tests/Mockito-ArgumentMatchers-parameterized-call.ql @@ -0,0 +1,45 @@ +/** + * Finds usage of Mockito's `ArgumentMatchers` methods where type arguments + * are explicitly provided. If the type arguments are not constrained by + * a method argument (e.g. `Class`) they have no effect at runtime and + * can be confusing, giving the false expression that Mockito will only + * match the specified types. + * + * Instead the type arguments should be omitted; the compiler will then + * infer them. + * + * For example: + * ```java + * // Error-prone: Looks as if this only matches String, but it actually + * // matches anything + * // Should instead just use `Mockito.any()`, or `Mockito.anyString()` + * verify(myObj).doSomething(Mockito.any()); + * ``` + * + * @kind problem + * @id TODO + */ + +import java + +from MethodAccess matcherCall, Method matcherMethod, Expr typeArg +where + matcherCall.getMethod().getSourceDeclaration() = matcherMethod and + matcherMethod.getDeclaringType().hasQualifiedName("org.mockito", "ArgumentMatchers") and + // There is no method parameter which could restrict the type argument (e.g. `Class`) + matcherMethod.hasNoParameters() and + // Explicitly specifies type arguments, instead of letting the compiler infer them + typeArg = matcherCall.getATypeArgument() and + // Ignore if type arguments are needed to select the correct overload + not exists(MethodAccess stubbedCall, Method stubbedMethod, int argIndex, SrcMethod overload | + stubbedCall.getMethod().getSourceDeclaration() = stubbedMethod and + stubbedCall.getArgument(argIndex) = matcherCall and + overload.getDeclaringType() = + stubbedCall.getReceiverType().getSourceDeclaration().getASourceSupertype*() and + overload.getName() = stubbedMethod.getName() and + overload.getNumberOfParameters() = stubbedMethod.getNumberOfParameters() and + overload.getParameterType(argIndex) != stubbedMethod.getParameterType(argIndex) and + overload != stubbedMethod and + not overload.isPrivate() + ) +select typeArg, "Explicit type argument should be omitted because it can be misleading"