public static void checkTypeArguments(ProducedType qualifyingType, Declaration declaration, List<ProducedType> typeArguments) {
if(declaration instanceof com.redhat.ceylon.compiler.typechecker.model.Generic){
List<com.redhat.ceylon.compiler.typechecker.model.TypeParameter> typeParameters = ((com.redhat.ceylon.compiler.typechecker.model.Generic) declaration).getTypeParameters();
if(typeParameters.size() < typeArguments.size())
throw new TypeApplicationException("Too many type arguments provided: "+typeArguments.size()+", but only accepts "+typeParameters.size());
int min = 0;
for (TypeParameter tp: typeParameters) {
if (!tp.isDefaulted()) min++;
}
if(typeArguments.size() < min){
String requires = (min == typeParameters.size()) ? "exactly" : "at least";
throw new TypeApplicationException("Not enough type arguments provided: "+typeArguments.size()+", but requires "+requires+" "+min);
}
for(int i=0;i<typeArguments.size();i++){
ProducedType typeArgument = typeArguments.get(i);
com.redhat.ceylon.compiler.typechecker.model.TypeParameter typeParameter = typeParameters.get(i);
for (ProducedType st: typeParameter.getSatisfiedTypes()) {
ProducedType sts = st.getProducedType(qualifyingType, declaration, typeArguments);
if (!typeArgument.isSubtypeOf(sts)) {
throw new TypeApplicationException("Type argument "+i+": "+typeArgument.getProducedTypeQualifiedName()
+" does not conform to upper bound constraint: "+sts.getProducedTypeQualifiedName()
+" of type parameter "+typeParameter.getQualifiedNameString());
}
}
if(!ExpressionVisitor.argumentSatisfiesEnumeratedConstraint(qualifyingType, declaration, typeArguments, typeArgument, typeParameter)){
throw new TypeApplicationException("Type argument "+i+": "+typeArgument.getProducedTypeQualifiedName()
+" does not conform to enumerated constraints "
+" of type parameter "+typeParameter.getQualifiedNameString());
}
}
}else{
if(!typeArguments.isEmpty())
throw new TypeApplicationException("Declaration does not accept type arguments");
}
}