Search in sources :

Example 36 with InnerClassNode

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

the class LazyASTTransformation method addHolderClassIdiomBody.

private static void addHolderClassIdiomBody(BlockStatement body, FieldNode fieldNode, Expression initExpr) {
    final ClassNode declaringClass = fieldNode.getDeclaringClass();
    final ClassNode fieldType = fieldNode.getType();
    final int visibility = ACC_PRIVATE | ACC_STATIC;
    final String fullName = declaringClass.getName() + "$" + fieldType.getNameWithoutPackage() + "Holder_" + fieldNode.getName().substring(1);
    final InnerClassNode holderClass = new InnerClassNode(declaringClass, fullName, visibility, ClassHelper.OBJECT_TYPE);
    final String innerFieldName = "INSTANCE";
    holderClass.addField(innerFieldName, ACC_PRIVATE | ACC_STATIC | ACC_FINAL, fieldType, initExpr);
    final Expression innerField = propX(classX(holderClass), innerFieldName);
    declaringClass.getModule().addClass(holderClass);
    body.addStatement(returnS(innerField));
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) Expression(org.codehaus.groovy.ast.expr.Expression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode)

Example 37 with InnerClassNode

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

the class MacroInvocationTrap method buildSubstitutionMap.

private MapExpression buildSubstitutionMap(final ASTNode expr) {
    final Map<MacroSubstitutionKey, ClosureExpression> map = new HashMap<MacroSubstitutionKey, ClosureExpression>();
    final MapExpression mapExpression = new MapExpression();
    ClassCodeVisitorSupport visitor = new ClassCodeVisitorSupport() {

        @Override
        protected SourceUnit getSourceUnit() {
            return null;
        }

        @Override
        public void visitClass(final ClassNode node) {
            super.visitClass(node);
            Iterator<InnerClassNode> it = node.getInnerClasses();
            while (it.hasNext()) {
                InnerClassNode next = it.next();
                visitClass(next);
            }
        }

        @Override
        public void visitMethodCallExpression(MethodCallExpression call) {
            super.visitMethodCallExpression(call);
            if (isBuildInvocation(call, MacroTransformation.DOLLAR_VALUE)) {
                ClosureExpression substitutionClosureExpression = getClosureArgument(call);
                if (substitutionClosureExpression == null) {
                    return;
                }
                Statement code = substitutionClosureExpression.getCode();
                if (code instanceof BlockStatement) {
                    ((BlockStatement) code).setVariableScope(null);
                }
                MacroSubstitutionKey key = new MacroSubstitutionKey(call, expr.getLineNumber(), expr.getColumnNumber());
                map.put(key, substitutionClosureExpression);
            }
        }
    };
    if (expr instanceof ClassNode) {
        visitor.visitClass((ClassNode) expr);
    } else {
        expr.visit(visitor);
    }
    for (Map.Entry<MacroSubstitutionKey, ClosureExpression> entry : map.entrySet()) {
        mapExpression.addMapEntryExpression(entry.getKey().toConstructorCallExpression(), entry.getValue());
    }
    return mapExpression;
}
Also used : MapExpression(org.codehaus.groovy.ast.expr.MapExpression) ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) HashMap(java.util.HashMap) Statement(org.codehaus.groovy.ast.stmt.Statement) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) MacroSubstitutionKey(org.codehaus.groovy.macro.runtime.MacroSubstitutionKey) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) ClassCodeVisitorSupport(org.codehaus.groovy.ast.ClassCodeVisitorSupport) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression) HashMap(java.util.HashMap) Map(java.util.Map)

Example 38 with InnerClassNode

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

the class AsmClassGenerator method visitClass.

// GroovyClassVisitor interface
//-------------------------------------------------------------------------
public void visitClass(ClassNode classNode) {
    referencedClasses.clear();
    WriterControllerFactory factory = (WriterControllerFactory) classNode.getNodeMetaData(WriterControllerFactory.class);
    WriterController normalController = new WriterController();
    if (factory != null) {
        this.controller = factory.makeController(normalController);
    } else {
        this.controller = normalController;
    }
    this.controller.init(this, context, cv, classNode);
    if (controller.shouldOptimizeForInt() || factory != null) {
        OptimizingStatementWriter.setNodeMeta(controller.getTypeChooser(), classNode);
    }
    try {
        cv.visit(controller.getBytecodeVersion(), adjustedClassModifiersForClassWriting(classNode), controller.getInternalClassName(), BytecodeHelper.getGenericsSignature(classNode), controller.getInternalBaseClassName(), BytecodeHelper.getClassInternalNames(classNode.getInterfaces()));
        cv.visitSource(sourceFile, null);
        if (classNode instanceof InnerClassNode) {
            InnerClassNode innerClass = (InnerClassNode) classNode;
            MethodNode enclosingMethod = innerClass.getEnclosingMethod();
            if (enclosingMethod != null) {
                String outerClassName = BytecodeHelper.getClassInternalName(innerClass.getOuterClass().getName());
                cv.visitOuterClass(outerClassName, enclosingMethod.getName(), BytecodeHelper.getMethodDescriptor(enclosingMethod));
            }
        }
        if (classNode.getName().endsWith("package-info")) {
            PackageNode packageNode = classNode.getPackage();
            if (packageNode != null) {
                // pull them out of package node but treat them like they were on class node
                for (AnnotationNode an : packageNode.getAnnotations()) {
                    // skip built-in properties
                    if (an.isBuiltIn())
                        continue;
                    if (an.hasSourceRetention())
                        continue;
                    AnnotationVisitor av = getAnnotationVisitor(classNode, an, cv);
                    visitAnnotationAttributes(an, av);
                    av.visitEnd();
                }
            }
            cv.visitEnd();
            return;
        } else {
            visitAnnotations(classNode, cv);
        }
        if (classNode.isInterface()) {
            ClassNode owner = classNode;
            if (owner instanceof InnerClassNode) {
                owner = owner.getOuterClass();
            }
            String outerClassName = classNode.getName();
            String name = outerClassName + "$" + context.getNextInnerClassIdx();
            controller.setInterfaceClassLoadingClass(new InterfaceHelperClassNode(owner, name, ACC_SUPER | ACC_SYNTHETIC | ACC_STATIC, ClassHelper.OBJECT_TYPE, controller.getCallSiteWriter().getCallSites()));
            super.visitClass(classNode);
            createInterfaceSyntheticStaticFields();
        } else {
            super.visitClass(classNode);
            MopWriter.Factory mopWriterFactory = classNode.getNodeMetaData(MopWriter.Factory.class);
            if (mopWriterFactory == null) {
                mopWriterFactory = MopWriter.FACTORY;
            }
            MopWriter mopWriter = mopWriterFactory.create(controller);
            mopWriter.createMopMethods();
            controller.getCallSiteWriter().generateCallSiteArray();
            createSyntheticStaticFields();
        }
        // GROOVY-6750 and GROOVY-6808
        for (Iterator<InnerClassNode> iter = classNode.getInnerClasses(); iter.hasNext(); ) {
            InnerClassNode innerClass = iter.next();
            makeInnerClassEntry(innerClass);
        }
        makeInnerClassEntry(classNode);
        cv.visitEnd();
    } catch (GroovyRuntimeException e) {
        e.setModule(classNode.getModule());
        throw e;
    } catch (NegativeArraySizeException nase) {
        throw new GroovyRuntimeException("NegativeArraySizeException while processing " + sourceFile, nase);
    } catch (NullPointerException npe) {
        throw new GroovyRuntimeException("NPE while processing " + sourceFile, npe);
    }
}
Also used : InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) InterfaceHelperClassNode(org.codehaus.groovy.ast.InterfaceHelperClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) GroovyRuntimeException(groovy.lang.GroovyRuntimeException) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) WriterController(org.codehaus.groovy.classgen.asm.WriterController) MethodNode(org.codehaus.groovy.ast.MethodNode) AnnotationNode(org.codehaus.groovy.ast.AnnotationNode) AnnotationVisitor(org.objectweb.asm.AnnotationVisitor) InterfaceHelperClassNode(org.codehaus.groovy.ast.InterfaceHelperClassNode) PackageNode(org.codehaus.groovy.ast.PackageNode) MopWriter(org.codehaus.groovy.classgen.asm.MopWriter) WriterControllerFactory(org.codehaus.groovy.classgen.asm.WriterControllerFactory)

Example 39 with InnerClassNode

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

the class AsmClassGenerator method visitStdMethod.

private void visitStdMethod(MethodNode node, boolean isConstructor, Parameter[] parameters, Statement code) {
    MethodVisitor mv = controller.getMethodVisitor();
    final ClassNode superClass = controller.getClassNode().getSuperClass();
    if (isConstructor && (code == null || !((ConstructorNode) node).firstStatementIsSpecialConstructorCall())) {
        boolean hasCallToSuper = false;
        if (code != null && controller.getClassNode() instanceof InnerClassNode) {
            // so we must ensure not to add it twice (see GROOVY-4471)
            if (code instanceof BlockStatement) {
                for (Statement statement : ((BlockStatement) code).getStatements()) {
                    if (statement instanceof ExpressionStatement) {
                        final Expression expression = ((ExpressionStatement) statement).getExpression();
                        if (expression instanceof ConstructorCallExpression) {
                            ConstructorCallExpression call = (ConstructorCallExpression) expression;
                            if (call.isSuperCall()) {
                                hasCallToSuper = true;
                                break;
                            }
                        }
                    }
                }
            }
        }
        if (!hasCallToSuper) {
            // invokes the super class constructor
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKESPECIAL, BytecodeHelper.getClassInternalName(superClass), "<init>", "()V", false);
        }
    }
    controller.getCompileStack().init(node.getVariableScope(), parameters);
    controller.getCallSiteWriter().makeSiteEntry();
    // handle body
    super.visitConstructorOrMethod(node, isConstructor);
    controller.getCompileStack().clear();
    if (node.isVoidMethod()) {
        mv.visitInsn(RETURN);
    } else {
        // we make a dummy return for label ranges that reach here
        ClassNode type = node.getReturnType().redirect();
        if (ClassHelper.isPrimitiveType(type)) {
            mv.visitLdcInsn(0);
            controller.getOperandStack().push(ClassHelper.int_TYPE);
            controller.getOperandStack().doGroovyCast(type);
            BytecodeHelper.doReturn(mv, type);
            controller.getOperandStack().remove(1);
        } else {
            mv.visitInsn(ACONST_NULL);
            BytecodeHelper.doReturn(mv, type);
        }
    }
}
Also used : InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) InterfaceHelperClassNode(org.codehaus.groovy.ast.InterfaceHelperClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) ConstructorNode(org.codehaus.groovy.ast.ConstructorNode) CaseStatement(org.codehaus.groovy.ast.stmt.CaseStatement) ForStatement(org.codehaus.groovy.ast.stmt.ForStatement) CatchStatement(org.codehaus.groovy.ast.stmt.CatchStatement) IfStatement(org.codehaus.groovy.ast.stmt.IfStatement) AssertStatement(org.codehaus.groovy.ast.stmt.AssertStatement) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) Statement(org.codehaus.groovy.ast.stmt.Statement) WhileStatement(org.codehaus.groovy.ast.stmt.WhileStatement) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) ThrowStatement(org.codehaus.groovy.ast.stmt.ThrowStatement) DoWhileStatement(org.codehaus.groovy.ast.stmt.DoWhileStatement) ContinueStatement(org.codehaus.groovy.ast.stmt.ContinueStatement) BreakStatement(org.codehaus.groovy.ast.stmt.BreakStatement) ReturnStatement(org.codehaus.groovy.ast.stmt.ReturnStatement) SynchronizedStatement(org.codehaus.groovy.ast.stmt.SynchronizedStatement) SwitchStatement(org.codehaus.groovy.ast.stmt.SwitchStatement) TryCatchStatement(org.codehaus.groovy.ast.stmt.TryCatchStatement) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) MethodVisitor(org.objectweb.asm.MethodVisitor)

Example 40 with InnerClassNode

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

the class AsmClassGenerator method visitAttributeOrProperty.

private void visitAttributeOrProperty(PropertyExpression expression, MethodCallerMultiAdapter adapter) {
    MethodVisitor mv = controller.getMethodVisitor();
    Expression objectExpression = expression.getObjectExpression();
    ClassNode classNode = controller.getClassNode();
    if (isThisOrSuper(objectExpression)) {
        // let's use the field expression if it's available
        String name = expression.getPropertyAsString();
        if (name != null) {
            FieldNode field = null;
            boolean privateSuperField = false;
            if (isSuperExpression(objectExpression)) {
                field = classNode.getSuperClass().getDeclaredField(name);
                if (field != null && ((field.getModifiers() & ACC_PRIVATE) != 0)) {
                    privateSuperField = true;
                }
            } else {
                if (controller.isNotExplicitThisInClosure(expression.isImplicitThis())) {
                    field = classNode.getDeclaredField(name);
                    if (field == null && classNode instanceof InnerClassNode) {
                        ClassNode outer = classNode.getOuterClass();
                        FieldNode outerClassField;
                        while (outer != null) {
                            outerClassField = outer.getDeclaredField(name);
                            if (outerClassField != null && outerClassField.isStatic() && outerClassField.isFinal()) {
                                if (outer != classNode.getOuterClass() && Modifier.isPrivate(outerClassField.getModifiers())) {
                                    throw new GroovyBugError("Trying to access private constant field [" + outerClassField.getDeclaringClass() + "#" + outerClassField.getName() + "] from inner class");
                                }
                                PropertyExpression pexp = new PropertyExpression(new ClassExpression(outer), expression.getProperty());
                                pexp.visit(controller.getAcg());
                                return;
                            }
                            outer = outer.getSuperClass();
                        }
                    }
                    if (field == null && expression instanceof AttributeExpression && isThisExpression(objectExpression) && controller.isStaticContext()) {
                        // GROOVY-6183
                        ClassNode current = classNode.getSuperClass();
                        while (field == null && current != null) {
                            field = current.getDeclaredField(name);
                            current = current.getSuperClass();
                        }
                        if (field != null && (field.isProtected() || field.isPublic())) {
                            visitFieldExpression(new FieldExpression(field));
                            return;
                        }
                    }
                }
            }
            if (field != null && !privateSuperField) {
                //GROOVY-4497: don't visit super field if it is private
                visitFieldExpression(new FieldExpression(field));
                return;
            }
            if (isSuperExpression(objectExpression)) {
                String prefix;
                if (controller.getCompileStack().isLHS()) {
                    throw new GroovyBugError("Unexpected super property set for:" + expression.getText());
                } else {
                    prefix = "get";
                }
                String propName = prefix + MetaClassHelper.capitalize(name);
                visitMethodCallExpression(new MethodCallExpression(objectExpression, propName, MethodCallExpression.NO_ARGUMENTS));
                return;
            }
        }
    }
    final String propName = expression.getPropertyAsString();
    //TODO: add support for super here too
    if (expression.getObjectExpression() instanceof ClassExpression && propName != null && propName.equals("this")) {
        // we have something like A.B.this, and need to make it
        // into this.this$0.this$0, where this.this$0 returns
        // A.B and this.this$0.this$0 return A.
        ClassNode type = objectExpression.getType();
        ClassNode iterType = classNode;
        if (controller.getCompileStack().isInSpecialConstructorCall() && classNode instanceof InnerClassNode) {
            boolean staticInnerClass = classNode.isStaticClass();
            // Outer.this in a special constructor call
            if (classNode.getOuterClass().equals(type)) {
                ConstructorNode ctor = controller.getConstructorNode();
                Expression receiver = !staticInnerClass ? new VariableExpression(ctor.getParameters()[0]) : new ClassExpression(type);
                receiver.setSourcePosition(expression);
                receiver.visit(this);
                return;
            }
        }
        mv.visitVarInsn(ALOAD, 0);
        while (!iterType.equals(type)) {
            String ownerName = BytecodeHelper.getClassInternalName(iterType);
            if (iterType.getOuterClass() == null)
                break;
            FieldNode thisField = iterType.getField("this$0");
            iterType = iterType.getOuterClass();
            if (thisField == null) {
                // closure within inner class
                mv.visitMethodInsn(INVOKEVIRTUAL, BytecodeHelper.getClassInternalName(ClassHelper.CLOSURE_TYPE), "getThisObject", "()Ljava/lang/Object;", false);
                mv.visitTypeInsn(CHECKCAST, BytecodeHelper.getClassInternalName(iterType));
            } else {
                ClassNode thisFieldType = thisField.getType();
                if (ClassHelper.CLOSURE_TYPE.equals(thisFieldType)) {
                    mv.visitFieldInsn(GETFIELD, ownerName, "this$0", BytecodeHelper.getTypeDescription(ClassHelper.CLOSURE_TYPE));
                    mv.visitMethodInsn(INVOKEVIRTUAL, BytecodeHelper.getClassInternalName(ClassHelper.CLOSURE_TYPE), "getThisObject", "()Ljava/lang/Object;", false);
                    mv.visitTypeInsn(CHECKCAST, BytecodeHelper.getClassInternalName(iterType));
                } else {
                    String typeName = BytecodeHelper.getTypeDescription(iterType);
                    mv.visitFieldInsn(GETFIELD, ownerName, "this$0", typeName);
                }
            }
        }
        controller.getOperandStack().push(type);
        return;
    }
    if (adapter == getProperty && !expression.isSpreadSafe() && propName != null) {
        controller.getCallSiteWriter().makeGetPropertySite(objectExpression, propName, expression.isSafe(), expression.isImplicitThis());
    } else if (adapter == getGroovyObjectProperty && !expression.isSpreadSafe() && propName != null) {
        controller.getCallSiteWriter().makeGroovyObjectGetPropertySite(objectExpression, propName, expression.isSafe(), expression.isImplicitThis());
    } else {
        // todo: for improved modularity and extensibility, this should be moved into a writer
        if (controller.getCompileStack().isLHS())
            controller.getOperandStack().box();
        controller.getInvocationWriter().makeCall(expression, // receiver
        objectExpression, // messageName
        new CastExpression(ClassHelper.STRING_TYPE, expression.getProperty()), MethodCallExpression.NO_ARGUMENTS, adapter, expression.isSafe(), expression.isSpreadSafe(), expression.isImplicitThis());
    }
}
Also used : InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) InterfaceHelperClassNode(org.codehaus.groovy.ast.InterfaceHelperClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) FieldNode(org.codehaus.groovy.ast.FieldNode) GroovyBugError(org.codehaus.groovy.GroovyBugError) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) MethodVisitor(org.objectweb.asm.MethodVisitor) ConstructorNode(org.codehaus.groovy.ast.ConstructorNode)

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