use of org.codehaus.groovy.ast.GenericsType.GenericsTypeName in project groovy by apache.
the class ResolveVisitor method resolve.
protected boolean resolve(final ClassNode type, final boolean testModuleImports, final boolean testDefaultImports, final boolean testStaticInnerClasses) {
resolveGenericsTypes(type.getGenericsTypes());
if (type.isResolved() || type.isPrimaryClassNode())
return true;
if (type.isArray()) {
ClassNode element = type.getComponentType();
boolean resolved = resolve(element, testModuleImports, testDefaultImports, testStaticInnerClasses);
if (resolved) {
ClassNode cn = element.makeArray();
type.setRedirect(cn);
}
return resolved;
}
// test if vanilla name is current class name
if (currentClass == type)
return true;
String typeName = type.getName();
GenericsType genericsType = genericParameterNames.get(new GenericsTypeName(typeName));
if (genericsType != null) {
type.setRedirect(genericsType.getType());
type.setGenericsTypes(new GenericsType[] { genericsType });
type.setGenericsPlaceHolder(true);
return true;
}
if (currentClass.getNameWithoutPackage().equals(typeName)) {
type.setRedirect(currentClass);
return true;
}
return (!type.hasPackageName() && resolveNestedClass(type)) || resolveFromModule(type, testModuleImports) || resolveFromCompileUnit(type) || (testDefaultImports && !type.hasPackageName() && resolveFromDefaultImports(type)) || resolveToOuter(type) || (testStaticInnerClasses && type.hasPackageName() && resolveFromStaticInnerClasses(type));
}
use of org.codehaus.groovy.ast.GenericsType.GenericsTypeName in project groovy by apache.
the class StaticTypeCheckingVisitor method extractPlaceHolders.
private static Map<GenericsTypeName, GenericsType> extractPlaceHolders(final ClassNode receiver, final ClassNode declaringClass) {
Map<GenericsTypeName, GenericsType> result = null;
ClassNode[] todo;
if (receiver instanceof UnionTypeClassNode) {
todo = ((UnionTypeClassNode) receiver).getDelegates();
} else {
todo = new ClassNode[] { !isPrimitiveType(declaringClass) ? wrapTypeIfNecessary(receiver) : receiver };
}
for (ClassNode type : todo) {
ClassNode current = type;
while (current != null) {
Map<GenericsTypeName, GenericsType> placeHolders = new HashMap<>();
// GROOVY-10055: handle diamond or raw
if (current.getGenericsTypes() != null ? current.getGenericsTypes().length == 0 : current.redirect().getGenericsTypes() != null) {
for (GenericsType gt : current.redirect().getGenericsTypes()) {
ClassNode cn = gt.getUpperBounds() != null ? gt.getUpperBounds()[0] : gt.getType().redirect();
placeHolders.put(new GenericsTypeName(gt.getName()), cn.getPlainNodeReference().asGenericsType());
}
}
boolean currentIsDeclaring = current.equals(declaringClass) || isGenericsPlaceHolderOrArrayOf(declaringClass);
if (currentIsDeclaring) {
extractGenericsConnections(placeHolders, current, declaringClass);
} else {
GenericsUtils.extractPlaceholders(current, placeHolders);
}
if (result != null) {
// merge maps
for (Map.Entry<GenericsTypeName, GenericsType> entry : placeHolders.entrySet()) {
GenericsType gt = entry.getValue();
if (!gt.isPlaceholder())
continue;
GenericsType referenced = result.get(new GenericsTypeName(gt.getName()));
if (referenced == null)
continue;
entry.setValue(referenced);
}
}
result = placeHolders;
// we are done if we are now in the declaring class
if (currentIsDeclaring)
break;
current = getNextSuperClass(current, declaringClass);
if (current == null && isClassType(declaringClass)) {
// this can happen if the receiver is Class<Foo>, then
// the actual receiver is Foo and declaringClass is Class
current = declaringClass;
} else {
current = applyGenericsContext(placeHolders, current);
}
}
}
if (result == null) {
throw new GroovyBugError("Declaring class " + prettyPrintTypeName(declaringClass) + " was not matched with receiver " + prettyPrintTypeName(receiver) + ". This should not have happened!");
}
return result;
}
use of org.codehaus.groovy.ast.GenericsType.GenericsTypeName in project groovy by apache.
the class StaticTypeCheckingSupport method extractResolvedPlaceHolders.
private static Set<GenericsTypeName> extractResolvedPlaceHolders(final Map<GenericsTypeName, GenericsType> resolvedMethodGenerics) {
if (resolvedMethodGenerics.isEmpty())
return Collections.emptySet();
Set<GenericsTypeName> result = new HashSet<>();
for (Map.Entry<GenericsTypeName, GenericsType> entry : resolvedMethodGenerics.entrySet()) {
GenericsType value = entry.getValue();
if (value.isPlaceholder())
continue;
result.add(entry.getKey());
}
return result;
}
use of org.codehaus.groovy.ast.GenericsType.GenericsTypeName in project groovy by apache.
the class StaticTypeCheckingSupport method fullyResolve.
/**
* Given a generics type representing SomeClass<T,V> and a resolved placeholder map, returns a new generics type
* for which placeholders are resolved recursively.
*/
protected static GenericsType fullyResolve(GenericsType gt, final Map<GenericsTypeName, GenericsType> placeholders) {
GenericsType fromMap = placeholders.get(new GenericsTypeName(gt.getName()));
if (gt.isPlaceholder() && fromMap != null) {
gt = fromMap;
}
ClassNode type = fullyResolveType(gt.getType(), placeholders);
ClassNode lowerBound = gt.getLowerBound();
if (lowerBound != null)
lowerBound = fullyResolveType(lowerBound, placeholders);
ClassNode[] upperBounds = gt.getUpperBounds();
if (upperBounds != null) {
ClassNode[] copy = new ClassNode[upperBounds.length];
for (int i = 0, upperBoundsLength = upperBounds.length; i < upperBoundsLength; i++) {
final ClassNode upperBound = upperBounds[i];
copy[i] = fullyResolveType(upperBound, placeholders);
}
upperBounds = copy;
}
GenericsType genericsType = new GenericsType(type, upperBounds, lowerBound);
genericsType.setWildcard(gt.isWildcard());
return genericsType;
}
use of org.codehaus.groovy.ast.GenericsType.GenericsTypeName in project groovy by apache.
the class StaticTypeCheckingSupport method fullyResolveType.
protected static ClassNode fullyResolveType(final ClassNode type, final Map<GenericsTypeName, GenericsType> placeholders) {
if (type.isArray()) {
return fullyResolveType(type.getComponentType(), placeholders).makeArray();
}
if (type.isUsingGenerics()) {
if (type.isGenericsPlaceHolder()) {
GenericsType gt = placeholders.get(new GenericsTypeName(type.getUnresolvedName()));
if (gt != null) {
return gt.getType();
}
ClassNode cn = type.redirect();
return cn != type ? cn : OBJECT_TYPE;
} else {
GenericsType[] gts = type.getGenericsTypes();
if (gts != null) {
gts = Arrays.stream(gts).map(gt -> {
if (gt.isPlaceholder()) {
GenericsTypeName gtn = new GenericsTypeName(gt.getName());
return placeholders.getOrDefault(gtn, extractType(gt).asGenericsType());
}
return fullyResolve(gt, placeholders);
}).toArray(GenericsType[]::new);
}
ClassNode cn = type.getPlainNodeReference();
cn.setGenericsTypes(gts);
return cn;
}
}
return type;
}
Aggregations