Search in sources :

Example 1 with RecordTypeMode

use of groovy.transform.RecordTypeMode in project groovy by apache.

the class RecordTypeASTTransformation method doProcessRecordType.

private void doProcessRecordType(ClassNode cNode, PropertyHandler handler) {
    List<AnnotationNode> annotations = cNode.getAnnotations(RECORD_OPTIONS_TYPE);
    AnnotationNode options = annotations.isEmpty() ? null : annotations.get(0);
    RecordTypeMode mode = getMode(options, "mode");
    boolean isPostJDK16 = false;
    String message = "Expecting JDK16+ but unable to determine target bytecode";
    if (sourceUnit != null) {
        CompilerConfiguration config = sourceUnit.getConfiguration();
        String targetBytecode = config.getTargetBytecode();
        isPostJDK16 = CompilerConfiguration.isPostJDK16(targetBytecode);
        message = "Expecting JDK16+ but found " + targetBytecode;
    }
    boolean isNative = isPostJDK16 && mode != RecordTypeMode.EMULATE;
    if (isNative) {
        String sName = cNode.getUnresolvedSuperClass().getName();
        // level when using the record keyword so do a few more sanity checks here
        if (!sName.equals("java.lang.Object") && !sName.equals(RECORD_CLASS_NAME)) {
            addError("Invalid superclass for native record found: " + sName, cNode);
        }
        cNode.setSuperClass(ClassHelper.makeWithoutCaching(RECORD_CLASS_NAME));
        cNode.setModifiers(cNode.getModifiers() | Opcodes.ACC_RECORD);
        final List<PropertyNode> pList = getInstanceProperties(cNode);
        if (!pList.isEmpty()) {
            cNode.setRecordComponents(new ArrayList<>());
        }
        for (PropertyNode pNode : pList) {
            cNode.getRecordComponents().add(new RecordComponentNode(cNode, pNode.getName(), pNode.getOriginType(), pNode.getAnnotations()));
        }
    } else if (mode == RecordTypeMode.NATIVE) {
        addError(message + " when attempting to create a native record", 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, ClassHelper.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, true, false, false, false, false, false, new String[] { "[", "]", "=", ", " });
        }
    }
    if (!hasAnnotation(cNode, EqualsAndHashCodeASTTransformation.MY_TYPE)) {
        if (isNative) {
            createRecordEquals(cNode);
            createRecordHashCode(cNode);
        } else {
            EqualsAndHashCodeASTTransformation.createEquals(cNode, false, false, false, null, null);
            EqualsAndHashCodeASTTransformation.createHashCode(cNode, false, false, false, null, null);
        }
    }
    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, PUBLIC_FINAL, int_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, returnS(constX(pList.size())));
    }
}
Also used : RecordTypeMode(groovy.transform.RecordTypeMode) RecordComponentNode(org.codehaus.groovy.ast.RecordComponentNode) FieldNode(org.codehaus.groovy.ast.FieldNode) AnnotationNode(org.codehaus.groovy.ast.AnnotationNode) PropertyNode(org.codehaus.groovy.ast.PropertyNode) CompilerConfiguration(org.codehaus.groovy.control.CompilerConfiguration)

Aggregations

RecordTypeMode (groovy.transform.RecordTypeMode)1 AnnotationNode (org.codehaus.groovy.ast.AnnotationNode)1 FieldNode (org.codehaus.groovy.ast.FieldNode)1 PropertyNode (org.codehaus.groovy.ast.PropertyNode)1 RecordComponentNode (org.codehaus.groovy.ast.RecordComponentNode)1 CompilerConfiguration (org.codehaus.groovy.control.CompilerConfiguration)1