use of org.eclipse.ceylon.model.typechecker.model.ClassAlias in project ceylon by eclipse.
the class Strategy method generateJpaCtor.
static boolean generateJpaCtor(ClassOrInterface declarationModel) {
if (declarationModel instanceof Class && !(declarationModel instanceof ClassAlias) && declarationModel.isToplevel()) {
Class cls = (Class) declarationModel;
if (cls.getCaseValues() != null && !cls.getCaseValues().isEmpty()) {
return false;
}
if (hasNullaryNonJpaConstructor(cls)) {
// The class will already have a nullary ctor
return false;
}
for (Annotation annotation : cls.getAnnotations()) {
Declaration annoDecl = cls.getUnit().getImportedDeclaration(annotation.getName(), null, false);
if (annoDecl != null && annoDecl.getQualifiedNameString().equals("java.lang::nonbean")) {
return false;
}
}
boolean hasDelegatableSuper = false;
Class superClass = (Class) cls.getExtendedType().getDeclaration();
if (superClass instanceof LazyClass && !((LazyClass) superClass).isCeylon()) {
if (superClass.isAbstraction()) {
for (Declaration s : superClass.getOverloads()) {
if (s instanceof Class && isNullary((Class) s)) {
hasDelegatableSuper = true;
break;
}
}
} else {
// If the superclass is Java then generate a Jpa constructor
// if there's a nullary superclass constructor we can call
hasDelegatableSuper = isNullary(superClass);
}
} else {
hasDelegatableSuper = hasNullaryNonJpaConstructor(superClass) || hasJpaConstructor(superClass);
}
boolean constrained = cls.getCaseValues() != null && !cls.getCaseValues().isEmpty() || cls.hasEnumerated() && Decl.hasOnlyValueConstructors(cls);
return hasDelegatableSuper && !constrained;
} else {
return false;
}
}
use of org.eclipse.ceylon.model.typechecker.model.ClassAlias in project ceylon by eclipse.
the class JsonPackage method loadClass.
/**
* Loads a class from the specified map. To avoid circularities, when the class is being created it is
* added to the map, and once it's been fully loaded, all other keys are removed.
*/
@SuppressWarnings("unchecked")
org.eclipse.ceylon.model.typechecker.model.Class loadClass(String name, Map<String, Object> m, Scope parent, final List<TypeParameter> existing) {
org.eclipse.ceylon.model.typechecker.model.Class cls;
m.remove(KEY_NAME);
if (m.get(KEY_METATYPE) instanceof org.eclipse.ceylon.model.typechecker.model.Class) {
cls = (org.eclipse.ceylon.model.typechecker.model.Class) m.get(KEY_METATYPE);
if (m.size() <= 3) {
// It's been fully loaded
return cls;
}
} else {
// It's not there, so create it
if (m.containsKey("$alias")) {
cls = new org.eclipse.ceylon.model.typechecker.model.ClassAlias();
} else {
cls = new org.eclipse.ceylon.model.typechecker.model.Class();
}
cls.setAbstract(m.remove("abstract") != null);
cls.setAnonymous(m.remove("$anon") != null);
cls.setDynamic(m.remove(KEY_DYNAMIC) != null);
cls.setContainer(parent);
cls.setScope(parent);
cls.setName(name);
cls.setUnit(u2);
if (parent == this) {
u2.addDeclaration(cls);
}
parent.addMember(cls);
m.put(KEY_METATYPE, cls);
setAnnotations(cls, (Integer) m.remove(KEY_PACKED_ANNS), m.remove(KEY_ANNOTATIONS));
}
// Type parameters are about the first thing we need to load
final List<TypeParameter> tparms = parseTypeParameters((List<Map<String, Object>>) m.remove(KEY_TYPE_PARAMS), cls, existing);
final List<TypeParameter> allparms = JsonPackage.merge(tparms, existing);
if (m.containsKey(KEY_SELF_TYPE)) {
for (TypeParameter t : tparms) {
if (t.getName().equals(m.get(KEY_SELF_TYPE))) {
cls.setSelfType(t.getType());
}
}
}
// This is to avoid circularity
if (!(isLanguagePackage() && ("Nothing".equals(name) || "Anything".equals(name)))) {
if (cls.getExtendedType() == null) {
if (m.containsKey("super")) {
Type father = getTypeFromJson((Map<String, Object>) m.get("super"), parent instanceof Declaration ? (Declaration) parent : null, allparms);
if (father != null) {
m.remove("super");
cls.setExtendedType(father);
}
} else {
cls.setExtendedType(getTypeFromJson(idobj, parent instanceof Declaration ? (Declaration) parent : null, allparms));
}
}
}
if (cls instanceof ClassAlias) {
ClassAlias ca = (ClassAlias) cls;
if (m.containsKey(KEY_CONSTRUCTOR)) {
String constructorName = (String) m.get(KEY_CONSTRUCTOR);
Function ctorFn = (Function) ca.getExtendedType().getDeclaration().getDirectMember(constructorName, null, false);
ca.setConstructor(ctorFn.getType().getDeclaration());
} else {
ca.setConstructor(ca.getExtendedType().getDeclaration());
}
}
if (m.containsKey(KEY_CONSTRUCTORS)) {
final Map<String, Map<String, Object>> constructors = (Map<String, Map<String, Object>>) m.remove(KEY_CONSTRUCTORS);
for (Map.Entry<String, Map<String, Object>> cons : constructors.entrySet()) {
Constructor cnst = new Constructor();
cnst.setName("$def".equals(cons.getKey()) ? null : cons.getKey());
cnst.setContainer(cls);
cnst.setScope(cls);
cnst.setUnit(cls.getUnit());
cnst.setExtendedType(cls.getType());
cnst.setDynamic(cons.getValue().remove(KEY_DYNAMIC) != null);
setAnnotations(cnst, (Integer) cons.getValue().remove(KEY_PACKED_ANNS), cons.getValue().remove(KEY_ANNOTATIONS));
final List<Map<String, Object>> modelPlist = (List<Map<String, Object>>) cons.getValue().remove(KEY_PARAMS);
cls.addMember(cnst);
if (modelPlist == null) {
// It's a value constructor
cls.setEnumerated(true);
Value cv = new Value();
cv.setName(cnst.getName());
cv.setType(cnst.getType());
cv.setContainer(cls);
cv.setScope(cls);
cv.setUnit(cls.getUnit());
cv.setVisibleScope(cls.getVisibleScope());
cv.setShared(cls.isShared());
cv.setDeprecated(cls.isDeprecated());
cls.addMember(cv);
} else {
cls.setConstructors(true);
final ParameterList plist = parseParameters(modelPlist, cnst, allparms);
cnst.addParameterList(plist);
plist.setNamedParametersSupported(true);
Function cf = new Function();
cf.setName(cnst.getName());
final Type ft = cnst.appliedType(cnst.getExtendedType(), Collections.<Type>emptyList());
cf.setType(ft);
cf.addParameterList(plist);
cf.setContainer(cls);
cf.setScope(cls);
cf.setUnit(cls.getUnit());
cf.setVisibleScope(cnst.getVisibleScope());
cf.setShared(cnst.isShared());
cf.setDeprecated(cnst.isDeprecated());
cf.setDynamic(cnst.isDynamic());
cls.addMember(cf);
}
if (cons.getValue().containsKey(KEY_JS_TSENUM)) {
cnst.setTypescriptEnum((String) cons.getValue().get(KEY_JS_TSENUM));
}
}
} else {
ParameterList plist = parseParameters((List<Map<String, Object>>) m.remove(KEY_PARAMS), cls, allparms);
plist.setNamedParametersSupported(true);
cls.setParameterList(plist);
}
if (m.containsKey("of") && cls.getCaseTypes() == null) {
cls.setCaseTypes(parseTypeList((List<Map<String, Object>>) m.get("of"), allparms));
m.remove("of");
}
if (m.containsKey(KEY_SATISFIES)) {
List<Map<String, Object>> stypes = (List<Map<String, Object>>) m.remove(KEY_SATISFIES);
cls.setSatisfiedTypes(parseTypeList(stypes, allparms));
}
if (m.containsKey(KEY_OBJECTS)) {
for (Map.Entry<String, Map<String, Object>> inner : ((Map<String, Map<String, Object>>) m.get(KEY_OBJECTS)).entrySet()) {
loadObject(inner.getKey(), inner.getValue(), cls, allparms);
}
m.remove(KEY_OBJECTS);
}
addAttributesAndMethods(m, cls, allparms);
if (m.containsKey(KEY_INTERFACES)) {
Map<String, Map<String, Object>> cdefs = (Map<String, Map<String, Object>>) m.get(KEY_INTERFACES);
for (Map.Entry<String, Map<String, Object>> cdef : cdefs.entrySet()) {
loadInterface(cdef.getKey(), cdef.getValue(), cls, allparms);
}
m.remove(KEY_INTERFACES);
}
if (m.containsKey(KEY_CLASSES)) {
Map<String, Map<String, Object>> cdefs = (Map<String, Map<String, Object>>) m.get(KEY_CLASSES);
for (Map.Entry<String, Map<String, Object>> cdef : cdefs.entrySet()) {
loadClass(cdef.getKey(), cdef.getValue(), cls, allparms);
}
m.remove(KEY_CLASSES);
}
if (cls.isDynamic() && (getModule().getJsMajor() < 9 || (getModule().getJsMajor() == 9 && getModule().getJsMinor() < 1))) {
// previous versions did not set dynamic flag on members
cls.makeMembersDynamic();
}
return cls;
}
use of org.eclipse.ceylon.model.typechecker.model.ClassAlias in project ceylon by eclipse.
the class MetamodelGenerator method encodeClass.
@SuppressWarnings("unchecked")
public Map<String, Object> encodeClass(org.eclipse.ceylon.model.typechecker.model.Class d) {
final Map<String, Object> m = new HashMap<>();
m.put(KEY_METATYPE, METATYPE_CLASS);
m.put(KEY_NAME, TypeUtils.modelName(d));
// Type parameters
List<Map<String, Object>> tpl = typeParameters(d.getTypeParameters(), d);
if (tpl != null) {
m.put(KEY_TYPE_PARAMS, tpl);
}
// self type
if (d.getSelfType() != null) {
m.put(KEY_SELF_TYPE, d.getSelfType().getDeclaration().getName());
}
// Extends
if (d.getExtendedType() != null) {
m.put("super", typeMap(d.getExtendedType(), d));
}
// Satisfies
encodeTypes(d.getSatisfiedTypes(), m, KEY_SATISFIES, d);
// Initializer parameters
final List<Map<String, Object>> inits = parameterListMap(d.getParameterList(), d);
if (inits != null && !inits.isEmpty()) {
m.put(KEY_PARAMS, inits);
}
// Case types
encodeTypes(d.getCaseTypes(), m, "of", d);
// Annotations
encodeAnnotations(d.getAnnotations(), d, m);
if (d.isAnonymous()) {
m.put("$anon", 1);
}
if (d.isAlias()) {
m.put("$alias", 1);
TypeDeclaration constructor = ((ClassAlias) d).getConstructor();
if (constructor instanceof Constructor) {
m.put(KEY_CONSTRUCTOR, ((Constructor) constructor).getName());
}
// else, it's the default "constructor", and will be the (Class) d.getExtendedType().getDeclaration()
}
Map<String, Object> parent = findParent(d);
if (parent != null) {
if (parent != getPackageMap(d.getUnit().getPackage())) {
if (!parent.containsKey(KEY_CLASSES)) {
parent.put(KEY_CLASSES, new HashMap<>());
}
parent = (Map<String, Object>) parent.get(KEY_CLASSES);
}
parent.put(TypeUtils.modelName(d), m);
}
return m;
}
use of org.eclipse.ceylon.model.typechecker.model.ClassAlias in project ceylon by eclipse.
the class TypeVisitor method visit.
@Override
public void visit(Tree.ClassDeclaration that) {
ClassAlias td = (ClassAlias) that.getDeclarationModel();
td.setExtendedType(null);
super.visit(that);
Tree.ClassSpecifier cs = that.getClassSpecifier();
if (cs == null) {
that.addError("missing class body or aliased class reference");
} else {
Tree.ExtendedType et = that.getExtendedType();
if (et != null) {
et.addError("class alias may not extend a type");
}
Tree.SatisfiedTypes sts = that.getSatisfiedTypes();
if (sts != null) {
sts.addError("class alias may not satisfy a type");
}
Tree.CaseTypes cts = that.getCaseTypes();
if (cts != null) {
that.addError("class alias may not have cases or a self type");
}
Tree.SimpleType ct = cs.getType();
if (ct == null) {
// that.addError("malformed aliased class");
} else if (!(ct instanceof Tree.StaticType)) {
ct.addError("aliased type must be a class");
} else {
Type type = ct.getTypeModel();
if (type != null && !type.isUnknown()) {
TypeDeclaration dec = type.getDeclaration();
td.setConstructor(dec);
if (dec instanceof Constructor) {
if (dec.isValueConstructor()) {
ct.addError("aliases a value constructor");
} else if (dec.isAbstract()) {
ct.addError("aliases a partial constructor: '" + dec.getName(unit) + "' is declared abstract");
}
if (td.isShared() && !dec.isShared()) {
ct.addError("shared alias of an unshared constructor: '" + dec.getName(unit) + "' is not shared");
}
type = type.getExtendedType();
dec = dec.getExtendedType().getDeclaration();
}
if (dec instanceof Class) {
td.setExtendedType(type);
} else {
ct.addError("not a class: '" + dec.getName(unit) + "'");
}
TypeDeclaration etd = ct.getDeclarationModel();
if (etd == td) {
ct.addError("directly aliases itself: '" + td.getName() + "'");
}
}
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.ClassAlias in project ceylon by eclipse.
the class Strategy method getEffectiveTypeParameters.
private static List<TypeParameter> getEffectiveTypeParameters(Declaration original, Declaration decl) {
if (Decl.isConstructor(original)) {
original = ModelUtil.getConstructedClass(original);
}
if (Decl.isConstructor(decl)) {
decl = ModelUtil.getConstructedClass(decl);
}
Scope container = decl.getContainer();
if (decl instanceof Value) {
if (decl.isStatic()) {
return getEffectiveTypeParameters(original, (Declaration) container);
} else {
return Collections.emptyList();
}
}
if (decl instanceof Function) {
if (original instanceof ClassAlias || decl.isStatic() && isCeylon(decl)) {
ArrayList<TypeParameter> copyDown = new ArrayList<TypeParameter>(getEffectiveTypeParameters(original, (Declaration) container));
copyDown.addAll(decl.getTypeParameters());
return copyDown;
} else {
return decl.getTypeParameters();
}
} else if (decl instanceof ClassAlias) {
// TODO
/*if (container instanceof Declaration) {
ArrayList<TypeParameter> copyDown = new ArrayList<TypeParameter>(getEffectiveTypeParameters(original, (Declaration)container));
copyDown.addAll(((Class)decl).getTypeParameters());
return copyDown;
} else*/
{
return ((ClassAlias) decl).getTypeParameters();
}
} else if (decl instanceof Class) {
if (((Class) decl).isStatic() && ((Class) decl).isMember() && isCeylon(decl)) {
// TODO and isCeylon
ArrayList<TypeParameter> copyDown = new ArrayList<TypeParameter>(getEffectiveTypeParameters(original, (Declaration) container));
copyDown.addAll(((Class) decl).getTypeParameters());
return copyDown;
} else {
return ((Class) decl).getTypeParameters();
}
} else if (decl instanceof Interface) {
/*if (((Interface) decl).isMember()) {
ArrayList<TypeParameter> copyDown = new ArrayList<TypeParameter>(getEffectiveTypeParameters(original, (Declaration)container));
copyDown.addAll(((Interface)decl).getTypeParameters());
return copyDown;
} else*/
{
return ((Interface) decl).getTypeParameters();
}
} else if (decl instanceof TypeAlias) {
return ((TypeAlias) decl).getTypeParameters();
} else {
throw BugException.unhandledDeclarationCase((Declaration) decl);
}
}
Aggregations