Refactoring: move utils to create & initialize SAM constructors to core

This commit is contained in:
Mikhail Zarechenskiy
2020-04-09 01:04:42 +03:00
parent 04223f5711
commit e9e21caeaf
3 changed files with 166 additions and 130 deletions
@@ -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
);
}
}
@@ -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)