Search in sources :

Example 16 with Variable

use of org.codehaus.groovy.ast.Variable in project groovy by apache.

the class ClosureWriter method createClosureClass.

protected ClassNode createClosureClass(ClosureExpression expression, int mods) {
    ClassNode classNode = controller.getClassNode();
    ClassNode outerClass = controller.getOutermostClass();
    MethodNode methodNode = controller.getMethodNode();
    String name = classNode.getName() + "$" + // add a more informative name
    controller.getContext().getNextClosureInnerName(outerClass, classNode, methodNode);
    boolean staticMethodOrInStaticClass = controller.isStaticMethod() || classNode.isStaticClass();
    Parameter[] parameters = expression.getParameters();
    if (parameters == null) {
        parameters = Parameter.EMPTY_ARRAY;
    } else if (parameters.length == 0) {
        // let's create a default 'it' parameter
        Parameter it = new Parameter(ClassHelper.OBJECT_TYPE, "it", ConstantExpression.NULL);
        parameters = new Parameter[] { it };
        Variable ref = expression.getVariableScope().getDeclaredVariable("it");
        if (ref != null)
            it.setClosureSharedVariable(ref.isClosureSharedVariable());
    }
    Parameter[] localVariableParams = getClosureSharedVariables(expression);
    removeInitialValues(localVariableParams);
    InnerClassNode answer = new InnerClassNode(classNode, name, mods, ClassHelper.CLOSURE_TYPE.getPlainNodeReference());
    answer.setEnclosingMethod(controller.getMethodNode());
    answer.setSynthetic(true);
    answer.setUsingGenerics(outerClass.isUsingGenerics());
    answer.setSourcePosition(expression);
    if (staticMethodOrInStaticClass) {
        answer.setStaticClass(true);
    }
    if (controller.isInScriptBody()) {
        answer.setScriptBody(true);
    }
    MethodNode method = answer.addMethod("doCall", ACC_PUBLIC, ClassHelper.OBJECT_TYPE, parameters, ClassNode.EMPTY_ARRAY, expression.getCode());
    method.setSourcePosition(expression);
    VariableScope varScope = expression.getVariableScope();
    if (varScope == null) {
        throw new RuntimeException("Must have a VariableScope by now! for expression: " + expression + " class: " + name);
    } else {
        method.setVariableScope(varScope.copy());
    }
    if (parameters.length > 1 || (parameters.length == 1 && parameters[0].getType() != null && parameters[0].getType() != ClassHelper.OBJECT_TYPE && !ClassHelper.OBJECT_TYPE.equals(parameters[0].getType().getComponentType()))) {
        // let's add a typesafe call method
        MethodNode call = answer.addMethod("call", ACC_PUBLIC, ClassHelper.OBJECT_TYPE, parameters, ClassNode.EMPTY_ARRAY, new ReturnStatement(new MethodCallExpression(VariableExpression.THIS_EXPRESSION, "doCall", new ArgumentListExpression(parameters))));
        call.setSourcePosition(expression);
    }
    // let's make the constructor
    BlockStatement block = new BlockStatement();
    // this block does not get a source position, because we don't
    // want this synthetic constructor to show up in corbertura reports
    VariableExpression outer = new VariableExpression("_outerInstance");
    outer.setSourcePosition(expression);
    block.getVariableScope().putReferencedLocalVariable(outer);
    VariableExpression thisObject = new VariableExpression("_thisObject");
    thisObject.setSourcePosition(expression);
    block.getVariableScope().putReferencedLocalVariable(thisObject);
    TupleExpression conArgs = new TupleExpression(outer, thisObject);
    block.addStatement(new ExpressionStatement(new ConstructorCallExpression(ClassNode.SUPER, conArgs)));
    // let's assign all the parameter fields from the outer context
    for (Parameter param : localVariableParams) {
        String paramName = param.getName();
        ClassNode type = param.getType();
        if (true) {
            VariableExpression initialValue = new VariableExpression(paramName);
            initialValue.setAccessedVariable(param);
            initialValue.setUseReferenceDirectly(true);
            ClassNode realType = type;
            type = ClassHelper.makeReference();
            param.setType(ClassHelper.makeReference());
            FieldNode paramField = answer.addField(paramName, ACC_PRIVATE | ACC_SYNTHETIC, type, initialValue);
            paramField.setOriginType(ClassHelper.getWrapper(param.getOriginType()));
            paramField.setHolder(true);
            String methodName = Verifier.capitalize(paramName);
            // let's add a getter & setter
            Expression fieldExp = new FieldExpression(paramField);
            answer.addMethod("get" + methodName, ACC_PUBLIC, realType.getPlainNodeReference(), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, new ReturnStatement(fieldExp));
        }
    }
    Parameter[] params = new Parameter[2 + localVariableParams.length];
    params[0] = new Parameter(ClassHelper.OBJECT_TYPE, "_outerInstance");
    params[1] = new Parameter(ClassHelper.OBJECT_TYPE, "_thisObject");
    System.arraycopy(localVariableParams, 0, params, 2, localVariableParams.length);
    ASTNode sn = answer.addConstructor(ACC_PUBLIC, params, ClassNode.EMPTY_ARRAY, block);
    sn.setSourcePosition(expression);
    correctAccessedVariable(answer, expression);
    return answer;
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) Variable(org.codehaus.groovy.ast.Variable) FieldNode(org.codehaus.groovy.ast.FieldNode) ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) FieldExpression(org.codehaus.groovy.ast.expr.FieldExpression) MethodNode(org.codehaus.groovy.ast.MethodNode) 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) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) FieldExpression(org.codehaus.groovy.ast.expr.FieldExpression) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) ReturnStatement(org.codehaus.groovy.ast.stmt.ReturnStatement) ASTNode(org.codehaus.groovy.ast.ASTNode) Parameter(org.codehaus.groovy.ast.Parameter) VariableScope(org.codehaus.groovy.ast.VariableScope)

Example 17 with Variable

use of org.codehaus.groovy.ast.Variable in project groovy by apache.

the class ClosureWriter method correctAccessedVariable.

private static void correctAccessedVariable(final InnerClassNode closureClass, ClosureExpression ce) {
    CodeVisitorSupport visitor = new CodeVisitorSupport() {

        @Override
        public void visitVariableExpression(VariableExpression expression) {
            Variable v = expression.getAccessedVariable();
            if (v == null)
                return;
            if (!(v instanceof FieldNode))
                return;
            String name = expression.getName();
            FieldNode fn = closureClass.getDeclaredField(name);
            if (fn != null) {
                // only overwrite if we find something more specific
                expression.setAccessedVariable(fn);
            }
        }
    };
    visitor.visitClosureExpression(ce);
}
Also used : CodeVisitorSupport(org.codehaus.groovy.ast.CodeVisitorSupport) Variable(org.codehaus.groovy.ast.Variable) FieldNode(org.codehaus.groovy.ast.FieldNode) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression)

Example 18 with Variable

use of org.codehaus.groovy.ast.Variable in project groovy by apache.

the class FinalVariableAnalyzer method visitBinaryExpression.

@Override
public void visitBinaryExpression(final BinaryExpression expression) {
    boolean assignment = StaticTypeCheckingSupport.isAssignment(expression.getOperation().getType());
    boolean isDeclaration = expression instanceof DeclarationExpression;
    Expression leftExpression = expression.getLeftExpression();
    Expression rightExpression = expression.getRightExpression();
    if (isDeclaration && leftExpression instanceof VariableExpression) {
        VariableExpression var = (VariableExpression) leftExpression;
        if (Modifier.isFinal(var.getModifiers())) {
            declaredFinalVariables.add(var);
        }
    }
    leftExpression.visit(this);
    inAssignment = assignment;
    rightExpression.visit(this);
    inAssignment = false;
    if (assignment) {
        if (leftExpression instanceof Variable) {
            boolean uninitialized = isDeclaration && rightExpression == EmptyExpression.INSTANCE;
            recordAssignment((Variable) leftExpression, isDeclaration, uninitialized, false, expression);
        } else if (leftExpression instanceof TupleExpression) {
            TupleExpression te = (TupleExpression) leftExpression;
            for (Expression next : te.getExpressions()) {
                if (next instanceof Variable) {
                    recordAssignment((Variable) next, isDeclaration, false, false, next);
                }
            }
        }
    }
}
Also used : Variable(org.codehaus.groovy.ast.Variable) PrefixExpression(org.codehaus.groovy.ast.expr.PrefixExpression) PostfixExpression(org.codehaus.groovy.ast.expr.PostfixExpression) EmptyExpression(org.codehaus.groovy.ast.expr.EmptyExpression) Expression(org.codehaus.groovy.ast.expr.Expression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) DeclarationExpression(org.codehaus.groovy.ast.expr.DeclarationExpression) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) DeclarationExpression(org.codehaus.groovy.ast.expr.DeclarationExpression) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression)

Example 19 with Variable

use of org.codehaus.groovy.ast.Variable in project groovy by apache.

the class FinalVariableAnalyzer method visitIfElse.

@Override
public void visitIfElse(final IfStatement ifElse) {
    visitStatement(ifElse);
    ifElse.getBooleanExpression().visit(this);
    Map<Variable, VariableState> ifState = pushState();
    ifElse.getIfBlock().visit(this);
    popState();
    Statement elseBlock = ifElse.getElseBlock();
    Map<Variable, VariableState> elseState = pushState();
    if (elseBlock instanceof EmptyStatement) {
        // dispatching to EmptyStatement will not call back visitor,
        // must call our visitEmptyStatement explicitly
        visitEmptyStatement((EmptyStatement) elseBlock);
    } else {
        elseBlock.visit(this);
    }
    popState();
    // merge if/else branches
    Map<Variable, VariableState> curState = getState();
    Set<Variable> allVars = new HashSet<Variable>();
    allVars.addAll(curState.keySet());
    allVars.addAll(ifState.keySet());
    allVars.addAll(elseState.keySet());
    for (Variable var : allVars) {
        VariableState beforeValue = curState.get(var);
        VariableState ifValue = ifState.get(var);
        VariableState elseValue = elseState.get(var);
        // merge if and else values
        VariableState mergedIfElse;
        mergedIfElse = ifValue != null && elseValue != null && ifValue.isFinal && elseValue.isFinal ? VariableState.is_final : VariableState.is_var;
        if (beforeValue == null) {
            curState.put(var, mergedIfElse);
        } else {
            if (beforeValue == VariableState.is_uninitialized) {
                curState.put(var, mergedIfElse);
            } else if (ifValue != null || elseValue != null) {
                curState.put(var, VariableState.is_var);
            }
        }
    }
}
Also used : Variable(org.codehaus.groovy.ast.Variable) Statement(org.codehaus.groovy.ast.stmt.Statement) CatchStatement(org.codehaus.groovy.ast.stmt.CatchStatement) EmptyStatement(org.codehaus.groovy.ast.stmt.EmptyStatement) IfStatement(org.codehaus.groovy.ast.stmt.IfStatement) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) TryCatchStatement(org.codehaus.groovy.ast.stmt.TryCatchStatement) EmptyStatement(org.codehaus.groovy.ast.stmt.EmptyStatement) HashSet(java.util.HashSet)

Example 20 with Variable

use of org.codehaus.groovy.ast.Variable in project groovy by apache.

the class FinalVariableAnalyzer method visitTryCatchFinally.

@Override
public void visitTryCatchFinally(final TryCatchStatement statement) {
    visitStatement(statement);
    Map<Variable, VariableState> beforeTryCatch = new HashMap<Variable, VariableState>(getState());
    statement.getTryStatement().visit(this);
    for (CatchStatement catchStatement : statement.getCatchStatements()) {
        catchStatement.visit(this);
    }
    Statement finallyStatement = statement.getFinallyStatement();
    // we need to recall which final variables are unassigned so cloning the current state
    Map<Variable, VariableState> afterTryCatchState = new HashMap<Variable, VariableState>(getState());
    if (finallyStatement instanceof EmptyStatement) {
        // dispatching to EmptyStatement will not call back visitor,
        // must call our visitEmptyStatement explicitly
        visitEmptyStatement((EmptyStatement) finallyStatement);
    } else {
        finallyStatement.visit(this);
    }
    // and now we must reset to uninitialized state variables which were only initialized during try/catch
    Map<Variable, VariableState> afterFinally = new HashMap<Variable, VariableState>(getState());
    for (Map.Entry<Variable, VariableState> entry : afterFinally.entrySet()) {
        Variable var = entry.getKey();
        VariableState afterFinallyState = entry.getValue();
        VariableState beforeTryCatchState = beforeTryCatch.get(var);
        if (afterFinallyState == VariableState.is_final && beforeTryCatchState != VariableState.is_final && afterTryCatchState.get(var) != beforeTryCatchState) {
            getState().put(var, beforeTryCatchState == null ? VariableState.is_uninitialized : beforeTryCatchState);
        }
    }
}
Also used : Variable(org.codehaus.groovy.ast.Variable) CatchStatement(org.codehaus.groovy.ast.stmt.CatchStatement) TryCatchStatement(org.codehaus.groovy.ast.stmt.TryCatchStatement) HashMap(java.util.HashMap) Statement(org.codehaus.groovy.ast.stmt.Statement) CatchStatement(org.codehaus.groovy.ast.stmt.CatchStatement) EmptyStatement(org.codehaus.groovy.ast.stmt.EmptyStatement) IfStatement(org.codehaus.groovy.ast.stmt.IfStatement) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) TryCatchStatement(org.codehaus.groovy.ast.stmt.TryCatchStatement) EmptyStatement(org.codehaus.groovy.ast.stmt.EmptyStatement) HashMap(java.util.HashMap) Map(java.util.Map)

Aggregations

Variable (org.codehaus.groovy.ast.Variable)43 DynamicVariable (org.codehaus.groovy.ast.DynamicVariable)23 ClassNode (org.codehaus.groovy.ast.ClassNode)21 InnerClassNode (org.codehaus.groovy.ast.InnerClassNode)16 VariableExpression (org.codehaus.groovy.ast.expr.VariableExpression)15 FieldNode (org.codehaus.groovy.ast.FieldNode)14 MethodNode (org.codehaus.groovy.ast.MethodNode)13 LowestUpperBoundClassNode (org.codehaus.groovy.ast.tools.WideningCategories.LowestUpperBoundClassNode)13 Parameter (org.codehaus.groovy.ast.Parameter)12 Expression (org.codehaus.groovy.ast.expr.Expression)9 ClassExpression (org.codehaus.groovy.ast.expr.ClassExpression)7 ClosureExpression (org.codehaus.groovy.ast.expr.ClosureExpression)7 LinkedList (java.util.LinkedList)6 ASTNode (org.codehaus.groovy.ast.ASTNode)6 BinaryExpression (org.codehaus.groovy.ast.expr.BinaryExpression)6 BlockStatement (org.codehaus.groovy.ast.stmt.BlockStatement)6 VariableScope (org.codehaus.groovy.ast.VariableScope)5 MethodCallExpression (org.codehaus.groovy.ast.expr.MethodCallExpression)5 PropertyExpression (org.codehaus.groovy.ast.expr.PropertyExpression)5 ClosureSignatureHint (groovy.transform.stc.ClosureSignatureHint)4