Search in sources :

Example 76 with InnerClassNode

use of org.codehaus.groovy.ast.InnerClassNode 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 77 with InnerClassNode

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

the class AstBuilder method visitEnumConstant.

@Override
public FieldNode visitEnumConstant(final EnumConstantContext ctx) {
    ClassNode classNode = ctx.getNodeMetaData(CLASS_DECLARATION_CLASS_NODE);
    Objects.requireNonNull(classNode, "classNode should not be null");
    InnerClassNode anonymousInnerClassNode = null;
    if (asBoolean(ctx.anonymousInnerClassDeclaration())) {
        ctx.anonymousInnerClassDeclaration().putNodeMetaData(ANONYMOUS_INNER_CLASS_SUPER_CLASS, classNode);
        anonymousInnerClassNode = this.visitAnonymousInnerClassDeclaration(ctx.anonymousInnerClassDeclaration());
    }
    FieldNode enumConstant = EnumHelper.addEnumConstant(classNode, this.visitIdentifier(ctx.identifier()), createEnumConstantInitExpression(ctx.arguments(), anonymousInnerClassNode));
    enumConstant.addAnnotations(this.visitAnnotationsOpt(ctx.annotationsOpt()));
    groovydocManager.handle(enumConstant, ctx);
    return configureAST(enumConstant, ctx);
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) EnumConstantClassNode(org.codehaus.groovy.ast.EnumConstantClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) FieldNode(org.codehaus.groovy.ast.FieldNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode)

Example 78 with InnerClassNode

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

the class GradleResolveVisitor method resolveNestedClass.

protected boolean resolveNestedClass(ClassNode type) {
    if (type instanceof ConstructedNestedClass) {
        return false;
    }
    // we have for example a class name A, are in class X
    // and there is a nested class A$X. we want to be able
    // to access that class directly, so A becomes a valid
    // name in X.
    // GROOVY-4043: Do this check up the hierarchy, if needed
    Map<String, ClassNode> classHierarchy = new LinkedHashMap<String, ClassNode>();
    ClassNode val;
    for (ClassNode classToCheck = currentClass; /*
             * We know that DefaultScript & friends don't have user-visible nested types,
             * so don't try to look up nonsensical types like org.gradle.Script#sourceCompatibility
             */
    classToCheck != null && classToCheck != ClassHelper.OBJECT_TYPE && !SCRIPTS_PACKAGE.equals(classToCheck.getPackageName()); classToCheck = classToCheck.getSuperClass()) {
        if (classHierarchy.containsKey(classToCheck.getName())) {
            break;
        }
        classHierarchy.put(classToCheck.getName(), classToCheck);
    }
    for (ClassNode classToCheck : classHierarchy.values()) {
        val = new ConstructedNestedClass(classToCheck, type.getName());
        if (resolveFromCompileUnit(val)) {
            type.setRedirect(val);
            return true;
        }
        // also check interfaces in case we have interfaces with nested classes
        for (ClassNode next : classToCheck.getAllInterfaces()) {
            if (type.getName().contains(next.getName())) {
                continue;
            }
            val = new ConstructedNestedClass(next, type.getName());
            if (resolve(val, false, false, false)) {
                type.setRedirect(val);
                return true;
            }
        }
    }
    // there is nothing to be done.
    if (!(currentClass instanceof InnerClassNode)) {
        return false;
    }
    // since we have B and want to get A we start with the most
    // outer class, put them together and then see if that does
    // already exist. In case of B from within A$B we are done
    // after the first step already. In case of for example
    // A.B.C.D.E.F and accessing E from F we test A$E=failed,
    // A$B$E=failed, A$B$C$E=fail, A$B$C$D$E=success
    LinkedList<ClassNode> outerClasses = new LinkedList<ClassNode>();
    ClassNode outer = currentClass.getOuterClass();
    while (outer != null) {
        outerClasses.addFirst(outer);
        outer = outer.getOuterClass();
    }
    // most outer class is now element 0
    for (ClassNode testNode : outerClasses) {
        val = new ConstructedNestedClass(testNode, type.getName());
        if (resolveFromCompileUnit(val)) {
            type.setRedirect(val);
            return true;
        }
        // also check interfaces in case we have interfaces with nested classes
        for (ClassNode next : testNode.getAllInterfaces()) {
            if (type.getName().contains(next.getName())) {
                continue;
            }
            val = new ConstructedNestedClass(next, type.getName());
            if (resolve(val, false, false, false)) {
                type.setRedirect(val);
                return true;
            }
        }
    }
    return false;
}
Also used : InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) LinkedList(java.util.LinkedList) LinkedHashMap(java.util.LinkedHashMap)

Aggregations

InnerClassNode (org.codehaus.groovy.ast.InnerClassNode)78 ClassNode (org.codehaus.groovy.ast.ClassNode)67 MethodNode (org.codehaus.groovy.ast.MethodNode)33 FieldNode (org.codehaus.groovy.ast.FieldNode)20 Parameter (org.codehaus.groovy.ast.Parameter)20 BlockStatement (org.codehaus.groovy.ast.stmt.BlockStatement)20 ArrayList (java.util.ArrayList)17 MethodCallExpression (org.codehaus.groovy.ast.expr.MethodCallExpression)16 ClassExpression (org.codehaus.groovy.ast.expr.ClassExpression)15 ConstructorCallExpression (org.codehaus.groovy.ast.expr.ConstructorCallExpression)15 Expression (org.codehaus.groovy.ast.expr.Expression)15 ExpressionStatement (org.codehaus.groovy.ast.stmt.ExpressionStatement)14 VariableExpression (org.codehaus.groovy.ast.expr.VariableExpression)13 Statement (org.codehaus.groovy.ast.stmt.Statement)13 ConstructorNode (org.codehaus.groovy.ast.ConstructorNode)12 ClosureExpression (org.codehaus.groovy.ast.expr.ClosureExpression)12 ConstantExpression (org.codehaus.groovy.ast.expr.ConstantExpression)11 EnumConstantClassNode (org.codehaus.groovy.ast.EnumConstantClassNode)10 GenericsType (org.codehaus.groovy.ast.GenericsType)10 ArgumentListExpression (org.codehaus.groovy.ast.expr.ArgumentListExpression)9