/** * A helper for {@link ResolvedJavaMethod#getParameterAnnotations()} that handles the absence of * parameter annotations on bridge methods where the bridged method has parameter annotations. */ public static Annotation[][] getParameterAnnotations(ResolvedJavaMethod method) { Annotation[][] a = method.getParameterAnnotations(); if (a.length == 0 && method.isBridge()) { a = getBridgedMethod(method).getParameterAnnotations(); } return a; }
/** * A helper for {@link ResolvedJavaMethod#getParameterAnnotation(Class, int)} that handles the * absence of parameter annotations on bridge methods where the bridged method has parameter * annotations. */ public static <T extends Annotation> T getParameterAnnotation( Class<T> annotationClass, int parameterIndex, ResolvedJavaMethod method) { T a = method.getParameterAnnotation(annotationClass, parameterIndex); if (a == null && method.isBridge()) { a = getBridgedMethod(method).getParameterAnnotation(annotationClass, parameterIndex); } return a; }
/** * Gets the method bridged to by a {@linkplain ResolvedJavaMethod#isBridge() bridge} method. The * value returned is the method called by {@code method} that has the same name as {@code bridge}. * * @param bridge a bridge method * @return the method called by {@code bridge} whose name is the same as {@code bridge.getName()} */ public static ResolvedJavaMethod getBridgedMethod(ResolvedJavaMethod bridge) { assert bridge.isBridge(); Bytecode code = new ResolvedJavaMethodBytecode(bridge); BytecodeStream stream = new BytecodeStream(code.getCode()); int opcode = stream.currentBC(); ResolvedJavaMethod bridged = null; while (opcode != Bytecodes.END) { switch (opcode) { case INVOKEVIRTUAL: case INVOKESPECIAL: case INVOKESTATIC: case INVOKEINTERFACE: { int cpi = stream.readCPI(); ConstantPool cp = code.getConstantPool(); cp.loadReferencedType(cpi, opcode); ResolvedJavaMethod method = (ResolvedJavaMethod) cp.lookupMethod(cpi, opcode); if (method.getName().equals(bridge.getName())) { if (!assertionsEnabled()) { return method; } assert bridged == null || bridged.equals(method) : String.format( "Found calls to different methods named %s in bridge method %s%n callee 1: %s%n callee 2: %s", bridge.getName(), bridge.format("%R %H.%n(%P)"), bridged.format("%R %H.%n(%P)"), method.format("%R %H.%n(%P)")); bridged = method; } break; } } stream.next(); opcode = stream.currentBC(); } if (bridged == null) { throw new InternalError("Couldn't find method bridged by " + bridge.format("%R %H.%n(%P)")); } return bridged; }