Corrected util method getFunctionTypeForSamType for flexible types.

This commit is contained in:
Stanislav Erokhin
2016-06-02 06:17:33 +03:00
parent a6da15f8e2
commit dd362f683c
6 changed files with 31 additions and 19 deletions
@@ -25,7 +25,7 @@ import org.jetbrains.kotlin.load.java.descriptors.JavaConstructorDescriptor
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaClassDescriptor import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaClassDescriptor
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.SimpleType
object SamConversionResolverImpl : SamConversionResolver { object SamConversionResolverImpl : SamConversionResolver {
override fun resolveSamConstructor(constructorOwner: DeclarationDescriptor, classifier: () -> ClassifierDescriptor?): SamConstructorDescriptor? { override fun resolveSamConstructor(constructorOwner: DeclarationDescriptor, classifier: () -> ClassifierDescriptor?): SamConstructorDescriptor? {
@@ -44,7 +44,7 @@ object SamConversionResolverImpl : SamConversionResolver {
} }
} }
override fun resolveFunctionTypeIfSamInterface(classDescriptor: JavaClassDescriptor): KotlinType? { override fun resolveFunctionTypeIfSamInterface(classDescriptor: JavaClassDescriptor): SimpleType? {
val abstractMethod = SingleAbstractMethodUtils.getSingleAbstractMethodOrNull(classDescriptor) ?: return null val abstractMethod = SingleAbstractMethodUtils.getSingleAbstractMethodOrNull(classDescriptor) ?: return null
return SingleAbstractMethodUtils.getFunctionTypeForAbstractMethod(abstractMethod) return SingleAbstractMethodUtils.getFunctionTypeForAbstractMethod(abstractMethod)
} }
@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations;
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl; import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl;
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl; import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl;
import org.jetbrains.kotlin.load.java.descriptors.*; import org.jetbrains.kotlin.load.java.descriptors.*;
import org.jetbrains.kotlin.load.java.lazy.types.LazyJavaTypeResolver;
import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.resolve.DescriptorUtils; import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.FunctionTypeResolveUtilsKt; import org.jetbrains.kotlin.resolve.FunctionTypeResolveUtilsKt;
@@ -55,15 +54,31 @@ public class SingleAbstractMethodUtils {
@Nullable @Nullable
public static KotlinType getFunctionTypeForSamType(@NotNull KotlinType samType) { public static KotlinType getFunctionTypeForSamType(@NotNull KotlinType samType) {
UnwrappedType unwrappedType = samType.unwrap();
if (unwrappedType instanceof FlexibleType) {
SimpleType lower = getFunctionTypeForSamType(((FlexibleType) unwrappedType).getLowerBound());
SimpleType upper = getFunctionTypeForSamType(((FlexibleType) unwrappedType).getUpperBound());
assert (lower == null) == (upper == null) : "Illegal flexible type: " + unwrappedType;
if (upper == null) return null;
return KotlinTypeFactory.flexibleType(lower, upper);
}
else {
return getFunctionTypeForSamType((SimpleType) unwrappedType);
}
}
@Nullable
private static SimpleType getFunctionTypeForSamType(@NotNull SimpleType samType) {
// e.g. samType == Comparator<String>? // e.g. samType == Comparator<String>?
ClassifierDescriptor classifier = samType.getConstructor().getDeclarationDescriptor(); ClassifierDescriptor classifier = samType.getConstructor().getDeclarationDescriptor();
if (classifier instanceof JavaClassDescriptor) { if (classifier instanceof JavaClassDescriptor) {
// Function2<T, T, Int> // Function2<T, T, Int>
KotlinType functionTypeDefault = ((JavaClassDescriptor) classifier).getFunctionTypeForSamInterface(); SimpleType functionTypeDefault = ((JavaClassDescriptor) classifier).getFunctionTypeForSamInterface();
if (functionTypeDefault != null) { if (functionTypeDefault != null) {
KotlinType noProjectionsSamType = SingleAbstractMethodUtilsKt.nonProjectionParametrization(samType); SimpleType noProjectionsSamType = SingleAbstractMethodUtilsKt.nonProjectionParametrization(samType);
if (noProjectionsSamType == null) return null; if (noProjectionsSamType == null) return null;
// Function2<String, String, Int>? // Function2<String, String, Int>?
@@ -71,19 +86,16 @@ public class SingleAbstractMethodUtils {
assert type != null : "Substitution based on type with no projections '" + noProjectionsSamType + assert type != null : "Substitution based on type with no projections '" + noProjectionsSamType +
"' should not end with conflict"; "' should not end with conflict";
if (FlexibleTypesKt.isNullabilityFlexible(samType)) { SimpleType simpleType = KotlinTypeKt.asSimpleType(type);
SimpleType simpleType = KotlinTypeKt.asSimpleType(type);
return KotlinTypeFactory.flexibleType(simpleType, simpleType.makeNullableAsSpecified(true));
}
return TypeUtils.makeNullableAsSpecified(type, samType.isMarkedNullable()); return simpleType.makeNullableAsSpecified(samType.isMarkedNullable());
} }
} }
return null; return null;
} }
@NotNull @NotNull
public static KotlinType getFunctionTypeForAbstractMethod(@NotNull FunctionDescriptor function) { public static SimpleType getFunctionTypeForAbstractMethod(@NotNull FunctionDescriptor function) {
KotlinType returnType = function.getReturnType(); KotlinType returnType = function.getReturnType();
assert returnType != null : "function is not initialized: " + function; assert returnType != null : "function is not initialized: " + function;
List<ValueParameterDescriptor> valueParameters = function.getValueParameters(); List<ValueParameterDescriptor> valueParameters = function.getValueParameters();
@@ -16,7 +16,7 @@
package org.jetbrains.kotlin.load.java.sam package org.jetbrains.kotlin.load.java.sam
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.SimpleType
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.replace import org.jetbrains.kotlin.types.replace
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
@@ -31,7 +31,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.check
// - Otherwise no non-projection parametrization exists for such 'samType' // - Otherwise no non-projection parametrization exists for such 'samType'
// //
// See Non-wildcard parametrization in JLS 8 p.9.9 for clarification // See Non-wildcard parametrization in JLS 8 p.9.9 for clarification
internal fun nonProjectionParametrization(samType: KotlinType): KotlinType? { internal fun nonProjectionParametrization(samType: SimpleType): SimpleType? {
if (samType.arguments.none { it.projectionKind != Variance.INVARIANT }) return samType if (samType.arguments.none { it.projectionKind != Variance.INVARIANT }) return samType
val parameters = samType.constructor.parameters val parameters = samType.constructor.parameters
val parametersSet = parameters.toSet() val parametersSet = parameters.toSet()
@@ -21,18 +21,18 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.SimpleType
interface SamConversionResolver { interface SamConversionResolver {
companion object EMPTY : SamConversionResolver { companion object EMPTY : SamConversionResolver {
override fun <D : FunctionDescriptor> resolveSamAdapter(original: D) = null override fun <D : FunctionDescriptor> resolveSamAdapter(original: D) = null
override fun resolveSamConstructor(constructorOwner: DeclarationDescriptor, classifier: () -> ClassifierDescriptor?) = null override fun resolveSamConstructor(constructorOwner: DeclarationDescriptor, classifier: () -> ClassifierDescriptor?) = null
override fun resolveFunctionTypeIfSamInterface(classDescriptor: JavaClassDescriptor): KotlinType? = null override fun resolveFunctionTypeIfSamInterface(classDescriptor: JavaClassDescriptor): SimpleType? = null
} }
fun resolveSamConstructor(constructorOwner: DeclarationDescriptor, classifier: () -> ClassifierDescriptor?): SamConstructorDescriptor? fun resolveSamConstructor(constructorOwner: DeclarationDescriptor, classifier: () -> ClassifierDescriptor?): SamConstructorDescriptor?
fun <D : FunctionDescriptor> resolveSamAdapter(original: D): D? fun <D : FunctionDescriptor> resolveSamAdapter(original: D): D?
fun resolveFunctionTypeIfSamInterface(classDescriptor: JavaClassDescriptor): KotlinType? fun resolveFunctionTypeIfSamInterface(classDescriptor: JavaClassDescriptor): SimpleType?
} }
@@ -18,9 +18,9 @@ package org.jetbrains.kotlin.load.java.descriptors;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.ClassDescriptor; import org.jetbrains.kotlin.descriptors.ClassDescriptor;
import org.jetbrains.kotlin.types.KotlinType; import org.jetbrains.kotlin.types.SimpleType;
public interface JavaClassDescriptor extends ClassDescriptor { public interface JavaClassDescriptor extends ClassDescriptor {
@Nullable @Nullable
KotlinType getFunctionTypeForSamInterface(); SimpleType getFunctionTypeForSamInterface();
} }
@@ -126,7 +126,7 @@ class LazyJavaClassDescriptor(
override fun getDeclaredTypeParameters() = declaredParameters() override fun getDeclaredTypeParameters() = declaredParameters()
override fun getFunctionTypeForSamInterface(): KotlinType? = functionTypeForSamInterface() override fun getFunctionTypeForSamInterface(): SimpleType? = functionTypeForSamInterface()
override fun isCompanionObject() = false override fun isCompanionObject() = false