Search in sources :

Example 26 with GenericsTypeName

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

the class StaticTypeCheckingSupport method inferenceCheck.

private static boolean inferenceCheck(final Set<GenericsTypeName> fixedPlaceHolders, final Map<GenericsTypeName, GenericsType> resolvedMethodGenerics, ClassNode type, final ClassNode wrappedArgument, final boolean lastArg) {
    // GROOVY-8090: handle generics varargs like "T x = ...; Arrays.asList(x)"
    if (lastArg && type.isArray() && type.getComponentType().isGenericsPlaceHolder() && !wrappedArgument.isArray() && wrappedArgument.isGenericsPlaceHolder()) {
        type = type.getComponentType();
    }
    // the context we compare with in the end is the one of the callsite
    // so far we specified the context of the method declaration only
    // thus for each argument, we try to find the connected generics first
    Map<GenericsTypeName, GenericsType> connections = new LinkedHashMap<>();
    extractGenericsConnections(connections, wrappedArgument, type);
    // each new connection must comply with previous connections
    for (Map.Entry<GenericsTypeName, GenericsType> entry : connections.entrySet()) {
        GenericsType candidate = entry.getValue(), resolved = resolvedMethodGenerics.get(entry.getKey());
        if (resolved == null || (candidate.isPlaceholder() && !hasNonTrivialBounds(candidate)))
            continue;
        if (!compatibleConnection(resolved, candidate)) {
            if (!resolved.isPlaceholder() && !resolved.isWildcard() && !fixedPlaceHolders.contains(entry.getKey())) {
                // GROOVY-5692, GROOVY-10006: multiple witnesses
                if (compatibleConnection(candidate, resolved)) {
                    // was "T=Integer" and now is "T=Number" or "T=Object"
                    resolvedMethodGenerics.put(entry.getKey(), candidate);
                    continue;
                } else if (!candidate.isPlaceholder() && !candidate.isWildcard()) {
                    // combine "T=Integer" and "T=String" to produce "T=? extends Serializable & Comparable<...>"
                    ClassNode lub = lowestUpperBound(candidate.getType(), resolved.getType());
                    resolvedMethodGenerics.put(entry.getKey(), lub.asGenericsType());
                    continue;
                }
            }
            // incompatible
            return true;
        }
    }
    // GROOVY-10337
    connections.keySet().removeAll(fixedPlaceHolders);
    // apply the new information to refine the method level information so
    // that the information slowly becomes information for the callsite
    applyGenericsConnections(connections, resolvedMethodGenerics);
    // since it is possible that the callsite uses some generics as well,
    // we may have to add additional elements here
    addMissingEntries(connections, resolvedMethodGenerics);
    // to finally see if the parameter and the argument fit together,
    // we use the provided information to transform the parameter
    // into something that can exist in the callsite context
    ClassNode resolvedType = applyGenericsContext(resolvedMethodGenerics, type);
    return !typeCheckMethodArgumentWithGenerics(resolvedType, wrappedArgument, lastArg);
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) GenericsType(org.codehaus.groovy.ast.GenericsType) GenericsTypeName(org.codehaus.groovy.ast.GenericsType.GenericsTypeName) Map(java.util.Map) LinkedHashMap(java.util.LinkedHashMap) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap)

Example 27 with GenericsTypeName

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

the class StaticTypeCheckingSupport method extractGenericsParameterMapOfThis.

private static Map<GenericsTypeName, GenericsType> extractGenericsParameterMapOfThis(final MethodNode mn) {
    if (mn == null)
        return null;
    Map<GenericsTypeName, GenericsType> map = null;
    if (!mn.isStatic()) {
        map = extractGenericsParameterMapOfThis(mn.getDeclaringClass());
    }
    GenericsType[] gts = mn.getGenericsTypes();
    if (gts != null) {
        if (map == null)
            map = new HashMap<>();
        for (GenericsType gt : gts) {
            assert gt.isPlaceholder();
            map.put(new GenericsTypeName(gt.getName()), gt);
        }
    }
    return map;
}
Also used : LinkedHashMap(java.util.LinkedHashMap) HashMap(java.util.HashMap) GenericsType(org.codehaus.groovy.ast.GenericsType) GenericsTypeName(org.codehaus.groovy.ast.GenericsType.GenericsTypeName)

Aggregations

GenericsType (org.codehaus.groovy.ast.GenericsType)27 GenericsTypeName (org.codehaus.groovy.ast.GenericsType.GenericsTypeName)27 ClassNode (org.codehaus.groovy.ast.ClassNode)25 InnerClassNode (org.codehaus.groovy.ast.InnerClassNode)25 HashMap (java.util.HashMap)16 LinkedHashMap (java.util.LinkedHashMap)15 Parameter (org.codehaus.groovy.ast.Parameter)14 Map (java.util.Map)12 MethodNode (org.codehaus.groovy.ast.MethodNode)12 StaticTypeCheckingSupport.findDGMMethodsForClassNode (org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.findDGMMethodsForClassNode)12 StaticTypeCheckingSupport.getCombinedGenericsType (org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.getCombinedGenericsType)12 ClosureSignatureHint (groovy.transform.stc.ClosureSignatureHint)10 ArgumentListExpression (org.codehaus.groovy.ast.expr.ArgumentListExpression)10 ArrayExpression (org.codehaus.groovy.ast.expr.ArrayExpression)10 BinaryExpression (org.codehaus.groovy.ast.expr.BinaryExpression)10 CastExpression (org.codehaus.groovy.ast.expr.CastExpression)10 ClosureExpression (org.codehaus.groovy.ast.expr.ClosureExpression)10 ConstantExpression (org.codehaus.groovy.ast.expr.ConstantExpression)10 Expression (org.codehaus.groovy.ast.expr.Expression)10 ListExpression (org.codehaus.groovy.ast.expr.ListExpression)10