use of org.eclipse.ceylon.model.typechecker.model.TypeParameter in project ceylon by eclipse.
the class JsonPackage method parseTypeParameters.
/**
* Creates a list of TypeParameter from a list of maps.
* @param typeParams The list of maps to create the TypeParameters.
* @param container The declaration which owns the resulting type parameters.
* @param existing A list of type parameters declared in the parent scopes which can be referenced from
* the ones that have to be parsed.
*/
private List<TypeParameter> parseTypeParameters(List<Map<String, Object>> typeParams, final Declaration container, List<TypeParameter> existing) {
if (typeParams == null)
return Collections.emptyList();
// New array with existing parms to avoid modifying that one
List<TypeParameter> allparms = new ArrayList<>((existing == null ? 0 : existing.size()) + typeParams.size());
if (existing != null && !existing.isEmpty()) {
allparms.addAll(existing);
}
List<TypeParameter> tparms = new ArrayList<>(typeParams.size());
// First create the type parameters
for (Map<String, Object> tp : typeParams) {
final Declaration maybe;
if (tp.get(KEY_METATYPE) instanceof TypeParameter) {
maybe = (TypeParameter) tp.get(KEY_METATYPE);
} else {
maybe = container.getDirectMember((String) tp.get(KEY_NAME), null, false);
}
if (maybe instanceof TypeParameter) {
// we already had it (from partial loading elsewhere)
allparms.add((TypeParameter) maybe);
tparms.add((TypeParameter) maybe);
tp.put(KEY_METATYPE, maybe);
} else {
TypeParameter tparm = new TypeParameter();
tparm.setUnit(container.getUnit());
tparm.setDeclaration(container);
container.getMembers().add(tparm);
if (tp.containsKey(KEY_NAME)) {
tparm.setName((String) tp.get(KEY_NAME));
} else if (!tp.containsKey(KEY_TYPES)) {
throw new IllegalArgumentException("Invalid type parameter map " + tp);
}
String variance = (String) tp.get(KEY_DS_VARIANCE);
if ("out".equals(variance)) {
tparm.setCovariant(true);
} else if ("in".equals(variance)) {
tparm.setContravariant(true);
}
if (container instanceof Scope) {
Scope scope = (Scope) container;
tparm.setContainer(scope);
tparm.setScope(scope);
}
tparm.setDefaulted(tp.containsKey(KEY_DEFAULT));
tparms.add(tparm);
allparms.add(tparm);
tp.put(KEY_METATYPE, tparm);
}
}
if (container instanceof Generic) {
((Generic) container).setTypeParameters(tparms);
}
// Second, add defaults and heritage
for (Map<String, Object> tp : typeParams) {
TypeParameter tparm = (TypeParameter) tp.get(KEY_METATYPE);
if (tparm.getExtendedType() == null) {
if (tp.containsKey(KEY_PACKAGE)) {
// Looks like this never happens but...
Type subtype = getTypeFromJson(tp, container, allparms);
tparm.setExtendedType(subtype);
} else if (tp.containsKey(KEY_TYPES)) {
if (!("u".equals(tp.get("comp")) || "i".equals(tp.get("comp")))) {
throw new IllegalArgumentException("Only union or intersection types are allowed as 'comp'");
}
Type subtype = getTypeFromJson(tp, container, allparms);
tparm.setName(subtype.asString());
tparm.setExtendedType(subtype);
} else {
tparm.setExtendedType(getTypeFromJson(voidclass, container, null));
}
}
if (tparm.isDefaulted()) {
@SuppressWarnings("unchecked") final Map<String, Object> deftype = (Map<String, Object>) tp.get(KEY_DEFAULT);
tparm.setDefaultTypeArgument(getTypeFromJson(deftype, container, existing));
}
if (tp.containsKey(KEY_SATISFIES)) {
@SuppressWarnings("unchecked") final List<Map<String, Object>> stypes = (List<Map<String, Object>>) tp.get(KEY_SATISFIES);
tparm.setSatisfiedTypes(parseTypeList(stypes, allparms));
tparm.setConstrained(true);
} else if (tp.containsKey("of")) {
@SuppressWarnings("unchecked") final List<Map<String, Object>> oftype = (List<Map<String, Object>>) tp.get("of");
tparm.setCaseTypes(parseTypeList(oftype, allparms));
tparm.setConstrained(true);
}
}
return tparms;
}
use of org.eclipse.ceylon.model.typechecker.model.TypeParameter in project ceylon by eclipse.
the class MetamodelGenerator method putTypeArguments.
private void putTypeArguments(Map<String, Object> container, Type pt, Declaration from) {
int tparmSize = 0;
Type t = pt;
while (t != null) {
tparmSize += t.getTypeArgumentList() == null ? 0 : t.getTypeArgumentList().size();
t = t.getQualifyingType();
}
if (tparmSize > 0) {
final Map<String, Map<String, Object>> targs = new HashMap<>(tparmSize);
t = pt;
while (t != null) {
final Map<TypeParameter, SiteVariance> usv = t.getVarianceOverrides();
if (t.getTypeArgumentList() != null && !t.getTypeArgumentList().isEmpty()) {
for (Map.Entry<TypeParameter, Type> targ : t.getTypeArguments().entrySet()) {
final Map<String, Object> tpmap = typeMap(targ.getValue(), from);
final SiteVariance variance = usv.get(targ.getKey());
if (variance != null) {
tpmap.put(MetamodelGenerator.KEY_US_VARIANCE, variance.ordinal());
}
targs.put(partiallyQualifiedName(targ.getKey().getDeclaration()) + "." + targ.getKey().getName(), tpmap);
}
}
t = t.getQualifyingType();
}
container.put(KEY_TYPE_ARGS, targs);
}
}
use of org.eclipse.ceylon.model.typechecker.model.TypeParameter 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.TypeParameter 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.TypeParameter in project ceylon by eclipse.
the class TypeUtils method mapTypeArgument.
/**
* Generates the right type arguments for operators that are sugar for method calls.
* @param methodName The name of the method that is to be invoked
* @param rightTpName The name of the type argument on the right term
* @param leftTpName The name of the type parameter on the method
* @return A map with the type parameter of the method as key
* and the produced type belonging to the type argument of the term on the right.
*/
public static Map<TypeParameter, Type> mapTypeArgument(final Tree.BinaryOperatorExpression expr, final String methodName, final String rightTpName, final String leftTpName) {
Function md = (Function) expr.getLeftTerm().getTypeModel().getDeclaration().getMember(methodName, null, false);
if (md == null) {
expr.addUnexpectedError("Left term of intersection operator should have method named " + methodName, Backend.JavaScript);
return null;
}
Map<TypeParameter, Type> targs = expr.getRightTerm().getTypeModel().getTypeArguments();
Type otherType = null;
for (TypeParameter tp : targs.keySet()) {
if (tp.getName().equals(rightTpName)) {
otherType = targs.get(tp);
break;
}
}
if (otherType == null) {
expr.addUnexpectedError("Right term of intersection operator should have type parameter named " + rightTpName, Backend.JavaScript);
return null;
}
targs = new HashMap<>();
TypeParameter mtp = null;
for (TypeParameter tp : md.getTypeParameters()) {
if (tp.getName().equals(leftTpName)) {
mtp = tp;
break;
}
}
if (mtp == null) {
expr.addUnexpectedError("Left term of intersection should have type parameter named " + leftTpName, Backend.JavaScript);
}
targs.put(mtp, otherType);
return targs;
}
Aggregations