private void printClassContents()

in src/main/java/org/codehaus/groovy/tools/javac/JavaStubGenerator.java [226:405]


    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 pn) {
                    // GROOVY-8233 skip static properties for traits since they don't make the interface
                    if (!pn.isStatic() || !Traits.isTrait(pn.getDeclaringClass())) {
                        super.visitProperty(pn);
                    }
                }

                @Override
                public void addCovariantMethods(ClassNode cn) {}
                @Override
                protected void addInitialization(ClassNode cn) {}
                @Override
                protected void addInitialization(ClassNode cn, ConstructorNode c) {}
                @Override
                protected void addPropertyMethod(MethodNode mn) {
                    markAsGenerated(getClassNode(), mn);
                    doAddMethod(mn);
                }
                @Override
                protected void addReturnIfNeeded(MethodNode mn) {}

                private   MethodNode doAddMethod(MethodNode mn) {
                    propertyMethods.putIfAbsent(mn.getTypeDescriptor(), mn);
                    return mn;
                }

                @Override
                protected MethodNode addMethod(ClassNode cn, boolean shouldBeSynthetic, String name, int modifiers, ClassNode returnType, Parameter[] parameters, ClassNode[] exceptions, Statement code) {
                    if (!shouldBeSynthetic) modifiers &= ~Opcodes.ACC_SYNTHETIC;
                    return doAddMethod(new MethodNode(name, modifiers, returnType, parameters, exceptions, code));
                }

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

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

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

                @Override
                protected FinalVariableAnalyzer.VariableNotFinalCallback getFinalVariablesCallback() {
                    return null;
                }
            };
            int constructorCount = classNode.getDeclaredConstructors().size();
            verifier.visitClass(classNode);
            // undo unwanted side effect of Verifier
            if (constructorCount == 0 && classNode.getDeclaredConstructors().size() == 1) {
                classNode.getDeclaredConstructors().clear();
            }

            boolean isEnum = classNode.isEnum();
            boolean isInterface = !isEnum && isInterfaceOrTrait(classNode);
            boolean isAnnotationDefinition = classNode.isAnnotationDefinition();
            printAnnotations(out, classNode);

            int flags = classNode.getModifiers();
            if (isEnum) flags &= ~Opcodes.ACC_FINAL;
            if (isEnum || isInterface) flags &= ~Opcodes.ACC_ABSTRACT;
            if (classNode.isSyntheticPublic() && hasPackageScopeXform(classNode,
                        PackageScopeTarget.CLASS)) flags &= ~Opcodes.ACC_PUBLIC;
            printModifiers(out, flags);

            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);
            printTypeParameters(out, classNode.getGenericsTypes());

            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, isInterface);
            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
                constructors.clear();
                propertyMethods.clear();
                printClassContents(out, inner.next());
            }

            out.println("}");
        } finally {
            constructors.clear();
            propertyMethods.clear();
        }
    }