Search in sources :

Example 1 with VerifierCodeVisitor

use of org.codehaus.groovy.classgen.VerifierCodeVisitor in project groovy by apache.

the class JavaStubGenerator method printClassContents.

private void printClassContents(PrintWriter out, ClassNode classNode) {
    if (classNode instanceof InnerClassNode && ((InnerClassNode) classNode).isAnonymous()) {
        // if it is an anonymous inner class, don't generate the stub code for it.
        return;
    }
    try {
        Verifier verifier = new Verifier() {

            @Override
            public void visitClass(ClassNode node) {
                List<Statement> savedStatements = new ArrayList<>(node.getObjectInitializerStatements());
                super.visitClass(node);
                node.getObjectInitializerStatements().addAll(savedStatements);
                for (ClassNode trait : findTraits(node)) {
                    // GROOVY-9031: replace property type placeholder with resolved type from trait generics
                    Map<String, ClassNode> generics = trait.isUsingGenerics() ? createGenericsSpec(trait) : null;
                    for (PropertyNode traitProperty : trait.getProperties()) {
                        ClassNode traitPropertyType = traitProperty.getType();
                        traitProperty.setType(correctToGenericsSpecRecurse(generics, traitPropertyType));
                        super.visitProperty(traitProperty);
                        traitProperty.setType(traitPropertyType);
                    }
                }
            }

            @Override
            public void visitConstructor(ConstructorNode node) {
                Statement stmt = node.getCode();
                if (stmt != null) {
                    stmt.visit(new VerifierCodeVisitor(getClassNode()));
                }
            }

            @Override
            public void visitProperty(PropertyNode node) {
                // GROOVY-8233 skip static properties for traits since they don't make the interface
                if (!node.isStatic() || !Traits.isTrait(node.getDeclaringClass())) {
                    super.visitProperty(node);
                }
            }

            @Override
            public void addCovariantMethods(ClassNode cn) {
            }

            @Override
            protected void addInitialization(ClassNode node) {
            }

            @Override
            protected void addPropertyMethod(MethodNode method) {
                doAddMethod(method);
            }

            @Override
            protected void addReturnIfNeeded(MethodNode node) {
            }

            @Override
            protected MethodNode addMethod(ClassNode node, boolean shouldBeSynthetic, String name, int modifiers, ClassNode returnType, Parameter[] parameters, ClassNode[] exceptions, Statement code) {
                return doAddMethod(new MethodNode(name, modifiers, returnType, parameters, exceptions, code));
            }

            @Override
            protected void addConstructor(Parameter[] newParams, ConstructorNode ctor, Statement code, ClassNode node) {
                if (code instanceof ExpressionStatement) {
                    // GROOVY-4508
                    Statement temp = code;
                    code = new BlockStatement();
                    ((BlockStatement) code).addStatement(temp);
                }
                ConstructorNode ctrNode = new ConstructorNode(ctor.getModifiers(), newParams, ctor.getExceptions(), code);
                ctrNode.setDeclaringClass(node);
                constructors.add(ctrNode);
            }

            @Override
            protected void addDefaultParameters(DefaultArgsAction action, MethodNode method) {
                final Parameter[] parameters = method.getParameters();
                final Expression[] saved = new Expression[parameters.length];
                for (int i = 0; i < parameters.length; i++) {
                    if (parameters[i].hasInitialExpression())
                        saved[i] = parameters[i].getInitialExpression();
                }
                super.addDefaultParameters(action, method);
                for (int i = 0; i < parameters.length; i++) {
                    if (saved[i] != null)
                        parameters[i].setInitialExpression(saved[i]);
                }
            }

            private MethodNode doAddMethod(MethodNode method) {
                String sig = method.getTypeDescriptor();
                if (propertyMethodsWithSigs.containsKey(sig))
                    return method;
                propertyMethods.add(method);
                propertyMethodsWithSigs.put(sig, method);
                return method;
            }

            @Override
            protected void addDefaultConstructor(ClassNode node) {
            // not required for stub generation
            }

            @Override
            protected FinalVariableAnalyzer.VariableNotFinalCallback getFinalVariablesCallback() {
                return null;
            }
        };
        int origNumConstructors = classNode.getDeclaredConstructors().size();
        verifier.visitClass(classNode);
        // undo unwanted side-effect of verifier
        if (origNumConstructors == 0 && classNode.getDeclaredConstructors().size() == 1) {
            classNode.getDeclaredConstructors().clear();
        }
        boolean isInterface = isInterfaceOrTrait(classNode);
        boolean isEnum = classNode.isEnum();
        boolean isAnnotationDefinition = classNode.isAnnotationDefinition();
        printAnnotations(out, classNode);
        printModifiers(out, classNode.getModifiers() & ~(isInterface ? Opcodes.ACC_ABSTRACT : 0) & ~(isEnum ? Opcodes.ACC_FINAL | Opcodes.ACC_ABSTRACT : 0));
        if (isInterface) {
            if (isAnnotationDefinition) {
                out.print("@");
            }
            out.print("interface ");
        } else if (isEnum) {
            out.print("enum ");
        } else {
            out.print("class ");
        }
        String className = classNode.getNameWithoutPackage();
        if (classNode instanceof InnerClassNode)
            className = className.substring(className.lastIndexOf('$') + 1);
        out.println(className);
        printGenericsBounds(out, classNode, true);
        ClassNode superClass = classNode.getUnresolvedSuperClass(false);
        if (!isInterface && !isEnum) {
            out.print("  extends ");
            printType(out, superClass);
        }
        ClassNode[] interfaces = classNode.getInterfaces();
        if (interfaces != null && interfaces.length > 0 && !isAnnotationDefinition) {
            if (isInterface) {
                out.println("  extends");
            } else {
                out.println("  implements");
            }
            for (int i = 0; i < interfaces.length - 1; ++i) {
                out.print("    ");
                printType(out, interfaces[i]);
                out.print(",");
            }
            out.print("    ");
            printType(out, interfaces[interfaces.length - 1]);
        }
        out.println(" {");
        printFields(out, classNode);
        printMethods(out, classNode, isEnum);
        for (Iterator<InnerClassNode> inner = classNode.getInnerClasses(); inner.hasNext(); ) {
            // GROOVY-4004: Clear the methods from the outer class so that they don't get duplicated in inner ones
            propertyMethods.clear();
            propertyMethodsWithSigs.clear();
            constructors.clear();
            printClassContents(out, inner.next());
        }
        out.println("}");
    } finally {
        propertyMethods.clear();
        propertyMethodsWithSigs.clear();
        constructors.clear();
    }
}
Also used : DecompiledClassNode(org.codehaus.groovy.ast.decompiled.DecompiledClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) 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) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) Verifier(org.codehaus.groovy.classgen.Verifier) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) VerifierCodeVisitor(org.codehaus.groovy.classgen.VerifierCodeVisitor) MethodNode(org.codehaus.groovy.ast.MethodNode) ListExpression(org.codehaus.groovy.ast.expr.ListExpression) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) PropertyExpression(org.codehaus.groovy.ast.expr.PropertyExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) Expression(org.codehaus.groovy.ast.expr.Expression) ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) PropertyNode(org.codehaus.groovy.ast.PropertyNode) ConstructorNode(org.codehaus.groovy.ast.ConstructorNode) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) Parameter(org.codehaus.groovy.ast.Parameter) FinalVariableAnalyzer(org.codehaus.groovy.classgen.FinalVariableAnalyzer)

Aggregations

ArrayList (java.util.ArrayList)1 ClassNode (org.codehaus.groovy.ast.ClassNode)1 ConstructorNode (org.codehaus.groovy.ast.ConstructorNode)1 InnerClassNode (org.codehaus.groovy.ast.InnerClassNode)1 MethodNode (org.codehaus.groovy.ast.MethodNode)1 Parameter (org.codehaus.groovy.ast.Parameter)1 PropertyNode (org.codehaus.groovy.ast.PropertyNode)1 DecompiledClassNode (org.codehaus.groovy.ast.decompiled.DecompiledClassNode)1 ArgumentListExpression (org.codehaus.groovy.ast.expr.ArgumentListExpression)1 ClassExpression (org.codehaus.groovy.ast.expr.ClassExpression)1 ClosureExpression (org.codehaus.groovy.ast.expr.ClosureExpression)1 ConstantExpression (org.codehaus.groovy.ast.expr.ConstantExpression)1 ConstructorCallExpression (org.codehaus.groovy.ast.expr.ConstructorCallExpression)1 Expression (org.codehaus.groovy.ast.expr.Expression)1 ListExpression (org.codehaus.groovy.ast.expr.ListExpression)1 MethodCallExpression (org.codehaus.groovy.ast.expr.MethodCallExpression)1 PropertyExpression (org.codehaus.groovy.ast.expr.PropertyExpression)1 VariableExpression (org.codehaus.groovy.ast.expr.VariableExpression)1 BlockStatement (org.codehaus.groovy.ast.stmt.BlockStatement)1 ExpressionStatement (org.codehaus.groovy.ast.stmt.ExpressionStatement)1