Search in sources :

Example 26 with StaticMethodCallExpression

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

the class TraitComposer method applyTrait.

private static void applyTrait(final ClassNode trait, final ClassNode cNode, final TraitHelpersTuple helpers, SourceUnit unit) {
    ClassNode helperClassNode = helpers.getHelper();
    ClassNode fieldHelperClassNode = helpers.getFieldHelper();
    ClassNode staticFieldHelperClassNode = helpers.getStaticFieldHelper();
    Map<String, ClassNode> genericsSpec = GenericsUtils.createGenericsSpec(trait, GenericsUtils.createGenericsSpec(cNode));
    for (MethodNode methodNode : helperClassNode.getAllDeclaredMethods()) {
        String name = methodNode.getName();
        Parameter[] helperMethodParams = methodNode.getParameters();
        int nParams = helperMethodParams.length;
        if (nParams > 0 && !methodNode.isAbstract() && ((methodNode.getModifiers() & Opcodes.ACC_STATIC) != 0) && (!name.contains("$") || (methodNode.getModifiers() & Opcodes.ACC_SYNTHETIC) == 0)) {
            ArgumentListExpression argList = new ArgumentListExpression();
            argList.addExpression(new VariableExpression("this"));
            Parameter[] origParams = new Parameter[nParams - 1];
            Parameter[] params = new Parameter[nParams - 1];
            System.arraycopy(methodNode.getParameters(), 1, params, 0, params.length);
            MethodNode originalMethod = trait.getMethod(name, params);
            Map<String, ClassNode> methodGenericsSpec = GenericsUtils.addMethodGenerics(Optional.ofNullable(originalMethod).orElse(methodNode), genericsSpec);
            for (int i = 1; i < nParams; i += 1) {
                Parameter parameter = helperMethodParams[i];
                ClassNode originType = parameter.getOriginType();
                ClassNode fixedType = correctToGenericsSpecRecurse(methodGenericsSpec, originType);
                Parameter newParam = new Parameter(fixedType, parameter.getName());
                List<AnnotationNode> copied = new LinkedList<>();
                List<AnnotationNode> notCopied = new LinkedList<>();
                GeneralUtils.copyAnnotatedNodeAnnotations(parameter, copied, notCopied);
                newParam.addAnnotations(copied);
                params[i - 1] = newParam;
                origParams[i - 1] = parameter;
                argList.addExpression(new VariableExpression(newParam));
            }
            createForwarderMethod(trait, cNode, methodNode, originalMethod, helperClassNode, methodGenericsSpec, helperMethodParams, origParams, params, argList, unit);
        }
    }
    MethodCallExpression staticInitCall = new MethodCallExpression(new ClassExpression(helperClassNode), Traits.STATIC_INIT_METHOD, new ArgumentListExpression(new ClassExpression(cNode)));
    MethodNode staticInitMethod = new MethodNode(Traits.STATIC_INIT_METHOD, Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC, ClassHelper.VOID_TYPE, new Parameter[] { new Parameter(ClassHelper.CLASS_Type, "clazz") }, ClassNode.EMPTY_ARRAY, EmptyStatement.INSTANCE);
    staticInitMethod.setDeclaringClass(helperClassNode);
    staticInitCall.setMethodTarget(staticInitMethod);
    cNode.addStaticInitializerStatements(Collections.singletonList(new ExpressionStatement(staticInitCall)), false);
    if (fieldHelperClassNode != null && !cNode.declaresInterface(fieldHelperClassNode)) {
        // we should implement the field helper interface too
        cNode.addInterface(fieldHelperClassNode);
        // implementation of methods
        List<MethodNode> declaredMethods = new LinkedList<>();
        for (MethodNode declaredMethod : fieldHelperClassNode.getAllDeclaredMethods()) {
            if (declaredMethod.getName().endsWith(Traits.DIRECT_GETTER_SUFFIX)) {
                declaredMethods.add(0, declaredMethod);
            } else {
                declaredMethods.add(declaredMethod);
            }
        }
        if (staticFieldHelperClassNode != null) {
            for (MethodNode declaredMethod : staticFieldHelperClassNode.getAllDeclaredMethods()) {
                if (declaredMethod.getName().endsWith(Traits.DIRECT_GETTER_SUFFIX)) {
                    declaredMethods.add(0, declaredMethod);
                } else {
                    declaredMethods.add(declaredMethod);
                }
            }
        }
        for (MethodNode methodNode : declaredMethods) {
            String fieldName = methodNode.getName();
            if (fieldName.endsWith(Traits.DIRECT_GETTER_SUFFIX) || fieldName.endsWith(Traits.DIRECT_SETTER_SUFFIX)) {
                int suffixIdx = fieldName.lastIndexOf('$');
                fieldName = fieldName.substring(0, suffixIdx);
                String operation = methodNode.getName().substring(suffixIdx + 1);
                boolean getter = "get".equals(operation);
                ClassNode returnType = correctToGenericsSpecRecurse(genericsSpec, methodNode.getReturnType());
                int fieldMods = 0;
                int isStatic = 0;
                boolean publicField = true;
                FieldNode helperField = null;
                fieldMods = 0;
                isStatic = 0;
                // look first for field with encoded modifier information
                for (Integer mod : Traits.FIELD_PREFIXES) {
                    helperField = fieldHelperClassNode.getField(String.format("$0x%04x", mod) + fieldName);
                    if (helperField != null) {
                        if ((mod & Opcodes.ACC_STATIC) != 0)
                            isStatic = Opcodes.ACC_STATIC;
                        fieldMods = fieldMods | mod;
                        break;
                    }
                }
                if (helperField == null) {
                    // look for possible legacy fields (trait compiled pre 2.4.8)
                    helperField = fieldHelperClassNode.getField(Traits.FIELD_PREFIX + Traits.PUBLIC_FIELD_PREFIX + fieldName);
                    if (helperField == null) {
                        publicField = false;
                        helperField = fieldHelperClassNode.getField(Traits.FIELD_PREFIX + Traits.PRIVATE_FIELD_PREFIX + fieldName);
                    }
                    if (helperField == null) {
                        publicField = true;
                        // try to find a static one
                        helperField = fieldHelperClassNode.getField(Traits.STATIC_FIELD_PREFIX + Traits.PUBLIC_FIELD_PREFIX + fieldName);
                        if (helperField == null) {
                            publicField = false;
                            helperField = fieldHelperClassNode.getField(Traits.STATIC_FIELD_PREFIX + Traits.PRIVATE_FIELD_PREFIX + fieldName);
                        }
                        fieldMods = fieldMods | Opcodes.ACC_STATIC;
                        isStatic = Opcodes.ACC_STATIC;
                    }
                    fieldMods = fieldMods | (publicField ? Opcodes.ACC_PUBLIC : Opcodes.ACC_PRIVATE);
                }
                if (getter) {
                    // add field
                    if (helperField != null) {
                        List<AnnotationNode> copied = new LinkedList<>();
                        List<AnnotationNode> notCopied = new LinkedList<>();
                        GeneralUtils.copyAnnotatedNodeAnnotations(helperField, copied, notCopied);
                        FieldNode fieldNode = cNode.addField(fieldName, fieldMods, returnType, null);
                        fieldNode.addAnnotations(copied);
                        // so instead set within (static) initializer
                        if (fieldNode.isFinal()) {
                            String baseName = fieldNode.isStatic() ? Traits.STATIC_INIT_METHOD : Traits.INIT_METHOD;
                            StaticMethodCallExpression mce = callX(helperClassNode, baseName + fieldNode.getName(), args(varX("this")));
                            if (helperClassNode.hasPossibleStaticMethod(mce.getMethod(), mce.getArguments())) {
                                Statement stmt = stmt(assignX(varX(fieldNode.getName(), fieldNode.getType()), mce));
                                if (isStatic == 0) {
                                    cNode.addObjectInitializerStatements(stmt);
                                } else {
                                    List<Statement> staticStatements = new ArrayList<Statement>();
                                    staticStatements.add(stmt);
                                    cNode.addStaticInitializerStatements(staticStatements, true);
                                }
                            }
                        }
                    }
                }
                Parameter[] newParams;
                if (getter) {
                    newParams = Parameter.EMPTY_ARRAY;
                } else {
                    ClassNode originType = methodNode.getParameters()[0].getOriginType();
                    ClassNode fixedType = originType.isGenericsPlaceHolder() ? ClassHelper.OBJECT_TYPE : correctToGenericsSpecRecurse(genericsSpec, originType);
                    newParams = new Parameter[] { new Parameter(fixedType, "val") };
                }
                Expression fieldExpr = varX(cNode.getField(fieldName));
                boolean finalSetter = !getter && (fieldMods & Opcodes.ACC_FINAL) != 0;
                Statement body = getter ? returnS(fieldExpr) : (finalSetter ? null : stmt(new BinaryExpression(fieldExpr, Token.newSymbol(Types.EQUAL, 0, 0), varX(newParams[0]))));
                // add getter/setter even though setter not strictly needed for final fields
                // but add empty body for setter for legacy compatibility
                MethodNode impl = new MethodNode(methodNode.getName(), Opcodes.ACC_PUBLIC | isStatic, returnType, newParams, ClassNode.EMPTY_ARRAY, body);
                AnnotationNode an = new AnnotationNode(COMPILESTATIC_CLASSNODE);
                impl.addAnnotation(an);
                cNode.addTransform(StaticCompileTransformation.class, an);
                cNode.addMethod(impl);
            }
        }
    }
    cNode.addObjectInitializerStatements(new ExpressionStatement(new MethodCallExpression(new ClassExpression(helperClassNode), Traits.INIT_METHOD, new ArgumentListExpression(new VariableExpression("this")))));
}
Also used : StaticMethodCallExpression(org.codehaus.groovy.ast.expr.StaticMethodCallExpression) ArrayList(java.util.ArrayList) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) MethodNode(org.codehaus.groovy.ast.MethodNode) StaticMethodCallExpression(org.codehaus.groovy.ast.expr.StaticMethodCallExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) AnnotationNode(org.codehaus.groovy.ast.AnnotationNode) ClassNode(org.codehaus.groovy.ast.ClassNode) FieldNode(org.codehaus.groovy.ast.FieldNode) Statement(org.codehaus.groovy.ast.stmt.Statement) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) EmptyStatement(org.codehaus.groovy.ast.stmt.EmptyStatement) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) LinkedList(java.util.LinkedList) 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) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) CastExpression(org.codehaus.groovy.ast.expr.CastExpression) StaticMethodCallExpression(org.codehaus.groovy.ast.expr.StaticMethodCallExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) Expression(org.codehaus.groovy.ast.expr.Expression) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) Parameter(org.codehaus.groovy.ast.Parameter)

Example 27 with StaticMethodCallExpression

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

the class TraitReceiverTransformer method transform.

@Override
public Expression transform(final Expression exp) {
    ClassNode weavedType = weaved.getOriginType();
    if (exp instanceof BinaryExpression) {
        return transformBinaryExpression((BinaryExpression) exp, weavedType);
    } else if (exp instanceof StaticMethodCallExpression) {
        StaticMethodCallExpression call = (StaticMethodCallExpression) exp;
        ClassNode ownerType = call.getOwnerType();
        if (traitClass.equals(ownerType)) {
            MethodCallExpression mce = callX(varX(weaved), call.getMethod(), transform(call.getArguments()));
            mce.setSafe(false);
            mce.setSpreadSafe(false);
            mce.setImplicitThis(false);
            mce.setSourcePosition(exp);
            return mce;
        }
    } else if (exp instanceof MethodCallExpression) {
        MethodCallExpression mce = (MethodCallExpression) exp;
        String obj = mce.getObjectExpression().getText();
        if (mce.isImplicitThis() || "this".equals(obj)) {
            return transformMethodCallOnThis(mce);
        } else if ("super".equals(obj)) {
            return transformSuperMethodCall(mce);
        }
    } else if (exp instanceof FieldExpression) {
        FieldNode fn = ((FieldExpression) exp).getField();
        return transformFieldReference(exp, fn, fn.isStatic());
    } else if (exp instanceof VariableExpression) {
        VariableExpression vexp = (VariableExpression) exp;
        Variable accessedVariable = vexp.getAccessedVariable();
        if (accessedVariable instanceof FieldNode || accessedVariable instanceof PropertyNode) {
            if (knownFields.contains(vexp.getName())) {
                boolean isStatic = Modifier.isStatic(accessedVariable.getModifiers());
                return transformFieldReference(exp, accessedVariable instanceof FieldNode ? (FieldNode) accessedVariable : ((PropertyNode) accessedVariable).getField(), isStatic);
            } else {
                PropertyExpression propertyExpression = propX(varX(weaved), vexp.getName());
                propertyExpression.getProperty().setSourcePosition(exp);
                return propertyExpression;
            }
        } else if (accessedVariable instanceof DynamicVariable && !inClosure) {
            // GROOVY-9386
            PropertyExpression propertyExpression = propX(varX(weaved), vexp.getName());
            propertyExpression.getProperty().setSourcePosition(exp);
            return propertyExpression;
        }
        if (vexp.isThisExpression()) {
            VariableExpression variableExpression = varX(weaved);
            variableExpression.setSourcePosition(exp);
            return variableExpression;
        }
        if (vexp.isSuperExpression()) {
            throwSuperError(vexp);
        }
    } else if (exp instanceof PropertyExpression) {
        PropertyExpression pexp = (PropertyExpression) exp;
        String obj = pexp.getObjectExpression().getText();
        if (pexp.isImplicitThis() || "this".equals(obj)) {
            String propName = pexp.getPropertyAsString();
            if (knownFields.contains(propName)) {
                FieldNode fn = new FieldNode(propName, 0, ClassHelper.OBJECT_TYPE, weavedType, null);
                return transformFieldReference(exp, fn, false);
            }
        }
    } else if (exp instanceof ClosureExpression) {
        MethodCallExpression mce = callX(exp, "rehydrate", args(varX(weaved), varX(weaved), varX(weaved)));
        mce.setImplicitThis(false);
        mce.setSourcePosition(exp);
        boolean oldInClosure = inClosure;
        inClosure = true;
        ((ClosureExpression) exp).getCode().visit(this);
        inClosure = oldInClosure;
        // The rewrite we do is causing some troubles with type checking, which will
        // not be able to perform closure parameter type inference
        // so we store the replacement, which will be done *after* type checking.
        exp.putNodeMetaData(TraitASTTransformation.POST_TYPECHECKING_REPLACEMENT, mce);
        return exp;
    }
    // TODO: unary expressions (field++, field+=, ...)
    return super.transform(exp);
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) Variable(org.codehaus.groovy.ast.Variable) DynamicVariable(org.codehaus.groovy.ast.DynamicVariable) FieldNode(org.codehaus.groovy.ast.FieldNode) StaticMethodCallExpression(org.codehaus.groovy.ast.expr.StaticMethodCallExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) FieldExpression(org.codehaus.groovy.ast.expr.FieldExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) StaticMethodCallExpression(org.codehaus.groovy.ast.expr.StaticMethodCallExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) DynamicVariable(org.codehaus.groovy.ast.DynamicVariable) PropertyNode(org.codehaus.groovy.ast.PropertyNode) PropertyExpression(org.codehaus.groovy.ast.expr.PropertyExpression) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression)

Example 28 with StaticMethodCallExpression

use of org.codehaus.groovy.ast.expr.StaticMethodCallExpression 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 29 with StaticMethodCallExpression

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

the class StaticMethodCallExpressionTransformer method transformStaticMethodCallExpression.

Expression transformStaticMethodCallExpression(final StaticMethodCallExpression orig) {
    MethodNode target = (MethodNode) orig.getNodeMetaData(StaticTypesMarker.DIRECT_METHOD_CALL_TARGET);
    if (target != null) {
        MethodCallExpression call = new MethodCallExpression(new ClassExpression(orig.getOwnerType()), orig.getMethod(), orig.getArguments());
        call.setMethodTarget(target);
        call.setSourcePosition(orig);
        call.copyNodeMetaData(orig);
        return transformer.transform(call);
    }
    return transformer.superTransform(orig);
}
Also used : MethodNode(org.codehaus.groovy.ast.MethodNode) StaticMethodCallExpression(org.codehaus.groovy.ast.expr.StaticMethodCallExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression)

Example 30 with StaticMethodCallExpression

use of org.codehaus.groovy.ast.expr.StaticMethodCallExpression in project gradle by gradle.

the class ExpressionReplacingVisitorSupport method visitStaticMethodCallExpression.

@Override
public void visitStaticMethodCallExpression(StaticMethodCallExpression expr) {
    StaticMethodCallExpression result = new StaticMethodCallExpression(expr.getOwnerType(), expr.getMethod(), replaceExpr(expr.getArguments()));
    result.setType(expr.getType());
    result.setSourcePosition(expr);
    replaceVisitedExpressionWith(result);
}
Also used : StaticMethodCallExpression(org.codehaus.groovy.ast.expr.StaticMethodCallExpression)

Aggregations

StaticMethodCallExpression (org.codehaus.groovy.ast.expr.StaticMethodCallExpression)30 MethodCallExpression (org.codehaus.groovy.ast.expr.MethodCallExpression)20 VariableExpression (org.codehaus.groovy.ast.expr.VariableExpression)20 ConstantExpression (org.codehaus.groovy.ast.expr.ConstantExpression)19 ArgumentListExpression (org.codehaus.groovy.ast.expr.ArgumentListExpression)18 ClassExpression (org.codehaus.groovy.ast.expr.ClassExpression)15 Expression (org.codehaus.groovy.ast.expr.Expression)15 BlockStatement (org.codehaus.groovy.ast.stmt.BlockStatement)13 Statement (org.codehaus.groovy.ast.stmt.Statement)13 MethodNode (org.codehaus.groovy.ast.MethodNode)12 ExpressionStatement (org.codehaus.groovy.ast.stmt.ExpressionStatement)12 BinaryExpression (org.codehaus.groovy.ast.expr.BinaryExpression)11 ConstructorCallExpression (org.codehaus.groovy.ast.expr.ConstructorCallExpression)11 ClassNode (org.codehaus.groovy.ast.ClassNode)10 Parameter (org.codehaus.groovy.ast.Parameter)10 ReturnStatement (org.codehaus.groovy.ast.stmt.ReturnStatement)10 CastExpression (org.codehaus.groovy.ast.expr.CastExpression)7 MapExpression (org.codehaus.groovy.ast.expr.MapExpression)7 PropertyExpression (org.codehaus.groovy.ast.expr.PropertyExpression)7 FieldNode (org.codehaus.groovy.ast.FieldNode)6