Searches for the bridged method in the given candidates.
@param candidateMethods the List of candidate Methods
@param bridgeMethod the bridge method
@return the bridged method, or {@code null} if none found
494459
private static Method searchCandidates(List<Method> candidateMethods, Method bridgeMethod) {
		if (candidateMethods.isEmpty()) {
			return null;
		}
		Method previousMethod = null;
		boolean sameSig = true;
		for (Method candidateMethod : candidateMethods) {
			if (isBridgeMethodFor(bridgeMethod, candidateMethod, bridgeMethod.getDeclaringClass())) {
				return candidateMethod;
			}
			else if (previousMethod != null) {
				sameSig = sameSig &&
						Arrays.equals(candidateMethod.getGenericParameterTypes(), previousMethod.getGenericParameterTypes());
			}
			previousMethod = candidateMethod;
		}
		return (sameSig ? candidateMethods.get(0) : null);
	}
1067089
private void addProxyMethods(TypeSpec.Builder classBuilder, Element member, int methodIndex) {
        ExecutableElement executableElement = (ExecutableElement) member;
        String methodName = executableElement.getSimpleName().toString();
        boolean isOnewayAnnotated = member.getAnnotation(Oneway.class) != null;
        boolean isOneWay = executableElement.getReturnType().getKind() == TypeKind.VOID
                && isOnewayAnnotated;

        if (!isOneWay && isOnewayAnnotated) {
            logWarning("@Oneway is expected only for methods with void return. Ignoring it for " + member.getSimpleName());
        }


        MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder(methodName)
                .addModifiers(Modifier.PUBLIC)
                .addAnnotation(Override.class)
                .returns(TypeName.get(executableElement.getReturnType()));

        //add Exceptions
        for (TypeMirror exceptions : executableElement.getThrownTypes()) {
            methodBuilder.addException(ClassName.bestGuess(exceptions.toString()));
        }

        //add parameters
        int paramIndex = 0;
        for (VariableElement params : executableElement.getParameters()) {
            methodBuilder.addParameter(TypeName.get(params.asType()), params.getSimpleName().toString() + "_" + paramIndex);
            paramIndex++;
        }

        methodBuilder
                .addStatement("__checkProxy()");
        //add statements
        methodBuilder
                .addStatement("android.os.Parcel data = android.os.Parcel.obtain()");

        if (!isOneWay) {
            methodBuilder.addStatement("android.os.Parcel reply = android.os.Parcel.obtain()");
        }

        //add return if any
        if (executableElement.getReturnType().getKind() != TypeKind.VOID) {
            TypeElement genericParceler = getBindingManager().getGenericType(executableElement.getReturnType());
            if (genericParceler != null) {
                methodBuilder.addStatement("$T<$T> result", List.class, genericParceler);
            } else {
                methodBuilder.addStatement(executableElement.getReturnType().toString() + " result");
            }
        }

        //start main body block
        methodBuilder.beginControlFlow("try");

        //write the descriptor
        methodBuilder.addStatement("data.writeInterfaceToken(DESCRIPTOR)");

        List<VariableElement> outParams = new ArrayList<>();

        //pass parameters
        paramIndex = 0;
        for (VariableElement param : executableElement.getParameters()) {
            ParamBuilder.ParamType paramType = param.getAnnotation(ParamIn.class) != null ? ParamBuilder.ParamType.IN
                    : param.getAnnotation(ParamOut.class) != null ? ParamBuilder.ParamType.OUT : ParamBuilder.ParamType.IN_OUT;

            VariableElement wrappedParam = new VariableElementWrapper(param, paramIndex);
            if (paramType != ParamBuilder.ParamType.IN) {
                outParams.add(wrappedParam);
            }
            ParamBuilder paramBuilder = getBindingManager().getBuilderForParam(param.asType());
            if (paramBuilder != null) {
                paramBuilder.writeParamsToProxy(wrappedParam, paramType, methodBuilder);
            } else {
                logError("Parameter cannot be marshalled " + param.getSimpleName());
            }
            paramIndex ++;
        }

        //send remote command
        if (isOneWay) {
            methodBuilder.addStatement("mRemote.transact(TRANSACTION_" + methodName + "_" + methodIndex + ", data, null, android.os.IBinder.FLAG_ONEWAY)");
        } else {
            methodBuilder.addStatement("mRemote.transact(TRANSACTION_" + methodName + "_" + methodIndex + ", data, reply, 0)");
            //read exception if any
            methodBuilder.addStatement("Throwable exception = checkException(reply)");
            methodBuilder.beginControlFlow("if(exception != null)");

            for (TypeMirror exceptions : executableElement.getThrownTypes()) {
                ClassName exceptionCName = ClassName.bestGuess(exceptions.toString());
                methodBuilder.beginControlFlow("if(exception instanceof $T)", exceptionCName);
                methodBuilder.addStatement("throw ($T)exception", exceptionCName);
                methodBuilder.endControlFlow();
            }
            methodBuilder.addStatement("throw ($T)exception", RuntimeException.class);
            methodBuilder.endControlFlow();

            //read result
            if (executableElement.getReturnType().getKind() != TypeKind.VOID) {
                ParamBuilder paramBuilder = getBindingManager().getBuilderForParam(executableElement.getReturnType());
                if (paramBuilder != null) {
                    paramBuilder.readResultsFromProxy(executableElement.getReturnType(), methodBuilder);
                } else {
                    logError("Unmarshellable return type " + executableElement.getReturnType());
                    methodBuilder.addStatement("result = null");
                }
            }

            for (VariableElement param : outParams) {
                ParamBuilder.ParamType paramType = param.getAnnotation(ParamIn.class) != null ? ParamBuilder.ParamType.IN
                        : param.getAnnotation(ParamOut.class) != null ? ParamBuilder.ParamType.OUT : ParamBuilder.ParamType.IN_OUT;
                ParamBuilder paramBuilder = getBindingManager().getBuilderForParam(param.asType());
                if (paramBuilder != null) {
                    paramBuilder.readOutParamsFromProxy(param, paramType, methodBuilder);
                }
            }
        }

        //end of try
        methodBuilder.endControlFlow();


        //catch rethrow
        methodBuilder.beginControlFlow("catch ($T re)", ClassName.get("android.os", "RemoteException"));
        methodBuilder.addStatement("throw new $T(re)", RuntimeException.class);
        methodBuilder.endControlFlow();


        //finally block
        methodBuilder.beginControlFlow("finally");
        if (!isOneWay) {
            methodBuilder.addStatement("reply.recycle()");
        }
        methodBuilder.addStatement("data.recycle()");
        methodBuilder.endControlFlow();
        if (executableElement.getReturnType().getKind() != TypeKind.VOID) {
            methodBuilder.addStatement("return result");
        }

        classBuilder.addMethod(methodBuilder.build());
    }
1332969
public static <T extends MethodDescription> ElementMatcher.Junction<T> definedMethod(ElementMatcher<? super MethodDescription.InDefinedShape> matcher) {
        return new DefinedShapeMatcher<T, MethodDescription.InDefinedShape>(matcher);
    }
77034
public static <T extends MethodDescription> ElementMatcher.Junction<T> isConstructor() {
        return new MethodSortMatcher<T>(MethodSortMatcher.Sort.CONSTRUCTOR);
    }
585309
public Method getMethod(MethodGen methodGen) {
        Method[] methodList = jclass.getMethods();
        for (Method method : methodList) {
            if (method.getName().equals(methodGen.getName()) && method.getSignature().equals(methodGen.getSignature())
                    && method.getAccessFlags() == methodGen.getAccessFlags()) {
                return method;
            }
        }
        return null;
    }
185482
public static TestMethod getRootMethod(
            TestMethodTable rootMethodTable, StackTraceElement[] currentStackTrace) {
        for (StackTraceElement element : currentStackTrace) {
            List<TestMethod> rootMethods
            = rootMethodTable.getByName(element.getClassName(), element.getMethodName());
            if (rootMethods.size() > 0) {
                assert rootMethods.size() == 1;
                return rootMethods.get(0);
            }
        }
        return null;
    }
1022712
public void traverseMethod(String methodID) {
    MethodReferenceNode node = (MethodReferenceNode) elementReferenceMap.get(methodID);
    if (node == null) {
      //TODO(malvania): This might never be reached, because we create a node for every method,
      //                both invoked and declared.
      ErrorUtil.warning("Encountered .class method while accessing: " + methodID);
      return;
    }
    if (node.reachable) {
      return;
    }
    node.reachable = true;
    markParentClasses(ElementUtil.getDeclaringClass(node.methodElement));

    for (String invokedMethodID : node.invokedMethods) {
      traverseMethod(invokedMethodID);
    }
    for (String overrideMethodID : node.overridingMethods) {
      traverseMethod(overrideMethodID);
    }
  }
150219
private static Set<Method> findMethods(
      final MasterClass masterClass,
      final GuestClass guestClass,
      final String methodName,
      final ReturnClass returnClass,
      final MethodsSource nextMethodsSource) {
    final Set<Method> methods = nextMethodsSource.findMethods();
    final MethodsSource emptyMethods = new EmptyMethods();
    for (final Class<?> guestInterface : guestClass.toClass().getInterfaces()) {
      try {
        final Method method = masterClass.toClass().getMethod(methodName, guestInterface);
        if (returnClass.toClass().isAssignableFrom(method.getReturnType())) {
          methods.add(method);
        }
      } catch (final NoSuchMethodException ignored) {
      }
      methods.addAll(ByParameterInterfaces.findMethods(masterClass,
                                                       new GuestClass(guestInterface),
                                                       methodName,
                                                       returnClass,
                                                       emptyMethods));
    }
    return methods;
  }
528088
protected boolean tryBridgeMethod(MethodNode target, Expression receiver, boolean implicitThis, TupleExpression args) {
        ClassNode lookupClassNode;
        if (target.isProtected()) {
            lookupClassNode = controller.getClassNode();
            if (controller.isInClosure()) {
                lookupClassNode = lookupClassNode.getOuterClass();
            }
        } else {
            lookupClassNode = target.getDeclaringClass().redirect();
        }
        Map<MethodNode, MethodNode> bridges = lookupClassNode.getNodeMetaData(PRIVATE_BRIDGE_METHODS);
        MethodNode bridge = bridges==null?null:bridges.get(target);
        if (bridge != null) {
            Expression fixedReceiver = receiver;
            ClassNode classNode = implicitThis?controller.getClassNode():null;
            ClassNode declaringClass = bridge.getDeclaringClass();
            if (implicitThis && !controller.isInClosure()
                    && !classNode.isDerivedFrom(declaringClass)
                    && !classNode.implementsInterface(declaringClass)
                    && classNode instanceof InnerClassNode) {
                fixedReceiver = new PropertyExpression(new ClassExpression(classNode.getOuterClass()), "this");
            }
            ArgumentListExpression newArgs = new ArgumentListExpression(target.isStatic()?new ConstantExpression(null):fixedReceiver);
            for (Expression expression : args.getExpressions()) {
                newArgs.addExpression(expression);
            }
            return writeDirectMethodCall(bridge, implicitThis, fixedReceiver, newArgs);
        }
        return false;
    }
1089038
public Method[] findAdaptMethodsFrom(Class from) {
        Method[] methods = mAdaptMethods;
        List<Method> candidates = new ArrayList<Method>(methods.length);
        for (int i=methods.length; --i>=0; ) {
            Method method = methods[i];
            if (method.getParameterTypes()[0].isAssignableFrom(from)) {
                candidates.add(method);
            }
        }
        return (Method[]) candidates.toArray(new Method[candidates.size()]);
    }
1307691
private Map<StandardMethod, UnderrideLevel> findUnderriddenMethods(
      Iterable<ExecutableElement> methods) {
    Map<StandardMethod, ExecutableElement> standardMethods = new LinkedHashMap<>();
    for (ExecutableElement method : methods) {
      Optional<StandardMethod> standardMethod = maybeStandardMethod(method);
      if (standardMethod.isPresent() && isUnderride(method)) {
        standardMethods.put(standardMethod.get(), method);
      }
    }
    if (standardMethods.containsKey(StandardMethod.EQUALS)
        != standardMethods.containsKey(StandardMethod.HASH_CODE)) {
      ExecutableElement underriddenMethod = standardMethods.containsKey(StandardMethod.EQUALS)
          ? standardMethods.get(StandardMethod.EQUALS)
          : standardMethods.get(StandardMethod.HASH_CODE);
      messager.printMessage(ERROR,
          "hashCode and equals must be implemented together on FreeBuilder types",
          underriddenMethod);
    }
    ImmutableMap.Builder<StandardMethod, UnderrideLevel> result = ImmutableMap.builder();
    for (StandardMethod standardMethod : standardMethods.keySet()) {
      if (standardMethods.get(standardMethod).getModifiers().contains(Modifier.FINAL)) {
        result.put(standardMethod, UnderrideLevel.FINAL);
      } else {
        result.put(standardMethod, UnderrideLevel.OVERRIDEABLE);
      }
    }
    return result.build();
  }
1135594
public MethodDoc findMatchingMethod(MethodDoc method, MethodFinder mf) {

        // Look in this class's interface set
        MethodDoc md = findMatchingInterfaceMethod(method, mf);

        if (md != null) {
            return md;
        }

        // Look in this class's superclass ancestry
        ClassDoc superClass = getSuperclass();
        if (superClass != null) {

            md = superClass.getMatchingMethod(method, mf);
            if (md != null) {
                return md;
            }

            return superClass.findMatchingMethod(method, mf);
        }

        return null;
    }
101917
protected boolean tryBridgeMethod(MethodNode target, Expression receiver, boolean implicitThis,
                                      TupleExpression args, ClassNode thisClass) {
        ClassNode lookupClassNode;
        if (target.isProtected()) {
            lookupClassNode = controller.getClassNode();
            while (lookupClassNode != null && !lookupClassNode.isDerivedFrom(target.getDeclaringClass())) {
                lookupClassNode = lookupClassNode.getOuterClass();
            }
            if (lookupClassNode == null) {
                return false;
            }
        } else {
            lookupClassNode = target.getDeclaringClass().redirect();
        }
        Map<MethodNode, MethodNode> bridges = lookupClassNode.getNodeMetaData(PRIVATE_BRIDGE_METHODS);
        MethodNode bridge = bridges==null?null:bridges.get(target);
        if (bridge != null) {
            Expression fixedReceiver = receiver;
            if (implicitThis) {
                if (!controller.isInClosure()) {
                    fixedReceiver = new PropertyExpression(new ClassExpression(lookupClassNode), "this");
                } else if (thisClass != null) {
                    ClassNode current = thisClass.getOuterClass();
                    fixedReceiver = new VariableExpression("thisObject", current);
                    // adjust for multiple levels of nesting if needed
                    while (current instanceof InnerClassNode && !lookupClassNode.equals(current)) {
                        FieldNode thisField = current.getField("this$0");
                        current = current.getOuterClass();
                        if (thisField != null) {
                            fixedReceiver = new PropertyExpression(fixedReceiver, "this$0");
                            fixedReceiver.setType(current);
                        }
                    }
                }
            }
            ArgumentListExpression newArgs = new ArgumentListExpression(target.isStatic()?new ConstantExpression(null):fixedReceiver);
            for (Expression expression : args.getExpressions()) {
                newArgs.addExpression(expression);
            }
            return writeDirectMethodCall(bridge, implicitThis, fixedReceiver, newArgs);
        }
        return false;
    }
417684
private static boolean goodMethod(Method method) {
    int modifiers = method.getModifiers();
    if (Modifier.isStatic(modifiers) || Modifier.isPrivate(modifiers)) return false;
    // Skip bridge methods generated method by compiler
    // For example. CompareTo(Some) and CompareTo(Object).
    if (method.isBridge()) return false;
    // Skip method in Object
    String methodName = method.getName();
    if (method.getParameterTypes().length == 0
        && (methodName.equals("hashCode") || methodName.equals("toString"))) return false;
    if (method.getParameterTypes().length == 1 & methodName.equals("equals")) return false;
    return true;
  }
1131006
public static MethodHandle lookupMethodHandle(Method method) throws ReflectiveOperationException {

        LettuceAssert.notNull(method, "Method must not be null");
        LettuceAssert.isTrue(method.isDefault(), "Method is not a default method");

        return methodHandleLookup.lookup(method);
    }
700109
@Nullable
    public static XMethod getXMethod(final XClass xClass, final String methodName, final String methodSig) {
        if (xClass == null) {
            return null;
        }

        XMethod xMethod = xClass.findMethod(methodName, methodSig, false);
        if (xMethod == null) {
            ClassDescriptor descriptor = xClass.getSuperclassDescriptor();
            if (descriptor != null) {
                final XClass superClass = getXClass(descriptor);
                xMethod = getXMethod(superClass, methodName, methodSig);
            }
        }
        return xMethod;
    }
746115
public static <T extends ParameterDescription> ElementMatcher.Junction<T> hasGenericType(ElementMatcher<? super TypeDescription.Generic> matcher) {
        return new MethodParameterTypeMatcher<T>(matcher);
    }