in src/com/facebook/buck/jvm/java/abi/source/PostEnterCanonicalizer.java [109:242]
public TypeMirror getCanonicalType(
@PropagatesNullable TypeMirror typeMirror, @Nullable TreePath treePath) {
if (typeMirror == null) {
return null;
}
Tree tree = treePath == null ? null : treePath.getLeaf();
switch (typeMirror.getKind()) {
case ARRAY:
{
ArrayType arrayType = (ArrayType) typeMirror;
return types.getArrayType(
getCanonicalType(
arrayType.getComponentType(),
treePath,
tree == null ? null : ((ArrayTypeTree) tree).getType()));
}
case TYPEVAR:
{
TypeVariable typeVar = (TypeVariable) typeMirror;
return elements.getCanonicalElement(typeVar.asElement()).asType();
}
case WILDCARD:
{
WildcardType wildcardType = (WildcardType) typeMirror;
Tree boundTree = tree == null ? null : ((WildcardTree) tree).getBound();
return types.getWildcardType(
getCanonicalType(wildcardType.getExtendsBound(), treePath, boundTree),
getCanonicalType(wildcardType.getSuperBound(), treePath, boundTree));
}
case DECLARED:
{
DeclaredType declaredType = (DeclaredType) typeMirror;
// It is possible to have a DeclaredType with ErrorTypes for arguments, so we must
// compute the TreePaths while canonicalizing type arguments
List<? extends TypeMirror> underlyingTypeArgs = declaredType.getTypeArguments();
TypeMirror[] canonicalTypeArgs;
if (underlyingTypeArgs.isEmpty()) {
canonicalTypeArgs = new TypeMirror[0];
} else {
canonicalTypeArgs =
getCanonicalTypes(
underlyingTypeArgs,
treePath,
tree == null ? null : ((ParameterizedTypeTree) tree).getTypeArguments())
.toArray(new TypeMirror[0]);
}
// While it is not possible to have a DeclaredType with an enclosing ErrorType (the only
// way to get a DeclaredType in the first place is if the compiler can resolve all
// enclosing types), it *is* possible to have a DeclaredType with an enclosing
// DeclaredType that has ErrorTypes for type arguments. So we need to check if there's an
// explicitly specified enclosing type and provide the tree if so.
TypeMirror enclosingType = declaredType.getEnclosingType();
DeclaredType canonicalEnclosingType = null;
if (enclosingType.getKind() != TypeKind.NONE) {
TreePath enclosingTypePath = treePath;
if (enclosingTypePath != null
&& enclosingTypePath.getLeaf().getKind() == Tree.Kind.PARAMETERIZED_TYPE) {
enclosingTypePath =
new TreePath(
enclosingTypePath,
((ParameterizedTypeTree) enclosingTypePath.getLeaf()).getType());
}
if (enclosingTypePath != null
&& enclosingTypePath.getLeaf().getKind() == Tree.Kind.MEMBER_SELECT) {
enclosingTypePath =
new TreePath(
enclosingTypePath,
((MemberSelectTree) enclosingTypePath.getLeaf()).getExpression());
} else {
enclosingTypePath = null;
}
canonicalEnclosingType =
(DeclaredType) getCanonicalType(enclosingType, enclosingTypePath);
}
TypeElement canonicalElement =
(TypeElement) elements.getCanonicalElement(declaredType.asElement());
// If an import statement for a type that is not available would shadow a type from a
// star-imported package (such as java.lang), the compiler will happily resolve to the
// star-imported type (expecting that the imported type will be filled in by an annotation
// processor). We check whether we would have inferred something different.
if (canonicalElement.getNestingKind() == NestingKind.TOP_LEVEL
&& treePath != null
&& treePath.getLeaf().getKind() == Tree.Kind.IDENTIFIER) {
DeclaredType inferredType = (DeclaredType) getImportedType(treePath);
if (inferredType != null) {
TypeElement inferredElement =
(TypeElement) elements.getCanonicalElement(inferredType.asElement());
canonicalElement = inferredElement;
}
}
return types.getDeclaredType(canonicalEnclosingType, canonicalElement, canonicalTypeArgs);
}
case PACKAGE:
case ERROR:
{
if (treePath == null) {
throw new IllegalArgumentException("Cannot resolve error types without a Tree.");
}
try {
return getInferredType(treePath);
} catch (CompilerErrorException e) {
javacTrees.printMessage(
Kind.ERROR, e.getMessage(), treePath.getLeaf(), treePath.getCompilationUnit());
return typeMirror;
}
}
case BOOLEAN:
case BYTE:
case SHORT:
case INT:
case LONG:
case CHAR:
case FLOAT:
case DOUBLE:
case VOID:
case NONE:
case NULL:
return typeMirror;
case EXECUTABLE:
case OTHER:
case UNION:
case INTERSECTION:
// Temporary. Remove once migration to Java 10/11 is complete.
// $CASES-OMITTED$
default:
throw new UnsupportedOperationException();
}
}