Search in sources :

Example 1 with CheckerFrameworkVersion

use of lombok.core.configuration.CheckerFrameworkVersion in project lombok by rzwitserloot.

the class HandleEqualsAndHashCode method createEquals.

public JCMethodDecl createEquals(JavacNode typeNode, java.util.List<Included<JavacNode, EqualsAndHashCode.Include>> members, boolean callSuper, FieldAccess fieldAccess, boolean needsCanEqual, JavacNode source, List<JCAnnotation> onParam) {
    JavacTreeMaker maker = typeNode.getTreeMaker();
    Name oName = typeNode.toName("o");
    Name otherName = typeNode.toName("other");
    Name thisName = typeNode.toName("this");
    List<JCAnnotation> annsOnParamOnMethod = List.nil();
    JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(typeNode, "Override"), List.<JCExpression>nil());
    List<JCAnnotation> annsOnMethod = List.of(overrideAnnotation);
    CheckerFrameworkVersion checkerFramework = getCheckerFrameworkVersion(typeNode);
    if (checkerFramework.generateSideEffectFree()) {
        annsOnMethod = annsOnMethod.prepend(maker.Annotation(genTypeRef(typeNode, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil()));
    }
    JCModifiers mods = maker.Modifiers(Flags.PUBLIC, annsOnMethod);
    JCExpression objectType;
    if (annsOnParamOnMethod.isEmpty()) {
        objectType = genJavaLangTypeRef(typeNode, "Object");
    } else {
        objectType = chainDots(typeNode, "java", "lang", "Object");
        objectType = maker.AnnotatedType(annsOnParamOnMethod, objectType);
    }
    JCExpression returnType = maker.TypeIdent(CTC_BOOLEAN);
    long finalFlag = JavacHandlerUtil.addFinalIfNeeded(0L, typeNode.getContext());
    ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
    JCVariableDecl param = maker.VarDef(maker.Modifiers(finalFlag | Flags.PARAMETER, onParam), oName, objectType, null);
    JavacHandlerUtil.createRelevantNullableAnnotation(typeNode, param);
    final List<JCVariableDecl> params = List.of(param);
    /* if (o == this) return true; */
    {
        statements.append(maker.If(maker.Binary(CTC_EQUAL, maker.Ident(oName), maker.Ident(thisName)), returnBool(maker, true), null));
    }
    /* if (!(o instanceof Outer.Inner.MyType)) return false; */
    {
        JCUnary notInstanceOf = maker.Unary(CTC_NOT, maker.Parens(maker.TypeTest(maker.Ident(oName), createTypeReference(typeNode, false))));
        statements.append(maker.If(notInstanceOf, returnBool(maker, false), null));
    }
    /* Outer.Inner.MyType<?> other = (Outer.Inner.MyType<?>) o; */
    {
        if (!members.isEmpty() || needsCanEqual) {
            final JCExpression selfType1 = createTypeReference(typeNode, true), selfType2 = createTypeReference(typeNode, true);
            statements.append(maker.VarDef(maker.Modifiers(finalFlag), otherName, selfType1, maker.TypeCast(selfType2, maker.Ident(oName))));
        }
    }
    /* if (!other.canEqual((java.lang.Object) this)) return false; */
    {
        if (needsCanEqual) {
            List<JCExpression> exprNil = List.nil();
            JCExpression thisRef = maker.Ident(thisName);
            JCExpression castThisRef = maker.TypeCast(genJavaLangTypeRef(typeNode, "Object"), thisRef);
            JCExpression equalityCheck = maker.Apply(exprNil, maker.Select(maker.Ident(otherName), typeNode.toName("canEqual")), List.of(castThisRef));
            statements.append(maker.If(maker.Unary(CTC_NOT, equalityCheck), returnBool(maker, false), null));
        }
    }
    /* if (!super.equals(o)) return false; */
    if (callSuper) {
        JCMethodInvocation callToSuper = maker.Apply(List.<JCExpression>nil(), maker.Select(maker.Ident(typeNode.toName("super")), typeNode.toName("equals")), List.<JCExpression>of(maker.Ident(oName)));
        JCUnary superNotEqual = maker.Unary(CTC_NOT, callToSuper);
        statements.append(maker.If(superNotEqual, returnBool(maker, false), null));
    }
    for (Included<JavacNode, EqualsAndHashCode.Include> member : members) {
        JavacNode memberNode = member.getNode();
        boolean isMethod = memberNode.getKind() == Kind.METHOD;
        JCExpression fType = unnotate(getFieldType(memberNode, fieldAccess));
        JCExpression thisFieldAccessor = isMethod ? createMethodAccessor(maker, memberNode) : createFieldAccessor(maker, memberNode, fieldAccess);
        JCExpression otherFieldAccessor = isMethod ? createMethodAccessor(maker, memberNode, maker.Ident(otherName)) : createFieldAccessor(maker, memberNode, fieldAccess, maker.Ident(otherName));
        if (fType instanceof JCPrimitiveTypeTree) {
            switch(((JCPrimitiveTypeTree) fType).getPrimitiveTypeKind()) {
                case FLOAT:
                    /* if (Float.compare(this.fieldName, other.fieldName) != 0) return false; */
                    statements.append(generateCompareFloatOrDouble(thisFieldAccessor, otherFieldAccessor, maker, typeNode, false));
                    break;
                case DOUBLE:
                    /* if (Double.compare(this.fieldName, other.fieldName) != 0) return false; */
                    statements.append(generateCompareFloatOrDouble(thisFieldAccessor, otherFieldAccessor, maker, typeNode, true));
                    break;
                default:
                    /* if (this.fieldName != other.fieldName) return false; */
                    statements.append(maker.If(maker.Binary(CTC_NOT_EQUAL, thisFieldAccessor, otherFieldAccessor), returnBool(maker, false), null));
                    break;
            }
        } else if (fType instanceof JCArrayTypeTree) {
            JCArrayTypeTree array = (JCArrayTypeTree) fType;
            /* if (!java.util.Arrays.deepEquals(this.fieldName, other.fieldName)) return false; //use equals for primitive arrays. */
            boolean multiDim = unnotate(array.elemtype) instanceof JCArrayTypeTree;
            boolean primitiveArray = unnotate(array.elemtype) instanceof JCPrimitiveTypeTree;
            boolean useDeepEquals = multiDim || !primitiveArray;
            JCExpression eqMethod = chainDots(typeNode, "java", "util", "Arrays", useDeepEquals ? "deepEquals" : "equals");
            List<JCExpression> args = List.of(thisFieldAccessor, otherFieldAccessor);
            statements.append(maker.If(maker.Unary(CTC_NOT, maker.Apply(List.<JCExpression>nil(), eqMethod, args)), returnBool(maker, false), null));
        } else /* objects */
        {
            /* final java.lang.Object this$fieldName = this.fieldName; */
            /* final java.lang.Object other$fieldName = other.fieldName; */
            /* if (this$fieldName == null ? other$fieldName != null : !this$fieldName.equals(other$fieldName)) return false; */
            Name thisDollarFieldName = memberNode.toName("this" + (isMethod ? "$$" : "$") + memberNode.getName());
            Name otherDollarFieldName = memberNode.toName("other" + (isMethod ? "$$" : "$") + memberNode.getName());
            statements.append(maker.VarDef(maker.Modifiers(finalFlag), thisDollarFieldName, genJavaLangTypeRef(typeNode, "Object"), thisFieldAccessor));
            statements.append(maker.VarDef(maker.Modifiers(finalFlag), otherDollarFieldName, genJavaLangTypeRef(typeNode, "Object"), otherFieldAccessor));
            JCExpression thisEqualsNull = maker.Binary(CTC_EQUAL, maker.Ident(thisDollarFieldName), maker.Literal(CTC_BOT, null));
            JCExpression otherNotEqualsNull = maker.Binary(CTC_NOT_EQUAL, maker.Ident(otherDollarFieldName), maker.Literal(CTC_BOT, null));
            JCExpression thisEqualsThat = maker.Apply(List.<JCExpression>nil(), maker.Select(maker.Ident(thisDollarFieldName), typeNode.toName("equals")), List.<JCExpression>of(maker.Ident(otherDollarFieldName)));
            JCExpression fieldsAreNotEqual = maker.Conditional(thisEqualsNull, otherNotEqualsNull, maker.Unary(CTC_NOT, thisEqualsThat));
            statements.append(maker.If(fieldsAreNotEqual, returnBool(maker, false), null));
        }
    }
    /* return true; */
    {
        statements.append(returnBool(maker, true));
    }
    JCBlock body = maker.Block(0, statements.toList());
    return recursiveSetGeneratedBy(maker.MethodDef(mods, typeNode.toName("equals"), returnType, List.<JCTypeParameter>nil(), params, List.<JCExpression>nil(), body, null), source);
}
Also used : JCBlock(com.sun.tools.javac.tree.JCTree.JCBlock) JavacTreeMaker(lombok.javac.JavacTreeMaker) ListBuffer(com.sun.tools.javac.util.ListBuffer) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement) JCVariableDecl(com.sun.tools.javac.tree.JCTree.JCVariableDecl) Name(com.sun.tools.javac.util.Name) JCTypeParameter(com.sun.tools.javac.tree.JCTree.JCTypeParameter) JCMethodInvocation(com.sun.tools.javac.tree.JCTree.JCMethodInvocation) JCPrimitiveTypeTree(com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JavacNode(lombok.javac.JavacNode) JCModifiers(com.sun.tools.javac.tree.JCTree.JCModifiers) JCUnary(com.sun.tools.javac.tree.JCTree.JCUnary) CheckerFrameworkVersion(lombok.core.configuration.CheckerFrameworkVersion) ArrayList(java.util.ArrayList) List(com.sun.tools.javac.util.List) JCAnnotation(com.sun.tools.javac.tree.JCTree.JCAnnotation) JCArrayTypeTree(com.sun.tools.javac.tree.JCTree.JCArrayTypeTree)

Example 2 with CheckerFrameworkVersion

use of lombok.core.configuration.CheckerFrameworkVersion in project lombok by rzwitserloot.

the class HandleEqualsAndHashCode method createHashCode.

public JCMethodDecl createHashCode(JavacNode typeNode, java.util.List<Included<JavacNode, EqualsAndHashCode.Include>> members, boolean callSuper, boolean cacheHashCode, FieldAccess fieldAccess, JavacNode source) {
    JavacTreeMaker maker = typeNode.getTreeMaker();
    JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(typeNode, "Override"), List.<JCExpression>nil());
    List<JCAnnotation> annsOnMethod = List.of(overrideAnnotation);
    CheckerFrameworkVersion checkerFramework = getCheckerFrameworkVersion(typeNode);
    if (cacheHashCode && checkerFramework.generatePure()) {
        annsOnMethod = annsOnMethod.prepend(maker.Annotation(genTypeRef(typeNode, CheckerFrameworkVersion.NAME__PURE), List.<JCExpression>nil()));
    } else if (checkerFramework.generateSideEffectFree()) {
        annsOnMethod = annsOnMethod.prepend(maker.Annotation(genTypeRef(typeNode, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil()));
    }
    JCModifiers mods = maker.Modifiers(Flags.PUBLIC, annsOnMethod);
    JCExpression returnType = maker.TypeIdent(CTC_INT);
    ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
    Name primeName = typeNode.toName(PRIME_NAME);
    Name resultName = typeNode.toName(RESULT_NAME);
    long finalFlag = JavacHandlerUtil.addFinalIfNeeded(0L, typeNode.getContext());
    boolean isEmpty = members.isEmpty();
    /* if (this.$hashCodeCache != 0) return this.$hashCodeCache; */
    {
        if (cacheHashCode) {
            JCIdent receiver = maker.Ident(typeNode.toName("this"));
            JCFieldAccess cacheHashCodeFieldAccess = maker.Select(receiver, typeNode.toName(HASH_CODE_CACHE_NAME));
            JCExpression cacheNotZero = maker.Binary(CTC_NOT_EQUAL, cacheHashCodeFieldAccess, maker.Literal(CTC_INT, 0));
            statements.append(maker.If(cacheNotZero, maker.Return(cacheHashCodeFieldAccess), null));
        }
    }
    /* final int PRIME = X; */
    {
        if (!isEmpty) {
            statements.append(maker.VarDef(maker.Modifiers(finalFlag), primeName, maker.TypeIdent(CTC_INT), maker.Literal(HandlerUtil.primeForHashcode())));
        }
    }
    /* int result = ... */
    {
        final JCExpression init;
        if (callSuper) {
            /* ... super.hashCode(); */
            init = maker.Apply(List.<JCExpression>nil(), maker.Select(maker.Ident(typeNode.toName("super")), typeNode.toName("hashCode")), List.<JCExpression>nil());
        } else {
            /* ... 1; */
            init = maker.Literal(1);
        }
        statements.append(maker.VarDef(maker.Modifiers(isEmpty && !cacheHashCode ? finalFlag : 0L), resultName, maker.TypeIdent(CTC_INT), init));
    }
    for (Included<JavacNode, EqualsAndHashCode.Include> member : members) {
        JavacNode memberNode = member.getNode();
        JCExpression fType = unnotate(getFieldType(memberNode, fieldAccess));
        boolean isMethod = memberNode.getKind() == Kind.METHOD;
        JCExpression fieldAccessor = isMethod ? createMethodAccessor(maker, memberNode) : createFieldAccessor(maker, memberNode, fieldAccess);
        if (fType instanceof JCPrimitiveTypeTree) {
            switch(((JCPrimitiveTypeTree) fType).getPrimitiveTypeKind()) {
                case BOOLEAN:
                    /* this.fieldName ? X : Y */
                    statements.append(createResultCalculation(typeNode, maker.Parens(maker.Conditional(fieldAccessor, maker.Literal(HandlerUtil.primeForTrue()), maker.Literal(HandlerUtil.primeForFalse())))));
                    break;
                case LONG:
                    {
                        Name dollarFieldName = memberNode.toName((isMethod ? "$$" : "$") + memberNode.getName());
                        statements.append(maker.VarDef(maker.Modifiers(finalFlag), dollarFieldName, maker.TypeIdent(CTC_LONG), fieldAccessor));
                        statements.append(createResultCalculation(typeNode, longToIntForHashCode(maker, maker.Ident(dollarFieldName), maker.Ident(dollarFieldName))));
                    }
                    break;
                case FLOAT:
                    /* Float.floatToIntBits(this.fieldName) */
                    statements.append(createResultCalculation(typeNode, maker.Apply(List.<JCExpression>nil(), genJavaLangTypeRef(typeNode, "Float", "floatToIntBits"), List.of(fieldAccessor))));
                    break;
                case DOUBLE:
                    {
                        /* longToIntForHashCode(Double.doubleToLongBits(this.fieldName)) */
                        Name dollarFieldName = memberNode.toName((isMethod ? "$$" : "$") + memberNode.getName());
                        JCExpression init = maker.Apply(List.<JCExpression>nil(), genJavaLangTypeRef(typeNode, "Double", "doubleToLongBits"), List.of(fieldAccessor));
                        statements.append(maker.VarDef(maker.Modifiers(finalFlag), dollarFieldName, maker.TypeIdent(CTC_LONG), init));
                        statements.append(createResultCalculation(typeNode, longToIntForHashCode(maker, maker.Ident(dollarFieldName), maker.Ident(dollarFieldName))));
                    }
                    break;
                default:
                case BYTE:
                case SHORT:
                case INT:
                case CHAR:
                    /* just the field */
                    statements.append(createResultCalculation(typeNode, fieldAccessor));
                    break;
            }
        } else if (fType instanceof JCArrayTypeTree) {
            JCArrayTypeTree array = (JCArrayTypeTree) fType;
            /* java.util.Arrays.deepHashCode(this.fieldName) //use just hashCode() for primitive arrays. */
            boolean multiDim = unnotate(array.elemtype) instanceof JCArrayTypeTree;
            boolean primitiveArray = unnotate(array.elemtype) instanceof JCPrimitiveTypeTree;
            boolean useDeepHC = multiDim || !primitiveArray;
            JCExpression hcMethod = chainDots(typeNode, "java", "util", "Arrays", useDeepHC ? "deepHashCode" : "hashCode");
            statements.append(createResultCalculation(typeNode, maker.Apply(List.<JCExpression>nil(), hcMethod, List.of(fieldAccessor))));
        } else /* objects */
        {
            /* final java.lang.Object $fieldName = this.fieldName; */
            /* ($fieldName == null ? NULL_PRIME : $fieldName.hashCode()) */
            Name dollarFieldName = memberNode.toName((isMethod ? "$$" : "$") + memberNode.getName());
            statements.append(maker.VarDef(maker.Modifiers(finalFlag), dollarFieldName, genJavaLangTypeRef(typeNode, "Object"), fieldAccessor));
            JCExpression hcCall = maker.Apply(List.<JCExpression>nil(), maker.Select(maker.Ident(dollarFieldName), typeNode.toName("hashCode")), List.<JCExpression>nil());
            JCExpression thisEqualsNull = maker.Binary(CTC_EQUAL, maker.Ident(dollarFieldName), maker.Literal(CTC_BOT, null));
            statements.append(createResultCalculation(typeNode, maker.Parens(maker.Conditional(thisEqualsNull, maker.Literal(HandlerUtil.primeForNull()), hcCall))));
        }
    }
    /* 
		 * if (result == 0) result = Integer.MIN_VALUE;
		 * this.$hashCodeCache = result;
		 * 
		 */
    {
        if (cacheHashCode) {
            statements.append(maker.If(maker.Binary(CTC_EQUAL, maker.Ident(resultName), maker.Literal(CTC_INT, 0)), maker.Exec(maker.Assign(maker.Ident(resultName), genJavaLangTypeRef(typeNode, "Integer", "MIN_VALUE"))), null));
            JCFieldAccess cacheHashCodeFieldAccess = maker.Select(maker.Ident(typeNode.toName("this")), typeNode.toName(HASH_CODE_CACHE_NAME));
            statements.append(maker.Exec(maker.Assign(cacheHashCodeFieldAccess, maker.Ident(resultName))));
        }
    }
    /* return result; */
    {
        statements.append(maker.Return(maker.Ident(resultName)));
    }
    JCBlock body = maker.Block(0, statements.toList());
    return recursiveSetGeneratedBy(maker.MethodDef(mods, typeNode.toName("hashCode"), returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null), source);
}
Also used : JCIdent(com.sun.tools.javac.tree.JCTree.JCIdent) JCBlock(com.sun.tools.javac.tree.JCTree.JCBlock) JavacTreeMaker(lombok.javac.JavacTreeMaker) JCFieldAccess(com.sun.tools.javac.tree.JCTree.JCFieldAccess) ListBuffer(com.sun.tools.javac.util.ListBuffer) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement) JCVariableDecl(com.sun.tools.javac.tree.JCTree.JCVariableDecl) Name(com.sun.tools.javac.util.Name) JCTypeParameter(com.sun.tools.javac.tree.JCTree.JCTypeParameter) JCPrimitiveTypeTree(com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JavacNode(lombok.javac.JavacNode) JCModifiers(com.sun.tools.javac.tree.JCTree.JCModifiers) CheckerFrameworkVersion(lombok.core.configuration.CheckerFrameworkVersion) JCAnnotation(com.sun.tools.javac.tree.JCTree.JCAnnotation) JCArrayTypeTree(com.sun.tools.javac.tree.JCTree.JCArrayTypeTree)

Example 3 with CheckerFrameworkVersion

use of lombok.core.configuration.CheckerFrameworkVersion in project lombok by rzwitserloot.

the class HandleEqualsAndHashCode method createCanEqual.

public JCMethodDecl createCanEqual(JavacNode typeNode, JavacNode source, List<JCAnnotation> onParam) {
    /* protected boolean canEqual(final java.lang.Object other) {
		 *     return other instanceof Outer.Inner.MyType;
		 * }
		 */
    JavacTreeMaker maker = typeNode.getTreeMaker();
    List<JCAnnotation> annsOnMethod = List.nil();
    CheckerFrameworkVersion checkerFramework = getCheckerFrameworkVersion(typeNode);
    if (checkerFramework.generatePure()) {
        annsOnMethod = annsOnMethod.prepend(maker.Annotation(genTypeRef(typeNode, CheckerFrameworkVersion.NAME__PURE), List.<JCExpression>nil()));
    }
    JCModifiers mods = maker.Modifiers(Flags.PROTECTED, annsOnMethod);
    JCExpression returnType = maker.TypeIdent(CTC_BOOLEAN);
    Name canEqualName = typeNode.toName("canEqual");
    JCExpression objectType = genJavaLangTypeRef(typeNode, "Object");
    Name otherName = typeNode.toName("other");
    long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, typeNode.getContext());
    JCVariableDecl param = maker.VarDef(maker.Modifiers(flags, onParam), otherName, objectType, null);
    createRelevantNullableAnnotation(typeNode, param);
    List<JCVariableDecl> params = List.of(param);
    JCBlock body = maker.Block(0, List.<JCStatement>of(maker.Return(maker.TypeTest(maker.Ident(otherName), createTypeReference(typeNode, false)))));
    return recursiveSetGeneratedBy(maker.MethodDef(mods, canEqualName, returnType, List.<JCTypeParameter>nil(), params, List.<JCExpression>nil(), body, null), source);
}
Also used : JCTypeParameter(com.sun.tools.javac.tree.JCTree.JCTypeParameter) JCBlock(com.sun.tools.javac.tree.JCTree.JCBlock) JavacTreeMaker(lombok.javac.JavacTreeMaker) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JCModifiers(com.sun.tools.javac.tree.JCTree.JCModifiers) CheckerFrameworkVersion(lombok.core.configuration.CheckerFrameworkVersion) JCAnnotation(com.sun.tools.javac.tree.JCTree.JCAnnotation) JCVariableDecl(com.sun.tools.javac.tree.JCTree.JCVariableDecl) Name(com.sun.tools.javac.util.Name)

Example 4 with CheckerFrameworkVersion

use of lombok.core.configuration.CheckerFrameworkVersion in project lombok by rzwitserloot.

the class HandleWith method createWith.

public JCMethodDecl createWith(long access, JavacNode field, JavacTreeMaker maker, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam, boolean makeAbstract) {
    String withName = toWithName(field);
    if (withName == null)
        return null;
    JCVariableDecl fieldDecl = (JCVariableDecl) field.get();
    List<JCAnnotation> copyableAnnotations = findCopyableAnnotations(field);
    Name methodName = field.toName(withName);
    JCExpression returnType = cloneSelfType(field);
    JCBlock methodBody = null;
    long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, field.getContext());
    List<JCAnnotation> annsOnParam = copyAnnotations(onParam).appendList(copyableAnnotations);
    JCExpression pType = cloneType(maker, fieldDecl.vartype, source);
    JCVariableDecl param = maker.VarDef(maker.Modifiers(flags, annsOnParam), fieldDecl.name, pType, null);
    if (!makeAbstract) {
        ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
        JCExpression selfType = cloneSelfType(field);
        if (selfType == null)
            return null;
        ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
        for (JavacNode child : field.up().down()) {
            if (child.getKind() != Kind.FIELD)
                continue;
            JCVariableDecl childDecl = (JCVariableDecl) child.get();
            // Skip fields that start with $
            if (childDecl.name.toString().startsWith("$"))
                continue;
            long fieldFlags = childDecl.mods.flags;
            // Skip static fields.
            if ((fieldFlags & Flags.STATIC) != 0)
                continue;
            // Skip initialized final fields.
            if (((fieldFlags & Flags.FINAL) != 0) && childDecl.init != null)
                continue;
            if (child.get() == field.get()) {
                args.append(maker.Ident(fieldDecl.name));
            } else {
                args.append(createFieldAccessor(maker, child, FieldAccess.ALWAYS_FIELD));
            }
        }
        JCNewClass newClass = maker.NewClass(null, List.<JCExpression>nil(), selfType, args.toList(), null);
        JCExpression identityCheck = maker.Binary(CTC_EQUAL, createFieldAccessor(maker, field, FieldAccess.ALWAYS_FIELD), maker.Ident(fieldDecl.name));
        JCConditional conditional = maker.Conditional(identityCheck, maker.Ident(field.toName("this")), newClass);
        JCReturn returnStatement = maker.Return(conditional);
        if (!hasNonNullAnnotations(field)) {
            statements.append(returnStatement);
        } else {
            JCStatement nullCheck = generateNullCheck(maker, field, source);
            if (nullCheck != null)
                statements.append(nullCheck);
            statements.append(returnStatement);
        }
        methodBody = maker.Block(0, statements.toList());
    }
    List<JCTypeParameter> methodGenericParams = List.nil();
    List<JCVariableDecl> parameters = List.of(param);
    List<JCExpression> throwsClauses = List.nil();
    JCExpression annotationMethodDefaultValue = null;
    List<JCAnnotation> annsOnMethod = copyAnnotations(onMethod);
    CheckerFrameworkVersion checkerFramework = getCheckerFrameworkVersion(source);
    if (checkerFramework.generateSideEffectFree())
        annsOnMethod = annsOnMethod.prepend(maker.Annotation(genTypeRef(source, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil()));
    if (isFieldDeprecated(field))
        annsOnMethod = annsOnMethod.prepend(maker.Annotation(genJavaLangTypeRef(field, "Deprecated"), List.<JCExpression>nil()));
    if (makeAbstract)
        access |= Flags.ABSTRACT;
    AnnotationValues<Accessors> accessors = JavacHandlerUtil.getAccessorsForField(field);
    boolean makeFinal = shouldMakeFinal(field, accessors);
    if (makeFinal)
        access |= Flags.FINAL;
    JCMethodDecl decl = recursiveSetGeneratedBy(maker.MethodDef(maker.Modifiers(access, annsOnMethod), methodName, returnType, methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue), source);
    copyJavadoc(field, decl, CopyJavadoc.WITH);
    return decl;
}
Also used : JCReturn(com.sun.tools.javac.tree.JCTree.JCReturn) ListBuffer(com.sun.tools.javac.util.ListBuffer) JCConditional(com.sun.tools.javac.tree.JCTree.JCConditional) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement) Accessors(lombok.experimental.Accessors) Name(com.sun.tools.javac.util.Name) JavacNode(lombok.javac.JavacNode) JCNewClass(com.sun.tools.javac.tree.JCTree.JCNewClass) JCAnnotation(com.sun.tools.javac.tree.JCTree.JCAnnotation) JCBlock(com.sun.tools.javac.tree.JCTree.JCBlock) JCMethodDecl(com.sun.tools.javac.tree.JCTree.JCMethodDecl) JCVariableDecl(com.sun.tools.javac.tree.JCTree.JCVariableDecl) JCTypeParameter(com.sun.tools.javac.tree.JCTree.JCTypeParameter) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) CheckerFrameworkVersion(lombok.core.configuration.CheckerFrameworkVersion)

Example 5 with CheckerFrameworkVersion

use of lombok.core.configuration.CheckerFrameworkVersion in project lombok by rzwitserloot.

the class HandleWithBy method createWithBy.

public JCMethodDecl createWithBy(long access, JavacNode field, JavacTreeMaker maker, JavacNode source, List<JCAnnotation> onMethod, boolean makeAbstract) {
    String withByName = toWithByName(field);
    if (withByName == null)
        return null;
    JCVariableDecl fieldDecl = (JCVariableDecl) field.get();
    Name methodName = field.toName(withByName);
    JCExpression returnType = cloneSelfType(field);
    JCBlock methodBody = null;
    long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, field.getContext());
    LombokImmutableList<String> functionalInterfaceName = null;
    TypeTag requiredCast = null;
    JCExpression parameterizer = null;
    boolean superExtendsStyle = true;
    String applyMethodName = "apply";
    if (fieldDecl.vartype instanceof JCPrimitiveTypeTree) {
        TypeKind kind = ((JCPrimitiveTypeTree) fieldDecl.vartype).getPrimitiveTypeKind();
        if (kind == TypeKind.CHAR) {
            requiredCast = Javac.CTC_CHAR;
            functionalInterfaceName = NAME_JUF_INTOP;
        } else if (kind == TypeKind.SHORT) {
            requiredCast = Javac.CTC_SHORT;
            functionalInterfaceName = NAME_JUF_INTOP;
        } else if (kind == TypeKind.BYTE) {
            requiredCast = Javac.CTC_BYTE;
            functionalInterfaceName = NAME_JUF_INTOP;
        } else if (kind == TypeKind.INT) {
            functionalInterfaceName = NAME_JUF_INTOP;
        } else if (kind == TypeKind.LONG) {
            functionalInterfaceName = NAME_JUF_LONGOP;
        } else if (kind == TypeKind.FLOAT) {
            functionalInterfaceName = NAME_JUF_DOUBLEOP;
            requiredCast = Javac.CTC_FLOAT;
        } else if (kind == TypeKind.DOUBLE) {
            functionalInterfaceName = NAME_JUF_DOUBLEOP;
        } else if (kind == TypeKind.BOOLEAN) {
            functionalInterfaceName = NAME_JUF_OP;
            parameterizer = JavacHandlerUtil.genJavaLangTypeRef(field, "Boolean");
            superExtendsStyle = false;
        }
    }
    if (functionalInterfaceName == null) {
        functionalInterfaceName = NAME_JUF_FUNCTION;
        parameterizer = cloneType(maker, fieldDecl.vartype, source);
    }
    if (functionalInterfaceName == NAME_JUF_INTOP)
        applyMethodName = "applyAsInt";
    if (functionalInterfaceName == NAME_JUF_LONGOP)
        applyMethodName = "applyAsLong";
    if (functionalInterfaceName == NAME_JUF_DOUBLEOP)
        applyMethodName = "applyAsDouble";
    JCExpression varType = chainDots(field, functionalInterfaceName);
    if (parameterizer != null && superExtendsStyle) {
        JCExpression parameterizer1 = parameterizer;
        JCExpression parameterizer2 = cloneType(maker, parameterizer, source);
        // TODO: Apply copyable annotations to 'parameterizer' and 'parameterizer2'.
        JCExpression arg1 = maker.Wildcard(maker.TypeBoundKind(BoundKind.SUPER), parameterizer1);
        JCExpression arg2 = maker.Wildcard(maker.TypeBoundKind(BoundKind.EXTENDS), parameterizer2);
        varType = maker.TypeApply(varType, List.of(arg1, arg2));
    }
    if (parameterizer != null && !superExtendsStyle) {
        varType = maker.TypeApply(varType, List.of(parameterizer));
    }
    Name paramName = field.toName("transformer");
    JCVariableDecl param = maker.VarDef(maker.Modifiers(flags), paramName, varType, null);
    if (!makeAbstract) {
        ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
        JCExpression selfType = cloneSelfType(field);
        if (selfType == null)
            return null;
        ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
        for (JavacNode child : field.up().down()) {
            if (child.getKind() != Kind.FIELD)
                continue;
            JCVariableDecl childDecl = (JCVariableDecl) child.get();
            // Skip fields that start with $
            if (childDecl.name.toString().startsWith("$"))
                continue;
            long fieldFlags = childDecl.mods.flags;
            // Skip static fields.
            if ((fieldFlags & Flags.STATIC) != 0)
                continue;
            // Skip initialized final fields.
            if (((fieldFlags & Flags.FINAL) != 0) && childDecl.init != null)
                continue;
            if (child.get() == field.get()) {
                JCExpression invoke = maker.Apply(List.<JCExpression>nil(), maker.Select(maker.Ident(paramName), field.toName(applyMethodName)), List.<JCExpression>of(createFieldAccessor(maker, child, FieldAccess.ALWAYS_FIELD)));
                if (requiredCast != null)
                    invoke = maker.TypeCast(maker.TypeIdent(requiredCast), invoke);
                args.append(invoke);
            } else {
                args.append(createFieldAccessor(maker, child, FieldAccess.ALWAYS_FIELD));
            }
        }
        JCNewClass newClass = maker.NewClass(null, List.<JCExpression>nil(), selfType, args.toList(), null);
        JCReturn returnStatement = maker.Return(newClass);
        statements.append(returnStatement);
        methodBody = maker.Block(0, statements.toList());
    }
    List<JCTypeParameter> methodGenericParams = List.nil();
    List<JCVariableDecl> parameters = List.of(param);
    List<JCExpression> throwsClauses = List.nil();
    JCExpression annotationMethodDefaultValue = null;
    List<JCAnnotation> annsOnMethod = copyAnnotations(onMethod);
    CheckerFrameworkVersion checkerFramework = getCheckerFrameworkVersion(source);
    if (checkerFramework.generateSideEffectFree())
        annsOnMethod = annsOnMethod.prepend(maker.Annotation(genTypeRef(source, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil()));
    if (isFieldDeprecated(field))
        annsOnMethod = annsOnMethod.prepend(maker.Annotation(genJavaLangTypeRef(field, "Deprecated"), List.<JCExpression>nil()));
    if (makeAbstract)
        access = access | Flags.ABSTRACT;
    AnnotationValues<Accessors> accessors = JavacHandlerUtil.getAccessorsForField(field);
    boolean makeFinal = shouldMakeFinal(field, accessors);
    if (makeFinal)
        access |= Flags.FINAL;
    createRelevantNonNullAnnotation(source, param);
    JCMethodDecl decl = recursiveSetGeneratedBy(maker.MethodDef(maker.Modifiers(access, annsOnMethod), methodName, returnType, methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue), source);
    copyJavadoc(field, decl, CopyJavadoc.WITH_BY);
    createRelevantNonNullAnnotation(source, decl);
    return decl;
}
Also used : JCReturn(com.sun.tools.javac.tree.JCTree.JCReturn) ListBuffer(com.sun.tools.javac.util.ListBuffer) TypeKind(javax.lang.model.type.TypeKind) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement) Accessors(lombok.experimental.Accessors) Name(com.sun.tools.javac.util.Name) JCPrimitiveTypeTree(com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree) JavacNode(lombok.javac.JavacNode) JCNewClass(com.sun.tools.javac.tree.JCTree.JCNewClass) JCAnnotation(com.sun.tools.javac.tree.JCTree.JCAnnotation) JCBlock(com.sun.tools.javac.tree.JCTree.JCBlock) JCMethodDecl(com.sun.tools.javac.tree.JCTree.JCMethodDecl) JCVariableDecl(com.sun.tools.javac.tree.JCTree.JCVariableDecl) JCTypeParameter(com.sun.tools.javac.tree.JCTree.JCTypeParameter) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) CheckerFrameworkVersion(lombok.core.configuration.CheckerFrameworkVersion) TypeTag(lombok.javac.JavacTreeMaker.TypeTag)

Aggregations

CheckerFrameworkVersion (lombok.core.configuration.CheckerFrameworkVersion)6 JCAnnotation (com.sun.tools.javac.tree.JCTree.JCAnnotation)5 JCBlock (com.sun.tools.javac.tree.JCTree.JCBlock)5 JCExpression (com.sun.tools.javac.tree.JCTree.JCExpression)5 JCTypeParameter (com.sun.tools.javac.tree.JCTree.JCTypeParameter)5 JCVariableDecl (com.sun.tools.javac.tree.JCTree.JCVariableDecl)5 Name (com.sun.tools.javac.util.Name)5 JCStatement (com.sun.tools.javac.tree.JCTree.JCStatement)4 ListBuffer (com.sun.tools.javac.util.ListBuffer)4 JavacNode (lombok.javac.JavacNode)4 JCModifiers (com.sun.tools.javac.tree.JCTree.JCModifiers)3 JCPrimitiveTypeTree (com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree)3 JavacTreeMaker (lombok.javac.JavacTreeMaker)3 JCArrayTypeTree (com.sun.tools.javac.tree.JCTree.JCArrayTypeTree)2 JCMethodDecl (com.sun.tools.javac.tree.JCTree.JCMethodDecl)2 JCNewClass (com.sun.tools.javac.tree.JCTree.JCNewClass)2 JCReturn (com.sun.tools.javac.tree.JCTree.JCReturn)2 ArrayList (java.util.ArrayList)2 Accessors (lombok.experimental.Accessors)2 JCConditional (com.sun.tools.javac.tree.JCTree.JCConditional)1