Search in sources :

Example 16 with ClassOrInterface

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

the class DeclarationVisitor method visit.

public void visit(Tree.SuperType that) {
    super.visit(that);
    if (inExtends) {
        final Scope scope = that.getScope();
        Type t = new LazyType(unit) {

            @Override
            public TypeDeclaration initDeclaration() {
                ClassOrInterface ci = getContainingClassOrInterface(scope);
                if (ci == null) {
                    return null;
                } else {
                    if (ci.isClassOrInterfaceMember()) {
                        ClassOrInterface oci = (ClassOrInterface) ci.getContainer();
                        return intersectionOfSupertypes(oci).getDeclaration();
                    } else {
                        return null;
                    }
                }
            }

            @Override
            public Map<TypeParameter, Type> initTypeArguments() {
                return emptyMap();
            }
        };
        that.setTypeModel(t);
    }
}
Also used : ModelUtil.getContainingClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ModelUtil.getContainingClassOrInterface) ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) IntersectionType(org.eclipse.ceylon.model.typechecker.model.IntersectionType) LazyType(org.eclipse.ceylon.model.typechecker.model.LazyType) UnionType(org.eclipse.ceylon.model.typechecker.model.UnionType) Type(org.eclipse.ceylon.model.typechecker.model.Type) UnknownType(org.eclipse.ceylon.model.typechecker.model.UnknownType) TypeVisitor.getTupleType(org.eclipse.ceylon.compiler.typechecker.analyzer.TypeVisitor.getTupleType) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) Scope(org.eclipse.ceylon.model.typechecker.model.Scope) ConditionScope(org.eclipse.ceylon.model.typechecker.model.ConditionScope) ModelUtil.getRealScope(org.eclipse.ceylon.model.typechecker.model.ModelUtil.getRealScope) LazyType(org.eclipse.ceylon.model.typechecker.model.LazyType)

Example 17 with ClassOrInterface

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

the class ClassTransformer method makeCompanionInstanceAssignment.

/**
 * Returns the companion instances assignment expression used in the constructor,
 * e.g.
 * <pre>
 * this.$ceylon$language$Enumerable$this$ = new .ceylon.language.Enumerable$impl<.org.eclipse.ceylon.compiler.java.test.structure.klass.SerializableEnumerable>(.org.eclipse.ceylon.compiler.java.test.structure.klass.SerializableEnumerable.$TypeDescriptor$, this);
 * </pre>
 * @param classBuilder
 * @return
 */
private JCExpressionStatement makeCompanionInstanceAssignment(final Class model, final Interface iface, final Type satisfiedType) {
    final Type bestSatisfiedType = getBestSatisfiedType(model.getType(), iface);
    JCExpression containerInstance = null;
    if (!iface.isToplevel() && !Decl.isLocal(iface)) {
        // if it's a member type we need to qualify the new instance with its $impl container
        ClassOrInterface interfaceContainer = ModelUtil.getClassOrInterfaceContainer(iface, false);
        if (interfaceContainer instanceof Interface) {
            ClassOrInterface modelContainer = model;
            // first try to find exactly the interface we are looking for
            while ((modelContainer = ModelUtil.getClassOrInterfaceContainer(modelContainer, false)) != null && !modelContainer.equals(interfaceContainer)) {
            // keep searching
            }
            // then find one that inherits it
            if (modelContainer == null) {
                modelContainer = model;
                while ((modelContainer = ModelUtil.getClassOrInterfaceContainer(modelContainer, false)) != null && modelContainer.getType().getSupertype(interfaceContainer) == null) {
                // keep searching
                }
            }
            if (modelContainer == null) {
                throw new BugException("Could not find container that satisfies interface " + iface.getQualifiedNameString() + " to find qualifying instance for companion instance for " + model.getQualifiedNameString());
            }
            // if it's an interface we just qualify it properly
            if (modelContainer instanceof Interface) {
                JCExpression containerType = makeJavaType(modelContainer.getType(), JT_COMPANION | JT_SATISFIES | JT_RAW);
                containerInstance = makeSelect(containerType, "this");
            } else {
                // it's a class: find the right field used for the interface container impl
                String containerFieldName = getCompanionFieldName((Interface) interfaceContainer);
                JCExpression containerType = makeJavaType(modelContainer.getType(), JT_SATISFIES);
                containerInstance = makeSelect(makeSelect(containerType, "this"), containerFieldName);
            }
        }
    }
    List<JCExpression> state = List.nil();
    // pass all reified type info to the constructor
    for (JCExpression t : makeReifiedTypeArguments(satisfiedType)) {
        state = state.append(t);
    }
    // pass the instance of this
    state = state.append(expressionGen().applyErasureAndBoxing(naming.makeThis(), model.getType(), false, true, BoxingStrategy.BOXED, bestSatisfiedType, ExpressionTransformer.EXPR_FOR_COMPANION));
    final JCExpression ifaceImplType;
    if (!iface.isToplevel() && !Decl.isLocal(iface) && ModelUtil.getClassOrInterfaceContainer(iface, false) instanceof Interface) {
        ifaceImplType = makeJavaType(bestSatisfiedType, JT_COMPANION | JT_CLASS_NEW | JT_NON_QUALIFIED);
    } else {
        ifaceImplType = makeJavaType(bestSatisfiedType, JT_COMPANION | JT_CLASS_NEW);
    }
    JCExpression newInstance = make().NewClass(containerInstance, null, ifaceImplType, state, null);
    JCExpressionStatement companionInstanceAssign = make().Exec(make().Assign(// TODO Use qualified name for quoting?
    makeSelect("this", getCompanionFieldName(iface)), newInstance));
    return companionInstanceAssign;
}
Also used : ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) Type(org.eclipse.ceylon.model.typechecker.model.Type) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) JCExpressionStatement(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpressionStatement) Interface(org.eclipse.ceylon.model.typechecker.model.Interface) ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) LazyInterface(org.eclipse.ceylon.model.loader.model.LazyInterface)

Example 18 with ClassOrInterface

use of org.eclipse.ceylon.model.typechecker.model.ClassOrInterface 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 19 with ClassOrInterface

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

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(new TransformedType(make().Type(syms().objectType), null, makeAtNonNull()));
    mdb.modifiers(PRIVATE | FINAL);
    ListBuffer<JCStatement> stmts = new ListBuffer<JCStatement>();
    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.Tag.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() && !model.isStatic()) {
        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(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) ListBuffer(org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer) Value(org.eclipse.ceylon.model.typechecker.model.Value) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue) JavaBeanValue(org.eclipse.ceylon.model.loader.model.JavaBeanValue) SyntheticName(org.eclipse.ceylon.compiler.java.codegen.Naming.SyntheticName) JCStatement(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) MethodDeclaration(org.eclipse.ceylon.compiler.typechecker.tree.Tree.MethodDeclaration)

Example 20 with ClassOrInterface

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

the class ClassTransformer method addAtContainer.

private void addAtContainer(ClassDefinitionBuilder classBuilder, TypeDeclaration model) {
    Scope scope = Decl.getNonSkippedContainer((Scope) model);
    Scope declarationScope = Decl.getFirstDeclarationContainer((Scope) model);
    boolean inlineObjectInToplevelAttr = Decl.isTopLevelObjectExpressionType(model);
    if (scope == null || (scope instanceof Package && !inlineObjectInToplevelAttr) && scope == declarationScope)
        return;
    if (scope instanceof ClassOrInterface && scope == declarationScope && !inlineObjectInToplevelAttr && // we do not check for types inside initialiser section which are private and not captured because we treat them as members
    !(model instanceof Interface && Decl.hasLocalNotInitializerAncestor(model))) {
        ClassOrInterface container = (ClassOrInterface) scope;
        List<JCAnnotation> atContainer = makeAtContainer(container.getType(), model.isStatic());
        classBuilder.annotations(atContainer);
    } else {
        if (model instanceof Interface)
            classBuilder.annotations(makeLocalContainerPath((Interface) model));
        Declaration declarationContainer = getDeclarationContainer(model);
        classBuilder.annotations(makeAtLocalDeclaration(model.getQualifier(), declarationContainer == null));
    }
}
Also used : ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) Scope(org.eclipse.ceylon.model.typechecker.model.Scope) Package(org.eclipse.ceylon.model.typechecker.model.Package) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) MethodDeclaration(org.eclipse.ceylon.compiler.typechecker.tree.Tree.MethodDeclaration) Interface(org.eclipse.ceylon.model.typechecker.model.Interface) ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) LazyInterface(org.eclipse.ceylon.model.loader.model.LazyInterface) JCAnnotation(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCAnnotation)

Aggregations

ClassOrInterface (org.eclipse.ceylon.model.typechecker.model.ClassOrInterface)102 TypeDeclaration (org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)62 Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)48 TypedDeclaration (org.eclipse.ceylon.model.typechecker.model.TypedDeclaration)46 Type (org.eclipse.ceylon.model.typechecker.model.Type)44 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)27 Class (org.eclipse.ceylon.model.typechecker.model.Class)24 Interface (org.eclipse.ceylon.model.typechecker.model.Interface)23 Scope (org.eclipse.ceylon.model.typechecker.model.Scope)23 TypeParameter (org.eclipse.ceylon.model.typechecker.model.TypeParameter)20 ModelUtil.getContainingClassOrInterface (org.eclipse.ceylon.model.typechecker.model.ModelUtil.getContainingClassOrInterface)19 Value (org.eclipse.ceylon.model.typechecker.model.Value)19 ModelUtil.appliedType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType)18 ArrayList (java.util.ArrayList)17 FunctionOrValue (org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)17 Constructor (org.eclipse.ceylon.model.typechecker.model.Constructor)16 Function (org.eclipse.ceylon.model.typechecker.model.Function)14 LazyInterface (org.eclipse.ceylon.model.loader.model.LazyInterface)13 JCExpression (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression)12 UnknownType (org.eclipse.ceylon.model.typechecker.model.UnknownType)12