Refactoring: move utils to create & initialize SAM constructors to core
This commit is contained in:
+5
-123
@@ -17,104 +17,23 @@
|
||||
package org.jetbrains.kotlin.load.java.sam;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl;
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl;
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassConstructorDescriptor;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor;
|
||||
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaClassDescriptor;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.resolve.jvm.JavaResolverUtils;
|
||||
import org.jetbrains.kotlin.resolve.sam.*;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.kotlin.types.SimpleType;
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor;
|
||||
import org.jetbrains.kotlin.types.Variance;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class JavaSingleAbstractMethodUtils {
|
||||
private JavaSingleAbstractMethodUtils() {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static SamConstructorDescriptor createSamConstructorFunction(
|
||||
@NotNull DeclarationDescriptor owner,
|
||||
@NotNull ClassDescriptor samInterface,
|
||||
@NotNull SamConversionResolver samResolver,
|
||||
@NotNull SamConversionOracle samConversionOracle
|
||||
) {
|
||||
assert SamConversionResolverImplKt.getSingleAbstractMethodOrNull(samInterface) != null : samInterface;
|
||||
|
||||
SamConstructorDescriptorImpl result = new SamConstructorDescriptorImpl(owner, samInterface);
|
||||
|
||||
List<TypeParameterDescriptor> samTypeParameters = samInterface.getTypeConstructor().getParameters();
|
||||
SimpleType unsubstitutedSamType = samInterface.getDefaultType();
|
||||
initializeSamConstructorDescriptor(samInterface, result, samTypeParameters, unsubstitutedSamType, samResolver, samConversionOracle);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void initializeSamConstructorDescriptor(
|
||||
@NotNull ClassDescriptor samInterface,
|
||||
@NotNull SimpleFunctionDescriptorImpl samConstructor,
|
||||
@NotNull List<TypeParameterDescriptor> samTypeParameters,
|
||||
@NotNull KotlinType unsubstitutedSamType,
|
||||
@NotNull SamConversionResolver samResolver,
|
||||
@NotNull SamConversionOracle samConversionOracle
|
||||
) {
|
||||
TypeParameters typeParameters = recreateAndInitializeTypeParameters(samTypeParameters, samConstructor);
|
||||
|
||||
KotlinType parameterTypeUnsubstituted =
|
||||
SamConversionResolverImplKt.getFunctionTypeForSamType(unsubstitutedSamType, samResolver, samConversionOracle);
|
||||
assert parameterTypeUnsubstituted != null : "couldn't get function type for SAM type " + unsubstitutedSamType;
|
||||
KotlinType parameterType = typeParameters.substitutor.substitute(parameterTypeUnsubstituted, Variance.IN_VARIANCE);
|
||||
assert parameterType != null : "couldn't substitute type: " + parameterTypeUnsubstituted +
|
||||
", substitutor = " + typeParameters.substitutor;
|
||||
ValueParameterDescriptor parameter = new ValueParameterDescriptorImpl(
|
||||
samConstructor, null, 0, Annotations.Companion.getEMPTY(), Name.identifier("function"), parameterType,
|
||||
/* declaresDefaultValue = */ false,
|
||||
/* isCrossinline = */ false,
|
||||
/* isNoinline = */ false,
|
||||
null, SourceElement.NO_SOURCE);
|
||||
|
||||
KotlinType returnType = typeParameters.substitutor.substitute(unsubstitutedSamType, Variance.OUT_VARIANCE);
|
||||
assert returnType != null : "couldn't substitute type: " + unsubstitutedSamType +
|
||||
", substitutor = " + typeParameters.substitutor;
|
||||
|
||||
samConstructor.initialize(
|
||||
null,
|
||||
null,
|
||||
typeParameters.descriptors,
|
||||
Collections.singletonList(parameter),
|
||||
returnType,
|
||||
Modality.FINAL,
|
||||
samInterface.getVisibility()
|
||||
);
|
||||
}
|
||||
|
||||
public static SamConstructorDescriptor createTypeAliasSamConstructorFunction(
|
||||
@NotNull TypeAliasDescriptor typeAliasDescriptor,
|
||||
@NotNull SamConstructorDescriptor underlyingSamConstructor,
|
||||
@NotNull SamConversionResolver samResolver,
|
||||
@NotNull SamConversionOracle samConversionOracle
|
||||
) {
|
||||
SamTypeAliasConstructorDescriptorImpl result = new SamTypeAliasConstructorDescriptorImpl(typeAliasDescriptor, underlyingSamConstructor);
|
||||
|
||||
ClassDescriptor samInterface = underlyingSamConstructor.getBaseDescriptorForSynthetic();
|
||||
List<TypeParameterDescriptor> samTypeParameters = typeAliasDescriptor.getTypeConstructor().getParameters();
|
||||
SimpleType unsubstitutedSamType = typeAliasDescriptor.getExpandedType();
|
||||
initializeSamConstructorDescriptor(samInterface, result, samTypeParameters, unsubstitutedSamType, samResolver, samConversionOracle);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static boolean isSamClassDescriptor(@NotNull ClassDescriptor descriptor) {
|
||||
if (descriptor.isFun()) return true;
|
||||
if (descriptor instanceof LazyJavaClassDescriptor && descriptor.getDefaultFunctionTypeForSamInterface() != null) return true;
|
||||
@@ -195,17 +114,17 @@ public class JavaSingleAbstractMethodUtils {
|
||||
@NotNull SamConversionResolver samResolver,
|
||||
@NotNull SamConversionOracle samConversionOracle
|
||||
) {
|
||||
TypeParameters typeParameters;
|
||||
SamConstructorTypeParameters typeParameters;
|
||||
if (adapter instanceof SamAdapterClassConstructorDescriptor) {
|
||||
typeParameters = new TypeParameters(original.getTypeParameters(), TypeSubstitutor.EMPTY);
|
||||
typeParameters = new SamConstructorTypeParameters(original.getTypeParameters(), TypeSubstitutor.EMPTY);
|
||||
} else {
|
||||
typeParameters = recreateAndInitializeTypeParameters(original.getTypeParameters(), adapter);
|
||||
typeParameters = SamConstructorUtilsKt.recreateAndInitializeTypeParameters(original.getTypeParameters(), adapter);
|
||||
}
|
||||
|
||||
KotlinType returnTypeUnsubstituted = original.getReturnType();
|
||||
assert returnTypeUnsubstituted != null : "Creating SAM adapter for not initialized original: " + original;
|
||||
|
||||
TypeSubstitutor substitutor = typeParameters.substitutor;
|
||||
TypeSubstitutor substitutor = typeParameters.getSubstitutor();
|
||||
KotlinType returnType = substitutor.substitute(returnTypeUnsubstituted, Variance.INVARIANT);
|
||||
assert returnType != null : "couldn't substitute type: " + returnTypeUnsubstituted +
|
||||
", substitutor = " + substitutor;
|
||||
@@ -214,7 +133,7 @@ public class JavaSingleAbstractMethodUtils {
|
||||
List<ValueParameterDescriptor> valueParameters =
|
||||
createValueParametersForSamAdapter(original, adapter, substitutor, samResolver, samConversionOracle);
|
||||
|
||||
initializer.initialize(typeParameters.descriptors, valueParameters, returnType);
|
||||
initializer.initialize(typeParameters.getDescriptors(), valueParameters, returnType);
|
||||
|
||||
return adapter;
|
||||
}
|
||||
@@ -248,41 +167,6 @@ public class JavaSingleAbstractMethodUtils {
|
||||
return valueParameters;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static TypeParameters recreateAndInitializeTypeParameters(
|
||||
@NotNull List<TypeParameterDescriptor> originalParameters,
|
||||
@Nullable DeclarationDescriptor newOwner
|
||||
) {
|
||||
Map<TypeParameterDescriptor, TypeParameterDescriptorImpl> traitToFunTypeParameters =
|
||||
JavaResolverUtils.recreateTypeParametersAndReturnMapping(originalParameters, newOwner);
|
||||
TypeSubstitutor typeParametersSubstitutor = JavaResolverUtils.createSubstitutorForTypeParameters(traitToFunTypeParameters);
|
||||
for (Map.Entry<TypeParameterDescriptor, TypeParameterDescriptorImpl> mapEntry : traitToFunTypeParameters.entrySet()) {
|
||||
TypeParameterDescriptor traitTypeParameter = mapEntry.getKey();
|
||||
TypeParameterDescriptorImpl funTypeParameter = mapEntry.getValue();
|
||||
|
||||
for (KotlinType upperBound : traitTypeParameter.getUpperBounds()) {
|
||||
KotlinType upperBoundSubstituted = typeParametersSubstitutor.substitute(upperBound, Variance.INVARIANT);
|
||||
assert upperBoundSubstituted != null : "couldn't substitute type: " + upperBound + ", substitutor = " + typeParametersSubstitutor;
|
||||
funTypeParameter.addUpperBound(upperBoundSubstituted);
|
||||
}
|
||||
|
||||
funTypeParameter.setInitialized();
|
||||
}
|
||||
|
||||
List<TypeParameterDescriptor> typeParameters = new ArrayList<>(traitToFunTypeParameters.values());
|
||||
return new TypeParameters(typeParameters, typeParametersSubstitutor);
|
||||
}
|
||||
|
||||
private static class TypeParameters {
|
||||
public final List<TypeParameterDescriptor> descriptors;
|
||||
public final TypeSubstitutor substitutor;
|
||||
|
||||
private TypeParameters(List<TypeParameterDescriptor> descriptors, TypeSubstitutor substitutor) {
|
||||
this.descriptors = descriptors;
|
||||
this.substitutor = substitutor;
|
||||
}
|
||||
}
|
||||
|
||||
private static abstract class FunctionInitializer {
|
||||
public abstract void initialize(
|
||||
@NotNull List<TypeParameterDescriptor> typeParameters,
|
||||
@@ -290,6 +174,4 @@ public class JavaSingleAbstractMethodUtils {
|
||||
@NotNull KotlinType returnType
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+3
-7
@@ -31,14 +31,11 @@ import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor
|
||||
import org.jetbrains.kotlin.load.java.sam.JavaSingleAbstractMethodUtils
|
||||
import org.jetbrains.kotlin.load.java.sam.SamAdapterDescriptor
|
||||
import org.jetbrains.kotlin.resolve.sam.SamConstructorDescriptor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.calls.components.isVararg
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.wrapWithCapturingSubstitution
|
||||
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
|
||||
import org.jetbrains.kotlin.resolve.sam.SAM_LOOKUP_NAME
|
||||
import org.jetbrains.kotlin.resolve.sam.SamConversionOracle
|
||||
import org.jetbrains.kotlin.resolve.sam.SamConversionResolver
|
||||
import org.jetbrains.kotlin.resolve.sam.*
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.kotlin.resolve.scopes.ResolutionScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.SyntheticScope
|
||||
@@ -75,8 +72,7 @@ class SamAdapterFunctionsScope(
|
||||
|
||||
private val samConstructorForClassifier =
|
||||
storageManager.createMemoizedFunction<ClassDescriptor, SamConstructorDescriptor> { classifier ->
|
||||
JavaSingleAbstractMethodUtils
|
||||
.createSamConstructorFunction(classifier.containingDeclaration, classifier, samResolver, samConversionOracle)
|
||||
createSamConstructorFunction(classifier.containingDeclaration, classifier, samResolver, samConversionOracle)
|
||||
}
|
||||
|
||||
private val samConstructorForJavaConstructor =
|
||||
@@ -271,7 +267,7 @@ class SamAdapterFunctionsScope(
|
||||
val classDescriptor = classifier.classDescriptor ?: return null
|
||||
if (!JavaSingleAbstractMethodUtils.isSamClassDescriptor(classDescriptor)) return null
|
||||
|
||||
return JavaSingleAbstractMethodUtils.createTypeAliasSamConstructorFunction(
|
||||
return createTypeAliasSamConstructorFunction(
|
||||
classifier, samConstructorForClassifier(classDescriptor), samResolver, samConversionOracle
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.sam
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations.Companion.EMPTY
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
|
||||
import java.util.*
|
||||
|
||||
fun createSamConstructorFunction(
|
||||
owner: DeclarationDescriptor,
|
||||
samInterface: ClassDescriptor,
|
||||
samResolver: SamConversionResolver,
|
||||
samConversionOracle: SamConversionOracle
|
||||
): SamConstructorDescriptor {
|
||||
assert(getSingleAbstractMethodOrNull(samInterface) != null) { samInterface }
|
||||
|
||||
val result = SamConstructorDescriptorImpl(owner, samInterface)
|
||||
val samTypeParameters = samInterface.typeConstructor.parameters
|
||||
val unsubstitutedSamType = samInterface.defaultType
|
||||
|
||||
initializeSamConstructorDescriptor(
|
||||
samInterface,
|
||||
result,
|
||||
samTypeParameters,
|
||||
unsubstitutedSamType,
|
||||
samResolver,
|
||||
samConversionOracle
|
||||
)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
fun createTypeAliasSamConstructorFunction(
|
||||
typeAliasDescriptor: TypeAliasDescriptor,
|
||||
underlyingSamConstructor: SamConstructorDescriptor,
|
||||
samResolver: SamConversionResolver,
|
||||
samConversionOracle: SamConversionOracle
|
||||
): SamConstructorDescriptor? {
|
||||
val result = SamTypeAliasConstructorDescriptorImpl(typeAliasDescriptor, underlyingSamConstructor)
|
||||
val samInterface = underlyingSamConstructor.baseDescriptorForSynthetic
|
||||
val samTypeParameters = typeAliasDescriptor.typeConstructor.parameters
|
||||
val unsubstitutedSamType = typeAliasDescriptor.expandedType
|
||||
|
||||
initializeSamConstructorDescriptor(
|
||||
samInterface,
|
||||
result,
|
||||
samTypeParameters,
|
||||
unsubstitutedSamType,
|
||||
samResolver,
|
||||
samConversionOracle
|
||||
)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun initializeSamConstructorDescriptor(
|
||||
samInterface: ClassDescriptor,
|
||||
samConstructor: SimpleFunctionDescriptorImpl,
|
||||
samTypeParameters: List<TypeParameterDescriptor>,
|
||||
unsubstitutedSamType: KotlinType,
|
||||
samResolver: SamConversionResolver,
|
||||
samConversionOracle: SamConversionOracle
|
||||
) {
|
||||
val typeParameters = recreateAndInitializeTypeParameters(samTypeParameters, samConstructor)
|
||||
val parameterTypeUnsubstituted = getFunctionTypeForSamType(unsubstitutedSamType, samResolver, samConversionOracle)
|
||||
?: error("couldn't get function type for SAM type $unsubstitutedSamType")
|
||||
|
||||
val parameterType =
|
||||
typeParameters.substitutor.substitute(parameterTypeUnsubstituted, Variance.IN_VARIANCE) ?: error(
|
||||
"couldn't substitute type: " + parameterTypeUnsubstituted +
|
||||
", substitutor = " + typeParameters.substitutor
|
||||
)
|
||||
|
||||
val parameter = ValueParameterDescriptorImpl(
|
||||
samConstructor, null, 0, EMPTY, Name.identifier("function"),
|
||||
parameterType,
|
||||
declaresDefaultValue = false,
|
||||
isCrossinline = false,
|
||||
isNoinline = false,
|
||||
varargElementType = null,
|
||||
source = SourceElement.NO_SOURCE
|
||||
)
|
||||
|
||||
val returnType =
|
||||
typeParameters.substitutor.substitute(unsubstitutedSamType, Variance.OUT_VARIANCE) ?: error(
|
||||
"couldn't substitute type: " + unsubstitutedSamType +
|
||||
", substitutor = " + typeParameters.substitutor
|
||||
)
|
||||
|
||||
samConstructor.initialize(
|
||||
null,
|
||||
null,
|
||||
typeParameters.descriptors, listOf(parameter),
|
||||
returnType,
|
||||
Modality.FINAL,
|
||||
samInterface.visibility
|
||||
)
|
||||
}
|
||||
|
||||
fun recreateAndInitializeTypeParameters(
|
||||
originalParameters: List<TypeParameterDescriptor>,
|
||||
newOwner: DeclarationDescriptor?
|
||||
): SamConstructorTypeParameters {
|
||||
val interfaceToFunTypeParameters = recreateTypeParametersAndReturnMapping(originalParameters, newOwner)
|
||||
|
||||
val typeParametersSubstitutor = createSubstitutorForTypeParameters(interfaceToFunTypeParameters)
|
||||
|
||||
for ((interfaceTypeParameter, funTypeParameter) in interfaceToFunTypeParameters) {
|
||||
for (upperBound in interfaceTypeParameter.upperBounds) {
|
||||
val upperBoundSubstituted =
|
||||
typeParametersSubstitutor.substitute(upperBound, Variance.INVARIANT)
|
||||
?: error("couldn't substitute type: $upperBound, substitutor = $typeParametersSubstitutor")
|
||||
funTypeParameter.addUpperBound(upperBoundSubstituted)
|
||||
}
|
||||
funTypeParameter.setInitialized()
|
||||
}
|
||||
return SamConstructorTypeParameters(interfaceToFunTypeParameters.values.toList(), typeParametersSubstitutor)
|
||||
}
|
||||
|
||||
fun recreateTypeParametersAndReturnMapping(
|
||||
originalParameters: List<TypeParameterDescriptor>,
|
||||
newOwner: DeclarationDescriptor?
|
||||
): Map<TypeParameterDescriptor, TypeParameterDescriptorImpl> =
|
||||
originalParameters.associateWith { typeParameter ->
|
||||
TypeParameterDescriptorImpl.createForFurtherModification(
|
||||
newOwner ?: typeParameter.containingDeclaration,
|
||||
typeParameter.annotations,
|
||||
typeParameter.isReified,
|
||||
typeParameter.variance,
|
||||
typeParameter.name,
|
||||
typeParameter.index,
|
||||
SourceElement.NO_SOURCE,
|
||||
typeParameter.storageManager
|
||||
)
|
||||
}
|
||||
|
||||
fun createSubstitutorForTypeParameters(
|
||||
originalToAltTypeParameters: Map<TypeParameterDescriptor, TypeParameterDescriptorImpl>
|
||||
): TypeSubstitutor {
|
||||
val typeSubstitutionContext =
|
||||
originalToAltTypeParameters
|
||||
.map { (key, value) -> key.typeConstructor to value.defaultType.asTypeProjection() }
|
||||
.toMap()
|
||||
|
||||
// TODO: Use IndexedParametersSubstitution here instead of map creation
|
||||
return TypeSubstitutor.create(typeSubstitutionContext)
|
||||
}
|
||||
|
||||
class SamConstructorTypeParameters(val descriptors: List<TypeParameterDescriptor>, val substitutor: TypeSubstitutor)
|
||||
Reference in New Issue
Block a user