use of org.eclipse.ceylon.model.typechecker.model.Scope 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.Scope in project ceylon by eclipse.
the class TypeVisitor method visit.
@Override
public void visit(Tree.QualifiedType that) {
boolean onl = inTypeLiteral;
boolean oiea = inExtendsOrClassAlias;
boolean oidc = inDelegatedConstructor;
inTypeLiteral = false;
inExtendsOrClassAlias = false;
inDelegatedConstructor = false;
super.visit(that);
inExtendsOrClassAlias = oiea;
inDelegatedConstructor = oidc;
inTypeLiteral = onl;
Tree.StaticType ot = that.getOuterType();
Type pt = ot.getTypeModel();
if (pt != null) {
// if (pt.isTypeConstructor()) {
// ot.addError("qualifying type may not be a type constructor");
// }
Tree.TypeArgumentList tal = that.getTypeArgumentList();
if (that.getMetamodel() && tal != null && isTypeUnknown(pt) && !pt.isUnknown()) {
tal.addError("qualifying type does not fully-specify type arguments");
}
TypeDeclaration d = pt.getDeclaration();
Tree.Identifier id = that.getIdentifier();
if (id != null) {
String name = name(id);
Scope scope = that.getScope();
TypeDeclaration type = getTypeMember(d, name, null, false, unit, scope);
if (type == null) {
if (!isNativeForWrongBackend(scope, unit)) {
if (d.isMemberAmbiguous(name, unit, null, false)) {
that.addError("member type declaration is ambiguous: '" + name + "' for type '" + d.getName() + "'");
} else {
that.addError("member type is not defined: '" + name + "' in type '" + d.getName() + "'" + memberCorrectionMessage(name, d, null, unit, cancellable), 100);
unit.setUnresolvedReferences();
}
}
} else {
visitSimpleType(that, pt, type);
if (type.isStatic()) {
ot.setStaticTypePrimary(true);
}
}
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.Scope in project ceylon by eclipse.
the class ExpressionVisitor method handleNativeHeader.
private Declaration handleNativeHeader(Declaration dec, Node that, boolean error) {
// really nasty workaround to get the "real" scope
// in which an annotation occurs! (bug #7143)
Scope scope = (that instanceof Tree.BaseMemberExpression ? ((Tree.BaseMemberExpression) that).getIdentifier() : that).getScope();
Declaration impl = dec;
Declaration hdr = null;
Module ctxModule = unit.getPackage().getModule();
Module decModule = dec.getUnit().getPackage().getModule();
Backends decModuleBackends = getModuleBackends(decModule, unit);
Backends inBackends = scope.getScopedBackends();
if (dec.isNative()) {
Backends backends = inBackends.none() ? unit.getSupportedBackends() : inBackends;
if (dec.isNativeHeader()) {
hdr = dec;
impl = getNativeDeclaration(hdr, backends);
} else {
Declaration tmp = getNativeHeader(dec);
if (tmp != dec) {
hdr = tmp;
if (hdr != null) {
if (backends.none() || !backends.supports(dec.getNativeBackends())) {
impl = getNativeDeclaration(hdr, backends);
}
}
}
}
}
if (error && impl != null && (dec.isToplevel() || dec.isMember()) && declarationScope(scope) != null && (hdr == null || !isImplemented(hdr)) && (ctxModule != decModule && !decModuleBackends.none() || ctxModule == decModule && dec.isNative() && hdr == null) && (inBackends.none() || impl.isNative() && !isForBackend(impl.getNativeBackends(), inBackends) || !decModuleBackends.none() && !isForBackend(decModuleBackends, inBackends))) {
Declaration d = declarationScope(scope);
if (!inBackends.none()) {
that.addError("illegal reference to native declaration '" + dec.getName(unit) + "': native declaration '" + d.getName(unit) + "' has a different backend");
} else {
that.addError("illegal reference to native declaration '" + dec.getName(unit) + "': declaration '" + d.getName(unit) + "' is not native (mark it or the module native)", 20010);
}
}
if (dec.isNative()) {
return inBackends.none() || impl == null ? dec : impl;
}
return dec;
}
use of org.eclipse.ceylon.model.typechecker.model.Scope in project ceylon by eclipse.
the class ValueDeclarationImpl method $getJavaAnnotations$.
@Override
@Ignore
public java.lang.annotation.Annotation[] $getJavaAnnotations$() {
Class<?> javaClass = Metamodel.getJavaClass(declaration);
ArrayList<java.lang.annotation.Annotation> result = new ArrayList<>();
HashSet<Class<? extends java.lang.annotation.Annotation>> cls = new HashSet<>();
if (javaClass != null) {
// FIXME: pretty sure this doesn't work with interop and fields
Method declaredGetter = Reflection.getDeclaredGetter(javaClass, NamingBase.getGetterName(declaration));
if (declaredGetter != null) {
addToList(result, cls, declaredGetter.getAnnotations());
}
if (!((Value) declaration).isTransient()) {
// TODO only include those which are java annotations
Field field = Reflection.getDeclaredField(javaClass, declaration.getName());
if (field != null) {
Annotation[] fieldAnnos = field.getAnnotations();
addToList(result, cls, fieldAnnos);
}
Method setter = Reflection.getDeclaredSetter(javaClass, NamingBase.getSetterName(declaration.getName()));
if (setter != null) {
Annotation[] setterAnnos = setter.getAnnotations();
addToList(result, cls, setterAnnos);
}
}
}
// one last chance
if (parameter != null && !parameter.getModel().isShared()) {
// get the annotations from the parameter itself
Annotation[][] parameterAnnotations;
Scope container = parameter.getModel().getContainer();
if (container instanceof org.eclipse.ceylon.model.typechecker.model.Function) {
parameterAnnotations = Metamodel.getJavaMethod((org.eclipse.ceylon.model.typechecker.model.Function) container).getParameterAnnotations();
} else if (container instanceof org.eclipse.ceylon.model.typechecker.model.ClassAlias) {
parameterAnnotations = Reflection.findClassAliasInstantiator(Metamodel.getJavaClass((org.eclipse.ceylon.model.typechecker.model.Class) container), (org.eclipse.ceylon.model.typechecker.model.ClassAlias) container).getParameterAnnotations();
} else if (container instanceof org.eclipse.ceylon.model.typechecker.model.Class) {
// FIXME: pretty sure that's wrong because of synthetic params. See ReflectionMethod.getParameters
parameterAnnotations = Reflection.findConstructor(Metamodel.getJavaClass((org.eclipse.ceylon.model.typechecker.model.Class) container)).getParameterAnnotations();
} else {
throw Metamodel.newModelError("Unsupported parameter container");
}
// now find the right parameter
List<Parameter> parameters = ((org.eclipse.ceylon.model.typechecker.model.Functional) container).getFirstParameterList().getParameters();
int index = parameters.indexOf(parameter);
if (index == -1)
throw Metamodel.newModelError("Parameter " + parameter + " not found in container " + parameter.getModel().getContainer());
if (index >= parameterAnnotations.length)
throw Metamodel.newModelError("Parameter " + parameter + " index is greater than JVM parameters for " + parameter.getModel().getContainer());
addToList(result, cls, parameterAnnotations[index]);
}
// nope
return result.toArray(new java.lang.annotation.Annotation[result.size()]);
}
use of org.eclipse.ceylon.model.typechecker.model.Scope in project ceylon by eclipse.
the class Metamodel method getMetamodel.
public static ceylon.language.meta.declaration.FunctionDeclaration getMetamodel(Function method) {
// find its container
Scope container = method.getContainer();
if (container instanceof org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) {
org.eclipse.ceylon.compiler.java.runtime.metamodel.decl.ClassOrInterfaceDeclarationImpl classOrInterface = (ClassOrInterfaceDeclarationImpl) getOrCreateMetamodel((org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) container);
// now find the method
ceylon.language.meta.declaration.FunctionDeclaration ret = classOrInterface.findMethod(method.getName());
if (ret == null)
throw Metamodel.newModelError("Failed to find method " + method.getName() + " in " + container);
return ret;
}
if (container instanceof org.eclipse.ceylon.model.typechecker.model.Package) {
ceylon.language.meta.declaration.Package pkg = getOrCreateMetamodel((org.eclipse.ceylon.model.typechecker.model.Package) container);
ceylon.language.meta.declaration.FunctionDeclaration ret = pkg.getFunction(method.getName());
if (ret == null)
throw Metamodel.newModelError("Failed to find method " + method.getName() + " in " + container);
return ret;
}
throw Metamodel.newModelError("Unsupported method container for " + method.getName() + ": " + container);
}
Aggregations