use of org.eclipse.ceylon.model.typechecker.model.TypeDeclaration in project ceylon by eclipse.
the class TypeUtils method wrapAsIterableArguments.
public static Map<TypeParameter, Type> wrapAsIterableArguments(Type pt) {
HashMap<TypeParameter, Type> r = new HashMap<TypeParameter, Type>();
final TypeDeclaration iterable = pt.getDeclaration().getUnit().getIterableDeclaration();
List<TypeParameter> typeParameters = iterable.getTypeParameters();
r.put(typeParameters.get(0), pt);
r.put(typeParameters.get(1), pt.getDeclaration().getUnit().getNullType());
return r;
}
use of org.eclipse.ceylon.model.typechecker.model.TypeDeclaration 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.TypeDeclaration in project ceylon by eclipse.
the class TypeUtils method printTypeArguments.
/**
* Prints the type arguments, usually for their reification.
*/
public static void printTypeArguments(final Node node, final Map<TypeParameter, Type> targs, final GenerateJsVisitor gen, final boolean skipSelfDecl, final Map<TypeParameter, SiteVariance> overrides) {
if (targs == null)
return;
gen.out("{");
boolean first = true;
for (Map.Entry<TypeParameter, Type> e : targs.entrySet()) {
if (first) {
first = false;
} else {
gen.out(",");
}
gen.out(gen.getNames().typeParameterName(e.getKey()), ":");
final Type pt = e.getValue() == null ? null : e.getValue().resolveAliases();
if (pt == null) {
gen.out("'", e.getKey().getName(), "'");
} else if (!outputTypeList(node, pt, gen, skipSelfDecl)) {
boolean hasParams = pt.getTypeArgumentList() != null && !pt.getTypeArgumentList().isEmpty();
boolean closeBracket = false;
final TypeDeclaration d = pt.getDeclaration();
if (pt.isTypeParameter()) {
resolveTypeParameter(node, (TypeParameter) d, gen, skipSelfDecl);
if (((TypeParameter) d).isInvariant() && (e.getKey().isCovariant() || e.getKey().isContravariant())) {
gen.out("/*ORALE!", d.getQualifiedNameString(), " inv pero ", e.getKey().getQualifiedNameString(), e.getKey().isCovariant() ? " out" : " in", "*/");
}
} else {
closeBracket = !pt.isTypeAlias();
if (closeBracket)
gen.out("{t:");
outputQualifiedTypename(node, node != null && gen.isImported(node.getUnit().getPackage(), pt.getDeclaration()), pt, gen, skipSelfDecl);
}
if (hasParams) {
gen.out(",a:");
printTypeArguments(node, pt.getTypeArguments(), gen, skipSelfDecl, pt.getVarianceOverrides());
}
SiteVariance siteVariance = overrides == null ? null : overrides.get(e.getKey());
printSiteVariance(siteVariance, gen);
if (closeBracket) {
gen.out("}");
}
}
}
gen.out("}");
}
use of org.eclipse.ceylon.model.typechecker.model.TypeDeclaration in project ceylon by eclipse.
the class JsIdentifierNames method getName.
private String getName(Declaration decl, boolean forGetterSetter, boolean priv) {
if (decl == null) {
return null;
}
String name = decl.getName();
if (name == null && ModelUtil.isConstructor(decl)) {
return "$c$";
}
if (name.startsWith("anonymous#")) {
name = "anon$" + name.substring(10);
}
if (decl.isDynamic()) {
return JsUtils.escapeStringLiteral(decl.getName());
}
boolean nonLocal = !priv;
if (nonLocal) {
// check if it's a shared member or a toplevel function
nonLocal = decl.isMember() ? decl.isShared() || decl instanceof TypeDeclaration : decl.isToplevel() && (forGetterSetter || decl instanceof Function || decl instanceof ClassOrInterface || decl instanceof TypeAlias);
}
if (nonLocal && decl instanceof Class && ((Class) decl).isAnonymous() && !forGetterSetter) {
// A lower-case class name belongs to an object and is not public.
nonLocal = false;
}
if (nonLocal) {
// The identifier might be accessed from other .js files, so it must
// be reliably reproducible. In most cases simply using the original
// name is ok because otherwise it would result in a name collision in
// Ceylon too. We just have to take care of a few exceptions:
String suffix = nestingSuffix(decl, false);
if (suffix.length() > 0) {
// nested type
name += suffix;
} else if ((!forGetterSetter && !ModelUtil.isConstructor(decl) && reservedWords.contains(name)) || isJsGlobal(decl)) {
// JavaScript keyword or global declaration
name = "$_" + name;
}
} else {
// The identifier will not be used outside the generated .js file,
// so we can simply disambiguate it with a numeric ID.
name = uniquePrivateName(decl, priv);
}
// Fix #204 - same top-level declarations in different packages
final Package declPkg = decl.getUnit().getPackage();
if (decl.isToplevel() && !declPkg.equals(declPkg.getModule().getRootPackage())) {
final Package raiz = declPkg.getModule().getRootPackage();
// rootPackage can be null when compiling from IDE
String rootName = raiz == null ? (declPkg.getModule().isDefaultModule() ? "" : declPkg.getModule().getNameAsString()) : raiz.getNameAsString();
String pkgName = declPkg.getNameAsString();
rootName = pkgName.substring(rootName.length()).replaceAll("\\.", "\\$");
if (rootName.length() > 0 && rootName.charAt(0) != '$') {
rootName = '$' + rootName;
}
name += rootName;
}
if (decl instanceof TypeAlias) {
name += "()";
}
return JsUtils.escapeStringLiteral(name);
}
use of org.eclipse.ceylon.model.typechecker.model.TypeDeclaration in project ceylon by eclipse.
the class RefinementVisitor method checkRefiningMemberUpperBounds.
private List<Type> checkRefiningMemberUpperBounds(Tree.Declaration that, ClassOrInterface ci, Declaration refined, List<TypeParameter> refinedTypeParams, List<TypeParameter> refiningTypeParams) {
int refiningSize = refiningTypeParams.size();
int refinedSize = refinedTypeParams.size();
int max = refiningSize <= refinedSize ? refiningSize : refinedSize;
if (max == 0) {
return NO_TYPE_ARGS;
}
// we substitute the type parameters of the refined
// declaration into the bounds of the refining
// declaration
Map<TypeParameter, Type> substitution = new HashMap<TypeParameter, Type>();
for (int i = 0; i < max; i++) {
TypeParameter refinedTypeParam = refinedTypeParams.get(i);
TypeParameter refiningTypeParam = refiningTypeParams.get(i);
substitution.put(refiningTypeParam, refinedTypeParam.getType());
}
Map<TypeParameter, SiteVariance> noVariances = emptyMap();
TypeDeclaration rc = (TypeDeclaration) refined.getContainer();
// we substitute the type arguments of the subtype's
// instantiation of the supertype into the bounds of
// the refined declaration
Type supertype = ci.getType().getSupertype(rc);
Map<TypeParameter, Type> args = supertype.getTypeArguments();
Map<TypeParameter, SiteVariance> variances = supertype.getVarianceOverrides();
List<Type> typeArgs = new ArrayList<Type>(max);
for (int i = 0; i < max; i++) {
TypeParameter refinedTypeParam = refinedTypeParams.get(i);
TypeParameter refiningTypeParam = refiningTypeParams.get(i);
refiningTypeParam.setReified(refinedTypeParam.isReified());
Type refinedProducedType = refinedTypeParam.getType();
List<Type> refinedBounds = refinedTypeParam.getSatisfiedTypes();
List<Type> refiningBounds = refiningTypeParam.getSatisfiedTypes();
Unit unit = that.getUnit();
for (Type bound : refiningBounds) {
Type refiningBound = bound.substitute(substitution, noVariances);
// for every type constraint of the refining member, there must
// be at least one type constraint of the refined member which
// is assignable to it, guaranteeing that the intersection of
// the refined member bounds is assignable to the intersection
// of the refining member bounds
// TODO: would it be better to just form the intersections and
// test assignability directly (the error messages might
// not be as helpful, but it might be less restrictive)
boolean ok = false;
for (Type refinedBound : refinedBounds) {
refinedBound = refinedBound.substitute(args, variances);
if (refinedBound.isSubtypeOf(refiningBound)) {
ok = true;
}
}
if (!ok) {
that.addError("refining member type parameter '" + refiningTypeParam.getName() + "' has upper bound which refined member type parameter '" + refinedTypeParam.getName() + "' of " + message(refined) + " does not satisfy: '" + bound.asString(unit) + "' ('" + refiningTypeParam.getName() + "' should be upper bounded by '" + intersectionOfSupertypes(refinedTypeParam).substitute(args, variances).asString(unit) + "')");
}
}
for (Type bound : refinedBounds) {
Type refinedBound = bound.substitute(args, variances);
boolean ok = false;
for (Type refiningBound : refiningBounds) {
refiningBound = refiningBound.substitute(substitution, noVariances);
if (refinedBound.isSubtypeOf(refiningBound)) {
ok = true;
}
}
if (!ok) {
that.addUnsupportedError("refined member type parameter '" + refinedTypeParam.getName() + "' of " + message(refined) + " has upper bound which refining member type parameter '" + refiningTypeParam.getName() + "' does not satisfy: '" + bound.asString(unit) + "' ('" + refiningTypeParam.getName() + "' should be upper bounded by '" + intersectionOfSupertypes(refinedTypeParam).substitute(args, variances).asString(unit) + "')");
}
}
typeArgs.add(refinedProducedType);
}
return typeArgs;
}
Aggregations