Search in sources :

Example 16 with BlockStatement

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

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 : BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) Statement(org.codehaus.groovy.ast.stmt.Statement) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) ReturnStatement(org.codehaus.groovy.ast.stmt.ReturnStatement) ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) ArrayList(java.util.ArrayList) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) HashSet(java.util.HashSet)

Example 17 with BlockStatement

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

the class InnerClassCompletionVisitor method addThisReference.

private void addThisReference(ConstructorNode node) {
    if (!shouldHandleImplicitThisForInnerClass(classNode))
        return;
    Statement code = node.getCode();
    // add "this$0" field init
    //add this parameter to node
    Parameter[] params = node.getParameters();
    Parameter[] newParams = new Parameter[params.length + 1];
    System.arraycopy(params, 0, newParams, 1, params.length);
    String name = getUniqueName(params, node);
    Parameter thisPara = new Parameter(classNode.getOuterClass().getPlainNodeReference(), name);
    newParams[0] = thisPara;
    node.setParameters(newParams);
    BlockStatement block = null;
    if (code == null) {
        block = new BlockStatement();
    } else if (!(code instanceof BlockStatement)) {
        block = new BlockStatement();
        block.addStatement(code);
    } else {
        block = (BlockStatement) code;
    }
    BlockStatement newCode = new BlockStatement();
    addFieldInit(thisPara, thisField, newCode);
    ConstructorCallExpression cce = getFirstIfSpecialConstructorCall(block);
    if (cce == null) {
        cce = new ConstructorCallExpression(ClassNode.SUPER, new TupleExpression());
        block.getStatements().add(0, new ExpressionStatement(cce));
    }
    if (shouldImplicitlyPassThisPara(cce)) {
        // add thisPara to this(...)
        TupleExpression args = (TupleExpression) cce.getArguments();
        List<Expression> expressions = args.getExpressions();
        VariableExpression ve = new VariableExpression(thisPara.getName());
        ve.setAccessedVariable(thisPara);
        expressions.add(0, ve);
    }
    if (cce.isSuperCall()) {
        // we have a call to super here, so we need to add
        // our code after that
        block.getStatements().add(1, newCode);
    }
    node.setCode(block);
}
Also used : ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) Expression(org.codehaus.groovy.ast.expr.Expression) Statement(org.codehaus.groovy.ast.stmt.Statement) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) Parameter(org.codehaus.groovy.ast.Parameter) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression)

Example 18 with BlockStatement

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

the class InnerClassCompletionVisitor method getFirstIfSpecialConstructorCall.

private static ConstructorCallExpression getFirstIfSpecialConstructorCall(BlockStatement code) {
    if (code == null)
        return null;
    final List<Statement> statementList = code.getStatements();
    if (statementList.isEmpty())
        return null;
    final Statement statement = statementList.get(0);
    if (!(statement instanceof ExpressionStatement))
        return null;
    Expression expression = ((ExpressionStatement) statement).getExpression();
    if (!(expression instanceof ConstructorCallExpression))
        return null;
    ConstructorCallExpression cce = (ConstructorCallExpression) expression;
    if (cce.isSpecialCall())
        return cce;
    return null;
}
Also used : ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) Expression(org.codehaus.groovy.ast.expr.Expression) Statement(org.codehaus.groovy.ast.stmt.Statement) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement)

Example 19 with BlockStatement

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

the class InnerClassCompletionVisitor method addDispatcherMethods.

private static void addDispatcherMethods(ClassNode classNode) {
    final int objectDistance = getObjectDistance(classNode);
    // since we added an anonymous inner class we should also
    // add the dispatcher methods
    // add method dispatcher
    Parameter[] parameters = new Parameter[] { new Parameter(ClassHelper.STRING_TYPE, "name"), new Parameter(ClassHelper.OBJECT_TYPE, "args") };
    MethodNode method = classNode.addSyntheticMethod("this$dist$invoke$" + objectDistance, ACC_PUBLIC + ACC_SYNTHETIC, ClassHelper.OBJECT_TYPE, parameters, ClassNode.EMPTY_ARRAY, null);
    BlockStatement block = new BlockStatement();
    setMethodDispatcherCode(block, VariableExpression.THIS_EXPRESSION, parameters);
    method.setCode(block);
    // add property setter
    parameters = new Parameter[] { new Parameter(ClassHelper.STRING_TYPE, "name"), new Parameter(ClassHelper.OBJECT_TYPE, "value") };
    method = classNode.addSyntheticMethod("this$dist$set$" + objectDistance, ACC_PUBLIC + ACC_SYNTHETIC, ClassHelper.VOID_TYPE, parameters, ClassNode.EMPTY_ARRAY, null);
    block = new BlockStatement();
    setPropertySetterDispatcher(block, VariableExpression.THIS_EXPRESSION, parameters);
    method.setCode(block);
    // add property getter
    parameters = new Parameter[] { new Parameter(ClassHelper.STRING_TYPE, "name") };
    method = classNode.addSyntheticMethod("this$dist$get$" + objectDistance, ACC_PUBLIC + ACC_SYNTHETIC, ClassHelper.OBJECT_TYPE, parameters, ClassNode.EMPTY_ARRAY, null);
    block = new BlockStatement();
    setPropertyGetterDispatcher(block, VariableExpression.THIS_EXPRESSION, parameters);
    method.setCode(block);
}
Also used : MethodNode(org.codehaus.groovy.ast.MethodNode) Parameter(org.codehaus.groovy.ast.Parameter) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement)

Example 20 with BlockStatement

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

the class InnerClassCompletionVisitor method addDefaultMethods.

private void addDefaultMethods(InnerClassNode node) {
    final boolean isStatic = isStatic(node);
    ClassNode outerClass = node.getOuterClass();
    final String classInternalName = org.codehaus.groovy.classgen.asm.BytecodeHelper.getClassInternalName(node);
    final String outerClassInternalName = getInternalName(outerClass, isStatic);
    final String outerClassDescriptor = getTypeDescriptor(outerClass, isStatic);
    final int objectDistance = getObjectDistance(outerClass);
    // add missing method dispatcher
    Parameter[] parameters = new Parameter[] { new Parameter(ClassHelper.STRING_TYPE, "name"), new Parameter(ClassHelper.OBJECT_TYPE, "args") };
    String methodName = "methodMissing";
    if (isStatic)
        addCompilationErrorOnCustomMethodNode(node, methodName, parameters);
    MethodNode method = node.addSyntheticMethod(methodName, Opcodes.ACC_PUBLIC, ClassHelper.OBJECT_TYPE, parameters, ClassNode.EMPTY_ARRAY, null);
    BlockStatement block = new BlockStatement();
    if (isStatic) {
        setMethodDispatcherCode(block, new ClassExpression(outerClass), parameters);
    } else {
        block.addStatement(new BytecodeSequence(new BytecodeInstruction() {

            public void visit(MethodVisitor mv) {
                getThis(mv, classInternalName, outerClassDescriptor, outerClassInternalName);
                mv.visitVarInsn(ALOAD, 1);
                mv.visitVarInsn(ALOAD, 2);
                mv.visitMethodInsn(INVOKEVIRTUAL, outerClassInternalName, "this$dist$invoke$" + objectDistance, "(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;", false);
                mv.visitInsn(ARETURN);
            }
        }));
    }
    method.setCode(block);
    // add static missing method dispatcher
    methodName = "$static_methodMissing";
    if (isStatic)
        addCompilationErrorOnCustomMethodNode(node, methodName, parameters);
    method = node.addSyntheticMethod(methodName, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, ClassHelper.OBJECT_TYPE, parameters, ClassNode.EMPTY_ARRAY, null);
    block = new BlockStatement();
    setMethodDispatcherCode(block, new ClassExpression(outerClass), parameters);
    method.setCode(block);
    // add property setter dispatcher
    parameters = new Parameter[] { new Parameter(ClassHelper.STRING_TYPE, "name"), new Parameter(ClassHelper.OBJECT_TYPE, "val") };
    methodName = "propertyMissing";
    if (isStatic)
        addCompilationErrorOnCustomMethodNode(node, methodName, parameters);
    method = node.addSyntheticMethod(methodName, Opcodes.ACC_PUBLIC, ClassHelper.VOID_TYPE, parameters, ClassNode.EMPTY_ARRAY, null);
    block = new BlockStatement();
    if (isStatic) {
        setPropertySetterDispatcher(block, new ClassExpression(outerClass), parameters);
    } else {
        block.addStatement(new BytecodeSequence(new BytecodeInstruction() {

            public void visit(MethodVisitor mv) {
                getThis(mv, classInternalName, outerClassDescriptor, outerClassInternalName);
                mv.visitVarInsn(ALOAD, 1);
                mv.visitVarInsn(ALOAD, 2);
                mv.visitMethodInsn(INVOKEVIRTUAL, outerClassInternalName, "this$dist$set$" + objectDistance, "(Ljava/lang/String;Ljava/lang/Object;)V", false);
                mv.visitInsn(RETURN);
            }
        }));
    }
    method.setCode(block);
    // add static property missing setter dispatcher
    methodName = "$static_propertyMissing";
    if (isStatic)
        addCompilationErrorOnCustomMethodNode(node, methodName, parameters);
    method = node.addSyntheticMethod(methodName, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, ClassHelper.VOID_TYPE, parameters, ClassNode.EMPTY_ARRAY, null);
    block = new BlockStatement();
    setPropertySetterDispatcher(block, new ClassExpression(outerClass), parameters);
    method.setCode(block);
    // add property getter dispatcher
    parameters = new Parameter[] { new Parameter(ClassHelper.STRING_TYPE, "name") };
    methodName = "propertyMissing";
    if (isStatic)
        addCompilationErrorOnCustomMethodNode(node, methodName, parameters);
    method = node.addSyntheticMethod(methodName, Opcodes.ACC_PUBLIC, ClassHelper.OBJECT_TYPE, parameters, ClassNode.EMPTY_ARRAY, null);
    block = new BlockStatement();
    if (isStatic) {
        setPropertyGetterDispatcher(block, new ClassExpression(outerClass), parameters);
    } else {
        block.addStatement(new BytecodeSequence(new BytecodeInstruction() {

            public void visit(MethodVisitor mv) {
                getThis(mv, classInternalName, outerClassDescriptor, outerClassInternalName);
                mv.visitVarInsn(ALOAD, 1);
                mv.visitMethodInsn(INVOKEVIRTUAL, outerClassInternalName, "this$dist$get$" + objectDistance, "(Ljava/lang/String;)Ljava/lang/Object;", false);
                mv.visitInsn(ARETURN);
            }
        }));
    }
    method.setCode(block);
    // add static property missing getter dispatcher
    methodName = "$static_propertyMissing";
    if (isStatic)
        addCompilationErrorOnCustomMethodNode(node, methodName, parameters);
    method = node.addSyntheticMethod(methodName, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, ClassHelper.OBJECT_TYPE, parameters, ClassNode.EMPTY_ARRAY, null);
    block = new BlockStatement();
    setPropertyGetterDispatcher(block, new ClassExpression(outerClass), parameters);
    method.setCode(block);
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) MethodNode(org.codehaus.groovy.ast.MethodNode) Parameter(org.codehaus.groovy.ast.Parameter) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) MethodVisitor(org.objectweb.asm.MethodVisitor)

Aggregations

BlockStatement (org.codehaus.groovy.ast.stmt.BlockStatement)200 ExpressionStatement (org.codehaus.groovy.ast.stmt.ExpressionStatement)86 Statement (org.codehaus.groovy.ast.stmt.Statement)82 Expression (org.codehaus.groovy.ast.expr.Expression)73 VariableExpression (org.codehaus.groovy.ast.expr.VariableExpression)65 MethodNode (org.codehaus.groovy.ast.MethodNode)55 ConstantExpression (org.codehaus.groovy.ast.expr.ConstantExpression)52 ClassNode (org.codehaus.groovy.ast.ClassNode)51 Parameter (org.codehaus.groovy.ast.Parameter)50 MethodCallExpression (org.codehaus.groovy.ast.expr.MethodCallExpression)45 ReturnStatement (org.codehaus.groovy.ast.stmt.ReturnStatement)41 ClassExpression (org.codehaus.groovy.ast.expr.ClassExpression)40 ConstructorCallExpression (org.codehaus.groovy.ast.expr.ConstructorCallExpression)38 FieldNode (org.codehaus.groovy.ast.FieldNode)37 ClosureExpression (org.codehaus.groovy.ast.expr.ClosureExpression)35 ArgumentListExpression (org.codehaus.groovy.ast.expr.ArgumentListExpression)33 ArrayList (java.util.ArrayList)31 EmptyStatement (org.codehaus.groovy.ast.stmt.EmptyStatement)27 IfStatement (org.codehaus.groovy.ast.stmt.IfStatement)27 BinaryExpression (org.codehaus.groovy.ast.expr.BinaryExpression)25