Render nullability for error types properly
This commit is contained in:
+9
-2
@@ -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()
|
||||
|
||||
+33
-27
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user