Search in sources :

Example 41 with JCStatement

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

the class ClassTransformer method buildJpaConstructor.

protected void buildJpaConstructor(Class model, ClassDefinitionBuilder classBuilder) {
    MethodDefinitionBuilder ctor = classBuilder.addConstructor();
    ctor.modelAnnotations(makeAtJpa());
    ctor.modelAnnotations(makeAtIgnore());
    ctor.modifiers(PROTECTED);
    for (TypeParameter tp : model.getTypeParameters()) {
        ctor.reifiedTypeParameter(tp);
    }
    final ListBuffer<JCStatement> stmts = ListBuffer.lb();
    // invoke super (or this if
    ListBuffer<JCExpression> superArgs = ListBuffer.<JCExpression>lb();
    if (model.isSerializable()) {
        superArgs.add(make().TypeCast(make().QualIdent(syms().ceylonSerializationType.tsym), makeNull()));
        for (JCExpression ta : makeReifiedTypeArguments(model.getType())) {
            superArgs.add(ta);
        }
    } else {
        for (JCExpression ta : makeReifiedTypeArguments(model.getExtendedType())) {
            superArgs.add(ta);
        }
    }
    stmts.add(make().Exec(make().Apply(null, model.isSerializable() ? naming.makeThis() : naming.makeSuper(), superArgs.toList())));
    if (!model.isSerializable()) {
        buildFieldInits(model, classBuilder, stmts);
    }
    ctor.body(stmts.toList());
}
Also used : TypeParameter(com.redhat.ceylon.model.typechecker.model.TypeParameter) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement)

Example 42 with JCStatement

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

the class ClassTransformer method transform.

public List<JCTree> transform(final Tree.ClassOrInterface def) {
    final ClassOrInterface model = def.getDeclarationModel();
    // in that case
    if (model.isAlias() && Decl.isAncestorLocal(def))
        return List.nil();
    naming.clearSubstitutions(model);
    final String javaClassName;
    String ceylonClassName = def.getIdentifier().getText();
    if (def instanceof Tree.AnyInterface) {
        javaClassName = naming.makeTypeDeclarationName(model, QUALIFIED).replaceFirst(".*\\.", "");
    } else {
        javaClassName = Naming.quoteClassName(ceylonClassName);
    }
    ClassDefinitionBuilder instantiatorImplCb;
    ClassDefinitionBuilder instantiatorDeclCb;
    if (Decl.withinInterface(model)) {
        instantiatorImplCb = gen().current().getCompanionBuilder((Interface) model.getContainer());
        instantiatorDeclCb = gen().current();
    } else {
        instantiatorImplCb = gen().current();
        instantiatorDeclCb = null;
    }
    ClassDefinitionBuilder classBuilder = ClassDefinitionBuilder.klass(this, javaClassName, ceylonClassName, Decl.isLocal(model)).forDefinition(model).hasDelegatingConstructors(CodegenUtil.hasDelegatingConstructors(def));
    // Very special case for Anything
    if ("ceylon.language::Anything".equals(model.getQualifiedNameString())) {
        classBuilder.extending(model.getType(), null);
    }
    if (def instanceof Tree.AnyClass) {
        classBuilder.getInitBuilder().modifiers(transformConstructorDeclFlags(model));
        Tree.AnyClass classDef = (Tree.AnyClass) def;
        Class cls = classDef.getDeclarationModel();
        // Member classes need a instantiator method
        boolean generateInstantiator = Strategy.generateInstantiator(cls);
        if (!cls.hasConstructors()) {
            classBuilder.getInitBuilder().userAnnotations(expressionGen().transformAnnotations(OutputElement.CONSTRUCTOR, def));
        }
        if (generateInstantiator && !cls.hasConstructors() && !cls.hasEnumerated()) {
            classBuilder.getInitBuilder().modifiers(PROTECTED);
            generateInstantiators(classBuilder, cls, null, instantiatorDeclCb, instantiatorImplCb, classDef, classDef.getParameterList());
        }
        classBuilder.annotations(expressionGen().transformAnnotations(OutputElement.TYPE, def));
        if (def instanceof Tree.ClassDefinition) {
            transformClass((Tree.ClassDefinition) def, cls, classBuilder, classDef.getParameterList(), generateInstantiator, instantiatorDeclCb, instantiatorImplCb);
        } else {
            // class alias
            classBuilder.getInitBuilder().modifiers(PRIVATE);
            transformClassAlias((Tree.ClassDeclaration) def, classBuilder);
        }
        addMissingUnrefinedMembers(def, cls, classBuilder);
    }
    if (def instanceof Tree.AnyInterface) {
        classBuilder.annotations(expressionGen().transformAnnotations(OutputElement.TYPE, def));
        if (def instanceof Tree.InterfaceDefinition) {
            transformInterface(def, (Interface) model, classBuilder);
        } else {
            // interface alias
            classBuilder.annotations(makeAtAlias(model.getExtendedType(), null));
            classBuilder.isAlias(true);
        }
        classBuilder.isDynamic(model.isDynamic());
    }
    // make sure we set the container in case we move it out
    addAtContainer(classBuilder, model);
    // Transform the class/interface members
    List<JCStatement> childDefs = visitClassOrInterfaceDefinition(def, classBuilder);
    // everything else is synthetic
    at(null);
    TransformationPlan plan = errors().hasDeclarationError(def);
    if (plan instanceof ThrowerCatchallConstructor) {
        MethodDefinitionBuilder initBuilder = classBuilder.addConstructor();
        initBuilder.body(statementGen().makeThrowUnresolvedCompilationError(plan.getErrorMessage().getMessage()));
        // Although we have the class pl which we could use we don't know 
        // that it won't collide with the default named constructor's pl
        // which would cause a javac error about two constructors with the same sig
        // so we generate a Object... here. There's still a risk of collision though
        // when the default constructor has pl (ObjectArray).
        ParameterDefinitionBuilder pdb = ParameterDefinitionBuilder.implicitParameter(this, "ignored");
        pdb.modifiers(VARARGS);
        pdb.type(make().TypeArray(make().Type(syms().objectType)), null);
        initBuilder.parameter(pdb);
    }
    // If it's a Class without initializer parameters...
    if (Strategy.generateMain(def)) {
        // ... then add a main() method
        classBuilder.method(makeMainForClass(model));
    }
    classBuilder.modelAnnotations(model.getAnnotations()).modifiers(transformClassDeclFlags(model)).satisfies(model.getSatisfiedTypes()).caseTypes(model.getCaseTypes(), model.getSelfType()).defs((List) childDefs);
    // aliases and native headers don't need a $getType method
    if (!model.isAlias()) {
        // only classes get a $getType method
        if (model instanceof Class)
            classBuilder.addGetTypeMethod(model.getType());
        if (supportsReifiedAlias(model))
            classBuilder.reifiedAlias(model.getType());
    }
    // we can add things which depend on knowing all the fields
    if (Strategy.generateJpaCtor(def)) {
        buildJpaConstructor((Class) def.getDeclarationModel(), classBuilder);
    }
    if (model instanceof Class && !(model instanceof ClassAlias)) {
        Class c = (Class) model;
        if (Strategy.introduceJavaIoSerializable(c, typeFact().getJavaIoSerializable())) {
            classBuilder.introduce(make().QualIdent(syms().serializableType.tsym));
            if (Strategy.useSerializationProxy(c) && noValueConstructorErrors((Tree.ClassDefinition) def)) {
                addWriteReplace(c, classBuilder);
            }
        }
        serialization(c, classBuilder);
    }
    // reset position before initializer constructor is generated. 
    at(def);
    List<JCTree> result;
    if (Decl.isAnnotationClass(def)) {
        ListBuffer<JCTree> trees = ListBuffer.lb();
        trees.addAll(transformAnnotationClass((Tree.AnyClass) def));
        transformAnnotationClassConstructor((Tree.AnyClass) def, classBuilder);
        // you only need that method if you satisfy Annotation which is erased to j.l.a.Annotation
        if (model.inherits(typeFact().getAnnotationDeclaration()))
            classBuilder.addAnnotationTypeMethod(model.getType());
        trees.addAll(classBuilder.build());
        result = trees.toList();
    } else {
        result = classBuilder.build();
    }
    return result;
}
Also used : ClassOrInterface(com.redhat.ceylon.model.typechecker.model.ClassOrInterface) ClassAlias(com.redhat.ceylon.model.typechecker.model.ClassAlias) JCTree(com.sun.tools.javac.tree.JCTree) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement) ThrowerCatchallConstructor(com.redhat.ceylon.compiler.java.codegen.recovery.ThrowerCatchallConstructor) 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) ClassOrInterface(com.redhat.ceylon.model.typechecker.model.ClassOrInterface) LazyInterface(com.redhat.ceylon.model.loader.model.LazyInterface) Interface(com.redhat.ceylon.model.typechecker.model.Interface) TransformationPlan(com.redhat.ceylon.compiler.java.codegen.recovery.TransformationPlan)

Example 43 with JCStatement

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

the class ClassTransformer method transformSpecifiedMethodBody.

List<JCStatement> transformSpecifiedMethodBody(Tree.MethodDeclaration def, SpecifierExpression specifierExpression) {
    final Function model = def.getDeclarationModel();
    List<JCStatement> body;
    Tree.MethodDeclaration methodDecl = def;
    boolean isLazy = specifierExpression instanceof Tree.LazySpecifierExpression;
    boolean returnNull = false;
    JCExpression bodyExpr;
    Tree.Term term = null;
    if (specifierExpression != null && specifierExpression.getExpression() != null) {
        term = Decl.unwrapExpressionsUntilTerm(specifierExpression.getExpression());
        HasErrorException error = errors().getFirstExpressionErrorAndMarkBrokenness(term);
        if (error != null) {
            return List.<JCStatement>of(this.makeThrowUnresolvedCompilationError(error));
        }
    }
    if (!isLazy && term instanceof Tree.FunctionArgument) {
        // Function specified with lambda: Don't bother generating a 
        // Callable, just transform the expr to use as the method body.
        Tree.FunctionArgument fa = (Tree.FunctionArgument) term;
        Type resultType = model.getType();
        returnNull = isAnything(resultType) && fa.getExpression().getUnboxed();
        final java.util.List<Tree.Parameter> lambdaParams = fa.getParameterLists().get(0).getParameters();
        final java.util.List<Tree.Parameter> defParams = def.getParameterLists().get(0).getParameters();
        List<Substitution> substitutions = List.nil();
        for (int ii = 0; ii < lambdaParams.size(); ii++) {
            substitutions = substitutions.append(naming.addVariableSubst((TypedDeclaration) lambdaParams.get(ii).getParameterModel().getModel(), defParams.get(ii).getParameterModel().getName()));
        }
        bodyExpr = gen().expressionGen().transformExpression(fa.getExpression(), returnNull ? BoxingStrategy.INDIFFERENT : CodegenUtil.getBoxingStrategy(model), resultType);
        for (Substitution subs : substitutions) {
            subs.close();
        }
    } else if (!isLazy && typeFact().isCallableType(term.getTypeModel())) {
        returnNull = isAnything(term.getTypeModel()) && term.getUnboxed();
        Function method = methodDecl.getDeclarationModel();
        boolean lazy = specifierExpression instanceof Tree.LazySpecifierExpression;
        boolean inlined = CodegenUtil.canOptimiseMethodSpecifier(term, method);
        Invocation invocation;
        if ((lazy || inlined) && term instanceof Tree.MemberOrTypeExpression && ((Tree.MemberOrTypeExpression) term).getDeclaration() instanceof Functional) {
            Declaration primaryDeclaration = ((Tree.MemberOrTypeExpression) term).getDeclaration();
            Reference producedReference = ((Tree.MemberOrTypeExpression) term).getTarget();
            invocation = new MethodReferenceSpecifierInvocation(this, (Tree.MemberOrTypeExpression) term, primaryDeclaration, producedReference, method, specifierExpression);
        } else if (!lazy && !inlined) {
            // must be a callable we stored
            String name = naming.getMethodSpecifierAttributeName(method);
            invocation = new CallableSpecifierInvocation(this, method, naming.makeUnquotedIdent(name), term, term);
        } else if (isCeylonCallableSubtype(term.getTypeModel())) {
            invocation = new CallableSpecifierInvocation(this, method, expressionGen().transformExpression(term), term, term);
        } else {
            throw new BugException(term, "unhandled primary: " + term == null ? "null" : term.getNodeType());
        }
        invocation.handleBoxing(true);
        invocation.setErased(CodegenUtil.hasTypeErased(term) || getReturnTypeOfCallable(term.getTypeModel()).isNothing());
        bodyExpr = expressionGen().transformInvocation(invocation);
    } else {
        bodyExpr = expressionGen().transformExpression(model, term);
        // The innermost of an MPL method declared void needs to return null
        returnNull = Decl.isUnboxedVoid(model) && Decl.isMpl(model);
    }
    if (!Decl.isUnboxedVoid(model) || Decl.isMpl(model) || Strategy.useBoxedVoid(model)) {
        if (returnNull) {
            body = List.<JCStatement>of(make().Exec(bodyExpr), make().Return(makeNull()));
        } else {
            body = List.<JCStatement>of(make().Return(bodyExpr));
        }
    } else {
        body = List.<JCStatement>of(make().Exec(bodyExpr));
    }
    return body;
}
Also used : JCMethodInvocation(com.sun.tools.javac.tree.JCTree.JCMethodInvocation) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement) Function(com.redhat.ceylon.model.typechecker.model.Function) FunctionArgument(com.redhat.ceylon.compiler.typechecker.tree.Tree.FunctionArgument) Substitution(com.redhat.ceylon.compiler.java.codegen.Naming.Substitution) JCPrimitiveTypeTree(com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree) JCTree(com.sun.tools.javac.tree.JCTree) Tree(com.redhat.ceylon.compiler.typechecker.tree.Tree) TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Declaration(com.redhat.ceylon.model.typechecker.model.Declaration) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration) MethodDeclaration(com.redhat.ceylon.compiler.typechecker.tree.Tree.MethodDeclaration) AttributeDeclaration(com.redhat.ceylon.compiler.typechecker.tree.Tree.AttributeDeclaration) FunctionArgument(com.redhat.ceylon.compiler.typechecker.tree.Tree.FunctionArgument) LazySpecifierExpression(com.redhat.ceylon.compiler.typechecker.tree.Tree.LazySpecifierExpression) Reference(com.redhat.ceylon.model.typechecker.model.Reference) TypedReference(com.redhat.ceylon.model.typechecker.model.TypedReference) MethodDeclaration(com.redhat.ceylon.compiler.typechecker.tree.Tree.MethodDeclaration) Functional(com.redhat.ceylon.model.typechecker.model.Functional) Type(com.redhat.ceylon.model.typechecker.model.Type) LazySpecifierExpression(com.redhat.ceylon.compiler.typechecker.tree.Tree.LazySpecifierExpression) 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)

Example 44 with JCStatement

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

the class ClassTransformer method addWriteReplace.

/**
     * Adds a write replace method which replaces value constructor instances 
     * with a SerializationProxy
     * @param model
     * @param classBuilder
     */
protected void addWriteReplace(final Class model, ClassDefinitionBuilder classBuilder) {
    MethodDefinitionBuilder mdb = MethodDefinitionBuilder.systemMethod(this, "writeReplace");
    mdb.resultType(null, make().Type(syms().objectType));
    mdb.modifiers(PRIVATE | FINAL);
    ListBuffer<JCStatement> stmts = ListBuffer.<JCStatement>lb();
    SyntheticName name = naming.synthetic(Unfix.$name$);
    stmts.add(makeVar(FINAL, name, make().Type(syms().stringType), null));
    if (model.hasEnumerated()) {
        JCStatement tail;
        if (Decl.hasOnlyValueConstructors(model)) {
            tail = make().Throw(statementGen().makeNewEnumeratedTypeError("Instance not of any constructor"));
        } else {
            tail = make().Return(naming.makeThis());
        }
        for (Declaration member : model.getMembers()) {
            if (Decl.isValueConstructor(member)) {
                Value val = (Value) member;
                tail = make().If(make().Binary(JCTree.EQ, naming.makeThis(), naming.getValueConstructorFieldName(val).makeIdent()), make().Block(0, List.<JCStatement>of(make().Exec(make().Assign(name.makeIdent(), make().Literal(Naming.getGetterName(member)))))), tail);
            }
        }
        stmts.add(tail);
    } else if (model.isAnonymous()) {
        stmts.add(make().Exec(make().Assign(name.makeIdent(), make().Literal(Naming.getGetterName((Value) model.getContainer().getDirectMember(model.getName(), null, false))))));
    } else {
        throw new BugException("Unsupported need for writeReplace()");
    }
    // final String name;
    // if(this == instA) {
    //    name = "getInstA";
    // } // ... else { throw new 
    // return new SerializationProxy(outer, Foo.clazz, name);
    List<JCExpression> args = List.<JCExpression>of(name.makeIdent());
    if (model.isMember()) {
        ClassOrInterface outer = (ClassOrInterface) model.getContainer();
        args = args.prepend(makeClassLiteral(outer.getType()));
        args = args.prepend(naming.makeQualifiedThis(naming.makeTypeDeclarationExpression(null, outer, DeclNameFlag.QUALIFIED)));
    } else {
        args = args.prepend(makeClassLiteral(model.getType()));
    }
    stmts.add(make().Return(make().NewClass(null, null, make().QualIdent(syms().ceylonSerializationProxyType.tsym), args, null)));
    mdb.body(stmts.toList());
    classBuilder.method(mdb);
}
Also used : ClassOrInterface(com.redhat.ceylon.model.typechecker.model.ClassOrInterface) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) FunctionOrValue(com.redhat.ceylon.model.typechecker.model.FunctionOrValue) JavaBeanValue(com.redhat.ceylon.model.loader.model.JavaBeanValue) Value(com.redhat.ceylon.model.typechecker.model.Value) SyntheticName(com.redhat.ceylon.compiler.java.codegen.Naming.SyntheticName) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement) TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Declaration(com.redhat.ceylon.model.typechecker.model.Declaration) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration) MethodDeclaration(com.redhat.ceylon.compiler.typechecker.tree.Tree.MethodDeclaration) AttributeDeclaration(com.redhat.ceylon.compiler.typechecker.tree.Tree.AttributeDeclaration)

Example 45 with JCStatement

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

the class CeylonTransformer method transformAttributeGetter.

public JCExpression transformAttributeGetter(TypedDeclaration declarationModel, final JCExpression expression) {
    final String attrName = declarationModel.getName();
    final String attrClassName = Naming.getAttrClassName(declarationModel, 0);
    JCBlock getterBlock = makeGetterBlock(expression);
    // For everything else generate a getter/setter method
    AttributeDefinitionBuilder builder = AttributeDefinitionBuilder.indirect(this, attrClassName, attrName, declarationModel, declarationModel.isToplevel()).getterBlock(getterBlock).immutable();
    List<JCTree> attr = builder.build();
    JCNewClass newExpr = makeNewClass(attrClassName, false, null);
    JCExpression result = makeLetExpr(naming.temp(), List.<JCStatement>of((JCStatement) attr.get(0)), newExpr);
    return result;
}
Also used : JCBlock(com.sun.tools.javac.tree.JCTree.JCBlock) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JCTree(com.sun.tools.javac.tree.JCTree) JCNewClass(com.sun.tools.javac.tree.JCTree.JCNewClass) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement)

Aggregations

JCStatement (com.sun.tools.javac.tree.JCTree.JCStatement)112 JCExpression (com.sun.tools.javac.tree.JCTree.JCExpression)82 JCVariableDecl (com.sun.tools.javac.tree.JCTree.JCVariableDecl)37 JCBlock (com.sun.tools.javac.tree.JCTree.JCBlock)33 JCTree (com.sun.tools.javac.tree.JCTree)32 Name (com.sun.tools.javac.util.Name)32 Type (com.redhat.ceylon.model.typechecker.model.Type)26 JCTypeParameter (com.sun.tools.javac.tree.JCTree.JCTypeParameter)26 ListBuffer (com.sun.tools.javac.util.ListBuffer)25 Tree (com.redhat.ceylon.compiler.typechecker.tree.Tree)23 SyntheticName (com.redhat.ceylon.compiler.java.codegen.Naming.SyntheticName)18 JCMethodDecl (com.sun.tools.javac.tree.JCTree.JCMethodDecl)16 JavacTreeMaker (lombok.javac.JavacTreeMaker)16 TypeParameter (com.redhat.ceylon.model.typechecker.model.TypeParameter)14 JCModifiers (com.sun.tools.javac.tree.JCTree.JCModifiers)14 TypedDeclaration (com.redhat.ceylon.model.typechecker.model.TypedDeclaration)12 JCAnnotation (com.sun.tools.javac.tree.JCTree.JCAnnotation)12 JCPrimitiveTypeTree (com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree)12 Parameter (com.redhat.ceylon.model.typechecker.model.Parameter)11 HasErrorException (com.redhat.ceylon.compiler.java.codegen.recovery.HasErrorException)10