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.SamConstructorDescriptor
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaClassDescriptor
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.SimpleType
object SamConversionResolverImpl : SamConversionResolver {
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
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.ValueParameterDescriptorImpl;
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.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.FunctionTypeResolveUtilsKt;
@@ -55,15 +54,31 @@ public class SingleAbstractMethodUtils {
@Nullable
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>?
ClassifierDescriptor classifier = samType.getConstructor().getDeclarationDescriptor();
if (classifier instanceof JavaClassDescriptor) {
// Function2<T, T, Int>
KotlinType functionTypeDefault = ((JavaClassDescriptor) classifier).getFunctionTypeForSamInterface();
SimpleType functionTypeDefault = ((JavaClassDescriptor) classifier).getFunctionTypeForSamInterface();
if (functionTypeDefault != null) {
KotlinType noProjectionsSamType = SingleAbstractMethodUtilsKt.nonProjectionParametrization(samType);
SimpleType noProjectionsSamType = SingleAbstractMethodUtilsKt.nonProjectionParametrization(samType);
if (noProjectionsSamType == null) return null;
// Function2<String, String, Int>?
@@ -71,19 +86,16 @@ public class SingleAbstractMethodUtils {
assert type != null : "Substitution based on type with no projections '" + noProjectionsSamType +
"' should not end with conflict";
if (FlexibleTypesKt.isNullabilityFlexible(samType)) {
SimpleType simpleType = KotlinTypeKt.asSimpleType(type);
return KotlinTypeFactory.flexibleType(simpleType, simpleType.makeNullableAsSpecified(true));
}
SimpleType simpleType = KotlinTypeKt.asSimpleType(type);
return TypeUtils.makeNullableAsSpecified(type, samType.isMarkedNullable());
return simpleType.makeNullableAsSpecified(samType.isMarkedNullable());
}
}
return null;
}
@NotNull
public static KotlinType getFunctionTypeForAbstractMethod(@NotNull FunctionDescriptor function) {
public static SimpleType getFunctionTypeForAbstractMethod(@NotNull FunctionDescriptor function) {
KotlinType returnType = function.getReturnType();
assert returnType != null : "function is not initialized: " + function;
List<ValueParameterDescriptor> valueParameters = function.getValueParameters();
@@ -16,7 +16,7 @@
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.replace
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'
//
// 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
val parameters = samType.constructor.parameters
val parametersSet = parameters.toSet()