use of org.eclipse.ceylon.model.typechecker.model.ClassOrInterface in project ceylon by eclipse.
the class RefinementVisitor method checkMember.
private void checkMember(Tree.Declaration that, Declaration member) {
String name = member.getName();
if (name == null) {
return;
}
if (member instanceof Setter) {
Setter setter = (Setter) member;
Value getter = setter.getGetter();
Declaration rd = getter.getRefinedDeclaration();
member.setRefinedDeclaration(rd);
return;
}
ClassOrInterface type = (ClassOrInterface) member.getContainer();
if (member.isFormal() && type instanceof Class) {
Class c = (Class) type;
if (!c.isAbstract() && !c.isFormal()) {
if (c.isClassOrInterfaceMember()) {
that.addError("formal member belongs to concrete nested class: '" + member.getName() + "' is a member of class '" + c.getName() + "' which is neither 'abstract' nor 'formal'", 1100);
} else {
that.addError("formal member belongs to concrete class: '" + member.getName() + "' is a member of class '" + c.getName() + "' which is not annotated 'abstract'", 1100);
}
}
}
if (member.isStatic() && !type.isToplevel()) {
that.addError("static member belongs to a nested class: '" + member.getName() + "' is a member of nested type '" + type.getName() + "'");
}
if (type.isDynamic()) {
if (member instanceof Class) {
that.addError("member class belongs to dynamic interface");
} else if (!member.isFormal()) {
that.addError("non-formal member belongs to dynamic interface");
}
}
if (member instanceof Functional && !that.hasErrors() && isOverloadedVersion(member)) {
checkOverloadedAnnotation(that, member);
checkOverloadedParameters(that, member);
}
checkRefinement(that, member, type);
}
use of org.eclipse.ceylon.model.typechecker.model.ClassOrInterface in project ceylon by eclipse.
the class RefinementVisitor method refineAttribute.
private void refineAttribute(Value assignedAttribute, Tree.BaseMemberExpression bme, Tree.SpecifierStatement that, ClassOrInterface c) {
if (!assignedAttribute.isFormal() && !assignedAttribute.isDefault() && !assignedAttribute.isShortcutRefinement()) {
// this condition is here to squash a dupe message
that.addError("inherited attribute may not be assigned in initializer and may not be refined: " + message(assignedAttribute) + " is declared neither 'formal' nor 'default'", 510);
// return;
} else if (assignedAttribute.isVariable()) {
that.addError("inherited attribute may not be assigned in initializer and may not be refined by non-variable: " + message(assignedAttribute) + " is declared 'variable'");
// return;
}
ClassOrInterface ci = (ClassOrInterface) assignedAttribute.getContainer();
String name = assignedAttribute.getName();
Declaration refined = ci.getRefinedMember(name, null, false);
Value root = refined instanceof Value ? (Value) refined : assignedAttribute;
Reference rv = getRefinedMemberReference(assignedAttribute, c);
boolean lazy = that.getSpecifierExpression() instanceof Tree.LazySpecifierExpression;
Value attribute = new Value();
attribute.setName(name);
attribute.setShared(true);
attribute.setActual(true);
attribute.getAnnotations().add(new Annotation("shared"));
attribute.getAnnotations().add(new Annotation("actual"));
attribute.setRefinedDeclaration(root);
Unit unit = that.getUnit();
attribute.setUnit(unit);
attribute.setContainer(c);
attribute.setScope(c);
attribute.setShortcutRefinement(true);
attribute.setTransient(lazy);
Declaration rvd = rv.getDeclaration();
if (rvd instanceof TypedDeclaration) {
TypedDeclaration rvtd = (TypedDeclaration) rvd;
attribute.setUncheckedNullType(rvtd.hasUncheckedNullType());
}
ModelUtil.setVisibleScope(attribute);
c.addMember(attribute);
that.setRefinement(true);
that.setDeclaration(attribute);
that.setRefined(assignedAttribute);
unit.addDeclaration(attribute);
setRefiningType(c, ci, name, null, false, root, attribute, unit, NO_SUBSTITUTIONS);
}
use of org.eclipse.ceylon.model.typechecker.model.ClassOrInterface in project ceylon by eclipse.
the class RefinementVisitor method refineMethod.
private void refineMethod(Function assignedMethod, Tree.BaseMemberExpression bme, Tree.SpecifierStatement that, ClassOrInterface c) {
if (!assignedMethod.isFormal() && !assignedMethod.isDefault() && !assignedMethod.isShortcutRefinement()) {
// this condition is here to squash a dupe message
bme.addError("inherited method may not be refined: " + message(assignedMethod) + " is declared neither 'formal' nor 'default'", 510);
// return;
}
ClassOrInterface ci = (ClassOrInterface) assignedMethod.getContainer();
String name = assignedMethod.getName();
List<Type> signature = getSignature(assignedMethod);
boolean variadic = isVariadic(assignedMethod);
Declaration refined = ci.getRefinedMember(name, signature, variadic);
Function root = refined instanceof Function ? (Function) refined : assignedMethod;
Reference rm = getRefinedMemberReference(assignedMethod, c);
Function method = new Function();
method.setName(name);
List<Tree.ParameterList> paramLists;
List<TypeParameter> typeParams;
Tree.Term me = that.getBaseMemberExpression();
if (me instanceof Tree.ParameterizedExpression) {
Tree.ParameterizedExpression pe = (Tree.ParameterizedExpression) me;
paramLists = pe.getParameterLists();
Tree.TypeParameterList typeParameterList = pe.getTypeParameterList();
if (typeParameterList != null) {
typeParams = new ArrayList<TypeParameter>();
for (Tree.TypeParameterDeclaration tpd : typeParameterList.getTypeParameterDeclarations()) {
typeParams.add(tpd.getDeclarationModel());
}
} else {
typeParams = null;
}
} else {
paramLists = emptyList();
typeParams = null;
}
Unit unit = that.getUnit();
final Map<TypeParameter, Type> subs;
if (typeParams != null) {
// the type parameters are written
// down in the shortcut refinement
method.setTypeParameters(typeParams);
// TODO: check 'em!!
// no need to check them because
// this case is actually disallowed
// elsewhere (specification statements
// may not have type parameters)
subs = NO_SUBSTITUTIONS;
} else if (assignedMethod.isParameterized()) {
if (me instanceof Tree.ParameterizedExpression) {
// we have parameters, but no type parameters
bme.addError("refined method is generic: '" + assignedMethod.getName(unit) + "' declares type parameters");
subs = NO_SUBSTITUTIONS;
} else {
// we're assigning a method reference
// so we need to magic up some "fake"
// type parameters
subs = copyTypeParametersFromRefined(assignedMethod, method, unit);
}
} else {
subs = NO_SUBSTITUTIONS;
}
int i = 0;
for (ParameterList pl : assignedMethod.getParameterLists()) {
Tree.ParameterList params = paramLists.size() <= i ? null : paramLists.get(i++);
createRefiningParameterList(rm, method, params, unit, subs, pl);
}
method.setShared(true);
method.setActual(true);
method.getAnnotations().add(new Annotation("shared"));
method.getAnnotations().add(new Annotation("actual"));
method.setRefinedDeclaration(root);
method.setUnit(unit);
method.setContainer(c);
method.setScope(c);
method.setShortcutRefinement(true);
method.setDeclaredVoid(assignedMethod.isDeclaredVoid());
Declaration rmd = rm.getDeclaration();
if (rmd instanceof TypedDeclaration) {
TypedDeclaration rmtd = (TypedDeclaration) rmd;
method.setUncheckedNullType(rmtd.hasUncheckedNullType());
}
ModelUtil.setVisibleScope(method);
c.addMember(method);
that.setRefinement(true);
that.setDeclaration(method);
that.setRefined(root);
unit.addDeclaration(method);
Scope scope = that.getScope();
if (scope instanceof Specification) {
Specification spec = (Specification) scope;
spec.setDeclaration(method);
}
setRefiningType(c, ci, name, signature, variadic, root, method, unit, subs);
inheritDefaultedArguments(method);
}
use of org.eclipse.ceylon.model.typechecker.model.ClassOrInterface in project ceylon by eclipse.
the class DeclarationVisitor method handleNativeHeader.
private void handleNativeHeader(Declaration model, String name) {
// Deal with implementations from the ModelLoader
ArrayList<FunctionOrValue> loadedFunctionsOrValues = null;
ArrayList<ClassOrInterface> loadedClasses = null;
ArrayList<Constructor> loadedConstructors = null;
for (Backend backendToSearch : Backend.getRegisteredBackends()) {
Declaration overloadFromModelLoader = model.getContainer().getDirectMemberForBackend(name, backendToSearch.asSet());
if (overloadFromModelLoader instanceof FunctionOrValue) {
if (loadedFunctionsOrValues == null) {
loadedFunctionsOrValues = new ArrayList<FunctionOrValue>();
}
FunctionOrValue fov = (FunctionOrValue) overloadFromModelLoader;
loadedFunctionsOrValues.add(fov);
} else if (overloadFromModelLoader instanceof ClassOrInterface) {
if (loadedClasses == null) {
loadedClasses = new ArrayList<ClassOrInterface>();
}
ClassOrInterface c = (ClassOrInterface) overloadFromModelLoader;
loadedClasses.add(c);
} else if (overloadFromModelLoader instanceof Constructor) {
if (loadedConstructors == null) {
loadedConstructors = new ArrayList<Constructor>();
}
Constructor c = (Constructor) overloadFromModelLoader;
loadedConstructors.add(c);
}
}
// Initialize the header's overloads
if (model instanceof FunctionOrValue) {
FunctionOrValue m = (FunctionOrValue) model;
if (loadedFunctionsOrValues != null) {
m.initOverloads(loadedFunctionsOrValues.toArray(NO_FUNCTIONS_OR_VALUES));
} else {
m.initOverloads();
}
} else if (model instanceof ClassOrInterface) {
ClassOrInterface c = (ClassOrInterface) model;
if (loadedClasses != null) {
c.initOverloads(loadedClasses.toArray(NO_CLASSES));
} else {
c.initOverloads();
}
} else if (model instanceof Constructor) {
Constructor c = (Constructor) model;
if (loadedConstructors != null) {
c.initOverloads(loadedConstructors.toArray(NO_CONSTRUCTORS));
} else {
c.initOverloads();
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.ClassOrInterface in project ceylon by eclipse.
the class DeclarationVisitor method visit.
@Override
public void visit(Tree.AttributeDeclaration that) {
Value v = new Value();
that.setDeclarationModel(v);
Tree.SpecifierOrInitializerExpression sie = that.getSpecifierOrInitializerExpression();
boolean lazy = sie instanceof Tree.LazySpecifierExpression;
v.setTransient(lazy);
v.setImplemented(sie != null);
visitDeclaration(that, v);
if (!lazy && v.isVariable() && v.isStatic()) {
Scope container = v.getContainer();
if (container instanceof ClassOrInterface) {
ClassOrInterface ci = (ClassOrInterface) container;
if (!ci.getTypeParameters().isEmpty()) {
that.addError("attribute of generic type may not be annotated both 'variable' and 'static'");
}
}
}
Scope o = null;
// if (lazy)
o = enterScope(v);
super.visit(that);
// if (lazy)
exitScope(o);
if (v.isInterfaceMember() && !v.isFormal() && !v.isNative()) {
if (sie == null) {
that.addError("interface attribute must be annotated 'formal'", 1400);
}
}
if (v.isLate()) {
if (lazy) {
that.addError("late attribute should specify initial value using '='");
}
if (v.isFormal()) {
that.addError("formal attribute may not be annotated 'late'");
} else if (v.isDefault()) {
that.addError("default attribute may not be annotated 'late'");
} else if (!v.isClassOrInterfaceMember() && !v.isToplevel()) {
that.addError("block-local value may not be annotated 'late'");
}
}
if (v.isFormal() && sie != null) {
that.addError("formal attribute may not have a value", 1102);
}
Tree.Type type = that.getType();
if (type instanceof Tree.ValueModifier) {
if (v.isToplevel()) {
if (sie == null) {
type.addError("toplevel value must explicitly specify a type");
} else {
type.addError("toplevel value must explicitly specify a type", 200);
}
} else if (mustHaveExplicitType(v)) {
type.addError("shared value must explicitly specify a type", 200);
}
}
}
Aggregations