Search in sources :

Example 56 with TypeParameter

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

the class ClassTransformer method transformClassOrCtorParameters.

private void transformClassOrCtorParameters(Tree.AnyClass def, Class cls, Constructor constructor, Tree.Declaration node, Tree.ParameterList paramList, boolean delegationConstructor, ClassDefinitionBuilder classBuilder, ParameterizedBuilder<?> constructorBuilder, boolean generateInstantiator, ClassDefinitionBuilder instantiatorDeclCb, ClassDefinitionBuilder instantiatorImplCb) {
    for (final Tree.Parameter param : paramList.getParameters()) {
        // Overloaded instantiators
        Parameter paramModel = param.getParameterModel();
        Parameter refinedParam = CodegenUtil.findParamForDecl((TypedDeclaration) CodegenUtil.getTopmostRefinedDeclaration(param.getParameterModel().getModel()));
        at(param);
        Tree.TypedDeclaration member = def != null ? Decl.getMemberDeclaration(def, param) : null;
        // transform the parameter and its annotations
        transformParameter(constructorBuilder, param, paramModel, member);
        if (Strategy.hasDefaultParameterValueMethod(paramModel) || Strategy.hasDefaultParameterOverload(paramModel) || (generateInstantiator && refinedParam != null && (Strategy.hasDefaultParameterValueMethod(refinedParam) || Strategy.hasDefaultParameterOverload(refinedParam)))) {
            ClassDefinitionBuilder cbForDevaultValues;
            ClassDefinitionBuilder cbForDevaultValuesDecls = null;
            switch(Strategy.defaultParameterMethodOwner(constructor != null ? constructor : cls)) {
                case STATIC:
                    cbForDevaultValues = classBuilder;
                    break;
                case OUTER:
                    cbForDevaultValues = classBuilder.getContainingClassBuilder();
                    break;
                case OUTER_COMPANION:
                    cbForDevaultValues = classBuilder.getContainingClassBuilder().getCompanionBuilder(Decl.getClassOrInterfaceContainer(cls, true));
                    if ((constructor == null || constructor.isShared()) && cls.isShared()) {
                        cbForDevaultValuesDecls = classBuilder.getContainingClassBuilder();
                    }
                    break;
                default:
                    cbForDevaultValues = classBuilder.getCompanionBuilder(cls);
            }
            if (!delegationConstructor) {
                if ((Strategy.hasDefaultParameterValueMethod(paramModel) || (refinedParam != null && Strategy.hasDefaultParameterValueMethod(refinedParam)))) {
                    if (!generateInstantiator || Decl.equal(refinedParam, paramModel)) {
                        // transform the default value into a method
                        cbForDevaultValues.method(makeParamDefaultValueMethod(false, constructor != null ? constructor : cls, paramList, param));
                        if (cbForDevaultValuesDecls != null) {
                            cbForDevaultValuesDecls.method(makeParamDefaultValueMethod(true, constructor != null ? constructor : cls, paramList, param));
                        }
                    } else if (Strategy.hasDelegatedDpm(cls) && cls.getContainer() instanceof Class) {
                        // generate a dpm which delegates to the companion
                        java.util.List<Parameter> parameters = paramList.getModel().getParameters();
                        MethodDefinitionBuilder mdb = makeDelegateToCompanion((Interface) cls.getRefinedDeclaration().getContainer(), paramModel.getModel().appliedTypedReference(cls.getType(), null), ((TypeDeclaration) cls.getContainer()).getType(), FINAL | (transformClassDeclFlags(cls) & ~ABSTRACT), List.<TypeParameter>nil(), Collections.<java.util.List<Type>>emptyList(), paramModel.getType().getFullType(), Naming.getDefaultedParamMethodName(cls, paramModel), parameters.subList(0, parameters.indexOf(paramModel)), false, Naming.getDefaultedParamMethodName(cls, paramModel), DelegateType.FOR_DEFAULT_VALUE);
                        cbForDevaultValues.method(mdb);
                    }
                }
            }
            boolean addOverloadedConstructor = false;
            if (generateInstantiator) {
                if (Decl.withinInterface(cls)) {
                    MethodDefinitionBuilder instBuilder = new DefaultedArgumentInstantiator(daoAbstract, cls, constructor, instantiatorDeclCb.isCompanionBuilder()).makeOverload(paramList.getModel(), param.getParameterModel(), cls.getTypeParameters());
                    instantiatorDeclCb.method(instBuilder);
                }
                if (!Decl.withinInterface(cls) || !cls.isFormal()) {
                    MethodDefinitionBuilder instBuilder = new DefaultedArgumentInstantiator(new DaoThis(node, paramList), cls, constructor, instantiatorImplCb.isCompanionBuilder()).makeOverload(paramList.getModel(), param.getParameterModel(), cls.getTypeParameters());
                    instantiatorImplCb.method(instBuilder);
                } else {
                    addOverloadedConstructor = true;
                }
            } else {
                addOverloadedConstructor = true;
            }
            if (addOverloadedConstructor) {
                // Add overloaded constructors for defaulted parameter
                MethodDefinitionBuilder overloadBuilder;
                DefaultedArgumentConstructor dac;
                if (constructor != null) {
                    dac = new DefaultedArgumentConstructor(classBuilder.addConstructor(), constructor, node, paramList, delegationConstructor);
                } else {
                    dac = new DefaultedArgumentConstructor(classBuilder.addConstructor(), cls, node, paramList, delegationConstructor);
                }
                overloadBuilder = dac.makeOverload(paramList.getModel(), param.getParameterModel(), cls.getTypeParameters());
            }
        }
    }
}
Also used : TypeParameter(com.redhat.ceylon.model.typechecker.model.TypeParameter) JCPrimitiveTypeTree(com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree) JCTree(com.sun.tools.javac.tree.JCTree) Tree(com.redhat.ceylon.compiler.typechecker.tree.Tree) TypeParameter(com.redhat.ceylon.model.typechecker.model.TypeParameter) Parameter(com.redhat.ceylon.model.typechecker.model.Parameter) Class(com.redhat.ceylon.model.typechecker.model.Class) JCNewClass(com.sun.tools.javac.tree.JCTree.JCNewClass) ArrayList(java.util.ArrayList) AnnotationList(com.redhat.ceylon.compiler.typechecker.tree.Tree.AnnotationList) List(com.sun.tools.javac.util.List) ParameterList(com.redhat.ceylon.model.typechecker.model.ParameterList) 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)

Example 57 with TypeParameter

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

the class ClassTransformer method getBestSatisfiedType.

private Type getBestSatisfiedType(Type currentType, Interface iface) {
    Type refinedSuperType = currentType.getSupertype(iface);
    Type firstSatisfiedType = getFirstSatisfiedType(currentType, iface);
    // in the very special case of the first satisfied type having type arguments erased to Object and
    // the most refined one having free type parameters, we prefer the one with free type parameters
    // because Java prefers it and it's in range with what nonWideningType does
    Map<TypeParameter, Type> refinedTAs = refinedSuperType.getTypeArguments();
    Map<TypeParameter, Type> firstTAs = firstSatisfiedType.getTypeArguments();
    for (TypeParameter tp : iface.getTypeParameters()) {
        Type refinedTA = refinedTAs.get(tp);
        Type firstTA = firstTAs.get(tp);
        if (willEraseToObject(firstTA) && isTypeParameter(refinedTA))
            return refinedSuperType;
    }
    return firstSatisfiedType;
}
Also used : Type(com.redhat.ceylon.model.typechecker.model.Type) TypeParameter(com.redhat.ceylon.model.typechecker.model.TypeParameter)

Example 58 with TypeParameter

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

the class ExpressionTransformer method erasesTypeArguments.

boolean erasesTypeArguments(Reference producedReference) {
    java.util.List<TypeParameter> tps = null;
    Declaration declaration = producedReference.getDeclaration();
    if (declaration instanceof Generic) {
        tps = ((Generic) declaration).getTypeParameters();
    }
    if (tps != null) {
        for (TypeParameter tp : tps) {
            Type ta = producedReference.getTypeArguments().get(tp);
            java.util.List<Type> bounds = null;
            boolean needsCastForBounds = false;
            if (!tp.getSatisfiedTypes().isEmpty()) {
                bounds = new ArrayList<Type>(tp.getSatisfiedTypes().size());
                for (Type bound : tp.getSatisfiedTypes()) {
                    // substitute the right type arguments
                    bound = substituteTypeArgumentsForTypeParameterBound(producedReference, bound);
                    bounds.add(bound);
                    needsCastForBounds |= needsCast(ta, bound, false, false, false);
                }
            }
            if (willEraseToObject(ta) || needsCastForBounds) {
                return true;
            }
        }
    }
    return false;
}
Also used : TypeParameter(com.redhat.ceylon.model.typechecker.model.TypeParameter) Type(com.redhat.ceylon.model.typechecker.model.Type) Generic(com.redhat.ceylon.model.typechecker.model.Generic) TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Declaration(com.redhat.ceylon.model.typechecker.model.Declaration) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration)

Example 59 with TypeParameter

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

the class ExpressionTransformer method transformTypeArguments.

private final void transformTypeArguments(CallBuilder callBuilder, Tree.StaticMemberOrTypeExpression mte) {
    java.util.List<TypeParameter> tps = null;
    Declaration declaration = mte.getDeclaration();
    if (declaration instanceof Generic) {
        tps = ((Generic) declaration).getTypeParameters();
    }
    if (mte.getTypeModel().isTypeConstructor()) {
        for (TypeParameter tp : tps) {
            callBuilder.typeArgument(makeJavaType(tp.getType(), JT_TYPE_ARGUMENT));
        }
        return;
    }
    if (tps != null) {
        for (TypeParameter tp : tps) {
            Type ta = mte.getTarget().getTypeArguments().get(tp);
            java.util.List<Type> bounds = null;
            boolean needsCastForBounds = false;
            if (!tp.getSatisfiedTypes().isEmpty()) {
                bounds = new ArrayList<Type>(tp.getSatisfiedTypes().size());
                for (Type bound : tp.getSatisfiedTypes()) {
                    // substitute the right type arguments
                    bound = substituteTypeArgumentsForTypeParameterBound(mte.getTarget(), bound);
                    bounds.add(bound);
                    needsCastForBounds |= needsCast(ta, bound, false, false, false);
                }
            }
            boolean hasMultipleBounds;
            Type firstBound;
            if (bounds != null) {
                hasMultipleBounds = bounds.size() > 1;
                firstBound = bounds.isEmpty() ? null : bounds.get(0);
            } else {
                hasMultipleBounds = false;
                firstBound = null;
            }
            if (willEraseToObject(ta) || needsCastForBounds) {
                boolean boundsSelfDependent = isBoundsSelfDependant(tp);
                if (hasDependentTypeParameters(tps, tp) || // and we cannot represent the intersection type in Java so give up
                hasMultipleBounds || // if we are going to use the first bound and it is self-dependent, we will make it raw
                boundsSelfDependent || (firstBound != null && willEraseToObject(firstBound))) {
                    // so at some point we'll have to introduce an intersection type AST node to satisfy multiple bounds
                    if (hasMultipleBounds) {
                        callBuilder.typeArguments(List.<JCExpression>nil());
                        return;
                    }
                    // if we have a bound
                    if (firstBound != null) {
                        // if it's self-dependent we cannot satisfy it without a raw type
                        if (boundsSelfDependent)
                            callBuilder.typeArgument(makeJavaType(firstBound, JT_TYPE_ARGUMENT | JT_RAW));
                        else
                            callBuilder.typeArgument(makeJavaType(firstBound, JT_TYPE_ARGUMENT));
                    } else {
                        // no bound, let's go with Object then
                        callBuilder.typeArgument(makeJavaType(typeFact().getObjectType(), JT_TYPE_ARGUMENT));
                    }
                } else if (firstBound == null) {
                    callBuilder.typeArgument(makeJavaType(ta, JT_TYPE_ARGUMENT));
                } else {
                    callBuilder.typeArgument(makeJavaType(firstBound, JT_TYPE_ARGUMENT));
                }
            } else {
                callBuilder.typeArgument(makeJavaType(ta, JT_TYPE_ARGUMENT));
            }
        }
    }
}
Also used : TypeParameter(com.redhat.ceylon.model.typechecker.model.TypeParameter) Type(com.redhat.ceylon.model.typechecker.model.Type) Generic(com.redhat.ceylon.model.typechecker.model.Generic) TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Declaration(com.redhat.ceylon.model.typechecker.model.Declaration) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration)

Aggregations

TypeParameter (com.redhat.ceylon.model.typechecker.model.TypeParameter)59 Type (com.redhat.ceylon.model.typechecker.model.Type)40 JCTypeParameter (com.sun.tools.javac.tree.JCTree.JCTypeParameter)24 TypeDeclaration (com.redhat.ceylon.model.typechecker.model.TypeDeclaration)23 ModelUtil.appliedType (com.redhat.ceylon.model.typechecker.model.ModelUtil.appliedType)21 ArrayList (java.util.ArrayList)15 Function (com.redhat.ceylon.model.typechecker.model.Function)14 Class (com.redhat.ceylon.model.typechecker.model.Class)13 ClassOrInterface (com.redhat.ceylon.model.typechecker.model.ClassOrInterface)13 Declaration (com.redhat.ceylon.model.typechecker.model.Declaration)13 TypedDeclaration (com.redhat.ceylon.model.typechecker.model.TypedDeclaration)13 Parameter (com.redhat.ceylon.model.typechecker.model.Parameter)12 TypedReference (com.redhat.ceylon.model.typechecker.model.TypedReference)12 JCExpression (com.sun.tools.javac.tree.JCTree.JCExpression)12 JCNewClass (com.sun.tools.javac.tree.JCTree.JCNewClass)10 Generic (com.redhat.ceylon.model.typechecker.model.Generic)9 Constructor (com.redhat.ceylon.model.typechecker.model.Constructor)8 Interface (com.redhat.ceylon.model.typechecker.model.Interface)8 ParameterList (com.redhat.ceylon.model.typechecker.model.ParameterList)8 FunctionOrValue (com.redhat.ceylon.model.typechecker.model.FunctionOrValue)7