Search in sources :

Example 61 with TypeParameter

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;
}
Also used : TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) Generic(org.eclipse.ceylon.model.typechecker.model.Generic) ArrayList(java.util.ArrayList) IntersectionType(org.eclipse.ceylon.model.typechecker.model.IntersectionType) NothingType(org.eclipse.ceylon.model.typechecker.model.NothingType) UnionType(org.eclipse.ceylon.model.typechecker.model.UnionType) Type(org.eclipse.ceylon.model.typechecker.model.Type) UnknownType(org.eclipse.ceylon.model.typechecker.model.UnknownType) Scope(org.eclipse.ceylon.model.typechecker.model.Scope) List(java.util.List) ParameterList(org.eclipse.ceylon.model.typechecker.model.ParameterList) ArrayList(java.util.ArrayList) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) Map(java.util.Map) HashMap(java.util.HashMap)

Example 62 with TypeParameter

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);
    }
}
Also used : Type(org.eclipse.ceylon.model.typechecker.model.Type) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) SiteVariance(org.eclipse.ceylon.model.typechecker.model.SiteVariance) HashMap(java.util.HashMap) HashMap(java.util.HashMap) Map(java.util.Map)

Example 63 with TypeParameter

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("}");
        }
    }
}
Also used : Function(org.eclipse.ceylon.model.typechecker.model.Function) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) Type(org.eclipse.ceylon.model.typechecker.model.Type) UnknownType(org.eclipse.ceylon.model.typechecker.model.UnknownType) NothingType(org.eclipse.ceylon.model.typechecker.model.NothingType) Scope(org.eclipse.ceylon.model.typechecker.model.Scope) Constructor(org.eclipse.ceylon.model.typechecker.model.Constructor) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)

Example 64 with TypeParameter

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;
}
Also used : TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) Type(org.eclipse.ceylon.model.typechecker.model.Type) UnknownType(org.eclipse.ceylon.model.typechecker.model.UnknownType) NothingType(org.eclipse.ceylon.model.typechecker.model.NothingType) HashMap(java.util.HashMap) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)

Example 65 with TypeParameter

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;
}
Also used : Function(org.eclipse.ceylon.model.typechecker.model.Function) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) Type(org.eclipse.ceylon.model.typechecker.model.Type) UnknownType(org.eclipse.ceylon.model.typechecker.model.UnknownType) NothingType(org.eclipse.ceylon.model.typechecker.model.NothingType)

Aggregations

TypeParameter (org.eclipse.ceylon.model.typechecker.model.TypeParameter)181 Type (org.eclipse.ceylon.model.typechecker.model.Type)138 TypeDeclaration (org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)82 ArrayList (java.util.ArrayList)57 ModelUtil.appliedType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType)57 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)54 UnknownType (org.eclipse.ceylon.model.typechecker.model.UnknownType)46 Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)45 ModelUtil.intersectionType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.intersectionType)35 TypedDeclaration (org.eclipse.ceylon.model.typechecker.model.TypedDeclaration)32 ClassOrInterface (org.eclipse.ceylon.model.typechecker.model.ClassOrInterface)30 Function (org.eclipse.ceylon.model.typechecker.model.Function)29 AnalyzerUtil.getTupleType (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTupleType)28 AnalyzerUtil.spreadType (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.spreadType)28 Parameter (org.eclipse.ceylon.model.typechecker.model.Parameter)28 IntersectionType (org.eclipse.ceylon.model.typechecker.model.IntersectionType)27 JCTypeParameter (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCTypeParameter)26 Class (org.eclipse.ceylon.model.typechecker.model.Class)26 UnionType (org.eclipse.ceylon.model.typechecker.model.UnionType)25 HashMap (java.util.HashMap)24