Search in sources :

Example 96 with Interface

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

the class InterfaceVisitor method visit.

@Override
public void visit(Tree.ClassOrInterface that) {
    ClassOrInterface model = that.getDeclarationModel();
    // and they are useless at runtime
    if (!model.isAlias()) {
        // we never need to collect other local declaration names since only interfaces compete in the $impl name range
        if (model instanceof Interface)
            collect(that, (Interface) model);
        Set<String> old = localCompanionClasses;
        localCompanionClasses = new HashSet<String>();
        super.visit(that);
        localCompanionClasses = old;
    }
    if (model instanceof Interface) {
        ((Interface) model).setCompanionClassNeeded(isInterfaceWithCode(model));
    }
}
Also used : ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) Interface(org.eclipse.ceylon.model.typechecker.model.Interface)

Example 97 with Interface

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

the class NamedArgumentInvocation method makeThis.

private final JCVariableDecl makeThis() {
    // first append $this
    JCExpression defaultedParameterInstance;
    // TODO Fix how we figure out the thisType, because it's doesn't
    // handle type parameters correctly
    // we used to use thisType = gen.getThisType(getPrimaryDeclaration());
    final JCExpression thisType;
    Reference target = ((Tree.MemberOrTypeExpression) getPrimary()).getTarget();
    if (getPrimary() instanceof Tree.BaseMemberExpression && !gen.expressionGen().isWithinSyntheticClassBody()) {
        Declaration primaryDec = getPrimaryDeclaration();
        if (primaryDec.isClassOrInterfaceMember()) {
            // a member method
            thisType = gen.makeJavaType(target.getQualifyingType(), JT_NO_PRIMITIVES | (primaryDec.isInterfaceMember() && !primaryDec.isShared() ? JT_COMPANION : 0));
            TypeDeclaration outer = Decl.getOuterScopeOfMemberInvocation((StaticMemberOrTypeExpression) getPrimary(), primaryDec);
            if (outer instanceof Interface && primaryDec.isShared()) {
                defaultedParameterInstance = gen.naming.makeQuotedThis();
            } else {
                defaultedParameterInstance = gen.naming.makeQualifiedThis(gen.makeJavaType(((TypeDeclaration) outer).getType(), JT_NO_PRIMITIVES | (primaryDec.isInterfaceMember() && !primaryDec.isShared() ? JT_COMPANION : 0)));
            }
        } else {
            // a local or toplevel function
            thisType = gen.naming.makeName((TypedDeclaration) primaryDec, Naming.NA_WRAPPER);
            defaultedParameterInstance = gen.naming.makeName((TypedDeclaration) primaryDec, Naming.NA_MEMBER);
        }
    } else if (getPrimary() instanceof Tree.BaseTypeExpression || getPrimary() instanceof Tree.QualifiedTypeExpression) {
        TypeDeclaration declaration = (TypeDeclaration) ((Tree.MemberOrTypeExpression) getPrimary()).getDeclaration();
        thisType = gen.makeJavaType(declaration.getType(), JT_COMPANION);
        defaultedParameterInstance = gen.make().NewClass(null, null, gen.makeJavaType(declaration.getType(), JT_COMPANION), List.<JCExpression>nil(), null);
    } else {
        if (isOnValueType()) {
            thisType = gen.makeJavaType(target.getQualifyingType());
        } else {
            thisType = gen.makeJavaType(target.getQualifyingType(), JT_NO_PRIMITIVES);
        }
        defaultedParameterInstance = callVarName.makeIdent();
    }
    JCVariableDecl thisDecl = gen.makeVar(varBaseName.suffixedBy(Suffix.$argthis$), thisType, defaultedParameterInstance);
    return thisDecl;
}
Also used : TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) TypedReference(org.eclipse.ceylon.model.typechecker.model.TypedReference) Reference(org.eclipse.ceylon.model.typechecker.model.Reference) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) StaticMemberOrTypeExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.StaticMemberOrTypeExpression) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Interface(org.eclipse.ceylon.model.typechecker.model.Interface) ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) QualifiedTypeExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.QualifiedTypeExpression) JCVariableDecl(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCVariableDecl)

Example 98 with Interface

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

the class AbstractTransformer method makeAtLocalDeclarations.

private List<JCAnnotation> makeAtLocalDeclarations(Set<String> localDeclarations, Set<Interface> localInterfaces) {
    if (localDeclarations.isEmpty() && localInterfaces.isEmpty())
        return List.nil();
    ListBuffer<JCExpression> array = new ListBuffer<JCTree.JCExpression>();
    // sort them to get the same behaviour on every JDK
    SortedSet<String> sortedNames = new TreeSet<String>();
    sortedNames.addAll(localDeclarations);
    for (Interface iface : localInterfaces) {
        sortedNames.add("::" + naming.makeTypeDeclarationName(iface));
    }
    for (String val : sortedNames) array.add(make().Literal(val));
    JCExpression attr = make().Assign(naming.makeUnquotedIdent("value"), make().NewArray(null, null, array.toList()));
    return makeModelAnnotation(syms().ceylonAtLocalDeclarationsType, List.of(attr));
}
Also used : JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) TreeSet(java.util.TreeSet) ListBuffer(org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) Interface(org.eclipse.ceylon.model.typechecker.model.Interface) ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface)

Example 99 with Interface

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

the class AbstractTransformer method isInheritedWithDifferentTypeArguments.

protected Type isInheritedWithDifferentTypeArguments(Scope container, Type currentType) {
    // only interfaces can be inherited twice
    if (container instanceof Interface == false)
        return null;
    if (currentType.getDeclaration() instanceof ClassOrInterface == false)
        return null;
    Interface iface = (Interface) container;
    // if we have no type parameter there's no problem
    if (iface.getTypeParameters().isEmpty())
        return null;
    Type[] arg = new Type[1];
    return findFirstInheritedTypeIfInheritedTwiceWithDifferentTypeArguments(iface, currentType, arg);
}
Also used : ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) Type(org.eclipse.ceylon.model.typechecker.model.Type) ModelUtil.appliedType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType) Interface(org.eclipse.ceylon.model.typechecker.model.Interface) ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface)

Example 100 with Interface

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

the class AbstractTransformer method makeJavaType.

JCExpression makeJavaType(final Type ceylonType, final int flags) {
    Type type = ceylonType;
    if (type == null || type.isUnknown())
        return make().Erroneous();
    if (type.isConstructor()) {
        type = type.getExtendedType();
    }
    // resolve aliases
    if ((flags & JT_CLASS_LITERAL) == 0)
        type = type.resolveAliases();
    if ((flags & __JT_RAW_TP_BOUND) != 0 && type.isTypeParameter()) {
        type = type.getExtendedType();
    }
    if (type.isUnion()) {
        for (Type pt : type.getCaseTypes()) {
            if (pt.getDeclaration().isAnonymous()) {
                // found one, let's try to make it simpler
                Type simplerType = typeFact().denotableType(type);
                if (!simplerType.isNothing() && !simplerType.isUnion()) {
                    type = simplerType;
                } else if (isCeylonBoolean(simplifyType(simplerType))) {
                    type = simplerType;
                }
                break;
            }
        }
    }
    if (type.isTypeConstructor()) {
        return make().QualIdent(syms().ceylonAbstractTypeConstructorType.tsym);
    }
    // ERASURE
    if ((flags & JT_CLASS_LITERAL) == 0 && // literals to the alias class
    willEraseToObject(type)) {
        // - The Ceylon type U|V results in the Java type Object
        if ((flags & JT_SATISFIES) != 0) {
            return null;
        } else {
            return make().Type(syms().objectType);
        }
    } else if (willEraseToAnnotation(type)) {
        return make().Type(syms().annotationType);
    } else if (willEraseToException(type)) {
        if ((flags & JT_CLASS_NEW) != 0 || (flags & JT_EXTENDS) != 0) {
            return makeIdent(syms().ceylonExceptionType);
        } else {
            return make().Type(syms().exceptionType);
        }
    } else if (willEraseToThrowable(type)) {
        if ((flags & JT_CLASS_NEW) != 0 || (flags & JT_EXTENDS) != 0) {
            return makeIdent(syms().throwableType);
        } else {
            return make().Type(syms().throwableType);
        }
    } else if (willEraseToSequence(type)) {
        if ((flags & (JT_CLASS_NEW | JT_EXTENDS | JT_IS)) == 0) {
            Type typeArg = simplifyType(type).getTypeArgumentList().get(0);
            Type seqType = typeFact.getSequenceType(typeArg);
            if (typeFact.isOptionalType(type)) {
                type = typeFact.getOptionalType(seqType);
            } else {
                type = seqType;
            }
        }
    } else if ((flags & (JT_SATISFIES | JT_EXTENDS | JT_NO_PRIMITIVES | JT_CLASS_NEW)) == 0 && ((isCeylonBasicType(type) && !isOptional(type)) || isJavaString(type))) {
        if (isCeylonString(type) || isJavaString(type)) {
            return make().Type(syms().stringType);
        } else if (isCeylonBoolean(type)) {
            return make().TypeIdent(TypeTag.BOOLEAN);
        } else if (isCeylonInteger(type)) {
            if ("short".equals(type.getUnderlyingType())) {
                return make().TypeIdent(TypeTag.SHORT);
            } else if ((flags & JT_SMALL) != 0 || "int".equals(type.getUnderlyingType())) {
                return make().TypeIdent(TypeTag.INT);
            } else {
                return make().TypeIdent(TypeTag.LONG);
            }
        } else if (isCeylonFloat(type)) {
            if ((flags & JT_SMALL) != 0 || "float".equals(type.getUnderlyingType())) {
                return make().TypeIdent(TypeTag.FLOAT);
            } else {
                return make().TypeIdent(TypeTag.DOUBLE);
            }
        } else if (isCeylonCharacter(type)) {
            if ((flags & JT_SMALL) != 0 || "char".equals(type.getUnderlyingType())) {
                return make().TypeIdent(TypeTag.CHAR);
            } else {
                return make().TypeIdent(TypeTag.INT);
            }
        } else if (isCeylonByte(type)) {
            return make().TypeIdent(TypeTag.BYTE);
        }
    } else if (isCeylonBoolean(type) && !isTypeParameter(type)) {
        // && (flags & TYPE_ARGUMENT) == 0){
        // special case to get rid of $true and $false types
        type = typeFact.getBooleanType();
    } else if ((flags & JT_VALUE_TYPE) == 0 && isJavaArray(type)) {
        return getJavaArrayElementType(type, flags);
    }
    JCExpression jt = null;
    Type simpleType;
    if ((flags & JT_CLASS_LITERAL) == 0)
        simpleType = simplifyType(type);
    else
        simpleType = type;
    // see if we need to cross methods when looking up container types
    // this is required to properly collect all the type parameters for local interfaces
    // which we pull up to the toplevel and capture all the container type parameters
    boolean needsQualifyingTypeArgumentsFromLocalContainers = ModelUtil.isCeylonDeclaration(simpleType.getDeclaration()) && simpleType.getDeclaration() instanceof Interface && // this is only valid for interfaces, not for their companion which stay where they are
    (flags & JT_COMPANION) == 0;
    java.util.List<Reference> qualifyingTypes = null;
    Reference qType = simpleType;
    boolean hasTypeParameters = false;
    while (qType != null) {
        hasTypeParameters |= !qType.getTypeArguments().isEmpty();
        if (qualifyingTypes != null)
            qualifyingTypes.add(qType);
        Declaration typeDeclaration = qType.getDeclaration();
        // all the containing type parameters that it captures
        if (// local or anonymous
        (Decl.isLocal(typeDeclaration) || !typeDeclaration.isNamed()) && needsQualifyingTypeArgumentsFromLocalContainers && typeDeclaration instanceof ClassOrInterface) {
            Declaration container = Decl.getDeclarationScope(typeDeclaration.getContainer());
            while (container instanceof Function) {
                qType = ((Function) container).getReference();
                if (qualifyingTypes == null) {
                    qualifyingTypes = new java.util.ArrayList<Reference>();
                    qualifyingTypes.add(simpleType);
                }
                hasTypeParameters = true;
                qualifyingTypes.add(qType);
                container = Decl.getDeclarationScope(container.getContainer());
            }
            if (container instanceof TypeDeclaration) {
                qType = ((TypeDeclaration) container).getType();
            } else {
                qType = null;
            }
        } else if (typeDeclaration.isNamed()) {
            // avoid anonymous types which may pretend that they have a qualifying type
            Reference oldType = qType;
            qType = qType.getQualifyingType();
            if (qType != null && qType.getDeclaration() instanceof ClassOrInterface == false) {
                // sometimes the typechecker throws qualifying intersections at us and
                // we can't make anything of them, since some members may be unrelated to
                // the qualified declaration. This happens with "extends super.Foo()"
                // for example. See https://github.com/ceylon/ceylon-compiler/issues/1478
                qType = ((Type) qType).getSupertype((TypeDeclaration) typeDeclaration.getContainer());
            }
            if (qType != null && !qType.equals(ceylonType) && // ceylonType.getDeclaration().getContainer() instanceof Interface &&
            oldType.getDeclaration().getContainer() instanceof Interface && // !ceylonType.getDeclaration().getContainer().equals(ceylonType.getQualifyingType().getDeclaration()) &&
            !oldType.getDeclaration().getContainer().equals(oldType.getQualifyingType().getDeclaration()) && (flags & JT_EXTENDS) == 0) {
                qType = oldType.getQualifyingType().getSupertype(((Interface) (oldType.getDeclaration().getContainer())));
            }
        } else {
            // skip local declaration containers
            qType = null;
        }
        // delayed allocation if we have a qualifying type
        if (qualifyingTypes == null && qType != null) {
            qualifyingTypes = new java.util.ArrayList<Reference>();
            qualifyingTypes.add(simpleType);
        }
    }
    int firstQualifyingTypeWithTypeParameters = qualifyingTypes != null ? qualifyingTypes.size() - 1 : 0;
    // find the first static one, from the right to the left
    if (qualifyingTypes != null) {
        for (Reference pt : qualifyingTypes) {
            Declaration declaration = pt.getDeclaration();
            if (declaration instanceof TypeDeclaration && Decl.isStatic((TypeDeclaration) declaration)) {
                break;
            }
            firstQualifyingTypeWithTypeParameters--;
        }
        if (firstQualifyingTypeWithTypeParameters < 0)
            firstQualifyingTypeWithTypeParameters = 0;
        // put them in outer->inner order
        Collections.reverse(qualifyingTypes);
    }
    if (((flags & JT_RAW) == 0) && hasTypeParameters && !rawSupertype(ceylonType, flags)) {
        // special case for interfaces because we pull them into toplevel types
        if (ModelUtil.isCeylonDeclaration(simpleType.getDeclaration()) && qualifyingTypes != null && qualifyingTypes.size() > 1 && simpleType.getDeclaration() instanceof Interface && // this is only valid for interfaces, not for their companion which stay where they are
        (flags & JT_COMPANION) == 0) {
            JCExpression baseType;
            TypeDeclaration tdecl = simpleType.getDeclaration();
            // collect all the qualifying type args we'd normally have
            java.util.List<TypeParameter> qualifyingTypeParameters = new java.util.ArrayList<TypeParameter>();
            java.util.Map<TypeParameter, Type> qualifyingTypeArguments = new java.util.HashMap<TypeParameter, Type>();
            collectQualifyingTypeArguments(qualifyingTypeParameters, qualifyingTypeArguments, qualifyingTypes);
            ListBuffer<JCExpression> typeArgs = makeTypeArgs(isCeylonCallable(simpleType), flags, qualifyingTypeArguments, qualifyingTypeParameters, simpleType);
            if (isCeylonCallable(type) && (flags & JT_CLASS_NEW) != 0) {
                baseType = makeIdent(syms().ceylonAbstractCallableType);
            } else {
                baseType = naming.makeDeclarationName(tdecl, DeclNameFlag.QUALIFIED);
            }
            if (typeArgs != null && typeArgs.size() > 0) {
                jt = make().TypeApply(baseType, typeArgs.toList());
            } else {
                jt = baseType;
            }
        } else if ((flags & JT_NON_QUALIFIED) == 0) {
            int index = 0;
            if (qualifyingTypes != null) {
                for (Reference qualifyingType : qualifyingTypes) {
                    if (!qualifyingType.getDeclaration().equals(simpleType.getDeclaration()) && simpleType.getDeclaration().isStatic()) {
                        jt = makeRawType(flags, (Type) qualifyingType, (Type) qualifyingType);
                    } else {
                        jt = makeParameterisedType(qualifyingType.getType(), type, flags | (simpleType.getDeclaration().isStatic() ? JT_RAW : 0), jt, qualifyingTypes, firstQualifyingTypeWithTypeParameters, index);
                    }
                    index++;
                }
            } else {
                jt = makeParameterisedType(simpleType, type, flags, jt, qualifyingTypes, firstQualifyingTypeWithTypeParameters, index);
            }
        } else {
            jt = makeParameterisedType(type, type, flags, jt, qualifyingTypes, 0, 0);
        }
    } else {
        jt = makeRawType(flags, type, simpleType);
    }
    return (jt != null) ? jt : makeErroneous(null, "compiler bug: the java type corresponding to " + ceylonType + " could not be computed");
}
Also used : ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) JCTypeParameter(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCTypeParameter) HashMap(java.util.HashMap) TypedReference(org.eclipse.ceylon.model.typechecker.model.TypedReference) Reference(org.eclipse.ceylon.model.typechecker.model.Reference) ArrayList(java.util.ArrayList) Function(org.eclipse.ceylon.model.typechecker.model.Function) Type(org.eclipse.ceylon.model.typechecker.model.Type) ModelUtil.appliedType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Interface(org.eclipse.ceylon.model.typechecker.model.Interface) ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface)

Aggregations

Interface (org.eclipse.ceylon.model.typechecker.model.Interface)105 ClassOrInterface (org.eclipse.ceylon.model.typechecker.model.ClassOrInterface)99 Type (org.eclipse.ceylon.model.typechecker.model.Type)64 TypeDeclaration (org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)58 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)40 Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)35 LazyInterface (org.eclipse.ceylon.model.loader.model.LazyInterface)34 Class (org.eclipse.ceylon.model.typechecker.model.Class)32 ModelUtil.getContainingClassOrInterface (org.eclipse.ceylon.model.typechecker.model.ModelUtil.getContainingClassOrInterface)32 TypedDeclaration (org.eclipse.ceylon.model.typechecker.model.TypedDeclaration)32 UnknownType (org.eclipse.ceylon.model.typechecker.model.UnknownType)29 ModelUtil.appliedType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType)27 TypeParameter (org.eclipse.ceylon.model.typechecker.model.TypeParameter)21 ModelUtil.getOuterClassOrInterface (org.eclipse.ceylon.model.typechecker.model.ModelUtil.getOuterClassOrInterface)20 UnionType (org.eclipse.ceylon.model.typechecker.model.UnionType)20 ModelUtil.intersectionType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.intersectionType)19 ModelUtil.unionType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.unionType)19 AnalyzerUtil.getTupleType (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTupleType)18 AnalyzerUtil.spreadType (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.spreadType)18 JCTree (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree)18