Search in sources :

Example 36 with ClosureExpression

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

the class MacroInvocationTrap method handleTargetMethodCallExpression.

@Override
protected boolean handleTargetMethodCallExpression(MethodCallExpression macroCall) {
    final ClosureExpression closureExpression = getClosureArgument(macroCall);
    if (closureExpression == null) {
        return true;
    }
    if (closureExpression.getParameters() != null && closureExpression.getParameters().length > 0) {
        addError("Macro closure arguments are not allowed", closureExpression);
        return true;
    }
    final MapExpression mapExpression = buildSubstitutionMap(closureExpression);
    String source = convertClosureToSource(closureExpression);
    BlockStatement closureBlock = (BlockStatement) closureExpression.getCode();
    Boolean asIs = false;
    TupleExpression macroArguments = getMacroArguments(macroCall);
    if (macroArguments == null) {
        return true;
    }
    List<Expression> macroArgumentsExpressions = macroArguments.getExpressions();
    if (macroArgumentsExpressions.size() == 2 || macroArgumentsExpressions.size() == 3) {
        Expression asIsArgumentExpression = macroArgumentsExpressions.get(macroArgumentsExpressions.size() - 2);
        if ((asIsArgumentExpression instanceof ConstantExpression)) {
            ConstantExpression asIsConstantExpression = (ConstantExpression) asIsArgumentExpression;
            if (!(asIsConstantExpression.getValue() instanceof Boolean)) {
                addError("AsIs argument value should be boolean", asIsConstantExpression);
                return true;
            }
            asIs = (Boolean) asIsConstantExpression.getValue();
        }
    }
    macroArgumentsExpressions.remove(macroArgumentsExpressions.size() - 1);
    macroArgumentsExpressions.add(new ConstantExpression(source));
    macroArgumentsExpressions.add(mapExpression);
    macroArgumentsExpressions.add(new ClassExpression(ClassHelper.makeWithoutCaching(MacroBuilder.getMacroValue(closureBlock, asIs).getClass(), false)));
    macroCall.setObjectExpression(new PropertyExpression(new ClassExpression(ClassHelper.makeWithoutCaching(MacroBuilder.class, false)), "INSTANCE"));
    macroCall.setSpreadSafe(false);
    macroCall.setSafe(false);
    macroCall.setImplicitThis(false);
    return true;
}
Also used : MapExpression(org.codehaus.groovy.ast.expr.MapExpression) MapExpression(org.codehaus.groovy.ast.expr.MapExpression) PropertyExpression(org.codehaus.groovy.ast.expr.PropertyExpression) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) Expression(org.codehaus.groovy.ast.expr.Expression) ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) PropertyExpression(org.codehaus.groovy.ast.expr.PropertyExpression) MacroBuilder(org.codehaus.groovy.macro.runtime.MacroBuilder) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression)

Example 37 with ClosureExpression

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

the class MacroInvocationTrap method getClosureArgument.

protected ClosureExpression getClosureArgument(MethodCallExpression call) {
    TupleExpression tupleArguments = getMacroArguments(call);
    if (tupleArguments.getExpressions().size() < 1) {
        addError("Call arguments should have at least one argument", tupleArguments);
        return null;
    }
    Expression result = tupleArguments.getExpression(tupleArguments.getExpressions().size() - 1);
    if (!(result instanceof ClosureExpression)) {
        addError("Last call argument should be a closure", result);
        return null;
    }
    return (ClosureExpression) result;
}
Also used : MapExpression(org.codehaus.groovy.ast.expr.MapExpression) PropertyExpression(org.codehaus.groovy.ast.expr.PropertyExpression) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) Expression(org.codehaus.groovy.ast.expr.Expression) ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression)

Example 38 with ClosureExpression

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

the class MacroInvocationTrap method buildSubstitutionMap.

private MapExpression buildSubstitutionMap(final ASTNode expr) {
    final Map<MacroSubstitutionKey, ClosureExpression> map = new HashMap<MacroSubstitutionKey, ClosureExpression>();
    final MapExpression mapExpression = new MapExpression();
    ClassCodeVisitorSupport visitor = new ClassCodeVisitorSupport() {

        @Override
        protected SourceUnit getSourceUnit() {
            return null;
        }

        @Override
        public void visitClass(final ClassNode node) {
            super.visitClass(node);
            Iterator<InnerClassNode> it = node.getInnerClasses();
            while (it.hasNext()) {
                InnerClassNode next = it.next();
                visitClass(next);
            }
        }

        @Override
        public void visitMethodCallExpression(MethodCallExpression call) {
            super.visitMethodCallExpression(call);
            if (isBuildInvocation(call, MacroTransformation.DOLLAR_VALUE)) {
                ClosureExpression substitutionClosureExpression = getClosureArgument(call);
                if (substitutionClosureExpression == null) {
                    return;
                }
                Statement code = substitutionClosureExpression.getCode();
                if (code instanceof BlockStatement) {
                    ((BlockStatement) code).setVariableScope(null);
                }
                MacroSubstitutionKey key = new MacroSubstitutionKey(call, expr.getLineNumber(), expr.getColumnNumber());
                map.put(key, substitutionClosureExpression);
            }
        }
    };
    if (expr instanceof ClassNode) {
        visitor.visitClass((ClassNode) expr);
    } else {
        expr.visit(visitor);
    }
    for (Map.Entry<MacroSubstitutionKey, ClosureExpression> entry : map.entrySet()) {
        mapExpression.addMapEntryExpression(entry.getKey().toConstructorCallExpression(), entry.getValue());
    }
    return mapExpression;
}
Also used : MapExpression(org.codehaus.groovy.ast.expr.MapExpression) ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) HashMap(java.util.HashMap) Statement(org.codehaus.groovy.ast.stmt.Statement) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) MacroSubstitutionKey(org.codehaus.groovy.macro.runtime.MacroSubstitutionKey) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) ClassCodeVisitorSupport(org.codehaus.groovy.ast.ClassCodeVisitorSupport) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression) HashMap(java.util.HashMap) Map(java.util.Map)

Example 39 with ClosureExpression

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

the class Verifier method addDefaultParameterMethods.

/**
     * Creates a new helper method for each combination of default parameter expressions
     */
protected void addDefaultParameterMethods(final ClassNode node) {
    List methods = new ArrayList(node.getMethods());
    addDefaultParameters(methods, new DefaultArgsAction() {

        public void call(ArgumentListExpression arguments, Parameter[] newParams, MethodNode method) {
            final BlockStatement code = new BlockStatement();
            MethodNode newMethod = new MethodNode(method.getName(), method.getModifiers(), method.getReturnType(), newParams, method.getExceptions(), code);
            // GROOVY-5681 and GROOVY-5632
            for (Expression argument : arguments.getExpressions()) {
                if (argument instanceof CastExpression) {
                    argument = ((CastExpression) argument).getExpression();
                }
                if (argument instanceof ConstructorCallExpression) {
                    ClassNode type = argument.getType();
                    if (type instanceof InnerClassNode && ((InnerClassNode) type).isAnonymous()) {
                        type.setEnclosingMethod(newMethod);
                    }
                }
                // check whether closure shared variables refer to params with default values (GROOVY-5632)
                if (argument instanceof ClosureExpression) {
                    final List<Parameter> newMethodNodeParameters = Arrays.asList(newParams);
                    CodeVisitorSupport visitor = new CodeVisitorSupport() {

                        @Override
                        public void visitVariableExpression(VariableExpression expression) {
                            Variable v = expression.getAccessedVariable();
                            if (!(v instanceof Parameter))
                                return;
                            Parameter param = (Parameter) v;
                            if (param.hasInitialExpression() && code.getVariableScope().getDeclaredVariable(param.getName()) == null && !newMethodNodeParameters.contains(param)) {
                                VariableExpression localVariable = new VariableExpression(param.getName(), ClassHelper.makeReference());
                                DeclarationExpression declarationExpression = new DeclarationExpression(localVariable, Token.newSymbol(Types.EQUAL, -1, -1), new ConstructorCallExpression(ClassHelper.makeReference(), param.getInitialExpression()));
                                code.addStatement(new ExpressionStatement(declarationExpression));
                                code.getVariableScope().putDeclaredVariable(localVariable);
                            }
                        }
                    };
                    visitor.visitClosureExpression((ClosureExpression) argument);
                }
            }
            MethodCallExpression expression = new MethodCallExpression(VariableExpression.THIS_EXPRESSION, method.getName(), arguments);
            expression.setMethodTarget(method);
            expression.setImplicitThis(true);
            if (method.isVoidMethod()) {
                code.addStatement(new ExpressionStatement(expression));
            } else {
                code.addStatement(new ReturnStatement(expression));
            }
            List<AnnotationNode> annotations = method.getAnnotations();
            if (annotations != null) {
                newMethod.addAnnotations(annotations);
            }
            MethodNode oldMethod = node.getDeclaredMethod(method.getName(), newParams);
            if (oldMethod != null) {
                throw new RuntimeParserException("The method with default parameters \"" + method.getTypeDescriptor() + "\" defines a method \"" + newMethod.getTypeDescriptor() + "\" that is already defined.", method);
            }
            addPropertyMethod(newMethod);
            newMethod.setGenericsTypes(method.getGenericsTypes());
            newMethod.putNodeMetaData(DEFAULT_PARAMETER_GENERATED, true);
        }
    });
}
Also used : ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) DeclarationExpression(org.codehaus.groovy.ast.expr.DeclarationExpression) ArrayList(java.util.ArrayList) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) FieldExpression(org.codehaus.groovy.ast.expr.FieldExpression) CastExpression(org.codehaus.groovy.ast.expr.CastExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) Expression(org.codehaus.groovy.ast.expr.Expression) ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) DeclarationExpression(org.codehaus.groovy.ast.expr.DeclarationExpression) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) ReturnStatement(org.codehaus.groovy.ast.stmt.ReturnStatement) List(java.util.List) ArrayList(java.util.ArrayList) CastExpression(org.codehaus.groovy.ast.expr.CastExpression) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression) RuntimeParserException(org.codehaus.groovy.syntax.RuntimeParserException)

Example 40 with ClosureExpression

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

the class AnnotationVisitor method visitExpression.

protected void visitExpression(String attrName, Expression attrExp, ClassNode attrType) {
    if (attrType.isArray()) {
        // check needed as @Test(attr = {"elem"}) passes through the parser
        if (attrExp instanceof ListExpression) {
            ListExpression le = (ListExpression) attrExp;
            visitListExpression(attrName, le, attrType.getComponentType());
        } else if (attrExp instanceof ClosureExpression) {
            addError("Annotation list attributes must use Groovy notation [el1, el2]", attrExp);
        } else {
            // treat like a singleton list as per Java
            ListExpression listExp = new ListExpression();
            listExp.addExpression(attrExp);
            if (annotation != null) {
                annotation.setMember(attrName, listExp);
            }
            visitExpression(attrName, listExp, attrType);
        }
    } else if (ClassHelper.isPrimitiveType(attrType)) {
        visitConstantExpression(attrName, getConstantExpression(attrExp, attrType), ClassHelper.getWrapper(attrType));
    } else if (ClassHelper.STRING_TYPE.equals(attrType)) {
        visitConstantExpression(attrName, getConstantExpression(attrExp, attrType), ClassHelper.STRING_TYPE);
    } else if (ClassHelper.CLASS_Type.equals(attrType)) {
        if (!(attrExp instanceof ClassExpression || attrExp instanceof ClosureExpression)) {
            addError("Only classes and closures can be used for attribute '" + attrName + "'", attrExp);
        }
    } else if (attrType.isDerivedFrom(ClassHelper.Enum_Type)) {
        if (attrExp instanceof PropertyExpression) {
            visitEnumExpression(attrName, (PropertyExpression) attrExp, attrType);
        } else {
            addError("Expected enum value for attribute " + attrName, attrExp);
        }
    } else if (isValidAnnotationClass(attrType)) {
        if (attrExp instanceof AnnotationConstantExpression) {
            visitAnnotationExpression(attrName, (AnnotationConstantExpression) attrExp, attrType);
        } else {
            addError("Expected annotation of type '" + attrType.getName() + "' for attribute " + attrName, attrExp);
        }
    } else {
        addError("Unexpected type " + attrType.getName(), attrExp);
    }
}
Also used : AnnotationConstantExpression(org.codehaus.groovy.ast.expr.AnnotationConstantExpression) ListExpression(org.codehaus.groovy.ast.expr.ListExpression) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) PropertyExpression(org.codehaus.groovy.ast.expr.PropertyExpression) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression)

Aggregations

ClosureExpression (org.codehaus.groovy.ast.expr.ClosureExpression)53 Expression (org.codehaus.groovy.ast.expr.Expression)40 MethodCallExpression (org.codehaus.groovy.ast.expr.MethodCallExpression)35 VariableExpression (org.codehaus.groovy.ast.expr.VariableExpression)35 ConstantExpression (org.codehaus.groovy.ast.expr.ConstantExpression)32 ArgumentListExpression (org.codehaus.groovy.ast.expr.ArgumentListExpression)28 ClassExpression (org.codehaus.groovy.ast.expr.ClassExpression)23 BlockStatement (org.codehaus.groovy.ast.stmt.BlockStatement)20 ClassNode (org.codehaus.groovy.ast.ClassNode)19 PropertyExpression (org.codehaus.groovy.ast.expr.PropertyExpression)18 BinaryExpression (org.codehaus.groovy.ast.expr.BinaryExpression)17 ConstructorCallExpression (org.codehaus.groovy.ast.expr.ConstructorCallExpression)17 DeclarationExpression (org.codehaus.groovy.ast.expr.DeclarationExpression)17 Parameter (org.codehaus.groovy.ast.Parameter)16 TupleExpression (org.codehaus.groovy.ast.expr.TupleExpression)15 ExpressionStatement (org.codehaus.groovy.ast.stmt.ExpressionStatement)14 ListExpression (org.codehaus.groovy.ast.expr.ListExpression)11 FieldNode (org.codehaus.groovy.ast.FieldNode)10 MapExpression (org.codehaus.groovy.ast.expr.MapExpression)10 ArrayList (java.util.ArrayList)9