Search in sources :

Example 41 with InnerClassNode

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

the class EnumVisitor method addInit.

private void addInit(ClassNode enumClass, FieldNode minValue, FieldNode maxValue, FieldNode values, 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", PUBLIC_FS | Opcodes.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);
    enumClass.addMethod(initMethod);
    // static init
    List<FieldNode> fields = enumClass.getFields();
    List<Expression> arrayInit = new ArrayList<Expression>();
    int value = -1;
    Token assign = Token.newSymbol(Types.ASSIGN, -1, -1);
    List<Statement> block = new ArrayList<Statement>();
    FieldNode tempMin = null;
    FieldNode tempMax = null;
    for (FieldNode field : fields) {
        if ((field.getModifiers() & Opcodes.ACC_ENUM) == 0)
            continue;
        value++;
        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.getModifiers() & Opcodes.ACC_ABSTRACT) != 0) {
                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<MapEntryExpression>();
            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.getModifiers() & Opcodes.ACC_ABSTRACT) != 0) {
                            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() & ~Opcodes.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) ArrayList(java.util.ArrayList) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) Token(org.codehaus.groovy.syntax.Token) MethodNode(org.codehaus.groovy.ast.MethodNode) ReturnStatement(org.codehaus.groovy.ast.stmt.ReturnStatement) EnumConstantClassNode(org.codehaus.groovy.ast.EnumConstantClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) FieldNode(org.codehaus.groovy.ast.FieldNode) 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) IfStatement(org.codehaus.groovy.ast.stmt.IfStatement) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) Parameter(org.codehaus.groovy.ast.Parameter)

Example 42 with InnerClassNode

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

the class AsmClassGenerator method makeInnerClassEntry.

private void makeInnerClassEntry(ClassNode cn) {
    if (!(cn instanceof InnerClassNode))
        return;
    InnerClassNode innerClass = (InnerClassNode) cn;
    String innerClassName = innerClass.getName();
    String innerClassInternalName = BytecodeHelper.getClassInternalName(innerClassName);
    {
        int index = innerClassName.lastIndexOf('$');
        if (index >= 0)
            innerClassName = innerClassName.substring(index + 1);
    }
    String outerClassName = BytecodeHelper.getClassInternalName(innerClass.getOuterClass().getName());
    MethodNode enclosingMethod = innerClass.getEnclosingMethod();
    if (enclosingMethod != null) {
        // local inner classes do not specify the outer class name
        outerClassName = null;
        if (innerClass.isAnonymous())
            innerClassName = null;
    }
    int mods = adjustedClassModifiersForInnerClassTable(cn);
    if (Modifier.isPrivate(mods)) {
        mods = mods ^ Modifier.PRIVATE;
        innerClass.setModifiers(mods);
    }
    cv.visitInnerClass(innerClassInternalName, outerClassName, innerClassName, mods);
}
Also used : MethodNode(org.codehaus.groovy.ast.MethodNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode)

Example 43 with InnerClassNode

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

the class InnerClassCompletionVisitor method visitClass.

@Override
public void visitClass(ClassNode node) {
    this.classNode = node;
    thisField = null;
    InnerClassNode innerClass = null;
    if (!node.isEnum() && !node.isInterface() && node instanceof InnerClassNode) {
        innerClass = (InnerClassNode) node;
        thisField = innerClass.getField("this$0");
        if (innerClass.getVariableScope() == null && innerClass.getDeclaredConstructors().isEmpty()) {
            // add dummy constructor
            innerClass.addConstructor(ACC_PUBLIC, Parameter.EMPTY_ARRAY, null, null);
        }
    }
    if (node.isEnum() || node.isInterface())
        return;
    // use Iterator.hasNext() to check for available inner classes
    if (node.getInnerClasses().hasNext())
        addDispatcherMethods(node);
    if (innerClass == null)
        return;
    super.visitClass(node);
    addDefaultMethods(innerClass);
}
Also used : InnerClassNode(org.codehaus.groovy.ast.InnerClassNode)

Example 44 with InnerClassNode

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

the class InnerClassVisitor method visitClass.

@Override
public void visitClass(ClassNode node) {
    this.classNode = node;
    thisField = null;
    InnerClassNode innerClass = null;
    if (!node.isEnum() && !node.isInterface() && node instanceof InnerClassNode) {
        innerClass = (InnerClassNode) node;
        if (!isStatic(innerClass) && innerClass.getVariableScope() == null) {
            thisField = innerClass.addField("this$0", PUBLIC_SYNTHETIC, node.getOuterClass().getPlainNodeReference(), null);
        }
    }
    super.visitClass(node);
    if (node.isEnum() || node.isInterface())
        return;
    if (innerClass == null)
        return;
    if (node.getSuperClass().isInterface()) {
        node.addInterface(node.getUnresolvedSuperClass());
        node.setUnresolvedSuperClass(ClassHelper.OBJECT_TYPE);
    }
}
Also used : InnerClassNode(org.codehaus.groovy.ast.InnerClassNode)

Example 45 with InnerClassNode

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

the class AntlrParserPlugin method innerClassDef.

protected void innerClassDef(AST classDef) {
    List<AnnotationNode> annotations = new ArrayList<AnnotationNode>();
    if (isType(TRAIT_DEF, classDef)) {
        annotations.add(new AnnotationNode(ClassHelper.make("groovy.transform.Trait")));
    }
    AST node = classDef.getFirstChild();
    int modifiers = Opcodes.ACC_PUBLIC;
    if (isType(MODIFIERS, node)) {
        modifiers = modifiers(node, annotations, modifiers);
        checkNoInvalidModifier(classDef, "Class", modifiers, Opcodes.ACC_SYNCHRONIZED, "synchronized");
        node = node.getNextSibling();
    }
    String name = identifier(node);
    node = node.getNextSibling();
    GenericsType[] genericsType = null;
    if (isType(TYPE_PARAMETERS, node)) {
        genericsType = makeGenericsType(node);
        node = node.getNextSibling();
    }
    ClassNode superClass = null;
    if (isType(EXTENDS_CLAUSE, node)) {
        superClass = makeTypeWithArguments(node);
        node = node.getNextSibling();
    }
    ClassNode[] interfaces = ClassNode.EMPTY_ARRAY;
    if (isType(IMPLEMENTS_CLAUSE, node)) {
        interfaces = interfaces(node);
        node = node.getNextSibling();
    }
    // TODO read mixins
    MixinNode[] mixins = {};
    ClassNode outerClass = classNode;
    boolean syntheticPublic = ((modifiers & Opcodes.ACC_SYNTHETIC) != 0);
    modifiers &= ~Opcodes.ACC_SYNTHETIC;
    if (classNode != null) {
        name = classNode.getNameWithoutPackage() + "$" + name;
        String fullName = dot(classNode.getPackageName(), name);
        if (classNode.isInterface()) {
            modifiers |= Opcodes.ACC_STATIC;
        }
        classNode = new InnerClassNode(classNode, fullName, modifiers, superClass, interfaces, mixins);
    } else {
        classNode = new ClassNode(dot(getPackageName(), name), modifiers, superClass, interfaces, mixins);
    }
    classNode.addAnnotations(annotations);
    classNode.setGenericsTypes(genericsType);
    classNode.setSyntheticPublic(syntheticPublic);
    configureAST(classNode, classDef);
    // we put the class already in output to avoid the most inner classes
    // will be used as first class later in the loader. The first class
    // there determines what GCL#parseClass for example will return, so we
    // have here to ensure it won't be the inner class
    output.addClass(classNode);
    int oldClassCount = innerClassCounter;
    assertNodeType(OBJBLOCK, node);
    objectBlock(node);
    classNode = outerClass;
    innerClassCounter = oldClassCount;
}
Also used : EnumConstantClassNode(org.codehaus.groovy.ast.EnumConstantClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) AST(antlr.collections.AST) ArrayList(java.util.ArrayList) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) AnnotationNode(org.codehaus.groovy.ast.AnnotationNode) GenericsType(org.codehaus.groovy.ast.GenericsType) MixinNode(org.codehaus.groovy.ast.MixinNode)

Aggregations

InnerClassNode (org.codehaus.groovy.ast.InnerClassNode)60 ClassNode (org.codehaus.groovy.ast.ClassNode)52 MethodNode (org.codehaus.groovy.ast.MethodNode)26 FieldNode (org.codehaus.groovy.ast.FieldNode)17 Parameter (org.codehaus.groovy.ast.Parameter)12 BlockStatement (org.codehaus.groovy.ast.stmt.BlockStatement)12 ArrayList (java.util.ArrayList)11 ExpressionStatement (org.codehaus.groovy.ast.stmt.ExpressionStatement)9 LinkedList (java.util.LinkedList)8 ConstructorNode (org.codehaus.groovy.ast.ConstructorNode)8 InterfaceHelperClassNode (org.codehaus.groovy.ast.InterfaceHelperClassNode)8 Expression (org.codehaus.groovy.ast.expr.Expression)8 GenericsType (org.codehaus.groovy.ast.GenericsType)7 ClassExpression (org.codehaus.groovy.ast.expr.ClassExpression)7 MethodCallExpression (org.codehaus.groovy.ast.expr.MethodCallExpression)7 VariableExpression (org.codehaus.groovy.ast.expr.VariableExpression)7 ReturnStatement (org.codehaus.groovy.ast.stmt.ReturnStatement)7 MethodVisitor (org.objectweb.asm.MethodVisitor)7 ClosureExpression (org.codehaus.groovy.ast.expr.ClosureExpression)6 ConstantExpression (org.codehaus.groovy.ast.expr.ConstantExpression)6