use of org.eclipse.ceylon.model.typechecker.model.TypeDeclaration in project ceylon by eclipse.
the class InheritanceVisitor method checkExtensionOfMemberType.
private void checkExtensionOfMemberType(Node that, TypeDeclaration td, Type type) {
Type qt = type.getQualifyingType();
if (qt != null && td instanceof ClassOrInterface) {
Unit unit = that.getUnit();
TypeDeclaration d = type.getDeclaration();
if (d.isStatic() || d instanceof Constructor) {
checkExtensionOfMemberType(that, td, qt);
} else {
Scope s = td;
while (s != null) {
s = s.getContainer();
if (s instanceof TypeDeclaration) {
TypeDeclaration otd = (TypeDeclaration) s;
if (otd.getType().isSubtypeOf(qt)) {
return;
}
}
}
that.addError("qualifying type '" + qt.asString(unit) + "' of supertype '" + type.asString(unit) + "' is not an outer type or supertype of any outer type of '" + td.getName(unit) + "'");
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.TypeDeclaration in project ceylon by eclipse.
the class InheritanceVisitor method collectCaseValues.
void collectCaseValues(Tree.CaseTypes that, TypeDeclaration td) {
Unit unit = that.getUnit();
Set<Declaration> valueSet = new HashSet<Declaration>();
for (Tree.StaticMemberOrTypeExpression bme : that.getBaseMemberExpressions()) {
String name = name(bme.getIdentifier());
TypedDeclaration value = bme instanceof Tree.BaseMemberExpression ? getTypedDeclaration(bme.getScope(), name, null, false, unit) : getPackageTypedDeclaration(name, null, false, unit);
if (value != null) {
if (value != null && !valueSet.add(value)) {
// this error is not really truly necessary
bme.addError("duplicate case: '" + value.getName(unit) + "' of '" + td.getName() + "'");
}
Type type = value.getType();
if (type != null) {
TypeDeclaration caseDec = type.getDeclaration();
if (caseDec instanceof Constructor) {
Scope scope = caseDec.getContainer();
if (scope instanceof Class) {
// enumerated singleton constructors
Constructor cons = (Constructor) caseDec;
Class c = (Class) scope;
if (!c.isToplevel() && !c.isStatic()) {
bme.addError("case must be a value constructor of a toplevel or static class: '" + c.getName(unit) + "' is not toplevel");
} else if (!cons.getParameterLists().isEmpty()) {
bme.addError("case must be a value constructor of a toplevel or static class: '" + cons.getName(unit) + "' is not a value constructor");
}
/*else if (!c.inherits(unit.getIdentifiableDeclaration())) {
bme.addError("case must be a value constructor of an identifiable class: '" +
c.getName(unit) +
"' is not a subtype of 'Identifiable'");
}*/
}
} else {
// enumerated anonymous subclasses
if (!caseDec.isObjectClass()) {
bme.addError("case must be a toplevel or static anonymous class: '" + value.getName(unit) + "' is not an anonymous class");
} else if (!value.isToplevel() && !value.isStatic()) {
bme.addError("case must be a toplevel or static anonymous class: '" + value.getName(unit) + "' is neither static nor toplevel");
}
}
if (checkDirectSubtype(td, bme, type)) {
checkAssignable(type, td.getType(), bme, getCaseTypeExplanation(td, type));
}
}
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.TypeDeclaration in project ceylon by eclipse.
the class InheritanceVisitor method checkCaseType.
void checkCaseType(TypeDeclaration type, Tree.StaticType ct, TypeDeclaration caseTypeDec) {
if (caseTypeDec instanceof ClassOrInterface && ct instanceof Tree.SimpleType && caseTypeDec.isParameterized()) {
Tree.SimpleType t = (Tree.SimpleType) ct;
Tree.TypeArgumentList tal = t.getTypeArgumentList();
List<Tree.Type> args = tal == null ? Collections.<Tree.Type>emptyList() : tal.getTypes();
List<TypeParameter> typeParameters = caseTypeDec.getTypeParameters();
Set<TypeParameter> used = new HashSet<TypeParameter>();
for (int i = 0; i < typeParameters.size(); i++) {
TypeParameter typeParameter = typeParameters.get(i);
Type argType;
Node node;
String typeArg;
if (i < args.size()) {
Tree.Type arg = args.get(i);
argType = arg.getTypeModel();
node = arg;
typeArg = "type argument";
} else {
argType = typeParameter.getDefaultTypeArgument();
node = tal;
typeArg = "default type argument '" + argType.asString(node.getUnit()) + "' of '" + typeParameter.getName() + "' ";
}
if (argType != null) {
TypeDeclaration argTypeDec = argType.getDeclaration();
if (argType.isTypeParameter()) {
TypeParameter tp = (TypeParameter) argTypeDec;
if (!tp.getDeclaration().equals(type)) {
node.addError(typeArg + "is not a type parameter of the enumerated type: '" + tp.getName() + "' is not a type parameter of '" + type.getName() + "'");
} else if (!used.add(tp)) {
node.addError("type parameter of the enumerated type is used twice as a type argument: '" + argTypeDec.getName());
}
} else if (typeParameter.isCovariant()) {
checkAssignable(typeParameter.getType(), argType, node, typeArg + " is not an upper bound of the type parameter '" + typeParameter.getName() + "' ");
} else if (typeParameter.isContravariant()) {
checkAssignable(argType, typeParameter.getType(), node, typeArg + " is not a lower bound of the type parameter '" + typeParameter.getName() + "' ");
} else {
node.addError(typeArg + "is not a type parameter of the enumerated type: '" + argTypeDec.getName() + "'");
}
}
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.TypeDeclaration in project ceylon by eclipse.
the class InheritanceVisitor method checkSelfTypes.
private void checkSelfTypes(Tree.StaticType that, TypeDeclaration td, Type type) {
if (!(td instanceof TypeParameter)) {
// TODO: is this really ok?!
List<TypeParameter> params = type.getDeclaration().getTypeParameters();
List<Type> args = type.getTypeArgumentList();
Unit unit = that.getUnit();
for (int i = 0; i < params.size(); i++) {
TypeParameter param = params.get(i);
if (param.isSelfType() && !args.isEmpty()) {
Type arg = args.get(i);
if (arg == null) {
arg = unit.getUnknownType();
}
TypeDeclaration std = param.getSelfTypedDeclaration();
Type at;
TypeDeclaration mtd;
if (param.getContainer().equals(std)) {
at = td.getType();
mtd = td;
} else {
// TODO: lots wrong here?
mtd = (TypeDeclaration) td.getMember(std.getName(), null, false);
at = mtd == null ? null : mtd.getType();
}
if (at != null && !at.isSubtypeOf(arg)) {
Type st = mtd.getSelfType();
if (st == null || !st.isExactly(arg)) {
String help = "";
TypeDeclaration atd = at.getDeclaration();
TypeDeclaration ad = arg.getDeclaration();
if (ad instanceof TypeParameter) {
TypeParameter tp = (TypeParameter) ad;
if (tp.getDeclaration().equals(td)) {
help = " (try making '" + ad.getName() + "' a self type of '" + td.getName() + "')";
}
} else if (ad instanceof Interface) {
help = " (try making " + message(atd) + " satisfy '" + ad.getName() + "')";
} else if (ad instanceof Class && td instanceof Class) {
help = " (try making " + message(atd) + " extend '" + ad.getName() + "')";
}
that.addError("type argument does not satisfy self type constraint on type parameter '" + param.getName() + "' of '" + type.getDeclaration().getName(unit) + "': '" + arg.asString(unit) + "' is not a supertype or self type of " + message(atd) + help);
}
}
}
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.TypeDeclaration in project ceylon by eclipse.
the class InheritanceVisitor method checkDirectSubtype.
private static boolean checkDirectSubtype(TypeDeclaration td, Node node, Type type) {
boolean found = false;
TypeDeclaration ctd = type.getDeclaration();
if (td instanceof Interface) {
for (Type st : ctd.getSatisfiedTypes()) {
if (st != null && st.resolveAliases().getDeclaration().equals(td)) {
found = true;
}
}
} else if (td instanceof Class) {
Type et = ctd.getExtendedType();
if (et != null && et.resolveAliases().getDeclaration().equals(td)) {
found = true;
}
}
if (!found) {
node.addError("case type is not a direct subtype of enumerated type: " + ctd.getName(node.getUnit()));
}
return found;
}
Aggregations