Search in sources :

Example 66 with JCBlock

use of com.sun.tools.javac.tree.JCTree.JCBlock in project ceylon-compiler by ceylon.

the class ClassTransformer method makeParamDefaultValueMethod.

/**
 * Creates a (possibly abstract) method for retrieving the value for a
 * defaulted parameter
 * @param typeParameterList
 */
MethodDefinitionBuilder makeParamDefaultValueMethod(boolean noBody, Declaration container, Tree.ParameterList params, Tree.Parameter currentParam) {
    at(currentParam);
    Parameter parameter = currentParam.getParameterModel();
    if (!Strategy.hasDefaultParameterValueMethod(parameter)) {
        throw new BugException();
    }
    MethodDefinitionBuilder methodBuilder = MethodDefinitionBuilder.systemMethod(this, Naming.getDefaultedParamMethodName(container, parameter));
    methodBuilder.ignoreModelAnnotations();
    if (container != null && Decl.isAnnotationConstructor(container)) {
        AnnotationInvocation ac = (AnnotationInvocation) ((Function) container).getAnnotationConstructor();
        for (AnnotationConstructorParameter acp : ac.getConstructorParameters()) {
            if (acp.getParameter().equals(parameter) && acp.getDefaultArgument() != null) {
                methodBuilder.userAnnotations(acp.getDefaultArgument().makeDpmAnnotations(expressionGen()));
            }
        }
    }
    int modifiers = 0;
    if (noBody) {
        modifiers |= PUBLIC | ABSTRACT;
    } else if (container == null || !(container instanceof Class && Strategy.defaultParameterMethodStatic(container))) {
        // initializers can override parameter defaults
        modifiers |= FINAL;
    }
    if (container != null && container.isShared()) {
        modifiers |= PUBLIC;
    } else if (container == null || (!container.isToplevel() && !noBody)) {
        modifiers |= PRIVATE;
    }
    boolean staticMethod = Strategy.defaultParameterMethodStatic(container);
    if (staticMethod) {
        // static default parameter methods should be consistently public so that if non-shared class Top and
        // shared class Bottom which extends Top both have the same default param name, we don't get an error
        // if the Bottom class tries to "hide" a static public method with a private one
        modifiers &= ~PRIVATE;
        modifiers |= STATIC | PUBLIC;
    }
    methodBuilder.modifiers(modifiers);
    if (container instanceof Constructor) {
        copyTypeParameters((Class) container.getContainer(), methodBuilder);
        methodBuilder.reifiedTypeParameters(((Class) container.getContainer()).getTypeParameters());
    } else if (container instanceof Generic) {
        // make sure reified type parameters are accepted
        copyTypeParameters((Generic) container, methodBuilder);
        methodBuilder.reifiedTypeParameters(((Generic) container).getTypeParameters());
    }
    WideningRules wideningRules = !staticMethod && container instanceof Class ? WideningRules.CAN_WIDEN : WideningRules.NONE;
    // Add any of the preceding parameters as parameters to the method
    for (Tree.Parameter p : params.getParameters()) {
        if (p.equals(currentParam)) {
            break;
        }
        at(p);
        methodBuilder.parameter(p.getParameterModel(), null, 0, wideningRules);
    }
    // The method's return type is the same as the parameter's type
    NonWideningParam nonWideningParam = methodBuilder.getNonWideningParam(currentParam.getParameterModel().getModel(), wideningRules);
    methodBuilder.resultType(nonWideningParam.nonWideningDecl, nonWideningParam.nonWideningType, nonWideningParam.flags);
    // The implementation of the method
    if (noBody) {
        methodBuilder.noBody();
    } else {
        HasErrorException error = errors().getFirstExpressionErrorAndMarkBrokenness(Decl.getDefaultArgument(currentParam).getExpression());
        if (error != null) {
            methodBuilder.body(this.makeThrowUnresolvedCompilationError(error));
        } else {
            java.util.List<TypeParameter> copiedTypeParameters = null;
            if (container instanceof Generic) {
                copiedTypeParameters = ((Generic) container).getTypeParameters();
                if (copiedTypeParameters != null)
                    addTypeParameterSubstitution(copiedTypeParameters);
            }
            try {
                JCExpression expr = expressionGen().transform(currentParam);
                JCBlock body = at(currentParam).Block(0, List.<JCStatement>of(at(currentParam).Return(expr)));
                methodBuilder.block(body);
            } finally {
                if (copiedTypeParameters != null)
                    popTypeParameterSubstitution();
            }
        }
    }
    return methodBuilder;
}
Also used : TypeParameter(com.redhat.ceylon.model.typechecker.model.TypeParameter) JCBlock(com.sun.tools.javac.tree.JCTree.JCBlock) NonWideningParam(com.redhat.ceylon.compiler.java.codegen.MethodDefinitionBuilder.NonWideningParam) ThrowerCatchallConstructor(com.redhat.ceylon.compiler.java.codegen.recovery.ThrowerCatchallConstructor) Constructor(com.redhat.ceylon.model.typechecker.model.Constructor) Generic(com.redhat.ceylon.model.typechecker.model.Generic) WideningRules(com.redhat.ceylon.compiler.java.codegen.MethodDefinitionBuilder.WideningRules) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) HasErrorException(com.redhat.ceylon.compiler.java.codegen.recovery.HasErrorException) TypeParameter(com.redhat.ceylon.model.typechecker.model.TypeParameter) Parameter(com.redhat.ceylon.model.typechecker.model.Parameter) JCPrimitiveTypeTree(com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree) JCTree(com.sun.tools.javac.tree.JCTree) Tree(com.redhat.ceylon.compiler.typechecker.tree.Tree) Class(com.redhat.ceylon.model.typechecker.model.Class) JCNewClass(com.sun.tools.javac.tree.JCTree.JCNewClass)

Example 67 with JCBlock

use of com.sun.tools.javac.tree.JCTree.JCBlock in project ceylon-compiler by ceylon.

the class ClassTransformer method transform.

public AttributeDefinitionBuilder transform(AttributeSetterDefinition decl, boolean forCompanion) {
    if (Strategy.onlyOnCompanion(decl.getDeclarationModel()) && !forCompanion) {
        return null;
    }
    String name = decl.getIdentifier().getText();
    final AttributeDefinitionBuilder builder = AttributeDefinitionBuilder.setter(this, name, decl.getDeclarationModel().getGetter()).modifiers(transformAttributeGetSetDeclFlags(decl.getDeclarationModel(), forCompanion));
    // companion class members are never actual no matter what the Declaration says
    if (forCompanion)
        builder.notActual();
    if (Decl.withinClass(decl) || forCompanion) {
        JCBlock setterBlock = makeSetterBlock(decl.getDeclarationModel(), decl.getBlock(), decl.getSpecifierExpression());
        builder.setterBlock(setterBlock);
    } else {
        builder.isFormal(true);
    }
    builder.userAnnotationsSetter(expressionGen().transformAnnotations(OutputElement.SETTER, decl));
    return builder;
}
Also used : JCBlock(com.sun.tools.javac.tree.JCTree.JCBlock)

Example 68 with JCBlock

use of com.sun.tools.javac.tree.JCTree.JCBlock in project ceylon-compiler by ceylon.

the class AbstractTransformer method makeSetterBlock.

JCBlock makeSetterBlock(TypedDeclaration declarationModel, final Tree.Block block, final Tree.SpecifierOrInitializerExpression expression) {
    List<JCStatement> stats;
    if (block != null) {
        stats = statementGen().transformBlock(block);
    } else {
        Type type = declarationModel.getType();
        JCStatement transStmt;
        HasErrorException error = errors().getFirstExpressionErrorAndMarkBrokenness(expression.getExpression());
        if (error != null) {
            transStmt = this.makeThrowUnresolvedCompilationError(error);
        } else {
            transStmt = make().Exec(expressionGen().transformExpression(expression.getExpression(), BoxingStrategy.INDIFFERENT, type));
        }
        stats = List.<JCStatement>of(transStmt);
    }
    JCBlock setterBlock = make().Block(0, stats);
    return setterBlock;
}
Also used : Type(com.redhat.ceylon.model.typechecker.model.Type) ModelUtil.appliedType(com.redhat.ceylon.model.typechecker.model.ModelUtil.appliedType) JCBlock(com.sun.tools.javac.tree.JCTree.JCBlock) HasErrorException(com.redhat.ceylon.compiler.java.codegen.recovery.HasErrorException) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement)

Example 69 with JCBlock

use of com.sun.tools.javac.tree.JCTree.JCBlock in project ceylon-compiler by ceylon.

the class AbstractTransformer method makeGetterBlock.

JCBlock makeGetterBlock(TypedDeclaration declarationModel, final Tree.Block block, final Tree.SpecifierOrInitializerExpression expression) {
    List<JCStatement> stats;
    if (block != null) {
        stats = statementGen().transformBlock(block);
    } else {
        BoxingStrategy boxing = CodegenUtil.getBoxingStrategy(declarationModel);
        Type type = declarationModel.getType();
        JCStatement transStat;
        HasErrorException error = errors().getFirstExpressionErrorAndMarkBrokenness(expression.getExpression());
        if (error != null) {
            transStat = this.makeThrowUnresolvedCompilationError(error);
        } else {
            transStat = make().Return(expressionGen().transformExpression(expression.getExpression(), boxing, type));
        }
        stats = List.<JCStatement>of(transStat);
    }
    JCBlock getterBlock = make().Block(0, stats);
    return getterBlock;
}
Also used : Type(com.redhat.ceylon.model.typechecker.model.Type) ModelUtil.appliedType(com.redhat.ceylon.model.typechecker.model.ModelUtil.appliedType) JCBlock(com.sun.tools.javac.tree.JCTree.JCBlock) HasErrorException(com.redhat.ceylon.compiler.java.codegen.recovery.HasErrorException) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement)

Example 70 with JCBlock

use of com.sun.tools.javac.tree.JCTree.JCBlock 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)

Aggregations

JCBlock (com.sun.tools.javac.tree.JCTree.JCBlock)85 JCExpression (com.sun.tools.javac.tree.JCTree.JCExpression)68 JCStatement (com.sun.tools.javac.tree.JCTree.JCStatement)64 JCVariableDecl (com.sun.tools.javac.tree.JCTree.JCVariableDecl)54 Name (com.sun.tools.javac.util.Name)48 JCTypeParameter (com.sun.tools.javac.tree.JCTree.JCTypeParameter)45 JCMethodDecl (com.sun.tools.javac.tree.JCTree.JCMethodDecl)41 ListBuffer (com.sun.tools.javac.util.ListBuffer)41 JCModifiers (com.sun.tools.javac.tree.JCTree.JCModifiers)37 JavacTreeMaker (lombok.javac.JavacTreeMaker)34 JCAnnotation (com.sun.tools.javac.tree.JCTree.JCAnnotation)28 JavacNode (lombok.javac.JavacNode)14 JCTree (com.sun.tools.javac.tree.JCTree)13 JCMethodInvocation (com.sun.tools.javac.tree.JCTree.JCMethodInvocation)11 JCPrimitiveTypeTree (com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree)11 JCReturn (com.sun.tools.javac.tree.JCTree.JCReturn)9 JCArrayTypeTree (com.sun.tools.javac.tree.JCTree.JCArrayTypeTree)6 JCClassDecl (com.sun.tools.javac.tree.JCTree.JCClassDecl)6 JCIf (com.sun.tools.javac.tree.JCTree.JCIf)6 JCNewClass (com.sun.tools.javac.tree.JCTree.JCNewClass)6