Search in sources :

Example 66 with TupleExpression

use of org.codehaus.groovy.ast.expr.TupleExpression in project groovy by apache.

the class RecursivenessTester method methodParamsMatchCallArgs.

private boolean methodParamsMatchCallArgs(MethodNode method, Expression call) {
    TupleExpression arguments;
    if (call instanceof MethodCallExpression) {
        arguments = ((TupleExpression) ((MethodCallExpression) call).getArguments());
    } else {
        arguments = ((TupleExpression) ((StaticMethodCallExpression) call).getArguments());
    }
    if (method.getParameters().length != arguments.getExpressions().size())
        return false;
    List<List<ClassNode>> classNodePairs = transpose(Arrays.asList(Arrays.stream(method.getParameters()).map(Parameter::getType).collect(Collectors.toList()), arguments.getExpressions().stream().map(Expression::getType).collect(Collectors.toList())));
    return classNodePairs.stream().allMatch(t -> areTypesCallCompatible(t.get(0), t.get(1)));
}
Also used : StaticMethodCallExpression(org.codehaus.groovy.ast.expr.StaticMethodCallExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) List(java.util.List)

Example 67 with TupleExpression

use of org.codehaus.groovy.ast.expr.TupleExpression in project groovy by apache.

the class StaticInvocationWriter method writeDirectMethodCall.

@Override
protected boolean writeDirectMethodCall(final MethodNode target, final boolean implicitThis, final Expression receiver, final TupleExpression args) {
    if (target == null)
        return false;
    ClassNode classNode = controller.getClassNode();
    if (target instanceof ExtensionMethodNode) {
        ExtensionMethodNode emn = (ExtensionMethodNode) target;
        MethodVisitor mv = controller.getMethodVisitor();
        MethodNode node = emn.getExtensionMethodNode();
        Parameter[] parameters = node.getParameters();
        ClassNode returnType = node.getReturnType();
        List<Expression> argumentList = new ArrayList<>();
        if (emn.isStaticExtension()) {
            argumentList.add(nullX());
        } else {
            Expression fixedReceiver = null;
            if (isThisOrSuper(receiver) && classNode.getOuterClass() != null && controller.isInGeneratedFunction()) {
                ClassNode current = classNode.getOuterClass();
                fixedReceiver = varX("thisObject", current);
                // adjust for multiple levels of nesting if needed
                while (current.getOuterClass() != null && !classNode.equals(current)) {
                    FieldNode thisField = current.getField("this$0");
                    current = current.getOuterClass();
                    if (thisField != null) {
                        fixedReceiver = propX(fixedReceiver, "this$0");
                        fixedReceiver.setType(current);
                    }
                }
            }
            argumentList.add(fixedReceiver != null ? fixedReceiver : receiver);
        }
        argumentList.addAll(args.getExpressions());
        loadArguments(argumentList, parameters);
        String owner = BytecodeHelper.getClassInternalName(node.getDeclaringClass());
        String desc = BytecodeHelper.getMethodDescriptor(returnType, parameters);
        mv.visitMethodInsn(INVOKESTATIC, owner, target.getName(), desc, false);
        controller.getOperandStack().remove(argumentList.size());
        if (isPrimitiveVoid(returnType)) {
            returnType = ClassHelper.OBJECT_TYPE;
            mv.visitInsn(ACONST_NULL);
        }
        controller.getOperandStack().push(returnType);
        return true;
    }
    if (target == StaticTypeCheckingVisitor.CLOSURE_CALL_VARGS) {
        // wrap arguments into an array
        Expression arr = new ArrayExpression(ClassHelper.OBJECT_TYPE, args.getExpressions());
        return super.writeDirectMethodCall(target, implicitThis, receiver, args(arr));
    }
    if (!target.isPublic() && controller.isInGeneratedFunction() && target.getDeclaringClass() != classNode) {
        if (!tryBridgeMethod(target, receiver, implicitThis, args, classNode)) {
            // replace call with an invoker helper call
            MethodNode methodNode = target.isStatic() ? INVOKERHELPER_INVOKESTATICMETHOD : INVOKERHELPER_INVOKEMETHOD;
            MethodCallExpression mce = callX(classX(INVOKERHELPER_CLASSNODE), methodNode.getName(), args(target.isStatic() ? classX(target.getDeclaringClass()) : receiver, constX(target.getName()), new ArrayExpression(ClassHelper.OBJECT_TYPE, args.getExpressions())));
            mce.setMethodTarget(methodNode);
            mce.visit(controller.getAcg());
        }
        return true;
    }
    if (target.isPrivate() && tryPrivateMethod(target, implicitThis, receiver, args, classNode)) {
        return true;
    }
    Expression fixedReceiver = null;
    boolean fixedImplicitThis = implicitThis;
    if (target.isProtected()) {
        ClassNode node = receiver == null ? ClassHelper.OBJECT_TYPE : controller.getTypeChooser().resolveType(receiver, controller.getClassNode());
        if (!implicitThis && !isThisOrSuper(receiver) && !samePackageName(node, classNode) && StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(node, target.getDeclaringClass())) {
            controller.getSourceUnit().addError(new SyntaxException("Method " + target.getName() + " is protected in " + target.getDeclaringClass().toString(false), receiver != null ? receiver : args));
        } else if (!node.isDerivedFrom(target.getDeclaringClass()) && tryBridgeMethod(target, receiver, implicitThis, args, classNode)) {
            return true;
        }
    } else if (target.isPublic() && receiver != null) {
        if (implicitThis && controller.isInGeneratedFunction() && !classNode.isDerivedFrom(target.getDeclaringClass()) && !classNode.implementsInterface(target.getDeclaringClass())) {
            ClassNode thisType = controller.getThisType();
            // GROOVY-7242
            if (isTrait(thisType.getOuterClass()))
                thisType = ClassHelper.dynamicType();
            fixedReceiver = varX("thisObject", thisType);
            // account for multiple levels of inner types
            while (thisType.getOuterClass() != null && !target.getDeclaringClass().equals(thisType)) {
                FieldNode thisField = thisType.getField("this$0");
                thisType = thisType.getOuterClass();
                if (thisField != null) {
                    fixedReceiver = propX(fixedReceiver, "this$0");
                    fixedReceiver.setType(thisType);
                    fixedImplicitThis = false;
                }
            }
        }
    }
    if (receiver != null && !isSuperExpression(receiver)) {
        // in order to avoid calls to castToType, which is the dynamic behaviour, we make sure that we call CHECKCAST instead then replace the top operand type
        return super.writeDirectMethodCall(target, fixedImplicitThis, new CheckcastReceiverExpression(fixedReceiver != null ? fixedReceiver : receiver, target), args);
    }
    return super.writeDirectMethodCall(target, implicitThis, receiver, args);
}
Also used : DecompiledClassNode(org.codehaus.groovy.ast.decompiled.DecompiledClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) FieldNode(org.codehaus.groovy.ast.FieldNode) ArrayList(java.util.ArrayList) MethodVisitor(org.objectweb.asm.MethodVisitor) ExtensionMethodNode(org.codehaus.groovy.transform.stc.ExtensionMethodNode) MethodNode(org.codehaus.groovy.ast.MethodNode) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) ArrayExpression(org.codehaus.groovy.ast.expr.ArrayExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) PropertyExpression(org.codehaus.groovy.ast.expr.PropertyExpression) ExpressionUtils.isSuperExpression(org.apache.groovy.ast.tools.ExpressionUtils.isSuperExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) Expression(org.codehaus.groovy.ast.expr.Expression) ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) TemporaryVariableExpression(org.codehaus.groovy.transform.sc.TemporaryVariableExpression) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) AttributeExpression(org.codehaus.groovy.ast.expr.AttributeExpression) SyntaxException(org.codehaus.groovy.syntax.SyntaxException) Parameter(org.codehaus.groovy.ast.Parameter) ArrayExpression(org.codehaus.groovy.ast.expr.ArrayExpression) ExtensionMethodNode(org.codehaus.groovy.transform.stc.ExtensionMethodNode)

Example 68 with TupleExpression

use of org.codehaus.groovy.ast.expr.TupleExpression in project groovy by apache.

the class StaticInvocationWriter method writeSpecialConstructorCall.

@Override
public void writeSpecialConstructorCall(final ConstructorCallExpression call) {
    MethodNode mn = call.getNodeMetaData(StaticTypesMarker.DIRECT_METHOD_CALL_TARGET);
    if (mn == null) {
        super.writeSpecialConstructorCall(call);
        return;
    }
    controller.getCompileStack().pushInSpecialConstructorCall();
    ConstructorNode cn;
    if (mn instanceof ConstructorNode) {
        cn = (ConstructorNode) mn;
    } else {
        cn = new ConstructorNode(mn.getModifiers(), mn.getParameters(), mn.getExceptions(), mn.getCode());
        cn.setDeclaringClass(mn.getDeclaringClass());
    }
    // load "this"
    controller.getMethodVisitor().visitVarInsn(ALOAD, 0);
    String ownerDescriptor = BytecodeHelper.getClassInternalName(cn.getDeclaringClass());
    TupleExpression args = makeArgumentList(call.getArguments());
    int before = controller.getOperandStack().getStackLength();
    loadArguments(args.getExpressions(), cn.getParameters());
    finnishConstructorCall(cn, ownerDescriptor, controller.getOperandStack().getStackLength() - before);
    // on a special call, there's no object on stack
    controller.getOperandStack().remove(1);
    controller.getCompileStack().pop();
}
Also used : ExtensionMethodNode(org.codehaus.groovy.transform.stc.ExtensionMethodNode) MethodNode(org.codehaus.groovy.ast.MethodNode) ConstructorNode(org.codehaus.groovy.ast.ConstructorNode) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression)

Example 69 with TupleExpression

use of org.codehaus.groovy.ast.expr.TupleExpression in project groovy by apache.

the class StaticImportVisitor method transformConstructorCallExpression.

protected Expression transformConstructorCallExpression(ConstructorCallExpression cce) {
    inSpecialConstructorCall = cce.isSpecialCall();
    Expression expression = cce.getArguments();
    if (expression instanceof TupleExpression) {
        TupleExpression tuple = (TupleExpression) expression;
        if (tuple.getExpressions().size() == 1) {
            expression = tuple.getExpression(0);
            if (expression instanceof NamedArgumentListExpression) {
                NamedArgumentListExpression namedArgs = (NamedArgumentListExpression) expression;
                List<MapEntryExpression> entryExpressions = namedArgs.getMapEntryExpressions();
                for (int i = 0; i < entryExpressions.size(); i++) {
                    entryExpressions.set(i, (MapEntryExpression) transformMapEntryExpression(entryExpressions.get(i), cce.getType()));
                }
            }
        }
    }
    Expression ret = cce.transformExpression(this);
    inSpecialConstructorCall = false;
    return ret;
}
Also used : MapEntryExpression(org.codehaus.groovy.ast.expr.MapEntryExpression) PropertyExpression(org.codehaus.groovy.ast.expr.PropertyExpression) StaticMethodCallExpression(org.codehaus.groovy.ast.expr.StaticMethodCallExpression) ExpressionUtils.isSuperExpression(org.apache.groovy.ast.tools.ExpressionUtils.isSuperExpression) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) NamedArgumentListExpression(org.codehaus.groovy.ast.expr.NamedArgumentListExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) EmptyExpression(org.codehaus.groovy.ast.expr.EmptyExpression) Expression(org.codehaus.groovy.ast.expr.Expression) ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) AnnotationConstantExpression(org.codehaus.groovy.ast.expr.AnnotationConstantExpression) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) MapEntryExpression(org.codehaus.groovy.ast.expr.MapEntryExpression) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) NamedArgumentListExpression(org.codehaus.groovy.ast.expr.NamedArgumentListExpression)

Example 70 with TupleExpression

use of org.codehaus.groovy.ast.expr.TupleExpression in project groovy by apache.

the class StaticInvocationWriter method tryBridgeMethod.

/**
 * Attempts to make a direct method call on a bridge method, if it exists.
 */
protected boolean tryBridgeMethod(final MethodNode target, final Expression receiver, final boolean implicitThis, final TupleExpression args, final 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(StaticCompilationMetadataKeys.PRIVATE_BRIDGE_METHODS);
    MethodNode bridge = bridges == null ? null : bridges.get(target);
    if (bridge != null) {
        Expression fixedReceiver = receiver;
        if (implicitThis) {
            if (!controller.isInGeneratedFunction()) {
                if (!thisClass.isDerivedFrom(lookupClassNode))
                    fixedReceiver = propX(classX(lookupClassNode), "this");
            } else if (thisClass != null) {
                ClassNode current = thisClass.getOuterClass();
                fixedReceiver = varX("thisObject", current);
                // adjust for multiple levels of nesting if needed
                while (current.getOuterClass() != null && !lookupClassNode.equals(current)) {
                    FieldNode thisField = current.getField("this$0");
                    current = current.getOuterClass();
                    if (thisField != null) {
                        fixedReceiver = propX(fixedReceiver, "this$0");
                        fixedReceiver.setType(current);
                    }
                }
            }
        }
        ArgumentListExpression newArgs = args(target.isStatic() ? nullX() : fixedReceiver);
        for (Expression expression : args.getExpressions()) {
            newArgs.addExpression(expression);
        }
        return writeDirectMethodCall(bridge, implicitThis, fixedReceiver, newArgs);
    }
    return false;
}
Also used : DecompiledClassNode(org.codehaus.groovy.ast.decompiled.DecompiledClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) ExtensionMethodNode(org.codehaus.groovy.transform.stc.ExtensionMethodNode) MethodNode(org.codehaus.groovy.ast.MethodNode) FieldNode(org.codehaus.groovy.ast.FieldNode) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) ArrayExpression(org.codehaus.groovy.ast.expr.ArrayExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) PropertyExpression(org.codehaus.groovy.ast.expr.PropertyExpression) ExpressionUtils.isSuperExpression(org.apache.groovy.ast.tools.ExpressionUtils.isSuperExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) Expression(org.codehaus.groovy.ast.expr.Expression) ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) TemporaryVariableExpression(org.codehaus.groovy.transform.sc.TemporaryVariableExpression) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) AttributeExpression(org.codehaus.groovy.ast.expr.AttributeExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression)

Aggregations

TupleExpression (org.codehaus.groovy.ast.expr.TupleExpression)78 Expression (org.codehaus.groovy.ast.expr.Expression)65 VariableExpression (org.codehaus.groovy.ast.expr.VariableExpression)56 MethodCallExpression (org.codehaus.groovy.ast.expr.MethodCallExpression)48 ArgumentListExpression (org.codehaus.groovy.ast.expr.ArgumentListExpression)44 PropertyExpression (org.codehaus.groovy.ast.expr.PropertyExpression)42 ConstantExpression (org.codehaus.groovy.ast.expr.ConstantExpression)41 ConstructorCallExpression (org.codehaus.groovy.ast.expr.ConstructorCallExpression)40 ClosureExpression (org.codehaus.groovy.ast.expr.ClosureExpression)35 ClassNode (org.codehaus.groovy.ast.ClassNode)34 ClassExpression (org.codehaus.groovy.ast.expr.ClassExpression)34 BinaryExpression (org.codehaus.groovy.ast.expr.BinaryExpression)31 ArrayExpression (org.codehaus.groovy.ast.expr.ArrayExpression)23 DeclarationExpression (org.codehaus.groovy.ast.expr.DeclarationExpression)23 MapExpression (org.codehaus.groovy.ast.expr.MapExpression)22 InnerClassNode (org.codehaus.groovy.ast.InnerClassNode)20 Parameter (org.codehaus.groovy.ast.Parameter)20 ListExpression (org.codehaus.groovy.ast.expr.ListExpression)18 MapEntryExpression (org.codehaus.groovy.ast.expr.MapEntryExpression)18 CastExpression (org.codehaus.groovy.ast.expr.CastExpression)17