Search in sources :

Example 11 with JCExpression

use of com.sun.tools.javac.tree.JCTree.JCExpression in project lombok by rzwitserloot.

the class HandleEqualsAndHashCode method createHashCode.

public JCMethodDecl createHashCode(JavacNode typeNode, List<JavacNode> fields, boolean callSuper, FieldAccess fieldAccess, JCTree source) {
    JavacTreeMaker maker = typeNode.getTreeMaker();
    JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(typeNode, "Override"), List.<JCExpression>nil());
    JCModifiers mods = maker.Modifiers(Flags.PUBLIC, List.of(overrideAnnotation));
    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());
    /* final int PRIME = X; */
    {
        if (!fields.isEmpty() || callSuper) {
            statements.append(maker.VarDef(maker.Modifiers(finalFlag), primeName, maker.TypeIdent(CTC_INT), maker.Literal(HandlerUtil.primeForHashcode())));
        }
    }
    /* int result = 1; */
    {
        statements.append(maker.VarDef(maker.Modifiers(0), resultName, maker.TypeIdent(CTC_INT), maker.Literal(1)));
    }
    if (callSuper) {
        JCMethodInvocation callToSuper = maker.Apply(List.<JCExpression>nil(), maker.Select(maker.Ident(typeNode.toName("super")), typeNode.toName("hashCode")), List.<JCExpression>nil());
        statements.append(createResultCalculation(typeNode, callToSuper));
    }
    Name dollar = typeNode.toName("$");
    for (JavacNode fieldNode : fields) {
        JCExpression fType = getFieldType(fieldNode, fieldAccess);
        JCExpression fieldAccessor = createFieldAccessor(maker, fieldNode, 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 = dollar.append(((JCVariableDecl) fieldNode.get()).name);
                        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 = dollar.append(((JCVariableDecl) fieldNode.get()).name);
                        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) {
            /* java.util.Arrays.deepHashCode(this.fieldName) //use just hashCode() for primitive arrays. */
            boolean multiDim = ((JCArrayTypeTree) fType).elemtype instanceof JCArrayTypeTree;
            boolean primitiveArray = ((JCArrayTypeTree) fType).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 = dollar.append(((JCVariableDecl) fieldNode.get()).name);
            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))));
        }
    }
    /* 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, typeNode.getContext());
}
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) JCAnnotation(com.sun.tools.javac.tree.JCTree.JCAnnotation) JCArrayTypeTree(com.sun.tools.javac.tree.JCTree.JCArrayTypeTree)

Example 12 with JCExpression

use of com.sun.tools.javac.tree.JCTree.JCExpression in project lombok by rzwitserloot.

the class HandleEqualsAndHashCode method createCanEqual.

public JCMethodDecl createCanEqual(JavacNode typeNode, JCTree source, List<JCAnnotation> onParam) {
    /* protected boolean canEqual(final java.lang.Object other) {
		 *     return other instanceof Outer.Inner.MyType;
		 * }
		 */
    JavacTreeMaker maker = typeNode.getTreeMaker();
    JCModifiers mods = maker.Modifiers(Flags.PROTECTED, List.<JCAnnotation>nil());
    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());
    List<JCVariableDecl> params = List.of(maker.VarDef(maker.Modifiers(flags, onParam), otherName, objectType, null));
    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, typeNode.getContext());
}
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) JCVariableDecl(com.sun.tools.javac.tree.JCTree.JCVariableDecl) Name(com.sun.tools.javac.util.Name)

Example 13 with JCExpression

use of com.sun.tools.javac.tree.JCTree.JCExpression in project lombok by rzwitserloot.

the class HandleEqualsAndHashCode method generateCompareFloatOrDouble.

public JCStatement generateCompareFloatOrDouble(JCExpression thisDotField, JCExpression otherDotField, JavacTreeMaker maker, JavacNode node, boolean isDouble) {
    /* if (Float.compare(fieldName, other.fieldName) != 0) return false; */
    JCExpression clazz = genJavaLangTypeRef(node, isDouble ? "Double" : "Float");
    List<JCExpression> args = List.of(thisDotField, otherDotField);
    JCBinary compareCallEquals0 = maker.Binary(CTC_NOT_EQUAL, maker.Apply(List.<JCExpression>nil(), maker.Select(clazz, node.toName("compare")), args), maker.Literal(0));
    return maker.If(compareCallEquals0, returnBool(maker, false), null);
}
Also used : JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JCBinary(com.sun.tools.javac.tree.JCTree.JCBinary)

Example 14 with JCExpression

use of com.sun.tools.javac.tree.JCTree.JCExpression in project lombok by rzwitserloot.

the class HandleEqualsAndHashCode method longToIntForHashCode.

/** The 2 references must be clones of each other. */
public JCExpression longToIntForHashCode(JavacTreeMaker maker, JCExpression ref1, JCExpression ref2) {
    /* (int) (ref >>> 32 ^ ref) */
    JCExpression shift = maker.Binary(CTC_UNSIGNED_SHIFT_RIGHT, ref1, maker.Literal(32));
    JCExpression xorBits = maker.Binary(CTC_BITXOR, shift, ref2);
    return maker.TypeCast(maker.TypeIdent(CTC_INT), maker.Parens(xorBits));
}
Also used : JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression)

Example 15 with JCExpression

use of com.sun.tools.javac.tree.JCTree.JCExpression in project lombok by rzwitserloot.

the class HandleGetter method createLazyGetterBody.

public List<JCStatement> createLazyGetterBody(JavacTreeMaker maker, JavacNode fieldNode, JCTree source) {
    /*
		java.lang.Object value = this.fieldName.get();
		if (value == null) {
			synchronized (this.fieldName) {
				value = this.fieldName.get();
				if (value == null) {
					final RawValueType actualValue = INITIALIZER_EXPRESSION;
					[IF PRIMITIVE]
					value = actualValue;
					[ELSE]
					value = actualValue == null ? this.fieldName : actualValue;
					[END IF]
					this.fieldName.set(value);
				}
			}
		}
		[IF PRIMITIVE]
		return (BoxedValueType) value;
		[ELSE]
		return (BoxedValueType) (value == this.fieldName ? null : value);
		[END IF]
		*/
    ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
    JCVariableDecl field = (JCVariableDecl) fieldNode.get();
    JCExpression copyOfRawFieldType = copyType(maker, field);
    JCExpression copyOfBoxedFieldType = null;
    field.type = null;
    boolean isPrimitive = false;
    if (field.vartype instanceof JCPrimitiveTypeTree) {
        String boxed = TYPE_MAP.get(typeTag(field.vartype));
        if (boxed != null) {
            isPrimitive = true;
            field.vartype = genJavaLangTypeRef(fieldNode, boxed);
            copyOfBoxedFieldType = genJavaLangTypeRef(fieldNode, boxed);
        }
    }
    if (copyOfBoxedFieldType == null)
        copyOfBoxedFieldType = copyType(maker, field);
    Name valueName = fieldNode.toName("value");
    Name actualValueName = fieldNode.toName("actualValue");
    /* java.lang.Object value = this.fieldName.get();*/
    {
        JCExpression valueVarType = genJavaLangTypeRef(fieldNode, "Object");
        statements.append(maker.VarDef(maker.Modifiers(0), valueName, valueVarType, callGet(fieldNode, createFieldAccessor(maker, fieldNode, FieldAccess.ALWAYS_FIELD))));
    }
    /* if (value == null) { */
    {
        JCSynchronized synchronizedStatement;
        /* synchronized (this.fieldName) { */
        {
            ListBuffer<JCStatement> synchronizedStatements = new ListBuffer<JCStatement>();
            /* value = this.fieldName.get(); */
            {
                JCExpressionStatement newAssign = maker.Exec(maker.Assign(maker.Ident(valueName), callGet(fieldNode, createFieldAccessor(maker, fieldNode, FieldAccess.ALWAYS_FIELD))));
                synchronizedStatements.append(newAssign);
            }
            /* if (value == null) { */
            {
                ListBuffer<JCStatement> innerIfStatements = new ListBuffer<JCStatement>();
                /* final RawValueType actualValue = INITIALIZER_EXPRESSION; */
                {
                    innerIfStatements.append(maker.VarDef(maker.Modifiers(Flags.FINAL), actualValueName, copyOfRawFieldType, field.init));
                }
                /* [IF primitive] value = actualValue; */
                {
                    if (isPrimitive) {
                        JCStatement statement = maker.Exec(maker.Assign(maker.Ident(valueName), maker.Ident(actualValueName)));
                        innerIfStatements.append(statement);
                    }
                }
                /* [ELSE] value = actualValue == null ? this.fieldName : actualValue; */
                {
                    if (!isPrimitive) {
                        JCExpression actualValueIsNull = maker.Binary(CTC_EQUAL, maker.Ident(actualValueName), maker.Literal(CTC_BOT, null));
                        JCExpression thisDotFieldName = createFieldAccessor(maker, fieldNode, FieldAccess.ALWAYS_FIELD);
                        JCExpression ternary = maker.Conditional(actualValueIsNull, thisDotFieldName, maker.Ident(actualValueName));
                        JCStatement statement = maker.Exec(maker.Assign(maker.Ident(valueName), ternary));
                        innerIfStatements.append(statement);
                    }
                }
                /* this.fieldName.set(value); */
                {
                    JCStatement statement = callSet(fieldNode, createFieldAccessor(maker, fieldNode, FieldAccess.ALWAYS_FIELD), maker.Ident(valueName));
                    innerIfStatements.append(statement);
                }
                JCBinary isNull = maker.Binary(CTC_EQUAL, maker.Ident(valueName), maker.Literal(CTC_BOT, null));
                JCIf ifStatement = maker.If(isNull, maker.Block(0, innerIfStatements.toList()), null);
                synchronizedStatements.append(ifStatement);
            }
            synchronizedStatement = maker.Synchronized(createFieldAccessor(maker, fieldNode, FieldAccess.ALWAYS_FIELD), maker.Block(0, synchronizedStatements.toList()));
        }
        JCBinary isNull = maker.Binary(CTC_EQUAL, maker.Ident(valueName), maker.Literal(CTC_BOT, null));
        JCIf ifStatement = maker.If(isNull, maker.Block(0, List.<JCStatement>of(synchronizedStatement)), null);
        statements.append(ifStatement);
    }
    /* [IF PRIMITIVE] return (BoxedValueType) value; */
    {
        if (isPrimitive) {
            statements.append(maker.Return(maker.TypeCast(copyOfBoxedFieldType, maker.Ident(valueName))));
        }
    }
    /* [ELSE] return (BoxedValueType) (value == this.fieldName ? null : value); */
    {
        if (!isPrimitive) {
            JCExpression valueEqualsSelf = maker.Binary(CTC_EQUAL, maker.Ident(valueName), createFieldAccessor(maker, fieldNode, FieldAccess.ALWAYS_FIELD));
            JCExpression ternary = maker.Conditional(valueEqualsSelf, maker.Literal(CTC_BOT, null), maker.Ident(valueName));
            JCExpression typeCast = maker.TypeCast(copyOfBoxedFieldType, maker.Parens(ternary));
            statements.append(maker.Return(typeCast));
        }
    }
    // update the field type and init last
    /*	private final java.util.concurrent.atomic.AtomicReference<Object> fieldName = new java.util.concurrent.atomic.AtomicReference<Object>(); */
    {
        field.vartype = recursiveSetGeneratedBy(maker.TypeApply(chainDotsString(fieldNode, AR), List.<JCExpression>of(genJavaLangTypeRef(fieldNode, "Object"))), source, fieldNode.getContext());
        field.init = recursiveSetGeneratedBy(maker.NewClass(null, NIL_EXPRESSION, copyType(maker, field), NIL_EXPRESSION, null), source, fieldNode.getContext());
    }
    return statements.toList();
}
Also used : ListBuffer(com.sun.tools.javac.util.ListBuffer) JCBinary(com.sun.tools.javac.tree.JCTree.JCBinary) JCSynchronized(com.sun.tools.javac.tree.JCTree.JCSynchronized) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement) JCExpressionStatement(com.sun.tools.javac.tree.JCTree.JCExpressionStatement) JCVariableDecl(com.sun.tools.javac.tree.JCTree.JCVariableDecl) Name(com.sun.tools.javac.util.Name) JCPrimitiveTypeTree(com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JCIf(com.sun.tools.javac.tree.JCTree.JCIf)

Aggregations

JCExpression (com.sun.tools.javac.tree.JCTree.JCExpression)311 JCTree (com.sun.tools.javac.tree.JCTree)95 Type (com.redhat.ceylon.model.typechecker.model.Type)85 JCStatement (com.sun.tools.javac.tree.JCTree.JCStatement)81 Tree (com.redhat.ceylon.compiler.typechecker.tree.Tree)67 JCVariableDecl (com.sun.tools.javac.tree.JCTree.JCVariableDecl)59 ListBuffer (com.sun.tools.javac.util.ListBuffer)54 JCTypeParameter (com.sun.tools.javac.tree.JCTree.JCTypeParameter)39 Name (com.sun.tools.javac.util.Name)39 SyntheticName (com.redhat.ceylon.compiler.java.codegen.Naming.SyntheticName)37 TypeDeclaration (com.redhat.ceylon.model.typechecker.model.TypeDeclaration)35 TypedDeclaration (com.redhat.ceylon.model.typechecker.model.TypedDeclaration)34 JCBlock (com.sun.tools.javac.tree.JCTree.JCBlock)34 JavacTreeMaker (lombok.javac.JavacTreeMaker)33 JCAnnotation (com.sun.tools.javac.tree.JCTree.JCAnnotation)30 TypeParameter (com.redhat.ceylon.model.typechecker.model.TypeParameter)29 Declaration (com.redhat.ceylon.model.typechecker.model.Declaration)27 Function (com.redhat.ceylon.model.typechecker.model.Function)26 Parameter (com.redhat.ceylon.model.typechecker.model.Parameter)26 JCNewClass (com.sun.tools.javac.tree.JCTree.JCNewClass)26