Search in sources :

Example 26 with FieldExpression

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

the class EnumVisitor method addInit.

private void addInit(final ClassNode enumClass, final FieldNode minValue, final FieldNode maxValue, final FieldNode values, final boolean isAIC) {
    // constructor helper
    // This method is used instead of calling the constructor as
    // calling the constructor may require a table with MetaClass
    // selecting the constructor for each enum value. So instead we
    // use this method to have a central point for constructor selection
    // and only one table. The whole construction is needed because
    // Reflection forbids access to the enum constructor.
    // code:
    // def $INIT(Object[] para) {
    // return this(*para)
    // }
    ClassNode enumRef = enumClass.getPlainNodeReference();
    Parameter[] parameter = new Parameter[] { new Parameter(ClassHelper.OBJECT_TYPE.makeArray(), "para") };
    MethodNode initMethod = new MethodNode("$INIT", ACC_FINAL | ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC, enumRef, parameter, ClassNode.EMPTY_ARRAY, null);
    initMethod.setSynthetic(true);
    ConstructorCallExpression cce = new ConstructorCallExpression(ClassNode.THIS, new ArgumentListExpression(new SpreadExpression(new VariableExpression("para"))));
    BlockStatement code = new BlockStatement();
    code.addStatement(new ReturnStatement(cce));
    initMethod.setCode(code);
    addGeneratedMethod(enumClass, initMethod);
    // static init
    List<FieldNode> fields = enumClass.getFields();
    List<Expression> arrayInit = new ArrayList<>();
    int value = -1;
    Token assign = Token.newSymbol(Types.ASSIGN, -1, -1);
    List<Statement> block = new ArrayList<>();
    FieldNode tempMin = null;
    FieldNode tempMax = null;
    for (FieldNode field : fields) {
        if (!field.isEnum())
            continue;
        value += 1;
        if (tempMin == null)
            tempMin = field;
        tempMax = field;
        ClassNode enumBase = enumClass;
        ArgumentListExpression args = new ArgumentListExpression();
        args.addExpression(new ConstantExpression(field.getName()));
        args.addExpression(new ConstantExpression(value));
        if (field.getInitialExpression() == null) {
            if (enumClass.isAbstract()) {
                addError(field, "The enum constant " + field.getName() + " must override abstract methods from " + enumBase.getName() + ".");
                continue;
            }
        } else {
            ListExpression oldArgs = (ListExpression) field.getInitialExpression();
            List<MapEntryExpression> savedMapEntries = new ArrayList<>();
            for (Expression exp : oldArgs.getExpressions()) {
                if (exp instanceof MapEntryExpression) {
                    savedMapEntries.add((MapEntryExpression) exp);
                    continue;
                }
                InnerClassNode inner = null;
                if (exp instanceof ClassExpression) {
                    ClassExpression clazzExp = (ClassExpression) exp;
                    ClassNode ref = clazzExp.getType();
                    if (ref instanceof EnumConstantClassNode) {
                        inner = (InnerClassNode) ref;
                    }
                }
                if (inner != null) {
                    List<MethodNode> baseMethods = enumBase.getMethods();
                    for (MethodNode methodNode : baseMethods) {
                        if (!methodNode.isAbstract())
                            continue;
                        MethodNode enumConstMethod = inner.getMethod(methodNode.getName(), methodNode.getParameters());
                        if (enumConstMethod == null || enumConstMethod.isAbstract()) {
                            addError(field, "Can't have an abstract method in enum constant " + field.getName() + ". Implement method '" + methodNode.getTypeDescriptor() + "'.");
                        }
                    }
                    if (inner.getVariableScope() == null) {
                        enumBase = inner;
                        /*
                             * GROOVY-3985: Remove the final modifier from $INIT method in this case
                             * so that subclasses of enum generated for enum constants (aic) can provide
                             * their own $INIT method
                             */
                        initMethod.setModifiers(initMethod.getModifiers() & ~ACC_FINAL);
                        continue;
                    }
                }
                args.addExpression(exp);
            }
            if (!savedMapEntries.isEmpty()) {
                args.getExpressions().add(2, new MapExpression(savedMapEntries));
            }
        }
        field.setInitialValueExpression(null);
        block.add(new ExpressionStatement(new BinaryExpression(new FieldExpression(field), assign, new StaticMethodCallExpression(enumBase, "$INIT", args))));
        arrayInit.add(new FieldExpression(field));
    }
    if (!isAIC) {
        if (tempMin != null) {
            block.add(new ExpressionStatement(new BinaryExpression(new FieldExpression(minValue), assign, new FieldExpression(tempMin))));
            block.add(new ExpressionStatement(new BinaryExpression(new FieldExpression(maxValue), assign, new FieldExpression(tempMax))));
            enumClass.addField(minValue);
            enumClass.addField(maxValue);
        }
        block.add(new ExpressionStatement(new BinaryExpression(new FieldExpression(values), assign, new ArrayExpression(enumClass, arrayInit))));
        enumClass.addField(values);
    }
    enumClass.addStaticInitializerStatements(block, true);
}
Also used : EnumConstantClassNode(org.codehaus.groovy.ast.EnumConstantClassNode) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) ArrayList(java.util.ArrayList) StaticMethodCallExpression(org.codehaus.groovy.ast.expr.StaticMethodCallExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) Token(org.codehaus.groovy.syntax.Token) MapEntryExpression(org.codehaus.groovy.ast.expr.MapEntryExpression) MethodNode(org.codehaus.groovy.ast.MethodNode) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) ReturnStatement(org.codehaus.groovy.ast.stmt.ReturnStatement) MapExpression(org.codehaus.groovy.ast.expr.MapExpression) EnumConstantClassNode(org.codehaus.groovy.ast.EnumConstantClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) FieldNode(org.codehaus.groovy.ast.FieldNode) ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) IfStatement(org.codehaus.groovy.ast.stmt.IfStatement) 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) EmptyStatement(org.codehaus.groovy.ast.stmt.EmptyStatement) ListExpression(org.codehaus.groovy.ast.expr.ListExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) FieldExpression(org.codehaus.groovy.ast.expr.FieldExpression) ListExpression(org.codehaus.groovy.ast.expr.ListExpression) MapExpression(org.codehaus.groovy.ast.expr.MapExpression) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) SpreadExpression(org.codehaus.groovy.ast.expr.SpreadExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) ArrayExpression(org.codehaus.groovy.ast.expr.ArrayExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) FieldExpression(org.codehaus.groovy.ast.expr.FieldExpression) BooleanExpression(org.codehaus.groovy.ast.expr.BooleanExpression) StaticMethodCallExpression(org.codehaus.groovy.ast.expr.StaticMethodCallExpression) 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) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) MapEntryExpression(org.codehaus.groovy.ast.expr.MapEntryExpression) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) Parameter(org.codehaus.groovy.ast.Parameter) ArrayExpression(org.codehaus.groovy.ast.expr.ArrayExpression) SpreadExpression(org.codehaus.groovy.ast.expr.SpreadExpression)

Example 27 with FieldExpression

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

the class EnumVisitor method addMethods.

private static void addMethods(final ClassNode enumClass, final FieldNode values) {
    List<MethodNode> methods = enumClass.getMethods();
    boolean hasNext = false;
    boolean hasPrevious = false;
    for (MethodNode m : methods) {
        if (m.getName().equals("next") && m.getParameters().length == 0)
            hasNext = true;
        if (m.getName().equals("previous") && m.getParameters().length == 0)
            hasPrevious = true;
        if (hasNext && hasPrevious)
            break;
    }
    ClassNode enumRef = enumClass.getPlainNodeReference();
    {
        // create values() method
        MethodNode valuesMethod = new MethodNode("values", ACC_FINAL | ACC_PUBLIC | ACC_STATIC, enumRef.makeArray(), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, null);
        valuesMethod.setSynthetic(true);
        BlockStatement code = new BlockStatement();
        MethodCallExpression cloneCall = new MethodCallExpression(new FieldExpression(values), "clone", MethodCallExpression.NO_ARGUMENTS);
        cloneCall.setMethodTarget(values.getType().getMethod("clone", Parameter.EMPTY_ARRAY));
        code.addStatement(new ReturnStatement(cloneCall));
        valuesMethod.setCode(code);
        addGeneratedMethod(enumClass, valuesMethod);
    }
    if (!hasNext) {
        // create next() method, code:
        // Day next() {
        // int ordinal = ordinal().next()
        // if (ordinal >= values().size()) ordinal = 0
        // return values()[ordinal]
        // }
        Token assign = Token.newSymbol(Types.ASSIGN, -1, -1);
        Token ge = Token.newSymbol(Types.COMPARE_GREATER_THAN_EQUAL, -1, -1);
        MethodNode nextMethod = new MethodNode("next", ACC_PUBLIC, enumRef, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, null);
        nextMethod.setSynthetic(true);
        BlockStatement code = new BlockStatement();
        BlockStatement ifStatement = new BlockStatement();
        ifStatement.addStatement(new ExpressionStatement(new BinaryExpression(new VariableExpression("ordinal"), assign, new ConstantExpression(0))));
        code.addStatement(new ExpressionStatement(new DeclarationExpression(localVarX("ordinal"), assign, new MethodCallExpression(new MethodCallExpression(VariableExpression.THIS_EXPRESSION, "ordinal", MethodCallExpression.NO_ARGUMENTS), "next", MethodCallExpression.NO_ARGUMENTS))));
        code.addStatement(new IfStatement(new BooleanExpression(new BinaryExpression(new VariableExpression("ordinal"), ge, new MethodCallExpression(new FieldExpression(values), "size", MethodCallExpression.NO_ARGUMENTS))), ifStatement, EmptyStatement.INSTANCE));
        code.addStatement(new ReturnStatement(new MethodCallExpression(new FieldExpression(values), "getAt", new VariableExpression("ordinal"))));
        nextMethod.setCode(code);
        addGeneratedMethod(enumClass, nextMethod);
    }
    if (!hasPrevious) {
        // create previous() method, code:
        // Day previous() {
        // int ordinal = ordinal().previous()
        // if (ordinal < 0) ordinal = values().size() - 1
        // return values()[ordinal]
        // }
        Token assign = Token.newSymbol(Types.ASSIGN, -1, -1);
        Token lt = Token.newSymbol(Types.COMPARE_LESS_THAN, -1, -1);
        MethodNode prevMethod = new MethodNode("previous", ACC_PUBLIC, enumRef, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, null);
        prevMethod.setSynthetic(true);
        BlockStatement code = new BlockStatement();
        BlockStatement ifStatement = new BlockStatement();
        ifStatement.addStatement(new ExpressionStatement(new BinaryExpression(new VariableExpression("ordinal"), assign, new MethodCallExpression(new MethodCallExpression(new FieldExpression(values), "size", MethodCallExpression.NO_ARGUMENTS), "minus", new ConstantExpression(1)))));
        code.addStatement(new ExpressionStatement(new DeclarationExpression(localVarX("ordinal"), assign, new MethodCallExpression(new MethodCallExpression(VariableExpression.THIS_EXPRESSION, "ordinal", MethodCallExpression.NO_ARGUMENTS), "previous", MethodCallExpression.NO_ARGUMENTS))));
        code.addStatement(new IfStatement(new BooleanExpression(new BinaryExpression(new VariableExpression("ordinal"), lt, new ConstantExpression(0))), ifStatement, EmptyStatement.INSTANCE));
        code.addStatement(new ReturnStatement(new MethodCallExpression(new FieldExpression(values), "getAt", new VariableExpression("ordinal"))));
        prevMethod.setCode(code);
        addGeneratedMethod(enumClass, prevMethod);
    }
    {
        // create valueOf
        Parameter stringParameter = new Parameter(ClassHelper.STRING_TYPE, "name");
        MethodNode valueOfMethod = new MethodNode("valueOf", ACC_PUBLIC | ACC_STATIC, enumRef, new Parameter[] { stringParameter }, ClassNode.EMPTY_ARRAY, null);
        ArgumentListExpression callArguments = new ArgumentListExpression();
        callArguments.addExpression(new ClassExpression(enumClass));
        callArguments.addExpression(new VariableExpression("name"));
        BlockStatement code = new BlockStatement();
        code.addStatement(new ReturnStatement(new MethodCallExpression(new ClassExpression(ClassHelper.Enum_Type), "valueOf", callArguments)));
        valueOfMethod.setCode(code);
        valueOfMethod.setSynthetic(true);
        addGeneratedMethod(enumClass, valueOfMethod);
    }
}
Also used : EnumConstantClassNode(org.codehaus.groovy.ast.EnumConstantClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) DeclarationExpression(org.codehaus.groovy.ast.expr.DeclarationExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) Token(org.codehaus.groovy.syntax.Token) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) FieldExpression(org.codehaus.groovy.ast.expr.FieldExpression) IfStatement(org.codehaus.groovy.ast.stmt.IfStatement) BooleanExpression(org.codehaus.groovy.ast.expr.BooleanExpression) MethodNode(org.codehaus.groovy.ast.MethodNode) StaticMethodCallExpression(org.codehaus.groovy.ast.expr.StaticMethodCallExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) ReturnStatement(org.codehaus.groovy.ast.stmt.ReturnStatement) Parameter(org.codehaus.groovy.ast.Parameter)

Example 28 with FieldExpression

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

the class Verifier method extractVariableReferenceInitializers.

private static List<Statement> extractVariableReferenceInitializers(final List<Statement> statements) {
    List<Statement> localVariableReferences = new ArrayList<>();
    for (ListIterator<Statement> it = statements.listIterator(1); it.hasNext(); ) {
        // the first statement is the super constructor call  ^
        Statement stmt = it.next();
        if (stmt instanceof ExpressionStatement && ((ExpressionStatement) stmt).getExpression() instanceof BinaryExpression) {
            BinaryExpression expr = (BinaryExpression) ((ExpressionStatement) stmt).getExpression();
            if (expr.getOperation().getType() == Types.ASSIGN && expr.getLeftExpression() instanceof FieldExpression && expr.getLeftExpression().getType().equals(ClassHelper.REFERENCE_TYPE) && (((FieldExpression) expr.getLeftExpression()).getField().getModifiers() & Opcodes.ACC_SYNTHETIC) != 0) /* also could check if the right expression is a variable expression that references ctor parameter */
            {
                localVariableReferences.add(stmt);
                it.remove();
            }
        }
    }
    return localVariableReferences;
}
Also used : BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) ReturnStatement(org.codehaus.groovy.ast.stmt.ReturnStatement) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) Statement(org.codehaus.groovy.ast.stmt.Statement) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) ArrayList(java.util.ArrayList) FieldExpression(org.codehaus.groovy.ast.expr.FieldExpression)

Aggregations

FieldExpression (org.codehaus.groovy.ast.expr.FieldExpression)28 BinaryExpression (org.codehaus.groovy.ast.expr.BinaryExpression)17 VariableExpression (org.codehaus.groovy.ast.expr.VariableExpression)17 ConstantExpression (org.codehaus.groovy.ast.expr.ConstantExpression)16 MethodCallExpression (org.codehaus.groovy.ast.expr.MethodCallExpression)15 ExpressionStatement (org.codehaus.groovy.ast.stmt.ExpressionStatement)15 FieldNode (org.codehaus.groovy.ast.FieldNode)13 ArgumentListExpression (org.codehaus.groovy.ast.expr.ArgumentListExpression)13 BlockStatement (org.codehaus.groovy.ast.stmt.BlockStatement)13 ClassNode (org.codehaus.groovy.ast.ClassNode)12 StaticMethodCallExpression (org.codehaus.groovy.ast.expr.StaticMethodCallExpression)11 ReturnStatement (org.codehaus.groovy.ast.stmt.ReturnStatement)10 Statement (org.codehaus.groovy.ast.stmt.Statement)10 Expression (org.codehaus.groovy.ast.expr.Expression)8 ClassExpression (org.codehaus.groovy.ast.expr.ClassExpression)7 ClosureExpression (org.codehaus.groovy.ast.expr.ClosureExpression)7 ConstructorCallExpression (org.codehaus.groovy.ast.expr.ConstructorCallExpression)7 IfStatement (org.codehaus.groovy.ast.stmt.IfStatement)7 MethodNode (org.codehaus.groovy.ast.MethodNode)6 BooleanExpression (org.codehaus.groovy.ast.expr.BooleanExpression)6