use of org.eclipse.ceylon.model.typechecker.model.FunctionOrValue in project ceylon by eclipse.
the class SpecificationVisitor method visit.
@Override
public void visit(Tree.ClassBody that) {
if (that.getScope() == declaration.getContainer()) {
Tree.Statement les = getLastExecutableStatement(that);
Tree.Declaration lc = getLastConstructor(that);
declarationSection = les == null;
lastExecutableStatement = les;
lastConstructor = lc;
new Visitor() {
boolean declarationSection = false;
@Override
public void visit(Tree.ExecutableStatement that) {
super.visit(that);
if (that == lastExecutableStatement) {
declarationSection = true;
}
}
@Override
public void visit(Tree.Declaration that) {
super.visit(that);
if (declarationSection && isSameDeclaration(that)) {
definedInDeclarationSection = true;
}
if (that == lastExecutableStatement) {
declarationSection = true;
}
}
@Override
public void visit(Tree.StaticMemberOrTypeExpression that) {
super.visit(that);
if (declarationSection && declaration instanceof FunctionOrValue && that.getDeclaration() == declaration) {
usedInDeclarationSection = true;
}
}
}.visit(that);
super.visit(that);
declarationSection = false;
lastExecutableStatement = null;
lastConstructor = null;
if (!declaration.isAnonymous()) {
if (isSharedDeclarationUninitialized()) {
Node d = getDeclaration(that);
if (d == null)
d = that;
d.addError("must be definitely specified by class initializer: " + message(declaration) + explanation(), 1401);
}
}
} else {
super.visit(that);
}
}
use of org.eclipse.ceylon.model.typechecker.model.FunctionOrValue in project ceylon by eclipse.
the class DeclarationVisitor method checkForNativeAnnotation.
private void checkForNativeAnnotation(Tree.Declaration that, Declaration model, Scope scope) {
Unit unit = model.getUnit();
if (model.isNative()) {
Backends mbackends = model.getNativeBackends();
boolean isHeader = model.isNativeHeader();
String name = model.getName();
boolean canBeNative = canBeNative(that);
if (canBeNative) {
Backends moduleBackends = unit.getPackage().getModule().getNativeBackends();
Backends backends = model.getScope().getScopedBackends();
if (!isHeader && !moduleBackends.none() && !mbackends.supports(moduleBackends)) {
that.addError("native backend name on declaration conflicts with module descriptor: '\"" + mbackends.names() + "\"' is not '\"" + moduleBackends.names() + "\"' for '" + name + "'");
} else if (!isHeader && !backends.none() && !backends.supports(mbackends)) {
that.addError("native backend for declaration conflicts with its scope: native implementation '" + name + "' for '\"" + mbackends.names() + "\"' occurs in a scope which only supports '\"" + backends.names() + "\"'");
}
if (isHeader && existImplementations(model)) {
that.addError("native header must be declared before its implementations: the native header '" + name + "' is declared after an implementation");
}
if (model instanceof Interface && ((Interface) model).isAlias()) {
that.addError("interface alias may not be marked native: '" + name + "' (add a body if a native interface was intended)");
}
model.setNativeBackends(mbackends);
Declaration member = getNativeHeader(model);
if (member == null || member.isNativeImplementation()) {
// it's not shared
if (!isHeader && mustHaveHeader(model) && !moduleBackends.equals(mbackends)) {
that.addError("shared native implementation must have a header: '" + model.getName() + "' has no native header");
}
}
if (member == null) {
if (model.isNativeHeader()) {
handleNativeHeader(model, name);
if (that instanceof Tree.ObjectDefinition) {
Tree.ObjectDefinition od = (Tree.ObjectDefinition) that;
handleNativeHeader(od.getAnonymousClass(), name);
} else if (that instanceof Tree.Constructor) {
Tree.Constructor c = (Tree.Constructor) that;
handleNativeHeader(c.getConstructor(), name);
}
} else {
member = model.getContainer().getDirectMemberForBackend(model.getName(), mbackends);
if (member != null && member != model) {
that.addError("duplicate native implementation: the implementation '" + name + "' for '\"" + mbackends.names() + "\"' is not unique");
unit.getDuplicateDeclarations().add(member);
}
}
} else {
if (member.isNative()) {
List<Declaration> overloads = member.getOverloads();
if (isHeader && member.isNativeHeader()) {
that.addError("duplicate native header: the header for '" + name + "' is not unique");
unit.getDuplicateDeclarations().add(member);
} else {
Declaration overload = findOverloadForBackend(mbackends, model, overloads);
if (overload != null) {
that.addError("duplicate native implementation: the implementation '" + name + "' for '\"" + mbackends.names() + "\"' is not unique");
unit.getDuplicateDeclarations().add(overload);
}
}
if (isAllowedToChangeModel(member) && !hasModelInOverloads(model, overloads)) {
overloads.add(model);
if (that instanceof Tree.ObjectDefinition) {
Tree.ObjectDefinition od = (Tree.ObjectDefinition) that;
Declaration objImplCls = od.getAnonymousClass();
Value value = (Value) member;
Class objHdrCls = (Class) value.getType().getDeclaration();
objHdrCls.getOverloads().add(objImplCls);
} else if (that instanceof Tree.Constructor) {
Tree.Constructor c = (Tree.Constructor) that;
Declaration cd = c.getConstructor();
FunctionOrValue fov = (FunctionOrValue) member;
Constructor hdr = (Constructor) fov.getType().getDeclaration();
hdr.getOverloads().add(cd);
}
}
} else {
if (isHeader) {
that.addError("native header for non-native declaration: '" + name + "' is not declared native");
} else {
that.addError("native implementation for non-native header: '" + name + "' is not declared native");
}
}
}
} else if (!(model instanceof Setter) && !isHeader) {
if (!canBeNative) {
that.addError("native declaration is not a class, constructor, method, attribute or object: '" + name + "' may not be annotated 'native'");
}
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.FunctionOrValue 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.FunctionOrValue in project ceylon by eclipse.
the class ExpressionVisitor method createInferredParameter.
/**
* Create a model for an inferred parameter of an
* anonymous function.
*/
private boolean createInferredParameter(Tree.FunctionArgument anon, Declaration declaration, Tree.Parameter ap, Parameter parameter, Type type, FunctionOrValue original, boolean error) {
if (isTypeUnknown(type)) {
type = unit.getUnknownType();
if (!dynamic) {
if (error) {
ap.addError("could not infer parameter type: '" + parameter.getName() + "' would have unknown type");
} else {
return false;
}
}
} else if (involvesTypeParams(declaration, type)) {
if (error) {
type = unit.getUnknownType();
ap.addError("could not infer parameter type: '" + parameter.getName() + "' would have type '" + type.asString(unit) + "' involving type parameters");
} else {
return false;
}
}
Value model = (Value) parameter.getModel();
if (model == null) {
model = new Value();
model.setUnit(unit);
model.setName(parameter.getName());
model.setOriginalParameterDeclaration(original);
parameter.setModel(model);
Function m = anon.getDeclarationModel();
model.setContainer(m);
model.setScope(m);
m.addMember(model);
}
model.setType(type);
model.setInferred(true);
if (declaration != null && type != null && declaration.isJava() && !type.isUnknown() && type.isSubtypeOf(unit.getObjectType()) && canHaveUncheckedNulls(type)) {
model.setUncheckedNullType(true);
}
model.setInitializerParameter(parameter);
if (ap instanceof Tree.ValueParameterDeclaration) {
Tree.ValueParameterDeclaration vpd = (Tree.ValueParameterDeclaration) ap;
vpd.getTypedDeclaration().getType().setTypeModel(type);
}
return true;
}
use of org.eclipse.ceylon.model.typechecker.model.FunctionOrValue in project ceylon by eclipse.
the class ExpressionVisitor method checkPositionalArgument.
private void checkPositionalArgument(Parameter p, Reference pr, Tree.ListedArgument a) {
FunctionOrValue paramModel = p.getModel();
if (paramModel != null) {
a.setParameter(p);
TypedReference paramRef = pr.getTypedParameterWithWildcardCaputure(p);
Type paramType = paramType(a.getScope(), paramRef, paramModel);
Type at = a.getTypeModel();
if (!isTypeUnknown(at) && !isTypeUnknown(paramType)) {
checkAssignable(at, paramType, a, "argument must be assignable to parameter " + argdesc(p, pr), 2100);
}
}
}
Aggregations