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