Search in sources :

Example 91 with BlockStatement

use of org.codehaus.groovy.ast.stmt.BlockStatement in project groovy-core by groovy.

the class MemoizedASTTransformation method visit.

public void visit(ASTNode[] nodes, final SourceUnit source) {
    init(nodes, source);
    AnnotationNode annotationNode = (AnnotationNode) nodes[0];
    AnnotatedNode annotatedNode = (AnnotatedNode) nodes[1];
    if (MY_TYPE.equals(annotationNode.getClassNode()) && annotatedNode instanceof MethodNode) {
        MethodNode methodNode = (MethodNode) annotatedNode;
        if (methodNode.isAbstract()) {
            addError("Annotation " + MY_TYPE_NAME + " cannot be used for abstract methods.", methodNode);
            return;
        }
        if (methodNode.isVoidMethod()) {
            addError("Annotation " + MY_TYPE_NAME + " cannot be used for void methods.", methodNode);
            return;
        }
        ClassNode ownerClassNode = methodNode.getDeclaringClass();
        MethodNode delegatingMethod = buildDelegatingMethod(methodNode, ownerClassNode);
        ownerClassNode.addMethod(delegatingMethod);
        int modifiers = FieldNode.ACC_PRIVATE | FieldNode.ACC_FINAL;
        if (methodNode.isStatic()) {
            modifiers = modifiers | FieldNode.ACC_STATIC;
        }
        int protectedCacheSize = getMemberIntValue(annotationNode, PROTECTED_CACHE_SIZE_NAME);
        int maxCacheSize = getMemberIntValue(annotationNode, MAX_CACHE_SIZE_NAME);
        MethodCallExpression memoizeClosureCallExpression = buildMemoizeClosureCallExpression(delegatingMethod, protectedCacheSize, maxCacheSize);
        String memoizedClosureFieldName = buildUniqueName(ownerClassNode, CLOSURE_LABEL, methodNode);
        FieldNode memoizedClosureField = new FieldNode(memoizedClosureFieldName, modifiers, newClass(ClassHelper.CLOSURE_TYPE), null, memoizeClosureCallExpression);
        ownerClassNode.addField(memoizedClosureField);
        BlockStatement newCode = new BlockStatement();
        MethodCallExpression closureCallExpression = callX(fieldX(memoizedClosureField), CLOSURE_CALL_METHOD_NAME, args(methodNode.getParameters()));
        closureCallExpression.setImplicitThis(false);
        newCode.addStatement(returnS(closureCallExpression));
        methodNode.setCode(newCode);
        VariableScopeVisitor visitor = new VariableScopeVisitor(source);
        visitor.visitClass(ownerClassNode);
    }
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) MethodNode(org.codehaus.groovy.ast.MethodNode) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) FieldNode(org.codehaus.groovy.ast.FieldNode) AnnotationNode(org.codehaus.groovy.ast.AnnotationNode) AnnotatedNode(org.codehaus.groovy.ast.AnnotatedNode) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) VariableScopeVisitor(org.codehaus.groovy.classgen.VariableScopeVisitor)

Example 92 with BlockStatement

use of org.codehaus.groovy.ast.stmt.BlockStatement in project groovy-core by groovy.

the class SingletonASTTransformation method createConstructor.

private void createConstructor(ClassNode classNode, FieldNode field, String propertyName, boolean isStrict) {
    final List<ConstructorNode> cNodes = classNode.getDeclaredConstructors();
    ConstructorNode foundNoArg = null;
    for (ConstructorNode cNode : cNodes) {
        final Parameter[] parameters = cNode.getParameters();
        if (parameters == null || parameters.length == 0) {
            foundNoArg = cNode;
            break;
        }
    }
    if (isStrict && cNodes.size() != 0) {
        for (ConstructorNode cNode : cNodes) {
            addError("@Singleton didn't expect to find one or more additional constructors: remove constructor(s) or set strict=false", cNode);
        }
    }
    if (foundNoArg == null) {
        final BlockStatement body = new BlockStatement();
        body.addStatement(ifS(notNullX(varX(field)), new ThrowStatement(ctorX(make(RuntimeException.class), args(constX("Can't instantiate singleton " + classNode.getName() + ". Use " + classNode.getName() + "." + propertyName))))));
        classNode.addConstructor(new ConstructorNode(ACC_PRIVATE, body));
    }
}
Also used : ConstructorNode(org.codehaus.groovy.ast.ConstructorNode) Parameter(org.codehaus.groovy.ast.Parameter) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) ThrowStatement(org.codehaus.groovy.ast.stmt.ThrowStatement)

Example 93 with BlockStatement

use of org.codehaus.groovy.ast.stmt.BlockStatement in project groovy-core by groovy.

the class Verifier method addDefaultConstructor.

protected void addDefaultConstructor(ClassNode node) {
    if (!node.getDeclaredConstructors().isEmpty())
        return;
    BlockStatement empty = new BlockStatement();
    empty.setSourcePosition(node);
    ConstructorNode constructor = new ConstructorNode(ACC_PUBLIC, empty);
    constructor.setSourcePosition(node);
    constructor.setHasNoRealSourcePosition(true);
    node.addConstructor(constructor);
}
Also used : BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement)

Example 94 with BlockStatement

use of org.codehaus.groovy.ast.stmt.BlockStatement in project groovy-core by groovy.

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());
        }
    });
}
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) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) 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) DeclarationExpression(org.codehaus.groovy.ast.expr.DeclarationExpression) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) FieldExpression(org.codehaus.groovy.ast.expr.FieldExpression) CastExpression(org.codehaus.groovy.ast.expr.CastExpression) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) ReturnStatement(org.codehaus.groovy.ast.stmt.ReturnStatement) ArrayList(java.util.ArrayList) List(java.util.List) CastExpression(org.codehaus.groovy.ast.expr.CastExpression) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression) RuntimeParserException(org.codehaus.groovy.syntax.RuntimeParserException)

Example 95 with BlockStatement

use of org.codehaus.groovy.ast.stmt.BlockStatement in project groovy-core by groovy.

the class Verifier method addInitialization.

protected void addInitialization(ClassNode node, ConstructorNode constructorNode) {
    Statement firstStatement = constructorNode.getFirstStatement();
    // if some transformation decided to generate constructor then it probably knows who it does
    if (firstStatement instanceof BytecodeSequence)
        return;
    ConstructorCallExpression first = getFirstIfSpecialConstructorCall(firstStatement);
    // in case of this(...) let the other constructor do the init
    if (first != null && (first.isThisCall()))
        return;
    List<Statement> statements = new ArrayList<Statement>();
    List<Statement> staticStatements = new ArrayList<Statement>();
    final boolean isEnum = node.isEnum();
    List<Statement> initStmtsAfterEnumValuesInit = new ArrayList<Statement>();
    Set<String> explicitStaticPropsInEnum = new HashSet<String>();
    if (isEnum) {
        for (PropertyNode propNode : node.getProperties()) {
            if (!propNode.isSynthetic() && propNode.getField().isStatic()) {
                explicitStaticPropsInEnum.add(propNode.getField().getName());
            }
        }
        for (FieldNode fieldNode : node.getFields()) {
            if (!fieldNode.isSynthetic() && fieldNode.isStatic() && fieldNode.getType() != node) {
                explicitStaticPropsInEnum.add(fieldNode.getName());
            }
        }
    }
    if (!Traits.isTrait(node)) {
        for (FieldNode fn : node.getFields()) {
            addFieldInitialization(statements, staticStatements, fn, isEnum, initStmtsAfterEnumValuesInit, explicitStaticPropsInEnum);
        }
    }
    statements.addAll(node.getObjectInitializerStatements());
    Statement code = constructorNode.getCode();
    BlockStatement block = new BlockStatement();
    List<Statement> otherStatements = block.getStatements();
    if (code instanceof BlockStatement) {
        block = (BlockStatement) code;
        otherStatements = block.getStatements();
    } else if (code != null) {
        otherStatements.add(code);
    }
    if (!otherStatements.isEmpty()) {
        if (first != null) {
            // it is super(..) since this(..) is already covered
            otherStatements.remove(0);
            statements.add(0, firstStatement);
        }
        Statement stmtThis$0 = getImplicitThis$0StmtIfInnerClass(otherStatements);
        if (stmtThis$0 != null) {
            // since there can be field init statements that depend on method/property dispatching
            // that uses this$0, it needs to bubble up before the super call itself (GROOVY-4471)
            statements.add(0, stmtThis$0);
        }
        statements.addAll(otherStatements);
    }
    BlockStatement newBlock = new BlockStatement(statements, block.getVariableScope());
    newBlock.setSourcePosition(block);
    constructorNode.setCode(newBlock);
    if (!staticStatements.isEmpty()) {
        if (isEnum) {
            /*
                 * GROOVY-3161: initialize statements for explicitly declared static fields
                 * inside an enum should come after enum values are initialized
                 */
            staticStatements.removeAll(initStmtsAfterEnumValuesInit);
            node.addStaticInitializerStatements(staticStatements, true);
            if (!initStmtsAfterEnumValuesInit.isEmpty()) {
                node.positionStmtsAfterEnumInitStmts(initStmtsAfterEnumValuesInit);
            }
        } else {
            node.addStaticInitializerStatements(staticStatements, true);
        }
    }
}
Also used : Statement(org.codehaus.groovy.ast.stmt.Statement) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) ReturnStatement(org.codehaus.groovy.ast.stmt.ReturnStatement) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) ArrayList(java.util.ArrayList) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) HashSet(java.util.HashSet)

Aggregations

BlockStatement (org.codehaus.groovy.ast.stmt.BlockStatement)212 ExpressionStatement (org.codehaus.groovy.ast.stmt.ExpressionStatement)94 Statement (org.codehaus.groovy.ast.stmt.Statement)87 VariableExpression (org.codehaus.groovy.ast.expr.VariableExpression)76 Expression (org.codehaus.groovy.ast.expr.Expression)75 MethodNode (org.codehaus.groovy.ast.MethodNode)64 ConstantExpression (org.codehaus.groovy.ast.expr.ConstantExpression)62 Parameter (org.codehaus.groovy.ast.Parameter)58 ClassNode (org.codehaus.groovy.ast.ClassNode)54 MethodCallExpression (org.codehaus.groovy.ast.expr.MethodCallExpression)52 ReturnStatement (org.codehaus.groovy.ast.stmt.ReturnStatement)51 ClassExpression (org.codehaus.groovy.ast.expr.ClassExpression)45 ConstructorCallExpression (org.codehaus.groovy.ast.expr.ConstructorCallExpression)45 ArgumentListExpression (org.codehaus.groovy.ast.expr.ArgumentListExpression)44 FieldNode (org.codehaus.groovy.ast.FieldNode)38 ClosureExpression (org.codehaus.groovy.ast.expr.ClosureExpression)37 EmptyStatement (org.codehaus.groovy.ast.stmt.EmptyStatement)33 IfStatement (org.codehaus.groovy.ast.stmt.IfStatement)33 ArrayList (java.util.ArrayList)32 BinaryExpression (org.codehaus.groovy.ast.expr.BinaryExpression)28