Common implementation of verification of static method calls.

@param method          The static method call to be verified
@param mode            The verification mode
@param instanceInOrder If set, the {@link StaticInOrder} object
439018
@SuppressWarnings({"CheckReturnValue", "MockitoUsage", "unchecked"})
    static void verifyInt(MockedVoidMethod method, VerificationMode mode, InOrder
            instanceInOrder) {
        if (onMethodCallDuringVerification.get() != null) {
            throw new IllegalStateException("Verification is already in progress on this "
                    + "thread.");
        }

        ArrayList<Method> verifications = new ArrayList<>();

        /* Set up callback that is triggered when the next static method is called on this thread.
         *
         * This is necessary as we don't know which class the method will be called on. Once the
         * call is intercepted this will
         *    1. Remove all matchers (e.g. eq(), any()) from the matcher stack
         *    2. Call verify on the marker for the class
         *    3. Add the markers back to the stack
         */
        onMethodCallDuringVerification.set((clazz, verifiedMethod) -> {
            // TODO: O holy reflection! Let's hope we can integrate this better.
            try {
                ArgumentMatcherStorageImpl argMatcherStorage = (ArgumentMatcherStorageImpl)
                        mockingProgress().getArgumentMatcherStorage();
                List<LocalizedMatcher> matchers;

                // Matcher are called before verify, hence remove the from the storage
                Method resetStackMethod
                        = argMatcherStorage.getClass().getDeclaredMethod("resetStack");
                resetStackMethod.setAccessible(true);

                matchers = (List<LocalizedMatcher>) resetStackMethod.invoke(argMatcherStorage);

                if (instanceInOrder == null) {
                    verify(staticMockMarker(clazz), mode);
                } else {
                    instanceInOrder.verify(staticMockMarker(clazz), mode);
                }

                // Add the matchers back after verify is called
                Field matcherStackField
                        = argMatcherStorage.getClass().getDeclaredField("matcherStack");
                matcherStackField.setAccessible(true);

                Method pushMethod = matcherStackField.getType().getDeclaredMethod("push",
                        Object.class);

                for (LocalizedMatcher matcher : matchers) {
                    pushMethod.invoke(matcherStackField.get(argMatcherStorage), matcher);
                }
            } catch (NoSuchFieldException | NoSuchMethodException | IllegalAccessException
                    | InvocationTargetException | ClassCastException e) {
                throw new Error("Reflection failed. Do you use a compatible version of "
                        + "mockito?", e);
            }

            verifications.add(verifiedMethod);
        });
        try {
            try {
                // Trigger the method call. This call will be intercepted and trigger the
                // onMethodCallDuringVerification callback.
                method.run();
            } catch (Throwable t) {
                if (t instanceof RuntimeException) {
                    throw (RuntimeException) t;
                } else if (t instanceof Error) {
                    throw (Error) t;
                }
                throw new RuntimeException(t);
            }

            if (verifications.isEmpty()) {
                // Make sure something was intercepted
                throw new IllegalArgumentException("Nothing was verified. Does the lambda call "
                        + "a static method on a 'static' mock/spy ?");
            } else if (verifications.size() > 1) {
                // A lambda might call several methods. In this case it is not clear what should
                // be verified. Hence throw an error.
                throw new IllegalArgumentException("Multiple intercepted calls on methods "
                        + verifications);
            }
        } finally {
            onMethodCallDuringVerification.remove();
        }
    }
339971
static List<Class<?>> getParameterTypes(Method method) {
		if (parameterTypeCache.containsKey(method)) {
			return parameterTypeCache.get(method);
		}
		List<Class<?>> types = new ArrayList<>();
		Collections.addAll(types, method.getParameterTypes());
		types = Collections.unmodifiableList(types);
		parameterTypeCache.put(method, types);
		return types;
	}
716853
public void addNewStaticMethod(Method method) {
        final CachedMethod cachedMethod = CachedMethod.find(method);
        NewStaticMetaMethod newMethod = new NewStaticMetaMethod(cachedMethod);
        final CachedClass declaringClass = newMethod.getDeclaringClass();
        addNewStaticMethodToIndex(newMethod, metaMethodIndex.getHeader(declaringClass.getTheClass()));
    }
107030
public static boolean isAnnotationPresent(final Class<? extends Annotation> annotation, final Method method) {
        final Annotation e = DaemonScanner.getAnnotation(annotation, method);
        return e != null;
    }
703114
public static void assertNoParameters(ReflectionMethod method) {
        final List<ReflectionParameter> parameters = method.getParameters();
        if (!parameters.isEmpty()) {
            final String message = "Class='"+method.getDeclaringClass()+"', method='"+method.getName()+"': Must take no parameters!";
            throw new IllegalArgumentException(message);
        }
    }
522326
@Override
    public MethodVisitor visitMethod(final int access, final String name,
            final String desc, final String signature, final String[] exceptions) {
        if (computeSVUID) {
            if ("<clinit>".equals(name)) {
                hasStaticInitializer = true;
            }
            /*
             * Remembers non private constructors and methods for SVUID
             * computation For constructor and method modifiers, only the
             * ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
             * ACC_SYNCHRONIZED, ACC_NATIVE, ACC_ABSTRACT and ACC_STRICT flags
             * are used.
             */
            int mods = access
                    & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE
                            | Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC
                            | Opcodes.ACC_FINAL | Opcodes.ACC_SYNCHRONIZED
                            | Opcodes.ACC_NATIVE | Opcodes.ACC_ABSTRACT | Opcodes.ACC_STRICT);

            // all non private methods
            if ((access & Opcodes.ACC_PRIVATE) == 0) {
                if ("<init>".equals(name)) {
                    svuidConstructors.add(new Item(name, mods, desc));
                } else if (!"<clinit>".equals(name)) {
                    svuidMethods.add(new Item(name, mods, desc));
                }
            }
        }

        return super.visitMethod(access, name, desc, signature, exceptions);
    }
711917
public static MethodParameters of(Method method) {

		Assert.notNull(method, "Method must not be null!");

		return CACHE.computeIfAbsent(method, MethodParameters::new);
	}
640766
public static boolean isObjectMethod(Method method) {
		if (method == null) {
			return false;
		}
		try {
			Object.class.getDeclaredMethod(method.getName(), method.getParameterTypes());
			return true;
		}
		catch (Exception ex) {
			return false;
		}
	}
345858
public static void assertVoidReturnType(final Method method, Class<? extends Annotation> annotation) 
   {
      if ((!method.getReturnType().equals(Void.class)) && (!method.getReturnType().equals(Void.TYPE)))
      {
         throw annotation == null ? MESSAGES.methodHasToReturnVoid(method) : MESSAGES.methodHasToReturnVoid2(method, annotation);
      }
   }
569816
public static <R, T> R invokeMethod(T instance, Method method, Object... arguments) {
        try {
            return (R) method.invoke(instance, arguments);
        } catch (IllegalAccessException e) {
            throw new InvocationException("Illegal access invoking method [" + method + "]: " + e.getMessage(), e);
        } catch (InvocationTargetException e) {
            throw new InvocationException("Exception occurred invoking method [" + method + "]: " + e.getMessage(), e);
        }
    }
427696
private boolean isFeatureMethod(MethodNode method) {
    for (Statement stat : AstUtil.getStatements(method)) {
      String label = stat.getStatementLabel();
      if (label == null) continue;

      // assertion: is (meant to be) a feature method, so we'll return true in the end
      if (method.isStatic())
        errorReporter.error(method, "Feature methods must not be static");

      return true;
    }

    return false;
  }
972098
public static void validateObserverMethod(ObserverMethod<?> observerMethod, BeanManager beanManager, ObserverMethod<?> originalObserverMethod) {
        Set<Annotation> qualifiers = observerMethod.getObservedQualifiers();
        if (observerMethod.getBeanClass() == null) {
            throw EventLogger.LOG.observerMethodsMethodReturnsNull("getBeanClass", observerMethod);
        }
        if (observerMethod.getObservedType() == null) {
            throw EventLogger.LOG.observerMethodsMethodReturnsNull("getObservedType", observerMethod);
        }
        Bindings.validateQualifiers(qualifiers, beanManager, observerMethod, "ObserverMethod.getObservedQualifiers");
        if (observerMethod.getReception() == null) {
            throw EventLogger.LOG.observerMethodsMethodReturnsNull("getReception", observerMethod);
        }
        if (observerMethod.getTransactionPhase() == null) {
            throw EventLogger.LOG.observerMethodsMethodReturnsNull("getTransactionPhase", observerMethod);
        }
        if (originalObserverMethod != null && (!observerMethod.getBeanClass().equals(originalObserverMethod.getBeanClass()))) {
            throw EventLogger.LOG.beanClassMismatch(originalObserverMethod, observerMethod);
        }
        if (!(observerMethod instanceof SyntheticObserverMethod) && !hasNotifyOverriden(observerMethod.getClass(), observerMethod)) {
            throw EventLogger.LOG.notifyMethodNotImplemented(observerMethod);
        }
    }
823117
public boolean referencesMethod(ExecutableElement method)
    {
        TypeElement declaringClass = (TypeElement) method.getEnclosingElement();
        String fullyQualifiedname = declaringClass.getQualifiedName().toString();
        String name = method.getSimpleName().toString();
        assert name.indexOf('.') == -1;
        String descriptor = Descriptor.getDesriptor(method);
        return getRefIndex(Methodref.class, fullyQualifiedname, name, descriptor) != -1;
    }
307151
static Method checkTimeMethod(Method timeMethod) throws InvalidBenchmarkException {
    checkArgument(isTimeMethod(timeMethod));
    Class<?>[] parameterTypes = timeMethod.getParameterTypes();
    if (!Arrays.equals(parameterTypes, new Class<?>[] {int.class})
        && !Arrays.equals(parameterTypes, new Class<?>[] {long.class})) {
      throw new InvalidBenchmarkException(
          "Microbenchmark methods must accept a single int parameter: " + timeMethod.getName());
    }

    // Static technically doesn't hurt anything, but it's just the completely wrong idea
    if (Util.isStatic(timeMethod)) {
      throw new InvalidBenchmarkException(
          "Microbenchmark methods must not be static: " + timeMethod.getName());
    }
    return timeMethod;
  }
392293
public static <T> T invoke(Object instance, String method, Object... args) {
        if (instance == null) return null;
        try {
            Method m = getPublicMethod(instance.getClass(), method, getArgsClasses(args));
            return (T) m.invoke(instance, args);
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            throw new IllegalStateException(e.getMessage(), e);
        }
    }
34368
private static boolean isAsyncMethod(Method method) {
        Class<?>[] parameterTypes = method.getParameterTypes();
        for (Class<?> c : parameterTypes)
        {
            if (c.isAssignableFrom(javax.ws.rs.container.AsyncResponse.class))
                return true;
        }
        return false;
    }
69851
private boolean isOperationMethod(Method method) {
    Class<?>[] paramTypes = method.getParameterTypes();
    return paramTypes.length == 1 && paramTypes[0] == Commit.class;
  }