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);
}
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;
}
Aggregations