// Build a search list for type parameters to find their definition,
// resolving enclosing classes as we go up.
TypeParameterLookup typeParamLookup = new TypeParameterLookup();
typeParamLookup.pushEnclosingScopes(unresolvedType);
CollectClassData classData = context.classDataByType.get(unresolvedType);
assert classData != null;
int access = classData.getAccess();
assert (!classData.getClassType().hasNoExternalName());
logger = logger.branch(
TreeLogger.SPAM, "Found type '" + unresolvedType.getQualifiedSourceName() + "'", null);
// Handle package-info classes.
if (isPackageInfoTypeName(unresolvedType.getSimpleSourceName())) {
return resolvePackage(logger, unresolvedType, classData.getAnnotations());
}
// Resolve annotations
Map<Class<? extends Annotation>, Annotation> declaredAnnotations = Maps.newHashMap();
resolveAnnotations(logger, classData.getAnnotations(), declaredAnnotations);
addAnnotations(unresolvedType, declaredAnnotations);
String signature = classData.getSignature();
/*
* Note: Byte code from the OpenJDK compiler doesn't contain a type signature for non-static
* inner classes of parameterized types that do not contain new parameters (but JDT compiled
* byte code does). That can cause some differences in the way generic types are represented in
* the type oracle.
*
* These differences also show up when using java.lang.reflect to look at types.
*/
if (signature != null) {
// If we have a signature, use it for superclass and interfaces
SignatureReader reader = new SignatureReader(signature);
ResolveClassSignature classResolver = new ResolveClassSignature(
context.resolver, logger, unresolvedType, typeParamLookup);
reader.accept(classResolver);
classResolver.finish();
if (unresolvedType.getSuperclass() != null
&& !resolveClass(logger, unresolvedType.getSuperclass(), context)) {
logger.log(TreeLogger.WARN,
"Unable to resolve supertype " + unresolvedType.getSuperclass().getName());
return false;
}
} else {
// Set the super type for non-interfaces
if ((access & Opcodes.ACC_INTERFACE) == 0) {
String superInternalName = classData.getSuperInternalName();
assert Name.isInternalName(superInternalName);
if (superInternalName != null) {
JClassType superType = findByInternalName(superInternalName);
if (superType == null || !resolveClass(logger, superType, context)) {
logger.log(TreeLogger.WARN, "Unable to resolve supertype " + superInternalName);
return false;
}
setSuperClass(unresolvedType, (JClassType) possiblySubstituteRawType(superType));
}
}
// Set interfaces
for (String interfaceInternalName : classData.getInterfaceInternalNames()) {
JClassType interfaceType = findByInternalName(interfaceInternalName);
if (interfaceType == null || !resolveClass(logger, interfaceType, context)) {
logger.log(TreeLogger.WARN, "Unable to resolve interface " + interfaceInternalName);
return false;
}
addImplementedInterface(
unresolvedType, (JClassType) possiblySubstituteRawType(interfaceType));
}
}
if (((access & Opcodes.ACC_INTERFACE) == 0) && unresolvedType.getSuperclass() == null) {
// Only Object or interfaces should not have a superclass
assert "java/lang/Object".equals(classData.getInternalName());
}
// Process methods
for (CollectMethodData method : classData.getMethods()) {
TreeLogger branch = logger.branch(TreeLogger.SPAM, "Resolving method " + method.getName());
if (!resolveMethod(branch, unresolvedType, method, typeParamLookup, context)) {
// Already logged.
return false;
}
}
// Process fields
// Track the next enum ordinal across resolveField calls.
int[] nextEnumOrdinal = new int[] {0};
for (CollectFieldData field : classData.getFields()) {
TreeLogger branch = logger.branch(TreeLogger.SPAM, "Resolving field " + field.getName());
if (!resolveField(branch, unresolvedType, field, typeParamLookup, nextEnumOrdinal, context)) {
// Already logged.
return false;
}