Search in sources :

Example 1 with ClassAlias

use of org.eclipse.ceylon.model.typechecker.model.ClassAlias in project ceylon by eclipse.

the class DeclarationVisitor method visit.

@Override
public void visit(Tree.Parameter that) {
    super.visit(that);
    Tree.SpecifierOrInitializerExpression sie = null;
    if (that instanceof Tree.ParameterDeclaration) {
        Tree.ParameterDeclaration pd = (Tree.ParameterDeclaration) that;
        Tree.TypedDeclaration td = pd.getTypedDeclaration();
        if (td instanceof Tree.AttributeDeclaration) {
            Tree.AttributeDeclaration ad = (Tree.AttributeDeclaration) td;
            sie = ad.getSpecifierOrInitializerExpression();
        } else if (td instanceof Tree.MethodDeclaration) {
            Tree.MethodDeclaration md = (Tree.MethodDeclaration) td;
            sie = md.getSpecifierExpression();
        }
    } else if (that instanceof Tree.InitializerParameter) {
        Tree.InitializerParameter ip = (Tree.InitializerParameter) that;
        sie = ip.getSpecifierExpression();
    }
    if (sie != null) {
        if (scope instanceof ClassAlias) {
            sie.addUnsupportedError("defaulted parameters are not yet supported for class aliases");
        }
        new Visitor() {

            public void visit(Tree.AssignmentOp that) {
                that.addError("assignment may not occur in default argument expression");
            }

            @Override
            public void visit(Tree.PostfixOperatorExpression that) {
                that.addError("postfix increment or decrement may not occur in default argument expression");
            }

            @Override
            public void visit(Tree.PrefixOperatorExpression that) {
                that.addError("prefix increment or decrement may not occur in default argument expression");
            }
        }.visit(sie);
    }
}
Also used : ClassAlias(org.eclipse.ceylon.model.typechecker.model.ClassAlias) Visitor(org.eclipse.ceylon.compiler.typechecker.tree.Visitor) CustomTree(org.eclipse.ceylon.compiler.typechecker.tree.CustomTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree)

Example 2 with ClassAlias

use of org.eclipse.ceylon.model.typechecker.model.ClassAlias in project ceylon by eclipse.

the class DeclarationVisitor method visit.

@Override
public void visit(Tree.ClassDeclaration that) {
    Class c = new ClassAlias();
    that.setDeclarationModel(c);
    super.visit(that);
    if (that.getParameterList() == null) {
        that.addError("class alias must have a parameter list");
    }
}
Also used : ClassAlias(org.eclipse.ceylon.model.typechecker.model.ClassAlias) Class(org.eclipse.ceylon.model.typechecker.model.Class) AnalyzerUtil.isVeryAbstractClass(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.isVeryAbstractClass) ModelUtil.isAnonymousClass(org.eclipse.ceylon.model.typechecker.model.ModelUtil.isAnonymousClass)

Example 3 with ClassAlias

use of org.eclipse.ceylon.model.typechecker.model.ClassAlias in project ceylon by eclipse.

the class ClassTransformer method transform.

public List<JCTree> transform(final Tree.ClassOrInterface def) {
    final ClassOrInterface model = def.getDeclarationModel();
    if (model.isToplevel() && isEe(model)) {
        replaceModifierTransformation(new EeModifierTransformation());
    }
    // in that case
    if (model.isAlias() && Decl.isAncestorLocal(model))
        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 (model.isInterfaceMember()) {
        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));
    classBuilder.getInitBuilder().deprecated(model.isDeprecated());
    // Very special case for Anything
    if (model.isAnything()) {
        classBuilder.extending(model.getType(), null);
    }
    if (def instanceof Tree.AnyClass) {
        classBuilder.getInitBuilder().modifiers(modifierTransformation().constructor(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()) {
            if (!cls.isStatic()) {
                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);
    transformTypeParameters(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) {
        classBuilder.broken();
        MethodDefinitionBuilder initBuilder = classBuilder.noInitConstructor().addConstructor(model.isDeprecated());
        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(new TransformedType(make().TypeArray(make().Type(syms().objectType))));
        initBuilder.parameter(pdb);
    } else if (plan instanceof PrivateConstructorOnly) {
        classBuilder.broken();
        MethodDefinitionBuilder initBuilder = classBuilder.noInitConstructor().addConstructor(model.isDeprecated());
        initBuilder.body(statementGen().makeThrowUnresolvedCompilationError(plan.getErrorMessage().getMessage()));
        initBuilder.modifiers(PRIVATE);
    }
    // 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(modifierTransformation().classFlags(model)).satisfies(model.getSatisfiedTypes()).caseTypes(model.getCaseTypes(), model.getSelfType()).defs(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(model) && plan instanceof Generate) {
        buildJpaConstructor((Class) model, classBuilder);
    }
    if (model instanceof Class && !(model instanceof ClassAlias) && plan instanceof Generate) {
        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)) {
                at(def);
                addWriteReplace(c, classBuilder);
            }
        }
        serialization(c, classBuilder);
    }
    // reset position before initializer constructor is generated.
    at(def);
    classBuilder.at(def);
    List<JCTree> result;
    if (Decl.isAnnotationClass(def.getDeclarationModel())) {
        ListBuffer<JCTree> trees = new ListBuffer<JCTree>();
        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();
    }
    if (model.isToplevel() && isEe(model)) {
        replaceModifierTransformation(new ModifierTransformation());
    }
    return result;
}
Also used : ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) ClassAlias(org.eclipse.ceylon.model.typechecker.model.ClassAlias) ListBuffer(org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer) JCStatement(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement) PrivateConstructorOnly(org.eclipse.ceylon.compiler.java.codegen.recovery.PrivateConstructorOnly) Generate(org.eclipse.ceylon.compiler.java.codegen.recovery.Generate) JCPrimitiveTypeTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCPrimitiveTypeTree) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) ThrowerCatchallConstructor(org.eclipse.ceylon.compiler.java.codegen.recovery.ThrowerCatchallConstructor) Class(org.eclipse.ceylon.model.typechecker.model.Class) JCNewClass(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCNewClass) Interface(org.eclipse.ceylon.model.typechecker.model.Interface) ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) LazyInterface(org.eclipse.ceylon.model.loader.model.LazyInterface) TransformationPlan(org.eclipse.ceylon.compiler.java.codegen.recovery.TransformationPlan)

Example 4 with ClassAlias

use of org.eclipse.ceylon.model.typechecker.model.ClassAlias in project ceylon by eclipse.

the class ClassTransformer method transformClassAlias.

private void transformClassAlias(final Tree.ClassDeclaration def, ClassDefinitionBuilder classBuilder) {
    ClassAlias model = (ClassAlias) def.getDeclarationModel();
    Type aliasedClass = model.getExtendedType();
    TypeDeclaration classOrCtor = def.getClassSpecifier().getType().getDeclarationModel();
    while (classOrCtor instanceof ClassAlias) {
        classOrCtor = ((ClassAlias) classOrCtor).getConstructor();
    }
    classBuilder.annotations(makeAtAlias(aliasedClass, classOrCtor instanceof Constructor ? (Constructor) classOrCtor : null));
    classBuilder.isAlias(true);
    MethodDefinitionBuilder instantiator = transformClassAliasInstantiator(def, model, aliasedClass);
    ClassDefinitionBuilder cbInstantiator = null;
    switch(Strategy.defaultParameterMethodOwner(model)) {
        case STATIC:
            cbInstantiator = classBuilder;
            break;
        case OUTER:
            cbInstantiator = classBuilder.getContainingClassBuilder();
            break;
        case OUTER_COMPANION:
            cbInstantiator = classBuilder.getContainingClassBuilder().getCompanionBuilder(ModelUtil.getClassOrInterfaceContainer(model, true));
            break;
        default:
            throw BugException.unhandledEnumCase(Strategy.defaultParameterMethodOwner(model));
    }
    cbInstantiator.method(instantiator);
}
Also used : ClassAlias(org.eclipse.ceylon.model.typechecker.model.ClassAlias) Type(org.eclipse.ceylon.model.typechecker.model.Type) ThrowerCatchallConstructor(org.eclipse.ceylon.compiler.java.codegen.recovery.ThrowerCatchallConstructor) Constructor(org.eclipse.ceylon.model.typechecker.model.Constructor) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)

Example 5 with ClassAlias

use of org.eclipse.ceylon.model.typechecker.model.ClassAlias in project ceylon by eclipse.

the class ClassTransformer method makeMainForClass.

/**
 * Makes a {@code main()} method which calls the given top-level method
 * @param def
 */
private MethodDefinitionBuilder makeMainForClass(ClassOrInterface model) {
    at(null);
    List<JCExpression> arguments = List.nil();
    if (model.isAlias()) {
        TypeDeclaration constr = ((ClassAlias) model).getConstructor();
        if (constr instanceof Constructor) {
            // must pass the constructor name arg
            arguments = List.of(naming.makeNamedConstructorName((Constructor) constr, false));
        }
        model = (ClassOrInterface) model.getExtendedType().getDeclaration();
    }
    JCExpression nameId = makeJavaType(model.getType(), JT_RAW);
    arguments = makeBottomReifiedTypeParameters(model.getTypeParameters(), arguments);
    JCNewClass expr = make().NewClass(null, null, nameId, arguments, null);
    return makeMainMethod(model, expr);
}
Also used : ClassAlias(org.eclipse.ceylon.model.typechecker.model.ClassAlias) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) ThrowerCatchallConstructor(org.eclipse.ceylon.compiler.java.codegen.recovery.ThrowerCatchallConstructor) Constructor(org.eclipse.ceylon.model.typechecker.model.Constructor) JCNewClass(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCNewClass) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)

Aggregations

ClassAlias (org.eclipse.ceylon.model.typechecker.model.ClassAlias)12 TypeDeclaration (org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)8 Class (org.eclipse.ceylon.model.typechecker.model.Class)6 Constructor (org.eclipse.ceylon.model.typechecker.model.Constructor)6 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)4 Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)4 ArrayList (java.util.ArrayList)3 ThrowerCatchallConstructor (org.eclipse.ceylon.compiler.java.codegen.recovery.ThrowerCatchallConstructor)3 Function (org.eclipse.ceylon.model.typechecker.model.Function)3 Scope (org.eclipse.ceylon.model.typechecker.model.Scope)3 Type (org.eclipse.ceylon.model.typechecker.model.Type)3 TypeParameter (org.eclipse.ceylon.model.typechecker.model.TypeParameter)3 HashMap (java.util.HashMap)2 Map (java.util.Map)2 AnalyzerUtil.isVeryAbstractClass (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.isVeryAbstractClass)2 MethodDeclaration (org.eclipse.ceylon.compiler.typechecker.tree.Tree.MethodDeclaration)2 JCNewClass (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCNewClass)2 LazyClass (org.eclipse.ceylon.model.loader.model.LazyClass)2 ClassOrInterface (org.eclipse.ceylon.model.typechecker.model.ClassOrInterface)2 Interface (org.eclipse.ceylon.model.typechecker.model.Interface)2