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());
}
}
}
}
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;
}
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;
}
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));
}
}
}
}
Aggregations