use of org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.ArrayList_TYPE in project groovy by apache.
the class StaticTypeCheckingVisitor method resolvePlaceholdersFromImplicitTypeHints.
/**
* Given method call like "m(Collections.emptyList())", the type of the call
* argument is {@code List<T>} without explicit type arguments. Knowning the
* method target of "m", {@code T} could be resolved.
*/
private void resolvePlaceholdersFromImplicitTypeHints(final ClassNode[] actuals, final ArgumentListExpression argumentList, final Parameter[] parameterArray) {
int np = parameterArray.length;
for (int i = 0, n = actuals.length; np > 0 && i < n; i += 1) {
Expression a = argumentList.getExpression(i);
Parameter p = parameterArray[Math.min(i, np - 1)];
ClassNode at = actuals[i], pt = p.getOriginType();
if (!isUsingGenericsOrIsArrayUsingGenerics(pt))
continue;
if (i >= (np - 1) && pt.isArray() && !at.isArray())
pt = pt.getComponentType();
if (a instanceof ListExpression) {
actuals[i] = getLiteralResultType(pt, at, ArrayList_TYPE);
} else if (a instanceof MapExpression) {
actuals[i] = getLiteralResultType(pt, at, LinkedHashMap_TYPE);
} else if (a instanceof ConstructorCallExpression) {
// GROOVY-10086
inferDiamondType((ConstructorCallExpression) a, pt);
} else if (a instanceof TernaryExpression && at.getGenericsTypes() != null && at.getGenericsTypes().length == 0) {
// GROOVY-9983: double diamond scenario -- "m(flag ? new Type<>(...) : new Type<>(...))"
typeCheckingContext.pushEnclosingBinaryExpression(assignX(varX(p), a, a));
// re-visit with target type witness
a.visit(this);
typeCheckingContext.popEnclosingBinaryExpression();
actuals[i] = getType(a);
}
// check for method call with known target
if (!(a instanceof MethodCallExpression))
continue;
if (((MethodCallExpression) a).isUsingGenerics())
continue;
MethodNode aNode = a.getNodeMetaData(DIRECT_METHOD_CALL_TARGET);
if (aNode == null || aNode.getGenericsTypes() == null)
continue;
// and unknown generics
if (!GenericsUtils.hasUnresolvedGenerics(at))
continue;
while (!at.equals(pt) && !isObjectType(at) && !isGenericsPlaceHolderOrArrayOf(at)) {
at = applyGenericsContext(GenericsUtils.extractPlaceholders(at), getNextSuperClass(at, pt));
}
// try to resolve placeholder(s) in argument type using parameter type
Map<GenericsTypeName, GenericsType> linked = new HashMap<>();
Map<GenericsTypeName, GenericsType> source = GenericsUtils.extractPlaceholders(at);
Map<GenericsTypeName, GenericsType> target = GenericsUtils.extractPlaceholders(pt);
// connect E:T from source to E:Type from target
for (GenericsType placeholder : aNode.getGenericsTypes()) {
for (Map.Entry<GenericsTypeName, GenericsType> e : source.entrySet()) {
if (e.getValue().getNodeMetaData(GenericsType.class) == placeholder) {
Optional.ofNullable(target.get(e.getKey())).filter(gt -> isAssignableTo(gt.getType(), placeholder.getType())).ifPresent(gt -> linked.put(new GenericsTypeName(e.getValue().getName()), gt));
break;
}
}
}
actuals[i] = applyGenericsContext(linked, at);
}
}
Aggregations