Search in sources :

Example 96 with VariableExpression

use of org.codehaus.groovy.ast.expr.VariableExpression in project groovy-core by groovy.

the class CategoryASTTransformation method createThisExpression.

private static VariableExpression createThisExpression() {
    VariableExpression expr = new VariableExpression("$this");
    expr.setClosureSharedVariable(true);
    return expr;
}
Also used : VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression)

Example 97 with VariableExpression

use of org.codehaus.groovy.ast.expr.VariableExpression in project groovy-core by groovy.

the class CategoryASTTransformation method visit.

/**
     * Property invocations done on 'this' reference are transformed so that the invocations at runtime are
     * done on the additional parameter 'self'
     */
public void visit(ASTNode[] nodes, final SourceUnit source) {
    if (nodes.length != 2 || !(nodes[0] instanceof AnnotationNode) || !(nodes[1] instanceof ClassNode)) {
        source.getErrorCollector().addError(new SyntaxErrorMessage(new SyntaxException("@Category can only be added to a ClassNode but got: " + (nodes.length == 2 ? nodes[1] : "nothing"), nodes[0].getLineNumber(), nodes[0].getColumnNumber()), source));
    }
    AnnotationNode annotation = (AnnotationNode) nodes[0];
    ClassNode parent = (ClassNode) nodes[1];
    ClassNode targetClass = getTargetClass(source, annotation);
    thisExpression.setType(targetClass);
    final LinkedList<Set<String>> varStack = new LinkedList<Set<String>>();
    if (!ensureNoInstanceFieldOrProperty(source, parent))
        return;
    Set<String> names = new HashSet<String>();
    for (FieldNode field : parent.getFields()) {
        names.add(field.getName());
    }
    for (PropertyNode field : parent.getProperties()) {
        names.add(field.getName());
    }
    varStack.add(names);
    final Reference parameter = new Reference();
    final ClassCodeExpressionTransformer expressionTransformer = new ClassCodeExpressionTransformer() {

        protected SourceUnit getSourceUnit() {
            return source;
        }

        private void addVariablesToStack(Parameter[] params) {
            Set<String> names = new HashSet<String>();
            names.addAll(varStack.getLast());
            for (Parameter param : params) {
                names.add(param.getName());
            }
            varStack.add(names);
        }

        @Override
        public void visitCatchStatement(CatchStatement statement) {
            varStack.getLast().add(statement.getVariable().getName());
            super.visitCatchStatement(statement);
            varStack.getLast().remove(statement.getVariable().getName());
        }

        @Override
        public void visitMethod(MethodNode node) {
            addVariablesToStack(node.getParameters());
            super.visitMethod(node);
            varStack.removeLast();
        }

        @Override
        public void visitBlockStatement(BlockStatement block) {
            Set<String> names = new HashSet<String>();
            names.addAll(varStack.getLast());
            varStack.add(names);
            super.visitBlockStatement(block);
            varStack.remove(names);
        }

        @Override
        public void visitClosureExpression(ClosureExpression ce) {
            addVariablesToStack(ce.getParameters());
            super.visitClosureExpression(ce);
            varStack.removeLast();
        }

        @Override
        public void visitDeclarationExpression(DeclarationExpression expression) {
            if (expression.isMultipleAssignmentDeclaration()) {
                TupleExpression te = expression.getTupleExpression();
                List<Expression> list = te.getExpressions();
                for (Expression arg : list) {
                    VariableExpression ve = (VariableExpression) arg;
                    varStack.getLast().add(ve.getName());
                }
            } else {
                VariableExpression ve = expression.getVariableExpression();
                varStack.getLast().add(ve.getName());
            }
            super.visitDeclarationExpression(expression);
        }

        @Override
        public void visitForLoop(ForStatement forLoop) {
            Expression exp = forLoop.getCollectionExpression();
            exp.visit(this);
            Parameter loopParam = forLoop.getVariable();
            if (loopParam != null) {
                varStack.getLast().add(loopParam.getName());
            }
            super.visitForLoop(forLoop);
        }

        @Override
        public void visitExpressionStatement(ExpressionStatement es) {
            // GROOVY-3543: visit the declaration expressions so that declaration variables get added on the varStack
            Expression exp = es.getExpression();
            if (exp instanceof DeclarationExpression) {
                exp.visit(this);
            }
            super.visitExpressionStatement(es);
        }

        @Override
        public Expression transform(Expression exp) {
            if (exp instanceof VariableExpression) {
                VariableExpression ve = (VariableExpression) exp;
                if (ve.getName().equals("this"))
                    return thisExpression;
                else {
                    if (!varStack.getLast().contains(ve.getName())) {
                        return new PropertyExpression(thisExpression, ve.getName());
                    }
                }
            } else if (exp instanceof PropertyExpression) {
                PropertyExpression pe = (PropertyExpression) exp;
                if (pe.getObjectExpression() instanceof VariableExpression) {
                    VariableExpression vex = (VariableExpression) pe.getObjectExpression();
                    if (vex.isThisExpression()) {
                        pe.setObjectExpression(thisExpression);
                        return pe;
                    }
                }
            } else if (exp instanceof ClosureExpression) {
                ClosureExpression ce = (ClosureExpression) exp;
                ce.getVariableScope().putReferencedLocalVariable((Parameter) parameter.get());
                Parameter[] params = ce.getParameters();
                if (params == null) {
                    params = Parameter.EMPTY_ARRAY;
                } else if (params.length == 0) {
                    params = new Parameter[] { new Parameter(ClassHelper.OBJECT_TYPE, "it") };
                }
                addVariablesToStack(params);
                ce.getCode().visit(this);
                varStack.removeLast();
            }
            return super.transform(exp);
        }
    };
    for (MethodNode method : parent.getMethods()) {
        if (!method.isStatic()) {
            method.setModifiers(method.getModifiers() | Opcodes.ACC_STATIC);
            final Parameter[] origParams = method.getParameters();
            final Parameter[] newParams = new Parameter[origParams.length + 1];
            Parameter p = new Parameter(targetClass, "$this");
            p.setClosureSharedVariable(true);
            newParams[0] = p;
            parameter.set(p);
            System.arraycopy(origParams, 0, newParams, 1, origParams.length);
            method.setParameters(newParams);
            expressionTransformer.visitMethod(method);
        }
    }
    new VariableScopeVisitor(source, true).visitClass(parent);
}
Also used : HashSet(java.util.HashSet) Set(java.util.Set) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) MethodNode(org.codehaus.groovy.ast.MethodNode) AnnotationNode(org.codehaus.groovy.ast.AnnotationNode) SyntaxException(org.codehaus.groovy.syntax.SyntaxException) PropertyNode(org.codehaus.groovy.ast.PropertyNode) PropertyExpression(org.codehaus.groovy.ast.expr.PropertyExpression) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression) ForStatement(org.codehaus.groovy.ast.stmt.ForStatement) HashSet(java.util.HashSet) ClassCodeExpressionTransformer(org.codehaus.groovy.ast.ClassCodeExpressionTransformer) ClassNode(org.codehaus.groovy.ast.ClassNode) FieldNode(org.codehaus.groovy.ast.FieldNode) SyntaxErrorMessage(org.codehaus.groovy.control.messages.SyntaxErrorMessage) Reference(groovy.lang.Reference) DeclarationExpression(org.codehaus.groovy.ast.expr.DeclarationExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) LinkedList(java.util.LinkedList) CatchStatement(org.codehaus.groovy.ast.stmt.CatchStatement) PropertyExpression(org.codehaus.groovy.ast.expr.PropertyExpression) 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) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) Parameter(org.codehaus.groovy.ast.Parameter) VariableScopeVisitor(org.codehaus.groovy.classgen.VariableScopeVisitor)

Example 98 with VariableExpression

use of org.codehaus.groovy.ast.expr.VariableExpression in project groovy-core by groovy.

the class EqualsAndHashCodeASTTransformation method createCanEqual.

private static void createCanEqual(ClassNode cNode) {
    boolean hasExistingCanEqual = hasDeclaredMethod(cNode, "canEqual", 1);
    if (hasExistingCanEqual && hasDeclaredMethod(cNode, "_canEqual", 1))
        return;
    final BlockStatement body = new BlockStatement();
    VariableExpression other = varX("other");
    body.addStatement(returnS(isInstanceOfX(other, GenericsUtils.nonGeneric(cNode))));
    cNode.addMethod(new MethodNode(hasExistingCanEqual ? "_canEqual" : "canEqual", hasExistingCanEqual ? ACC_PRIVATE : ACC_PUBLIC, ClassHelper.boolean_TYPE, params(param(OBJECT_TYPE, other.getName())), ClassNode.EMPTY_ARRAY, body));
}
Also used : MethodNode(org.codehaus.groovy.ast.MethodNode) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression)

Example 99 with VariableExpression

use of org.codehaus.groovy.ast.expr.VariableExpression in project groovy-core by groovy.

the class EqualsAndHashCodeASTTransformation method createEquals.

public static void createEquals(ClassNode cNode, boolean includeFields, boolean callSuper, boolean useCanEqual, List<String> excludes, List<String> includes) {
    if (useCanEqual)
        createCanEqual(cNode);
    // make a public method if none exists otherwise try a private method with leading underscore
    boolean hasExistingEquals = hasDeclaredMethod(cNode, "equals", 1);
    if (hasExistingEquals && hasDeclaredMethod(cNode, "_equals", 1))
        return;
    final BlockStatement body = new BlockStatement();
    VariableExpression other = varX("other");
    // some short circuit cases for efficiency
    body.addStatement(ifS(equalsNullX(other), returnS(constX(Boolean.FALSE, true))));
    body.addStatement(ifS(sameX(varX("this"), other), returnS(constX(Boolean.TRUE, true))));
    if (useCanEqual) {
        body.addStatement(ifS(notX(isInstanceOfX(other, GenericsUtils.nonGeneric(cNode))), returnS(constX(Boolean.FALSE, true))));
    } else {
        body.addStatement(ifS(notX(hasClassX(other, GenericsUtils.nonGeneric(cNode))), returnS(constX(Boolean.FALSE, true))));
    }
    VariableExpression otherTyped = varX("otherTyped", GenericsUtils.nonGeneric(cNode));
    CastExpression castExpression = new CastExpression(GenericsUtils.nonGeneric(cNode), other);
    castExpression.setStrict(true);
    body.addStatement(declS(otherTyped, castExpression));
    if (useCanEqual) {
        body.addStatement(ifS(notX(callX(otherTyped, "canEqual", varX("this"))), returnS(constX(Boolean.FALSE, true))));
    }
    List<PropertyNode> pList = getInstanceProperties(cNode);
    for (PropertyNode pNode : pList) {
        if (shouldSkip(pNode.getName(), excludes, includes))
            continue;
        boolean canBeSelf = StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(pNode.getOriginType(), cNode);
        if (!canBeSelf) {
            body.addStatement(ifS(notX(hasEqualPropertyX(pNode, otherTyped)), returnS(constX(Boolean.FALSE, true))));
        } else {
            body.addStatement(ifS(notX(hasSamePropertyX(pNode, otherTyped)), ifElseS(differentSelfRecursivePropertyX(pNode, otherTyped), returnS(constX(Boolean.FALSE, true)), ifS(notX(bothSelfRecursivePropertyX(pNode, otherTyped)), ifS(notX(hasEqualPropertyX(pNode, otherTyped)), returnS(constX(Boolean.FALSE, true)))))));
        }
    }
    List<FieldNode> fList = new ArrayList<FieldNode>();
    if (includeFields) {
        fList.addAll(getInstanceNonPropertyFields(cNode));
    }
    for (FieldNode fNode : fList) {
        if (shouldSkip(fNode.getName(), excludes, includes))
            continue;
        body.addStatement(ifS(notX(hasSameFieldX(fNode, otherTyped)), ifElseS(differentSelfRecursiveFieldX(fNode, otherTyped), returnS(constX(Boolean.FALSE, true)), ifS(notX(bothSelfRecursiveFieldX(fNode, otherTyped)), ifS(notX(hasEqualFieldX(fNode, otherTyped)), returnS(constX(Boolean.FALSE, true)))))));
    }
    if (callSuper) {
        body.addStatement(ifS(notX(isTrueX(callSuperX("equals", other))), returnS(constX(Boolean.FALSE, true))));
    }
    // default
    body.addStatement(returnS(constX(Boolean.TRUE, true)));
    cNode.addMethod(new MethodNode(hasExistingEquals ? "_equals" : "equals", hasExistingEquals ? ACC_PRIVATE : ACC_PUBLIC, ClassHelper.boolean_TYPE, params(param(OBJECT_TYPE, other.getName())), ClassNode.EMPTY_ARRAY, body));
}
Also used : FieldNode(org.codehaus.groovy.ast.FieldNode) MethodNode(org.codehaus.groovy.ast.MethodNode) PropertyNode(org.codehaus.groovy.ast.PropertyNode) ArrayList(java.util.ArrayList) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) CastExpression(org.codehaus.groovy.ast.expr.CastExpression)

Example 100 with VariableExpression

use of org.codehaus.groovy.ast.expr.VariableExpression in project groovy-core by groovy.

the class NewifyASTTransformation method determineClasses.

/** allow non-strict mode in scripts because parsing not complete at that point */
private ListExpression determineClasses(Expression expr, boolean searchSourceUnit) {
    ListExpression list = new ListExpression();
    if (expr instanceof ClassExpression) {
        list.addExpression(expr);
    } else if (expr instanceof VariableExpression && searchSourceUnit) {
        VariableExpression ve = (VariableExpression) expr;
        ClassNode fromSourceUnit = getSourceUnitClass(ve);
        if (fromSourceUnit != null) {
            ClassExpression found = classX(fromSourceUnit);
            found.setSourcePosition(ve);
            list.addExpression(found);
        } else {
            addError(BASE_BAD_PARAM_ERROR + "an unresolvable reference to '" + ve.getName() + "'.", expr);
        }
    } else if (expr instanceof ListExpression) {
        list = (ListExpression) expr;
        final List<Expression> expressions = list.getExpressions();
        for (int i = 0; i < expressions.size(); i++) {
            Expression next = expressions.get(i);
            if (next instanceof VariableExpression && searchSourceUnit) {
                VariableExpression ve = (VariableExpression) next;
                ClassNode fromSourceUnit = getSourceUnitClass(ve);
                if (fromSourceUnit != null) {
                    ClassExpression found = classX(fromSourceUnit);
                    found.setSourcePosition(ve);
                    expressions.set(i, found);
                } else {
                    addError(BASE_BAD_PARAM_ERROR + "a list containing an unresolvable reference to '" + ve.getName() + "'.", next);
                }
            } else if (!(next instanceof ClassExpression)) {
                addError(BASE_BAD_PARAM_ERROR + "a list containing type: " + next.getType().getName() + ".", next);
            }
        }
        checkDuplicateNameClashes(list);
    } else if (expr != null) {
        addError(BASE_BAD_PARAM_ERROR + "a type: " + expr.getType().getName() + ".", expr);
    }
    return list;
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) ListExpression(org.codehaus.groovy.ast.expr.ListExpression) 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) DeclarationExpression(org.codehaus.groovy.ast.expr.DeclarationExpression) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) ListExpression(org.codehaus.groovy.ast.expr.ListExpression) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression)

Aggregations

VariableExpression (org.codehaus.groovy.ast.expr.VariableExpression)174 Expression (org.codehaus.groovy.ast.expr.Expression)84 MethodCallExpression (org.codehaus.groovy.ast.expr.MethodCallExpression)84 ArgumentListExpression (org.codehaus.groovy.ast.expr.ArgumentListExpression)76 ConstantExpression (org.codehaus.groovy.ast.expr.ConstantExpression)70 BinaryExpression (org.codehaus.groovy.ast.expr.BinaryExpression)66 ClassExpression (org.codehaus.groovy.ast.expr.ClassExpression)59 BlockStatement (org.codehaus.groovy.ast.stmt.BlockStatement)58 ClassNode (org.codehaus.groovy.ast.ClassNode)52 ExpressionStatement (org.codehaus.groovy.ast.stmt.ExpressionStatement)52 PropertyExpression (org.codehaus.groovy.ast.expr.PropertyExpression)47 TupleExpression (org.codehaus.groovy.ast.expr.TupleExpression)47 ConstructorCallExpression (org.codehaus.groovy.ast.expr.ConstructorCallExpression)46 ClosureExpression (org.codehaus.groovy.ast.expr.ClosureExpression)43 Parameter (org.codehaus.groovy.ast.Parameter)40 DeclarationExpression (org.codehaus.groovy.ast.expr.DeclarationExpression)40 MethodNode (org.codehaus.groovy.ast.MethodNode)37 FieldNode (org.codehaus.groovy.ast.FieldNode)36 BooleanExpression (org.codehaus.groovy.ast.expr.BooleanExpression)35 Statement (org.codehaus.groovy.ast.stmt.Statement)33