private void doProcessRecordType()

in src/main/java/org/codehaus/groovy/transform/RecordTypeASTTransformation.java [200:315]


    private void doProcessRecordType(final ClassNode cNode, final PropertyHandler handler) {
        if (cNode.getNodeMetaData("_RECORD_HEADER") != null) {
            cNode.putNodeMetaData("_SKIPPABLE_ANNOTATIONS", Boolean.TRUE);
        }
        List<AnnotationNode> annotations = cNode.getAnnotations(RECORD_OPTIONS_TYPE);
        AnnotationNode options = annotations.isEmpty() ? null : annotations.get(0);
        RecordTypeMode mode = getMode(options, "mode");
        boolean isAtLeastJDK16 = false;
        String message = "Expecting JDK16+ but unable to determine target bytecode";
        if (sourceUnit != null) {
            CompilerConfiguration config = sourceUnit.getConfiguration();
            String targetBytecode = config.getTargetBytecode();
            isAtLeastJDK16 = isAtLeast(targetBytecode, CompilerConfiguration.JDK16);
            message = "Expecting JDK16+ but found " + targetBytecode;
        }
        boolean isNative = (isAtLeastJDK16 && mode != RecordTypeMode.EMULATE);
        if (isNative) {
            String sName = cNode.getUnresolvedSuperClass().getName();
            // don't expect any parent to be set at this point but we only check at grammar
            // level when using the record keyword so do a few more sanity checks here
            if (!sName.equals(OBJECT) && !sName.equals(RECORD_CLASS_NAME)) {
                addError("Invalid superclass for native record found: " + sName, cNode);
            }
            cNode.setSuperClass(compilationUnit.getClassNodeResolver().resolveName(RECORD_CLASS_NAME, compilationUnit).getClassNode());
            cNode.setModifiers(cNode.getModifiers() | Opcodes.ACC_RECORD);
            final List<PropertyNode> pList = getInstanceProperties(cNode);
            if (!pList.isEmpty()) {
                cNode.setRecordComponents(new ArrayList<>());
            }
            for (PropertyNode pNode : pList) {
                ClassNode pType = pNode.getOriginType();
                ClassNode type = pType.getPlainNodeReference();
                type.setGenericsPlaceHolder(pType.isGenericsPlaceHolder());
                type.setGenericsTypes(pType.getGenericsTypes());
                RecordComponentNode rec = new RecordComponentNode(cNode, pNode.getName(), type, pNode.getAnnotations());
                rec.putNodeMetaData("_SKIPPABLE_ANNOTATIONS", Boolean.TRUE);
                cNode.getRecordComponents().add(rec);
            }
        } else if (mode == RecordTypeMode.NATIVE) {
            addError(message + " when attempting to create a native record", cNode);
        } else {
            createBeanInfoClass(cNode);
        }

        String cName = cNode.getName();
        if (!checkNotInterface(cNode, MY_TYPE_NAME)) return;
        makeClassFinal(this, cNode);
        makeInnerRecordStatic(cNode);

        final List<PropertyNode> pList = getInstanceProperties(cNode);
        for (PropertyNode pNode : pList) {
            adjustPropertyForShallowImmutability(cNode, pNode, handler);
            pNode.setModifiers(pNode.getModifiers() | ACC_FINAL);
        }
        final List<FieldNode> fList = cNode.getFields();
        for (FieldNode fNode : fList) {
            ensureNotPublic(this, cName, fNode);
        }
        // 0L serialVersionUID by default
        if (cNode.getDeclaredField("serialVersionUID") == null) {
            cNode.addField("serialVersionUID", ACC_PRIVATE | ACC_STATIC | ACC_FINAL, long_TYPE, constX(0L));
        }

        if (!hasAnnotation(cNode, ToStringASTTransformation.MY_TYPE)) {
            if (isNative) {
                createRecordToString(cNode);
            } else {
                ToStringASTTransformation.createToString(cNode, false, false, null,
                        null, true, false, false, false,
                        false, false, false, false, true,
                        new String[]{"[", "]", "=", ", "}, false);
            }
        }

        if (!hasAnnotation(cNode, EqualsAndHashCodeASTTransformation.MY_TYPE)) {
            if (isNative) {
                createRecordEquals(cNode);
                createRecordHashCode(cNode);
            } else {
                EqualsAndHashCodeASTTransformation.createEquals(cNode, false, false, false, null, null, false, false, true, false);
                EqualsAndHashCodeASTTransformation.createHashCode(cNode, true, false, false, null, null, false, false, true, false);
            }
        }

        if (hasAnnotation(cNode, TupleConstructorASTTransformation.MY_TYPE)) {
            AnnotationNode tupleCons = cNode.getAnnotations(TupleConstructorASTTransformation.MY_TYPE).get(0);
            if (unsupportedTupleAttribute(tupleCons, "excludes")) return;
            if (unsupportedTupleAttribute(tupleCons, "includes")) return;
            if (unsupportedTupleAttribute(tupleCons, "includeProperties")) return;
            if (unsupportedTupleAttribute(tupleCons, "includeSuperFields")) return;
        }

        if (options != null && memberHasValue(options, COPY_WITH, Boolean.TRUE) && !hasDeclaredMethod(cNode, COPY_WITH, 1)) {
            createCopyWith(cNode, pList);
        }

        if ((options == null || !memberHasValue(options, GET_AT, Boolean.FALSE)) && !hasDeclaredMethod(cNode, GET_AT, 1)) {
            createGetAt(cNode, pList);
        }

        if ((options == null || !memberHasValue(options, TO_LIST, Boolean.FALSE)) && !hasDeclaredMethod(cNode, TO_LIST, 0)) {
            createToList(cNode, pList);
        }

        if ((options == null || !memberHasValue(options, TO_MAP, Boolean.FALSE)) && !hasDeclaredMethod(cNode, TO_MAP, 0)) {
            createToMap(cNode, pList);
        }

        if (options != null && memberHasValue(options, COMPONENTS, Boolean.TRUE) && !hasDeclaredMethod(cNode, COMPONENTS, 0)) {
            createComponents(cNode, pList);
        }

        if ((options == null || !memberHasValue(options, SIZE, Boolean.FALSE)) && !hasDeclaredMethod(cNode, SIZE, 0)) {
            addGeneratedMethod(cNode, SIZE, ACC_PUBLIC | ACC_FINAL, int_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, returnS(constX(pList.size(), true)));
        }
    }