@Override public List<MethodNode> handleMissingMethod( final ClassNode receiver, final String name, final ArgumentListExpression argumentList, final ClassNode[] argumentTypes, final MethodCall call) { String[] decomposed = Traits.decomposeSuperCallName(name); if (decomposed != null) { return convertToDynamicCall(call, receiver, decomposed, argumentTypes); } if (call instanceof MethodCallExpression) { MethodCallExpression mce = (MethodCallExpression) call; if (mce.getReceiver() instanceof VariableExpression) { VariableExpression var = (VariableExpression) mce.getReceiver(); // GROOVY-7322 // static method call in trait? ClassNode type = null; if (isStaticTraitReceiver(receiver, var)) { type = receiver.getGenericsTypes()[0].getType(); } else if (isThisTraitReceiver(var)) { type = receiver; } if (type != null && Traits.isTrait(type)) { ClassNode helper = Traits.findHelper(type); Parameter[] params = new Parameter[argumentTypes.length + 1]; params[0] = new Parameter(ClassHelper.CLASS_Type.getPlainNodeReference(), "staticSelf"); for (int i = 1; i < params.length; i++) { params[i] = new Parameter(argumentTypes[i - 1], "p" + i); } MethodNode method = helper.getDeclaredMethod(name, params); if (method != null) { return Collections.singletonList(makeDynamic(call, method.getReturnType())); } } } ClassNode dynamic = mce.getNodeMetaData(TraitASTTransformation.DO_DYNAMIC); if (dynamic != null) { return Collections.singletonList(makeDynamic(call, dynamic)); } } return NOTFOUND; }
/** * Given a method call, first checks that it's a static method call, and if it is, returns the * class node for the receiver. For example, with the following code: <code></code>Person.findAll * { ... }</code>, it would return the class node for <i>Person</i>. If it's not a static method * call, returns null. * * @param call a method call * @return null if it's not a static method call, or the class node for the receiver instead. */ public ClassNode extractStaticReceiver(MethodCall call) { if (call instanceof StaticMethodCallExpression) { return ((StaticMethodCallExpression) call).getOwnerType(); } else if (call instanceof MethodCallExpression) { Expression objectExpr = ((MethodCallExpression) call).getObjectExpression(); if (objectExpr instanceof ClassExpression && ClassHelper.CLASS_Type.equals(objectExpr.getType())) { GenericsType[] genericsTypes = objectExpr.getType().getGenericsTypes(); if (genericsTypes != null && genericsTypes.length == 1) { return genericsTypes[0].getType(); } } if (objectExpr instanceof ClassExpression) { return objectExpr.getType(); } } return null; }