use of org.eclipse.ceylon.model.typechecker.model.Class in project ceylon by eclipse.
the class TypeVisitor method visit.
/*@Override
public void visit(Tree.TypeConstraint that) {
super.visit(that);
if (that.getSelfType()!=null) {
TypeDeclaration td = (TypeDeclaration) that.getSelfType().getScope();
TypeParameter tp = that.getDeclarationModel();
td.setSelfType(tp.getType());
if (tp.isSelfType()) {
that.addError("type parameter may not act as self type for two different types");
}
else {
tp.setSelfTypedDeclaration(td);
}
}
}*/
@Override
public void visit(Tree.CaseTypes that) {
super.visit(that);
TypeDeclaration td = (TypeDeclaration) that.getScope();
List<Tree.StaticMemberOrTypeExpression> bmes = that.getBaseMemberExpressions();
List<Tree.StaticType> cts = that.getTypes();
List<TypedDeclaration> caseValues = new ArrayList<TypedDeclaration>(bmes.size());
List<Type> caseTypes = new ArrayList<Type>(bmes.size() + cts.size());
if (td instanceof TypeParameter) {
if (!bmes.isEmpty()) {
that.addError("cases of type parameter must be a types");
}
} else {
for (Tree.StaticMemberOrTypeExpression bme : bmes) {
// bmes have not yet been resolved
String name = name(bme.getIdentifier());
TypedDeclaration od = bme instanceof Tree.BaseMemberExpression ? getTypedDeclaration(bme.getScope(), name, null, false, unit) : getPackageTypedDeclaration(name, null, false, unit);
if (od != null) {
caseValues.add(od);
Type type = od.getType();
if (type != null) {
caseTypes.add(type);
}
}
}
}
for (Tree.StaticType ct : cts) {
inheritedType(ct);
Type type = ct.getTypeModel();
if (!isTypeUnknown(type)) {
if (type.isUnion() || type.isIntersection() || type.isNothing()) {
// union/intersection types don't have equals()
if (td instanceof TypeParameter) {
ct.addError("enumerated bound must be a class or interface type");
} else {
ct.addError("case type must be a class, interface, or self type");
}
} else {
TypeDeclaration ctd = type.getDeclaration();
if (ctd.equals(td)) {
ct.addError("directly enumerates itself: '" + td.getName() + "'");
} else if (type.isClassOrInterface()) {
caseTypes.add(type);
} else if (type.isTypeParameter()) {
if (td instanceof TypeParameter) {
caseTypes.add(type);
} else {
TypeParameter tp = (TypeParameter) ctd;
td.setSelfType(type);
if (tp.isSelfType()) {
ct.addError("type parameter may not act as self type for two different types");
} else {
tp.setSelfTypedDeclaration(td);
caseTypes.add(type);
}
if (cts.size() > 1) {
ct.addError("a type may not have more than one self type");
}
}
} else {
if (td instanceof TypeParameter) {
ct.addError("enumerated bound must be a class or interface type");
} else {
ct.addError("case type must be a class, interface, or self type");
}
}
}
}
}
if (!caseTypes.isEmpty()) {
TypeDeclaration first = caseTypes.get(0).getDeclaration();
if (caseTypes.size() == 1 && first.isSelfType()) {
// for a type family, the type that declares
// the type parameter may not be the same
// type for which it acts as a self type
Scope scope = first.getContainer();
if (scope instanceof ClassOrInterface) {
ClassOrInterface ci = (ClassOrInterface) scope;
if (!ci.isAbstract()) {
Tree.StaticType ct = cts.get(0);
if (ci.equals(td)) {
ct.addError("concrete class parameterized by self type: '" + ci.getName() + "' is not abstract but has the self type '" + first.getName() + "' (make '" + ci.getName() + "' abstract)", 905);
} else {
// type family
ct.addError("concrete class parameterized by self type: '" + ci.getName() + "' is not abstract but declares the self type '" + first.getName() + "' of '" + td.getName() + "' (make '" + ci.getName() + "' abstract)", 905);
}
}
}
} else {
if (td instanceof ClassOrInterface) {
ClassOrInterface ci = (ClassOrInterface) td;
if (!ci.isAbstract()) {
Class c = (Class) ci;
if (!c.hasEnumerated()) {
that.addError("concrete class has enumerated subtypes: " + "enumerated class '" + ci.getName() + "' is not abstract" + " (make '" + ci.getName() + "' abstract)", 905);
}
}
}
}
td.setCaseTypes(caseTypes);
td.setCaseValues(caseValues);
}
}
use of org.eclipse.ceylon.model.typechecker.model.Class in project ceylon by eclipse.
the class TypeVisitor method visit.
@Override
public void visit(Tree.TypeParameterDeclaration that) {
TypeParameter p = that.getDeclarationModel();
p.setExtendedType(null);
p.getSatisfiedTypes().clear();
Class vd = unit.getAnythingDeclaration();
if (vd != null) {
p.setExtendedType(vd.getType());
}
super.visit(that);
Tree.TypeSpecifier ts = that.getTypeSpecifier();
if (ts != null) {
Tree.StaticType type = ts.getType();
if (type != null) {
Type dta = type.getTypeModel();
Declaration dec = p.getDeclaration();
if (dta != null && dta.involvesDeclaration(dec)) {
type.addError("default type argument involves parameterized type: '" + dta.asString(unit) + "' involves '" + dec.getName(unit) + "'");
dta = null;
}
/*else if (dta.containsTypeParameters()) {
type.addError("default type argument involves type parameters: " +
dta.asString(unit));
dta = null;
}*/
p.setDefaultTypeArgument(dta);
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.Class in project ceylon by eclipse.
the class TypeVisitor method visit.
@Override
public void visit(Tree.ClassDefinition that) {
Class cd = that.getDeclarationModel();
if (!isVeryAbstractClass(that, unit)) {
cd.setExtendedType(unit.getBasicType());
} else {
cd.setExtendedType(null);
}
cd.getSatisfiedTypes().clear();
super.visit(that);
Tree.ParameterList pl = that.getParameterList();
if (pl != null) {
if (cd.hasConstructors()) {
pl.addError("class with parameters may not declare constructors: class '" + cd.getName() + "' has a parameter list and a constructor", 1002);
} else if (cd.hasEnumerated()) {
pl.addError("class with parameters may not declare constructors: class '" + cd.getName() + "' has a parameter list and a value constructor", 1003);
} else if (cd.hasStaticMembers()) {
pl.addError("class with parameters may not declare static members: class '" + cd.getName() + "' has a parameter list and a static member", 1003);
}
} else {
if (!cd.hasConstructors() && !cd.hasEnumerated()) {
// No parameter list and no constructors or enumerated
// normally means something is wrong
boolean error = true;
// Check if the declaration is a native implementation
if (cd.isNativeImplementation()) {
Declaration hdr = getNativeHeader(cd);
// Check that it has a native header
if (hdr instanceof Class) {
Class hcd = (Class) hdr;
// constructors or enumerated
if (hcd.hasConstructors() || hcd.hasEnumerated()) {
// In that case there's no error
error = false;
}
}
}
if (error) {
that.addError("class must have a parameter list or at least one constructor: class '" + cd.getName() + "' has neither parameter list nor constructor", 1001);
}
}
/*else {
// Check if the class has at least one shared constructor
boolean found = hasSharedConstructors(cd);
// If not found check if the declaration is a native implementation
if (!found &&
cd.isNative() &&
!cd.isNativeHeader()) {
Declaration hdr = getNativeHeader(cd);
// And check that it has a native header
if (hdr instanceof Class) {
Class hcd = (Class) hdr;
// In that case we try again with the header
found = hasSharedConstructors(hcd);
}
}
if (!found) {
that.addError("class with constructors must declare at least one shared constructor: class '" +
cd.getName() +
"' has no shared constructor");
}
}*/
}
}
use of org.eclipse.ceylon.model.typechecker.model.Class in project ceylon by eclipse.
the class ExpressionVisitor method visitDirectInvocation.
/**
* Typecheck a direct invocation.
*/
private void visitDirectInvocation(Tree.InvocationExpression that) {
Tree.Term primary = unwrapExpressionUntilTerm(that.getPrimary());
if (primary == null) {
return;
}
Tree.MemberOrTypeExpression mte = (Tree.MemberOrTypeExpression) primary;
Reference prf = mte.getTarget();
Declaration dec = mte.getDeclaration();
Functional fun = (Functional) dec;
if (dec != null) {
if (!(primary instanceof Tree.ExtendedTypeExpression)) {
if (dec instanceof Class) {
Class c = (Class) dec;
if (c.isAbstract()) {
that.addError("abstract class may not be instantiated: '" + dec.getName(unit) + "'");
}
}
}
Tree.NamedArgumentList nal = that.getNamedArgumentList();
if (nal != null && dec.isAbstraction()) {
// TODO: this is not really right - it's the fact
// that we're calling Java and don't have
// meaningful parameter names that is the
// real problem, not the overload
that.addError("overloaded declarations may not be called using named arguments: '" + dec.getName(unit) + "'");
}
// that.setTypeModel(prf.getType());
Type ct = primary.getTypeModel();
if (ct != null) {
List<Type> tal = ct.getTypeArgumentList();
if (!tal.isEmpty()) {
// pull the return type out of the Callable
that.setTypeModel(tal.get(0));
}
}
if (nal != null) {
List<ParameterList> parameterLists = fun.getParameterLists();
if (!parameterLists.isEmpty() && !parameterLists.get(0).isNamedParametersSupported()) {
that.addError("named invocations of Java methods not supported");
}
}
if (dec.isAbstraction()) {
// nothing to check the argument types against
// that.addError("no matching overloaded declaration");
} else {
// typecheck arguments using the parameter list
// of the target declaration
checkInvocationArguments(that, prf, fun);
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.Class in project ceylon by eclipse.
the class ExpressionVisitor method defaultType.
private Type defaultType() {
TypeDeclaration ut = new UnknownType(unit);
Class ad = unit.getAnythingDeclaration();
if (ad != null) {
ut.setExtendedType(ad.getType());
}
return ut.getType();
}
Aggregations