Search in sources :

Example 41 with GenericsType

use of org.codehaus.groovy.ast.GenericsType in project groovy by apache.

the class StaticTypeCheckingVisitor method extractPlaceHolders.

private static Map<String, GenericsType> extractPlaceHolders(MethodNode method, ClassNode receiver, ClassNode declaringClass) {
    if (declaringClass.equals(OBJECT_TYPE)) {
        Map<String, GenericsType> resolvedPlaceholders = new HashMap<String, GenericsType>();
        if (method != null)
            addMethodLevelDeclaredGenerics(method, resolvedPlaceholders);
        return resolvedPlaceholders;
    }
    Map<String, GenericsType> resolvedPlaceholders = null;
    if (isPrimitiveType(receiver) && !isPrimitiveType(declaringClass)) {
        receiver = getWrapper(receiver);
    }
    final List<ClassNode> queue;
    if (receiver instanceof UnionTypeClassNode) {
        queue = Arrays.asList(((UnionTypeClassNode) receiver).getDelegates());
    } else {
        queue = Collections.singletonList(receiver);
    }
    for (ClassNode item : queue) {
        ClassNode current = item;
        while (current != null) {
            boolean continueLoop = true;
            //extract the place holders
            Map<String, GenericsType> currentPlaceHolders = new HashMap<String, GenericsType>();
            if (isGenericsPlaceHolderOrArrayOf(declaringClass) || declaringClass.equals(current)) {
                extractGenericsConnections(currentPlaceHolders, current, declaringClass);
                if (method != null)
                    addMethodLevelDeclaredGenerics(method, currentPlaceHolders);
                continueLoop = false;
            } else {
                GenericsUtils.extractPlaceholders(current, currentPlaceHolders);
            }
            if (resolvedPlaceholders != null) {
                // merge maps
                Set<Map.Entry<String, GenericsType>> entries = currentPlaceHolders.entrySet();
                for (Map.Entry<String, GenericsType> entry : entries) {
                    GenericsType gt = entry.getValue();
                    if (!gt.isPlaceholder())
                        continue;
                    GenericsType referenced = resolvedPlaceholders.get(gt.getName());
                    if (referenced == null)
                        continue;
                    entry.setValue(referenced);
                }
            }
            resolvedPlaceholders = currentPlaceHolders;
            // we are done if we are now in the declaring class
            if (!continueLoop)
                break;
            current = getNextSuperClass(current, declaringClass);
            if (current == null && CLASS_Type.equals(declaringClass)) {
                // this can happen if the receiver is Class<Foo>, then
                // the actual receiver is Foo and declaringClass is Class
                current = declaringClass;
            }
        }
    }
    if (resolvedPlaceholders == null) {
        String descriptor = "<>";
        if (method != null)
            descriptor = method.getTypeDescriptor();
        throw new GroovyBugError("Declaring class for method call to '" + descriptor + "' declared in " + declaringClass.getName() + " was not matched with found receiver " + receiver.getName() + "." + " This should not have happened!");
    }
    return resolvedPlaceholders;
}
Also used : LowestUpperBoundClassNode(org.codehaus.groovy.ast.tools.WideningCategories.LowestUpperBoundClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) LinkedHashMap(java.util.LinkedHashMap) ListHashMap(org.codehaus.groovy.util.ListHashMap) HashMap(java.util.HashMap) GroovyBugError(org.codehaus.groovy.GroovyBugError) GenericsType(org.codehaus.groovy.ast.GenericsType) Map(java.util.Map) LinkedHashMap(java.util.LinkedHashMap) ListHashMap(org.codehaus.groovy.util.ListHashMap) HashMap(java.util.HashMap)

Example 42 with GenericsType

use of org.codehaus.groovy.ast.GenericsType in project groovy by apache.

the class StaticTypeCheckingVisitor method hasRHSIncompleteGenericTypeInfo.

protected static boolean hasRHSIncompleteGenericTypeInfo(final ClassNode inferredRightExpressionType) {
    boolean replaceType = false;
    GenericsType[] genericsTypes = inferredRightExpressionType.getGenericsTypes();
    if (genericsTypes != null) {
        for (GenericsType genericsType : genericsTypes) {
            if (genericsType.isPlaceholder()) {
                replaceType = true;
                break;
            }
        }
    }
    return replaceType;
}
Also used : GenericsType(org.codehaus.groovy.ast.GenericsType)

Example 43 with GenericsType

use of org.codehaus.groovy.ast.GenericsType in project groovy by apache.

the class StaticTypeCheckingVisitor method inferMapExpressionType.

protected ClassNode inferMapExpressionType(final MapExpression map) {
    ClassNode mapType = LINKEDHASHMAP_CLASSNODE.getPlainNodeReference();
    List<MapEntryExpression> entryExpressions = map.getMapEntryExpressions();
    if (entryExpressions.isEmpty())
        return mapType;
    GenericsType[] genericsTypes = mapType.getGenericsTypes();
    if (genericsTypes == null || genericsTypes.length < 2 || (genericsTypes.length == 2 && OBJECT_TYPE.equals(genericsTypes[0].getType()) && OBJECT_TYPE.equals(genericsTypes[1].getType()))) {
        List<ClassNode> keyTypes = new LinkedList<ClassNode>();
        List<ClassNode> valueTypes = new LinkedList<ClassNode>();
        for (MapEntryExpression entryExpression : entryExpressions) {
            keyTypes.add(getType(entryExpression.getKeyExpression()));
            valueTypes.add(getType(entryExpression.getValueExpression()));
        }
        // to be used in generics, type must be boxed
        ClassNode keyType = getWrapper(lowestUpperBound(keyTypes));
        // to be used in generics, type must be boxed
        ClassNode valueType = getWrapper(lowestUpperBound(valueTypes));
        if (!OBJECT_TYPE.equals(keyType) || !OBJECT_TYPE.equals(valueType)) {
            ClassNode inferred = mapType.getPlainNodeReference();
            inferred.setGenericsTypes(new GenericsType[] { new GenericsType(wrapTypeIfNecessary(keyType)), new GenericsType(wrapTypeIfNecessary(valueType)) });
            return inferred;
        }
    }
    return mapType;
}
Also used : LowestUpperBoundClassNode(org.codehaus.groovy.ast.tools.WideningCategories.LowestUpperBoundClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) GenericsType(org.codehaus.groovy.ast.GenericsType) LinkedList(java.util.LinkedList)

Example 44 with GenericsType

use of org.codehaus.groovy.ast.GenericsType in project groovy by apache.

the class StaticTypeCheckingSupport method extractGenericsConnections.

private static void extractGenericsConnections(Map<String, GenericsType> connections, GenericsType[] usage, GenericsType[] declaration) {
    // if declaration does not provide generics, there is no connection to make 
    if (usage == null || declaration == null || declaration.length == 0)
        return;
    if (usage.length != declaration.length)
        return;
    // both have generics
    for (int i = 0; i < usage.length; i++) {
        GenericsType ui = usage[i];
        GenericsType di = declaration[i];
        if (di.isPlaceholder()) {
            connections.put(di.getName(), ui);
        } else if (di.isWildcard()) {
            if (ui.isWildcard()) {
                extractGenericsConnections(connections, ui.getLowerBound(), di.getLowerBound());
                extractGenericsConnections(connections, ui.getUpperBounds(), di.getUpperBounds());
            } else {
                ClassNode cu = ui.getType();
                extractGenericsConnections(connections, cu, di.getLowerBound());
                ClassNode[] upperBounds = di.getUpperBounds();
                if (upperBounds != null) {
                    for (ClassNode cn : upperBounds) {
                        extractGenericsConnections(connections, cu, cn);
                    }
                }
            }
        } else {
            extractGenericsConnections(connections, ui.getType(), di.getType());
        }
    }
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) GenericsType(org.codehaus.groovy.ast.GenericsType)

Example 45 with GenericsType

use of org.codehaus.groovy.ast.GenericsType in project groovy by apache.

the class StaticTypeCheckingVisitor method makeOwnerList.

/**
     * Given an object expression (a receiver expression), generate the list of potential receiver types.
     * @param objectExpression the receiver expression
     * @return the list of types the receiver may be
     */
protected List<Receiver<String>> makeOwnerList(final Expression objectExpression) {
    final ClassNode receiver = getType(objectExpression);
    List<Receiver<String>> owners = new LinkedList<Receiver<String>>();
    owners.add(Receiver.<String>make(receiver));
    if (isClassClassNodeWrappingConcreteType(receiver)) {
        GenericsType clazzGT = receiver.getGenericsTypes()[0];
        owners.add(0, Receiver.<String>make(clazzGT.getType()));
    }
    if (receiver.isInterface()) {
        // GROOVY-xxxx
        owners.add(Receiver.<String>make(OBJECT_TYPE));
    }
    addSelfTypes(receiver, owners);
    if (!typeCheckingContext.temporaryIfBranchTypeInformation.empty()) {
        List<ClassNode> potentialReceiverType = getTemporaryTypesForExpression(objectExpression);
        if (potentialReceiverType != null) {
            for (ClassNode node : potentialReceiverType) {
                owners.add(Receiver.<String>make(node));
            }
        }
    }
    if (typeCheckingContext.lastImplicitItType != null && objectExpression instanceof VariableExpression && ((VariableExpression) objectExpression).getName().equals("it")) {
        owners.add(Receiver.<String>make(typeCheckingContext.lastImplicitItType));
    }
    return owners;
}
Also used : LowestUpperBoundClassNode(org.codehaus.groovy.ast.tools.WideningCategories.LowestUpperBoundClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) GenericsType(org.codehaus.groovy.ast.GenericsType) LinkedList(java.util.LinkedList)

Aggregations

GenericsType (org.codehaus.groovy.ast.GenericsType)171 ClassNode (org.codehaus.groovy.ast.ClassNode)148 InnerClassNode (org.codehaus.groovy.ast.InnerClassNode)76 LowestUpperBoundClassNode (org.codehaus.groovy.ast.tools.WideningCategories.LowestUpperBoundClassNode)52 Parameter (org.codehaus.groovy.ast.Parameter)21 MethodNode (org.codehaus.groovy.ast.MethodNode)20 ClosureSignatureHint (groovy.transform.stc.ClosureSignatureHint)19 LinkedList (java.util.LinkedList)18 HashMap (java.util.HashMap)17 ArrayList (java.util.ArrayList)15 LinkedHashMap (java.util.LinkedHashMap)9 AST (antlr.collections.AST)8 AnnotationNode (org.codehaus.groovy.ast.AnnotationNode)8 ListHashMap (org.codehaus.groovy.util.ListHashMap)8 Map (java.util.Map)6 AtomicReference (java.util.concurrent.atomic.AtomicReference)6 EnumConstantClassNode (org.codehaus.groovy.ast.EnumConstantClassNode)6 FieldNode (org.codehaus.groovy.ast.FieldNode)6 GroovyBugError (org.codehaus.groovy.GroovyBugError)5 DynamicVariable (org.codehaus.groovy.ast.DynamicVariable)4