Search in sources :

Example 1 with TransformationPlan

use of com.redhat.ceylon.compiler.java.codegen.recovery.TransformationPlan 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 2 with TransformationPlan

use of com.redhat.ceylon.compiler.java.codegen.recovery.TransformationPlan in project ceylon-compiler by ceylon.

the class ClassTransformer method transformClass.

private void transformClass(Tree.AnyClass def, Class model, ClassDefinitionBuilder classBuilder, Tree.ParameterList paramList, boolean generateInstantiator, ClassDefinitionBuilder instantiatorDeclCb, ClassDefinitionBuilder instantiatorImplCb) {
    // do reified type params first
    classBuilder.reifiedTypeParameters(model.getTypeParameters());
    if (def.getParameterList() != null) {
        TransformationPlan error = errors().hasDeclarationAndMarkBrokenness(def);
        if (error instanceof ThrowerCatchallConstructor) {
            InitializerBuilder initBuilder = classBuilder.getInitBuilder();
            initBuilder.init(make().If(make().Literal(true), statementGen().makeThrowUnresolvedCompilationError(error.getErrorMessage().getMessage()), null));
        }
        for (Tree.Parameter param : def.getParameterList().getParameters()) {
            Tree.TypedDeclaration member = def != null ? Decl.getMemberDeclaration(def, param) : null;
            makeAttributeForValueParameter(classBuilder, param, member);
            makeMethodForFunctionalParameter(classBuilder, param, member);
        }
        transformClassOrCtorParameters(def, model, null, def, def.getParameterList(), false, classBuilder, classBuilder.getInitBuilder(), generateInstantiator, instantiatorDeclCb, instantiatorImplCb);
    }
    satisfaction(def.getSatisfiedTypes(), model, classBuilder);
    at(def);
    // Generate the inner members list for model loading
    addAtMembers(classBuilder, model, def);
    addAtLocalDeclarations(classBuilder, def);
    // Make sure top types satisfy reified type
    addReifiedTypeInterface(classBuilder, model);
}
Also used : 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) TransformationPlan(com.redhat.ceylon.compiler.java.codegen.recovery.TransformationPlan)

Example 3 with TransformationPlan

use of com.redhat.ceylon.compiler.java.codegen.recovery.TransformationPlan in project ceylon-compiler by ceylon.

the class CeylonVisitor method visit.

/*
     * Compilation Unit
     */
public void visit(Tree.TypeAliasDeclaration decl) {
    TransformationPlan plan = gen.errors().hasDeclarationAndMarkBrokenness(decl);
    if (plan instanceof Drop) {
        return;
    }
    int annots = gen.checkCompilerAnnotations(decl, defs);
    if (Decl.withinClassOrInterface(decl)) {
        if (Decl.withinInterface(decl)) {
            classBuilder.getCompanionBuilder((Interface) decl.getDeclarationModel().getContainer()).defs(gen.classGen().transform(decl));
        } else {
            classBuilder.defs(gen.classGen().transform(decl));
        }
    } else {
        appendList(gen.classGen().transform(decl));
    }
    gen.resetCompilerAnnotations(annots);
}
Also used : TransformationPlan(com.redhat.ceylon.compiler.java.codegen.recovery.TransformationPlan) Interface(com.redhat.ceylon.model.typechecker.model.Interface) ClassOrInterface(com.redhat.ceylon.model.typechecker.model.ClassOrInterface) Drop(com.redhat.ceylon.compiler.java.codegen.recovery.Drop)

Example 4 with TransformationPlan

use of com.redhat.ceylon.compiler.java.codegen.recovery.TransformationPlan in project ceylon-compiler by ceylon.

the class CeylonVisitor method visit.

public void visit(Tree.ClassOrInterface decl) {
    TransformationPlan plan = gen.errors().hasDeclarationAndMarkBrokenness(decl);
    if (plan instanceof Drop) {
        return;
    }
    if (skipHeaderMergeLater(decl)) {
        return;
    }
    // To accept this class it is either not native or native for this backend
    if (!acceptDeclaration(decl))
        return;
    int annots = gen.checkCompilerAnnotations(decl, defs);
    if (Decl.withinClassOrInterface(decl)) {
        if (Decl.withinInterface(decl)) {
            classBuilder.getCompanionBuilder((Interface) decl.getDeclarationModel().getContainer()).defs(gen.classGen().transform(decl));
        } else {
            classBuilder.defs(gen.classGen().transform(decl));
        }
    } else {
        appendList(gen.classGen().transform(decl));
    }
    gen.resetCompilerAnnotations(annots);
}
Also used : TransformationPlan(com.redhat.ceylon.compiler.java.codegen.recovery.TransformationPlan) Interface(com.redhat.ceylon.model.typechecker.model.Interface) ClassOrInterface(com.redhat.ceylon.model.typechecker.model.ClassOrInterface) Drop(com.redhat.ceylon.compiler.java.codegen.recovery.Drop)

Example 5 with TransformationPlan

use of com.redhat.ceylon.compiler.java.codegen.recovery.TransformationPlan in project ceylon-compiler by ceylon.

the class ClassTransformer method addAtMembers.

private void addAtMembers(ClassDefinitionBuilder classBuilder, ClassOrInterface model, Tree.ClassOrInterface def) {
    List<JCExpression> members = List.nil();
    for (Declaration member : model.getMembers()) {
        if (member instanceof ClassOrInterface == false && member instanceof TypeAlias == false) {
            continue;
        }
        TypeDeclaration innerType = (TypeDeclaration) member;
        Tree.Declaration innerTypeTree = findInnerType(def, innerType.getName());
        if (innerTypeTree != null) {
            TransformationPlan plan = errors().hasDeclarationAndMarkBrokenness(innerTypeTree);
            if (plan instanceof Drop) {
                continue;
            }
        }
        if (innerType.isAlias() && innerTypeTree != null && Decl.isAncestorLocal(innerTypeTree))
            // for the same reason we do not generate aliases in transform(ClassOrInterface def) let's not list them
            continue;
        JCAnnotation atMember;
        // interfaces are moved to toplevel so they can lose visibility of member types if they are local
        if (Decl.isLocal(model) && model instanceof Interface)
            atMember = makeAtMember(innerType.getName());
        else
            atMember = makeAtMember(innerType.getType());
        members = members.prepend(atMember);
    }
    classBuilder.annotations(makeAtMembers(members));
}
Also used : ClassOrInterface(com.redhat.ceylon.model.typechecker.model.ClassOrInterface) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JCPrimitiveTypeTree(com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree) JCTree(com.sun.tools.javac.tree.JCTree) Tree(com.redhat.ceylon.compiler.typechecker.tree.Tree) TypeAlias(com.redhat.ceylon.model.typechecker.model.TypeAlias) 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) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration) TransformationPlan(com.redhat.ceylon.compiler.java.codegen.recovery.TransformationPlan) JCAnnotation(com.sun.tools.javac.tree.JCTree.JCAnnotation) ClassOrInterface(com.redhat.ceylon.model.typechecker.model.ClassOrInterface) LazyInterface(com.redhat.ceylon.model.loader.model.LazyInterface) Interface(com.redhat.ceylon.model.typechecker.model.Interface) Drop(com.redhat.ceylon.compiler.java.codegen.recovery.Drop)

Aggregations

TransformationPlan (com.redhat.ceylon.compiler.java.codegen.recovery.TransformationPlan)11 Drop (com.redhat.ceylon.compiler.java.codegen.recovery.Drop)9 Tree (com.redhat.ceylon.compiler.typechecker.tree.Tree)4 ClassOrInterface (com.redhat.ceylon.model.typechecker.model.ClassOrInterface)4 Interface (com.redhat.ceylon.model.typechecker.model.Interface)4 JCTree (com.sun.tools.javac.tree.JCTree)4 JCPrimitiveTypeTree (com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree)3 ThrowerCatchallConstructor (com.redhat.ceylon.compiler.java.codegen.recovery.ThrowerCatchallConstructor)2 LazyInterface (com.redhat.ceylon.model.loader.model.LazyInterface)2 Class (com.redhat.ceylon.model.typechecker.model.Class)2 JCExpression (com.sun.tools.javac.tree.JCTree.JCExpression)2 JCStatement (com.sun.tools.javac.tree.JCTree.JCStatement)2 SyntheticName (com.redhat.ceylon.compiler.java.codegen.Naming.SyntheticName)1 CustomTree (com.redhat.ceylon.compiler.typechecker.tree.CustomTree)1 AttributeDeclaration (com.redhat.ceylon.compiler.typechecker.tree.Tree.AttributeDeclaration)1 MethodDeclaration (com.redhat.ceylon.compiler.typechecker.tree.Tree.MethodDeclaration)1 Return (com.redhat.ceylon.compiler.typechecker.tree.Tree.Return)1 ClassAlias (com.redhat.ceylon.model.typechecker.model.ClassAlias)1 Declaration (com.redhat.ceylon.model.typechecker.model.Declaration)1 Parameter (com.redhat.ceylon.model.typechecker.model.Parameter)1