use of org.eclipse.ceylon.model.typechecker.model.Constructor 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.Constructor in project ceylon by eclipse.
the class TypeUtils method metamodelTypeNameOrList.
/**
* Prints out an object with a type constructor under the property "t" and its type arguments under
* the property "a", or a union/intersection type with "u" or "i" under property "t" and the list
* of types that compose it in an array under the property "l", or a type parameter as a reference to
* already existing params.
* @param resolveTargsFromScope Indicates whether to resolve a type argument if it's within reach in the
* node's scope. This is useful for parameters of JsCallables but must be disabled for metamodel functions.
* @param node The node to use as starting point for resolution of other references.
* @param pkg The package of the current declaration
* @param pt The produced type for which a name must be output.
* @param gen The generator to use for output.
*/
static void metamodelTypeNameOrList(final boolean resolveTargsFromScope, final Node node, final org.eclipse.ceylon.model.typechecker.model.Package pkg, Type pt, SiteVariance useSiteVariance, GenerateJsVisitor gen) {
if (pt == null) {
// In dynamic blocks we sometimes get a null producedType
gen.out("'$U'");
return;
}
if (!outputMetamodelTypeList(resolveTargsFromScope, node, pkg, pt, gen)) {
TypeDeclaration type = pt.getDeclaration();
if (pt.isTypeParameter()) {
final TypeParameter tparm = (TypeParameter) type;
final Declaration tpowner = tparm.getDeclaration();
final boolean nodeIsDecl = node instanceof Tree.Declaration;
boolean rtafs = tpowner instanceof TypeDeclaration == false && (nodeIsDecl ? ((Tree.Declaration) node).getDeclarationModel() != tpowner : true);
if (rtafs && ModelUtil.contains((Scope) tpowner, node.getScope())) {
// Attempt to resolve this to an argument if the scope allows for it
if (tpowner instanceof TypeDeclaration) {
gen.out(gen.getNames().self((TypeDeclaration) tpowner), ".$$targs$$.", gen.getNames().typeParameterName(tparm));
} else if (tpowner instanceof Function) {
gen.out(gen.getNames().typeArgsParamName((Function) tpowner), ".", gen.getNames().typeParameterName(tparm));
}
} else if (resolveTargsFromScope && tpowner instanceof TypeDeclaration && (nodeIsDecl ? ((Tree.Declaration) node).getDeclarationModel() == tpowner : true) && ModelUtil.contains((Scope) tpowner, node.getScope())) {
typeNameOrList(node, tparm.getType(), gen, false);
} else {
gen.out("'", gen.getNames().typeParameterName(tparm), "'");
}
} else if (pt.isTypeAlias()) {
outputQualifiedTypename(node, gen.isImported(pkg, type), pt, gen, false);
} else {
gen.out("{t:");
// For constructors, output the type of the class
final Type qt = type instanceof Constructor ? pt.getQualifyingType() : pt;
outputQualifiedTypename(node, gen.isImported(pkg, type), qt, gen, false);
// Type Parameters
if (!pt.getTypeArguments().isEmpty()) {
gen.out(",a:{");
boolean first = true;
for (Map.Entry<TypeParameter, Type> e : pt.getTypeArguments().entrySet()) {
if (first)
first = false;
else
gen.out(",");
gen.out(gen.getNames().typeParameterName(e.getKey()), ":");
metamodelTypeNameOrList(resolveTargsFromScope, node, pkg, e.getValue(), pt.getVarianceOverrides().get(e.getKey()), gen);
}
gen.out("}");
}
printSiteVariance(useSiteVariance, gen);
gen.out("}");
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.Constructor in project ceylon by eclipse.
the class TypeUtils method generateModelPath.
/**
* Returns the list of keys to get from the package to the declaration, in the model.
*/
public static List<String> generateModelPath(final Declaration d) {
final ArrayList<String> sb = new ArrayList<>();
final Package pkg = d.getUnit().getPackage();
sb.add(pkg.isLanguagePackage() ? "$" : pkg.getNameAsString());
if (d.isToplevel()) {
sb.add(d.getName());
if (d instanceof Setter) {
sb.add("$set");
}
} else {
Declaration p = d;
final int i = sb.size();
while (p instanceof Declaration) {
if (p instanceof Setter) {
sb.add(i, "$set");
}
final String mname = TypeUtils.modelName(p);
if (!(mname.startsWith("anon$") || mname.startsWith("anonymous#"))) {
sb.add(i, mname);
// Build the path in reverse
if (!p.isToplevel()) {
if (p instanceof Class) {
sb.add(i, p.isAnonymous() ? MetamodelGenerator.KEY_OBJECTS : MetamodelGenerator.KEY_CLASSES);
} else if (p instanceof org.eclipse.ceylon.model.typechecker.model.Interface) {
sb.add(i, MetamodelGenerator.KEY_INTERFACES);
} else if (p instanceof Function) {
if (!p.isAnonymous()) {
sb.add(i, MetamodelGenerator.KEY_METHODS);
}
} else if (p instanceof TypeAlias || p instanceof Setter) {
sb.add(i, MetamodelGenerator.KEY_ATTRIBUTES);
} else if (p instanceof Constructor || ModelUtil.isConstructor(p)) {
sb.add(i, MetamodelGenerator.KEY_CONSTRUCTORS);
} else {
// It's a value
TypeDeclaration td = ((TypedDeclaration) p).getTypeDeclaration();
sb.add(i, (td != null && td.isAnonymous()) ? MetamodelGenerator.KEY_OBJECTS : MetamodelGenerator.KEY_ATTRIBUTES);
}
}
}
p = ModelUtil.getContainingDeclaration(p);
while (p != null && p instanceof ClassOrInterface == false && !(p.isToplevel() || p.isAnonymous() || p.isClassOrInterfaceMember() || p.isJsCaptured())) {
p = ModelUtil.getContainingDeclaration(p);
}
}
}
return sb;
}
use of org.eclipse.ceylon.model.typechecker.model.Constructor in project ceylon by eclipse.
the class RefinementVisitor method checkNonMember.
private void checkNonMember(Tree.Declaration that, Declaration dec) {
boolean mayBeShared = !(dec instanceof TypeParameter);
boolean nonTypeMember = !dec.isClassOrInterfaceMember();
String name = dec.getName();
if (dec.isStatic()) {
if (nonTypeMember) {
that.addError("static declaration is not a member of a class or interface: '" + name + "' is not defined directly in the body of a class or interface");
} else {
ClassOrInterface type = (ClassOrInterface) dec.getContainer();
if (!type.isToplevel()) {
that.addError("static declaration belongs to a nested a class or interface: '" + name + "' is a member of nested type '" + type.getName() + "'");
}
}
}
if (nonTypeMember && mayBeShared) {
if (dec.isActual()) {
that.addError("actual declaration is not a member of a class or interface: '" + name + "'", 1301);
}
if (dec.isFormal()) {
that.addError("formal declaration is not a member of a class or interface: '" + name + "'", 1302);
}
if (dec.isDefault()) {
that.addError("default declaration is not a member of a class or interface: '" + name + "'", 1303);
}
} else if (!dec.isShared() && mayBeShared) {
if (dec.isActual()) {
that.addError("actual declaration must be shared: '" + name + "'", 701);
}
if (dec.isFormal()) {
that.addError("formal declaration must be shared: '" + name + "'", 702);
}
if (dec.isDefault()) {
that.addError("default declaration must be shared: '" + name + "'", 703);
}
} else {
if (dec.isActual()) {
that.addError("declaration may not be actual: '" + name + "'", 1301);
}
if (dec.isFormal()) {
that.addError("declaration may not be formal: '" + name + "'", 1302);
}
if (dec.isDefault()) {
that.addError("declaration may not be default: '" + name + "'", 1303);
}
}
if (isOverloadedVersion(dec)) {
if (isConstructor(dec)) {
checkOverloadedAnnotation(that, dec);
checkOverloadedParameters(that, dec);
} else {
that.addError("duplicate declaration: the name '" + name + "' is not unique in this scope");
}
} else if (isAbstraction(dec)) {
// that is considered overloaded in the model
if (that instanceof Tree.ClassDefinition && !that.hasErrors()) {
Tree.ClassDefinition def = (Tree.ClassDefinition) that;
// this is an abstraction
Class abs = (Class) dec;
// correctly located)
for (Tree.Statement st : def.getClassBody().getStatements()) {
if (st instanceof Tree.Constructor) {
Tree.Constructor node = (Tree.Constructor) st;
if (node.getIdentifier() == null) {
Constructor con = node.getConstructor();
// get the corresponding overloaded version
Class cla = classOverloadForConstructor(abs, con);
checkOverloadedAnnotation(node, con);
checkOverloadedParameters(node, cla);
}
}
}
}
}
if (isConstructor(dec) && dec.isShared()) {
Scope container = dec.getContainer();
if (container instanceof Class) {
Class clazz = (Class) container;
Declaration member = intersectionOfSupertypes(clazz).getDeclaration().getMember(name, null, false);
if (member != null && member.isShared() && !isConstructor(member)) {
Declaration supertype = (Declaration) member.getContainer();
that.addError("constructor has same name as an inherited member '" + clazz.getName() + "' inherits '" + member.getName() + "' from '" + supertype.getName(that.getUnit()) + "'");
}
}
}
}
use of org.eclipse.ceylon.model.typechecker.model.Constructor in project ceylon by eclipse.
the class RefinementVisitor method checkOverloadedAnnotation.
private void checkOverloadedAnnotation(Tree.Declaration that, Declaration member) {
// non-actual overloaded methods
// must be annotated 'overloaded'
boolean marked = false;
Unit unit = that.getUnit();
for (Tree.Annotation a : that.getAnnotationList().getAnnotations()) {
Tree.Primary p = a.getPrimary();
if (p instanceof Tree.BaseMemberExpression) {
Tree.BaseMemberExpression bme = (Tree.BaseMemberExpression) p;
String aname = bme.getIdentifier().getText();
Declaration ad = p.getScope().getMemberOrParameter(unit, aname, null, false);
if (ad != null && isOverloadedAnnotation(ad)) {
marked = true;
}
}
}
if (!marked) {
if (member.isActual()) {
that.addUsageWarning(Warning.unknownWarning, "overloaded function should be declared with the 'overloaded' annotation in 'java.lang'");
} else {
if (member instanceof Constructor) {
// default constructors are the only
// thing that can legally have no name
that.addError("duplicate default constructor (overloaded default constructor must be declared with the 'overloaded' annotation in 'java.lang')");
} else if (member instanceof Function) {
// functions are the only thing
// that can legally have a name
// and be overloaded
that.addError("duplicate declaration: the name '" + member.getName() + "' is not unique in this scope " + "(overloaded function must be declared with the 'overloaded' annotation in 'java.lang')");
}
}
}
}
Aggregations