Render nullability for error types properly

This commit is contained in:
Andrey Breslav
2013-10-30 14:30:24 +04:00
parent 1eb38febf2
commit 834b306706
4 changed files with 51 additions and 33 deletions
@@ -24,6 +24,7 @@ import org.jetbrains.jet.lang.resolve.java.resolver.TypeUsage.*
import org.jetbrains.jet.lang.resolve.java.resolver.*
import org.jetbrains.jet.lang.types.Variance.*
import org.jetbrains.jet.lang.types.*
import com.intellij.openapi.diagnostic.Logger
import org.jetbrains.kotlin.util.iif
import org.jetbrains.kotlin.util.eq
import org.jetbrains.jet.lang.resolve.java.structure.JavaPrimitiveType
@@ -43,6 +44,8 @@ import org.jetbrains.jet.lang.resolve.java.structure.JavaMethod
import java.util.HashSet
import org.jetbrains.jet.lang.types.checker.JetTypeChecker
private val LOG = Logger.getInstance(javaClass<LazyJavaTypeResolver>())
class LazyJavaTypeResolver(
private val c: LazyJavaResolverContext,
private val typeParameterResolver: TypeParameterResolver
@@ -234,14 +237,18 @@ class LazyJavaTypeResolver(
// 'L extends List<T>' in Java is a List<T> in Kotlin, not a List<T?>
// nullability will be taken care of in individual member signatures
when (classifier()) {
is JavaClass -> attr.howThisTypeIsUsed !in setOf(TYPE_ARGUMENT, SUPERTYPE_ARGUMENT, SUPERTYPE)
is JavaTypeParameter -> {
if (isConstructorTypeParameter())
getConstructorTypeParameterSubstitute().isNullable()
else
attr.howThisTypeIsUsed !in setOf(TYPE_ARGUMENT, UPPER_BOUND, SUPERTYPE_ARGUMENT, SUPERTYPE)
}
else -> true
is JavaClass,
null -> attr.howThisTypeIsUsed !in setOf(TYPE_ARGUMENT, SUPERTYPE_ARGUMENT, SUPERTYPE)
else -> {
LOG.error("Unknown classifier: ${classifier()}")
true
}
}
}
override fun isNullable(): Boolean = _nullable()
@@ -78,11 +78,7 @@ public class JavaTypeTransformer {
) {
if (type instanceof JavaClassifierType) {
JavaClassifierType classifierType = (JavaClassifierType) type;
JetType jetType = transformClassifierType(classifierType, howThisTypeIsUsed, typeVariableResolver);
if (jetType == null) {
return ErrorUtils.createErrorType("Unresolved java classifier: " + classifierType.getPresentableText());
}
return jetType;
return transformClassifierType(classifierType, howThisTypeIsUsed, typeVariableResolver);
}
else if (type instanceof JavaPrimitiveType) {
String canonicalText = ((JavaPrimitiveType) type).getCanonicalText();
@@ -98,58 +94,55 @@ public class JavaTypeTransformer {
}
}
@Nullable
@NotNull
private JetType transformClassifierType(
@NotNull JavaClassifierType classifierType,
@NotNull TypeUsage howThisTypeIsUsed,
@NotNull TypeVariableResolver typeVariableResolver
) {
JavaClassifier javaClassifier = classifierType.getClassifier();
if (javaClassifier == null) {
return null;
}
if (javaClassifier instanceof JavaTypeParameter) {
return transformTypeParameter((JavaTypeParameter) javaClassifier, howThisTypeIsUsed, typeVariableResolver);
}
else if (javaClassifier instanceof JavaClass) {
FqName fqName = ((JavaClass) javaClassifier).getFqName();
assert fqName != null : "Class type should have a FQ name: " + javaClassifier;
return transformClassType(fqName, classifierType, howThisTypeIsUsed, typeVariableResolver);
return transformTypeParameter((JavaTypeParameter) javaClassifier, classifierType, howThisTypeIsUsed, typeVariableResolver);
}
else {
throw new UnsupportedOperationException("Unsupported classifier: " + javaClassifier);
return transformClassType(javaClassifier, classifierType, howThisTypeIsUsed, typeVariableResolver);
}
}
@Nullable
@NotNull
private JetType transformTypeParameter(
@NotNull JavaTypeParameter typeParameter,
@NotNull JavaClassifierType classifierType,
@NotNull TypeUsage howThisTypeIsUsed,
@NotNull TypeVariableResolver typeVariableResolver
) {
// In Java: ArrayList<T>
// In Kotlin: ArrayList<T>, not ArrayList<T?>
// nullability will be taken care of in individual member signatures
boolean nullable = !EnumSet.of(TYPE_ARGUMENT, UPPER_BOUND, SUPERTYPE_ARGUMENT).contains(howThisTypeIsUsed);
JavaTypeParameterListOwner owner = typeParameter.getOwner();
if (owner instanceof JavaMethod && ((JavaMethod) owner).isConstructor()) {
Set<JetType> supertypesJet = new HashSet<JetType>();
for (JavaClassifierType supertype : typeParameter.getUpperBounds()) {
supertypesJet.add(transformToType(supertype, UPPER_BOUND, typeVariableResolver));
}
return TypeUtils.intersect(JetTypeChecker.INSTANCE, supertypesJet);
JetType intersection = TypeUtils.intersect(JetTypeChecker.INSTANCE, supertypesJet);
if (intersection == null) {
return createErrorClassifierType(classifierType, nullable);
}
return intersection;
}
TypeParameterDescriptor descriptor = typeVariableResolver.getTypeVariable(typeParameter.getName());
if (descriptor == null) return null;
// In Java: ArrayList<T>
// In Kotlin: ArrayList<T>, not ArrayList<T?>
// nullability will be taken care of in individual member signatures
boolean nullable = !EnumSet.of(TYPE_ARGUMENT, UPPER_BOUND, SUPERTYPE_ARGUMENT).contains(howThisTypeIsUsed);
if (descriptor == null) return createErrorClassifierType(classifierType, nullable);
return TypeUtils.makeNullableIfNeeded(descriptor.getDefaultType(), nullable);
}
@Nullable
@NotNull
private JetType transformClassType(
@NotNull FqName fqName,
@Nullable JavaClassifier javaClassifier,
@NotNull JavaClassifierType classifierType,
@NotNull TypeUsage howThisTypeIsUsed,
@NotNull TypeVariableResolver typeVariableResolver
@@ -157,13 +150,18 @@ public class JavaTypeTransformer {
// 'L extends List<T>' in Java is a List<T> in Kotlin, not a List<T?>
boolean nullable = !EnumSet.of(TYPE_ARGUMENT, SUPERTYPE_ARGUMENT, SUPERTYPE).contains(howThisTypeIsUsed);
if (javaClassifier == null) return createErrorClassifierType(classifierType, nullable);
FqName fqName = ((JavaClass) javaClassifier).getFqName();
assert fqName != null : "Class type should have a FQ name: " + javaClassifier;
ClassDescriptor classData = JavaToKotlinClassMap.getInstance().mapKotlinClass(fqName, howThisTypeIsUsed);
if (classData == null) {
classData = classResolver.resolveClass(fqName, INCLUDE_KOTLIN_SOURCES);
}
if (classData == null) {
return null;
return createErrorClassifierType(classifierType, nullable);
}
List<TypeProjection> arguments = new ArrayList<TypeProjection>();
@@ -221,6 +219,14 @@ public class JavaTypeTransformer {
classData.getMemberScope(arguments));
}
@NotNull
private static JetType createErrorClassifierType(JavaClassifierType classifierType, boolean nullable) {
return TypeUtils.makeNullableAsSpecified(
ErrorUtils.createErrorType("Unresolved java classifier: " + classifierType.getPresentableText()),
nullable
);
}
@NotNull
private JetType transformArrayType(
@NotNull JavaArrayType arrayType,