use of org.eclipse.ceylon.model.typechecker.model.Unit 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.Unit in project ceylon by eclipse.
the class InheritanceVisitor method validateEnumeratedSupertypeArgument.
private void validateEnumeratedSupertypeArgument(Node that, TypeDeclaration type, Type supertype, TypeParameter tp, Type arg) {
Unit unit = that.getUnit();
if (arg.isTypeParameter()) {
TypeParameter atp = (TypeParameter) arg.getDeclaration();
if (atp.getDeclaration().equals(type)) {
// parameter of the enumerated supertype
if (tp.isCovariant() && !atp.isCovariant()) {
that.addError("argument to covariant type parameter of enumerated supertype must be covariant: " + typeDescription(tp, unit));
}
if (tp.isContravariant() && !atp.isContravariant()) {
that.addError("argument to contravariant type parameter of enumerated supertype must be contravariant: " + typeDescription(tp, unit));
}
} else {
that.addError("argument to type parameter of enumerated supertype must be a type parameter of '" + type.getName() + "': " + typeDescription(tp, unit));
}
} else if (tp.isCovariant()) {
if (!(arg.isNothing())) {
// TODO: let it be the union of the lower bounds on p
that.addError("argument to covariant type parameter of enumerated supertype must be a type parameter or 'Nothing': " + typeDescription(tp, unit));
}
} else if (tp.isContravariant()) {
List<Type> sts = tp.getSatisfiedTypes();
// TODO: do I need to do type arg substitution here??
Type ub = intersectionOfSupertypes(tp);
if (!(arg.isExactly(ub))) {
that.addError("argument to contravariant type parameter of enumerated supertype must be a type parameter or '" + typeNamesAsIntersection(sts, unit) + "': " + typeDescription(tp, unit));
}
} else {
that.addError("argument to type parameter of enumerated supertype must be a type parameter: " + typeDescription(tp, unit));
}
}
use of org.eclipse.ceylon.model.typechecker.model.Unit 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.Unit 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.Unit in project ceylon by eclipse.
the class InheritanceVisitor method visit.
@Override
public void visit(Tree.ExtendedType that) {
super.visit(that);
TypeDeclaration td = (TypeDeclaration) that.getScope();
if (!td.isAlias()) {
Tree.SimpleType et = that.getType();
if (et != null) {
Tree.InvocationExpression ie = that.getInvocationExpression();
Class clazz = (Class) td;
boolean hasConstructors = clazz.hasConstructors() || clazz.hasEnumerated();
boolean anonymous = clazz.isAnonymous();
if (ie == null) {
if (!hasConstructors || anonymous) {
et.addError("missing instantiation arguments");
}
} else {
if (hasConstructors && !anonymous) {
et.addError("unnecessary instantiation arguments");
}
}
Unit unit = that.getUnit();
Type type = et.getTypeModel();
if (type != null) {
checkSelfTypes(et, td, type);
checkExtensionOfMemberType(et, td, type);
// checkCaseOfSupertype(et, td, type);
Type ext = td.getExtendedType();
TypeDeclaration etd = ext == null ? null : ext.getDeclaration();
TypeDeclaration aetd = type.getDeclaration();
if (aetd instanceof Constructor && aetd.isAbstract()) {
et.addError("extends a partial constructor: '" + aetd.getName(unit) + "' is declared abstract");
}
while (etd != null && etd.isAlias()) {
Type etdet = etd.getExtendedType();
etd = etdet == null ? null : etdet.getDeclaration();
}
if (etd != null) {
if (etd.isFinal()) {
et.addError("extends a final class: '" + etd.getName(unit) + "' is declared final");
}
if (aetd instanceof Class && !contains(aetd, that.getScope())) {
Class c = (Class) aetd;
Constructor dc = c.getDefaultConstructor();
if (dc != null && !dc.isShared()) {
that.addError("extends a class with an unshared default constructor: default constructor of '" + c.getName(unit) + "' is not 'shared'");
}
}
if (etd.isSealed() && !unit.inSameModule(etd)) {
String moduleName = etd.getUnit().getPackage().getModule().getNameAsString();
et.addError("extends a sealed class in a different module: '" + etd.getName(unit) + "' in '" + moduleName + "' is sealed");
}
}
}
checkSupertypeVarianceAnnotations(et);
}
}
}
Aggregations