Search in sources :

Example 31 with Interface

use of com.redhat.ceylon.model.typechecker.model.Interface 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)

Example 32 with Interface

use of com.redhat.ceylon.model.typechecker.model.Interface in project ceylon-compiler by ceylon.

the class ClassTransformer method addAmbiguousMembers.

private void addAmbiguousMembers(ClassDefinitionBuilder classBuilder, Interface model) {
    // only if we refine more than one interface
    java.util.List<Type> satisfiedTypes = model.getSatisfiedTypes();
    if (satisfiedTypes.size() <= 1)
        return;
    Set<Interface> satisfiedInterfaces = new HashSet<Interface>();
    for (Type interfaceDecl : model.getSatisfiedTypes()) {
        collectInterfaces((Interface) interfaceDecl.getDeclaration(), satisfiedInterfaces);
    }
    Set<Interface> ambiguousInterfaces = new HashSet<Interface>();
    for (Interface satisfiedInterface : satisfiedInterfaces) {
        if (isInheritedWithDifferentTypeArguments(satisfiedInterface, model.getType()) != null) {
            ambiguousInterfaces.add(satisfiedInterface);
        }
    }
    Set<String> treated = new HashSet<String>();
    for (Interface ambiguousInterface : ambiguousInterfaces) {
        for (Declaration member : ambiguousInterface.getMembers()) {
            String name = member.getName();
            // skip if already handled
            if (treated.contains(name))
                continue;
            // skip if it's implemented directly
            if (model.getDirectMember(name, null, false) != null) {
                treated.add(name);
                continue;
            }
            // find if we have different implementations in two direct interfaces
            LOOKUP: for (int i = 0; i < satisfiedTypes.size(); i++) {
                Type firstInterface = satisfiedTypes.get(i);
                Declaration member1 = firstInterface.getDeclaration().getMember(name, null, false);
                // if we can't find it in this interface, move to the next
                if (member1 == null)
                    continue;
                // try to find member in other interfaces
                for (int j = i + 1; j < satisfiedTypes.size(); j++) {
                    Type secondInterface = satisfiedTypes.get(j);
                    Declaration member2 = secondInterface.getDeclaration().getMember(name, null, false);
                    // if we can't find it in this interface, move to the next
                    if (member2 == null)
                        continue;
                    // we have it in two separate interfaces
                    Reference typedMember1 = firstInterface.getTypedReference(member1, Collections.<Type>emptyList());
                    Reference typedMember2 = secondInterface.getTypedReference(member2, Collections.<Type>emptyList());
                    Type type1 = simplifyType(typedMember1.getType());
                    Type type2 = simplifyType(typedMember2.getType());
                    if (!type1.isExactly(type2)) {
                        // treat it and stop looking for other interfaces
                        addAmbiguousMember(classBuilder, model, name);
                        break LOOKUP;
                    }
                }
            }
            // that member has no conflict
            treated.add(name);
        }
    }
}
Also used : Type(com.redhat.ceylon.model.typechecker.model.Type) Reference(com.redhat.ceylon.model.typechecker.model.Reference) TypedReference(com.redhat.ceylon.model.typechecker.model.TypedReference) 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) ClassOrInterface(com.redhat.ceylon.model.typechecker.model.ClassOrInterface) LazyInterface(com.redhat.ceylon.model.loader.model.LazyInterface) Interface(com.redhat.ceylon.model.typechecker.model.Interface) HashSet(java.util.HashSet)

Example 33 with Interface

use of com.redhat.ceylon.model.typechecker.model.Interface in project ceylon-compiler by ceylon.

the class ClassTransformer method makeNamedConstructor.

/**
 * Makes a named constructor
 * @param that
 * @param classBuilder
 * @param mods
 * @param ctorName
 * @param ctorBody
 * @param declFlags
 * @return
 */
public List<JCTree> makeNamedConstructor(Tree.Declaration that, Tree.ParameterList parameterList, Constructor ctor, ClassDefinitionBuilder classBuilder, boolean generateInstantiator, int mods, boolean atIgnoreCtor, String ctorName, List<JCStatement> ctorBody, DeclNameFlag... declFlags) {
    ListBuffer<JCTree> result = ListBuffer.<JCTree>lb();
    Class clz = (Class) ctor.getContainer();
    at(that);
    MethodDefinitionBuilder ctorDb = MethodDefinitionBuilder.constructor(this);
    ClassDefinitionBuilder decl = null;
    ClassDefinitionBuilder impl = null;
    if (generateInstantiator) {
        if (clz.getContainer() instanceof Interface) {
            decl = classBuilder.getContainingClassBuilder();
            impl = classBuilder.getContainingClassBuilder().getCompanionBuilder((Interface) clz.getContainer());
        } else {
            decl = classBuilder.getContainingClassBuilder();
            impl = classBuilder.getContainingClassBuilder();
        }
        generateInstantiators(classBuilder, clz, ctor, decl, impl, that, parameterList);
    }
    ctorDb.userAnnotations(expressionGen().transformAnnotations(OutputElement.CONSTRUCTOR, that));
    if (atIgnoreCtor) {
        ctorDb.modelAnnotations(makeAtIgnore());
    } else if (!Decl.isDefaultConstructor(ctor)) {
        ctorDb.modelAnnotations(makeAtName(ctor.getName()));
    }
    if (Decl.isEnumeratedConstructor(ctor)) {
        ctorDb.modelAnnotations(makeAtEnumerated());
    }
    ctorDb.modifiers(mods);
    for (TypeParameter tp : clz.getTypeParameters()) {
        ctorDb.reifiedTypeParameter(tp);
    }
    if (ctorName != null) {
        // generate a constructor name class (and constant)
        transformConstructorName(classBuilder, result, ctor, clz, mods, ctorName, declFlags);
        // Add the name paramter
        ctorDb.parameter(makeConstructorNameParameter(ctor, declFlags));
    }
    // Add the rest of the parameters (this worries about aliasing)
    if (parameterList != null) {
        transformClassOrCtorParameters(null, (Class) ctor.getContainer(), ctor, that, parameterList, contains(declFlags, DeclNameFlag.DELEGATION), classBuilder, ctorDb, generateInstantiator, decl, impl);
    }
    // Transformation of body has to happen after transformation of parameter so we know about parameter aliasing.
    at(that);
    ctorDb.block(make().Block(0, ctorBody));
    result.add(ctorDb.build());
    return result.toList();
}
Also used : TypeParameter(com.redhat.ceylon.model.typechecker.model.TypeParameter) JCTree(com.sun.tools.javac.tree.JCTree) 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)

Example 34 with Interface

use of com.redhat.ceylon.model.typechecker.model.Interface in project ceylon-compiler by ceylon.

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<.com.redhat.ceylon.compiler.java.test.structure.klass.SerializableEnumerable>(.com.redhat.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 (!Decl.isToplevel(iface) && !Decl.isLocal(iface)) {
        // if it's a member type we need to qualify the new instance with its $impl container
        ClassOrInterface interfaceContainer = Decl.getClassOrInterfaceContainer(iface, false);
        if (interfaceContainer instanceof Interface) {
            ClassOrInterface modelContainer = model;
            // first try to find exactly the interface we are looking for
            while ((modelContainer = Decl.getClassOrInterfaceContainer(modelContainer, false)) != null && !modelContainer.equals(interfaceContainer)) {
            // keep searching
            }
            // then find one that inherits it
            if (modelContainer == null) {
                modelContainer = model;
                while ((modelContainer = Decl.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 (!Decl.isToplevel(iface) && !Decl.isLocal(iface) && Decl.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(com.redhat.ceylon.model.typechecker.model.ClassOrInterface) Type(com.redhat.ceylon.model.typechecker.model.Type) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JCExpressionStatement(com.sun.tools.javac.tree.JCTree.JCExpressionStatement) ClassOrInterface(com.redhat.ceylon.model.typechecker.model.ClassOrInterface) LazyInterface(com.redhat.ceylon.model.loader.model.LazyInterface) Interface(com.redhat.ceylon.model.typechecker.model.Interface)

Example 35 with Interface

use of com.redhat.ceylon.model.typechecker.model.Interface in project ceylon-compiler by ceylon.

the class ClassTransformer method satisfaction.

private void satisfaction(Tree.SatisfiedTypes satisfied, final Class model, ClassDefinitionBuilder classBuilder) {
    Set<Interface> satisfiedInterfaces = new HashSet<Interface>();
    // start by saying that we already satisfied each interface from superclasses
    Type superClass = model.getExtendedType();
    while (superClass != null) {
        for (Type interfaceDecl : superClass.getSatisfiedTypes()) {
            collectInterfaces((Interface) interfaceDecl.getDeclaration(), satisfiedInterfaces);
        }
        superClass = superClass.getExtendedType();
    }
    // now satisfy each new interface
    if (satisfied != null) {
        for (Tree.StaticType type : satisfied.getTypes()) {
            try {
                Type satisfiedType = type.getTypeModel();
                TypeDeclaration decl = satisfiedType.getDeclaration();
                if (!(decl instanceof Interface)) {
                    continue;
                }
                // make sure we get the right instantiation of the interface
                satisfiedType = model.getType().getSupertype(decl);
                concreteMembersFromSuperinterfaces(model, classBuilder, satisfiedType, satisfiedInterfaces);
            } catch (BugException e) {
                e.addError(type);
            }
        }
    }
    // now find the set of interfaces we implemented twice with more refined type parameters
    if (model.getExtendedType() != null) {
        // reuse that Set
        satisfiedInterfaces.clear();
        for (Type interfaceDecl : model.getSatisfiedTypes()) {
            collectInterfaces((Interface) interfaceDecl.getDeclaration(), satisfiedInterfaces);
        }
        if (!satisfiedInterfaces.isEmpty()) {
            // sort it to facilitate test comparisons that work in JDK7 and 8
            ArrayList<Interface> sortedInterfaces = new ArrayList<Interface>(satisfiedInterfaces.size());
            sortedInterfaces.addAll(satisfiedInterfaces);
            Collections.sort(sortedInterfaces, DeclarationComparator);
            // now see if we refined them
            for (Interface iface : sortedInterfaces) {
                // skip those we can't do anything about
                if (!supportsReified(iface) || !CodegenUtil.isCompanionClassNeeded(iface))
                    continue;
                Type thisType = model.getType().getSupertype(iface);
                Type superClassType = model.getExtendedType().getSupertype(iface);
                if (thisType != null && superClassType != null && !thisType.isExactly(superClassType) && thisType.isSubtypeOf(superClassType)) {
                    // we're refining it
                    classBuilder.refineReifiedType(thisType);
                }
            }
        }
    }
}
Also used : Type(com.redhat.ceylon.model.typechecker.model.Type) ArrayList(java.util.ArrayList) JCPrimitiveTypeTree(com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree) JCTree(com.sun.tools.javac.tree.JCTree) Tree(com.redhat.ceylon.compiler.typechecker.tree.Tree) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration) ClassOrInterface(com.redhat.ceylon.model.typechecker.model.ClassOrInterface) LazyInterface(com.redhat.ceylon.model.loader.model.LazyInterface) Interface(com.redhat.ceylon.model.typechecker.model.Interface) HashSet(java.util.HashSet)

Aggregations

Interface (com.redhat.ceylon.model.typechecker.model.Interface)56 ClassOrInterface (com.redhat.ceylon.model.typechecker.model.ClassOrInterface)53 TypeDeclaration (com.redhat.ceylon.model.typechecker.model.TypeDeclaration)35 Type (com.redhat.ceylon.model.typechecker.model.Type)30 TypedDeclaration (com.redhat.ceylon.model.typechecker.model.TypedDeclaration)21 Declaration (com.redhat.ceylon.model.typechecker.model.Declaration)20 Tree (com.redhat.ceylon.compiler.typechecker.tree.Tree)18 JCTree (com.sun.tools.javac.tree.JCTree)18 Class (com.redhat.ceylon.model.typechecker.model.Class)17 JCExpression (com.sun.tools.javac.tree.JCTree.JCExpression)17 LazyInterface (com.redhat.ceylon.model.loader.model.LazyInterface)14 JCNewClass (com.sun.tools.javac.tree.JCTree.JCNewClass)12 Scope (com.redhat.ceylon.model.typechecker.model.Scope)10 TypeParameter (com.redhat.ceylon.model.typechecker.model.TypeParameter)10 Function (com.redhat.ceylon.model.typechecker.model.Function)9 Value (com.redhat.ceylon.model.typechecker.model.Value)9 TypeParser (com.redhat.ceylon.model.loader.TypeParser)8 Constructor (com.redhat.ceylon.model.typechecker.model.Constructor)8 FunctionOrValue (com.redhat.ceylon.model.typechecker.model.FunctionOrValue)8 IntersectionType (com.redhat.ceylon.model.typechecker.model.IntersectionType)8