Refactoring: generify and remove duplicated code

This commit is contained in:
Mikhail Zarechenskiy
2020-01-27 10:40:09 +03:00
parent 4e3c27c4ec
commit 0530f9ed1c
8 changed files with 108 additions and 102 deletions
@@ -5,9 +5,16 @@
package org.jetbrains.kotlin.load.java.sam
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
import org.jetbrains.kotlin.load.java.descriptors.JavaClassConstructorDescriptor
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
import org.jetbrains.kotlin.resolve.sam.SamConversionOracle
import org.jetbrains.kotlin.resolve.sam.SamConversionResolver
import org.jetbrains.kotlin.synthetic.hasJavaOriginInHierarchy
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.SimpleType
object JavaBasedSamConversionResolver : SamConversionResolver {
@@ -15,4 +22,20 @@ object JavaBasedSamConversionResolver : SamConversionResolver {
if (classDescriptor !is JavaClassDescriptor) return null
return classDescriptor.defaultFunctionTypeForSamInterface
}
}
object JavaBasedSamConversionOracle : SamConversionOracle {
override fun shouldRunSamConversionForFunction(candidate: CallableDescriptor): Boolean {
val functionDescriptor = candidate.original as? FunctionDescriptor ?: return false
if (functionDescriptor is TypeAliasConstructorDescriptor &&
functionDescriptor.underlyingConstructorDescriptor is JavaClassConstructorDescriptor
) return true
return functionDescriptor.hasJavaOriginInHierarchy()
}
override fun isPossibleSamType(samType: KotlinType): Boolean {
val descriptor = samType.constructor.declarationDescriptor
return descriptor is ClassDescriptor && (descriptor.isFun || descriptor is JavaClassDescriptor)
}
}
@@ -8,13 +8,7 @@ package org.jetbrains.kotlin.load.java.sam
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
import org.jetbrains.kotlin.load.java.descriptors.JavaClassConstructorDescriptor
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
import org.jetbrains.kotlin.resolve.sam.SamConversionOracle
import org.jetbrains.kotlin.synthetic.hasJavaOriginInHierarchy
import org.jetbrains.kotlin.types.KotlinType
class JvmSamConversionOracle(
@@ -23,16 +17,9 @@ class JvmSamConversionOracle(
override fun shouldRunSamConversionForFunction(candidate: CallableDescriptor): Boolean {
if (languageVersionSettings.supportsFeature(LanguageFeature.SamConversionForKotlinFunctions)) return true
val functionDescriptor = candidate.original as? FunctionDescriptor ?: return false
if (functionDescriptor is TypeAliasConstructorDescriptor &&
functionDescriptor.underlyingConstructorDescriptor is JavaClassConstructorDescriptor) return true
return functionDescriptor.hasJavaOriginInHierarchy()
return JavaBasedSamConversionOracle.shouldRunSamConversionForFunction(candidate)
}
override fun isPossibleSamType(samType: KotlinType): Boolean {
val descriptor = samType.constructor.declarationDescriptor
return descriptor is ClassDescriptor && (descriptor.isFun || descriptor is JavaClassDescriptor)
}
override fun isPossibleSamType(samType: KotlinType): Boolean =
JavaBasedSamConversionOracle.isPossibleSamType(samType)
}
@@ -24,77 +24,33 @@ 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.JavaClassDescriptor;
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.sam.SamConversionResolver;
import org.jetbrains.kotlin.resolve.jvm.JavaResolverUtils;
import org.jetbrains.kotlin.resolve.sam.SamConversionOracle;
import org.jetbrains.kotlin.resolve.sam.SamConversionResolver;
import org.jetbrains.kotlin.resolve.sam.SamConversionResolverImplKt;
import org.jetbrains.kotlin.types.*;
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;
import static org.jetbrains.kotlin.resolve.sam.SamConversionResolverImplKt.nonProjectionParametrization;
import static org.jetbrains.kotlin.types.Variance.IN_VARIANCE;
public class SingleAbstractMethodUtils {
private SingleAbstractMethodUtils() {
}
@Nullable
public static KotlinType getFunctionTypeForSamType(@NotNull KotlinType samType, @NotNull SamConversionResolver samResolver) {
UnwrappedType unwrappedType = samType.unwrap();
if (unwrappedType instanceof FlexibleType) {
SimpleType lower = getFunctionTypeForSamType(((FlexibleType) unwrappedType).getLowerBound(), samResolver);
SimpleType upper = getFunctionTypeForSamType(((FlexibleType) unwrappedType).getUpperBound(), samResolver);
assert (lower == null) == (upper == null) : "Illegal flexible type: " + unwrappedType;
if (upper == null) return null;
return KotlinTypeFactory.flexibleType(lower, upper);
}
else {
return getFunctionTypeForSamType((SimpleType) unwrappedType, samResolver);
}
}
@Nullable
private static SimpleType getFunctionTypeForSamType(@NotNull SimpleType samType, @NotNull SamConversionResolver samResolver) {
// e.g. samType == Comparator<String>?
ClassifierDescriptor classifier = samType.getConstructor().getDeclarationDescriptor();
if (classifier instanceof ClassDescriptor) {
ClassDescriptor descriptor = (ClassDescriptor) classifier;
if (!(descriptor instanceof JavaClassDescriptor) && !descriptor.isFun()) return null;
// Function2<T, T, Int>
SimpleType functionTypeDefault = samResolver.resolveFunctionTypeIfSamInterface(descriptor);
if (functionTypeDefault != null) {
SimpleType noProjectionsSamType = nonProjectionParametrization(samType);
if (noProjectionsSamType == null) return null;
// Function2<String, String, Int>?
KotlinType type = TypeSubstitutor.create(noProjectionsSamType).substitute(functionTypeDefault, IN_VARIANCE);
assert type != null : "Substitution based on type with no projections '" + noProjectionsSamType +
"' should not end with conflict";
SimpleType simpleType = TypeSubstitutionKt.asSimpleType(type);
return simpleType.makeNullableAsSpecified(samType.isMarkedNullable());
}
}
return null;
}
@NotNull
public static SamConstructorDescriptor createSamConstructorFunction(
@NotNull DeclarationDescriptor owner,
@NotNull ClassDescriptor samInterface,
@NotNull SamConversionResolver samResolver
@NotNull SamConversionResolver samResolver,
@NotNull SamConversionOracle samConversionOracle
) {
assert SamConversionResolverImplKt.getSingleAbstractMethodOrNull(samInterface) != null : samInterface;
@@ -102,7 +58,7 @@ public class SingleAbstractMethodUtils {
List<TypeParameterDescriptor> samTypeParameters = samInterface.getTypeConstructor().getParameters();
SimpleType unsubstitutedSamType = samInterface.getDefaultType();
initializeSamConstructorDescriptor(samInterface, result, samTypeParameters, unsubstitutedSamType, samResolver);
initializeSamConstructorDescriptor(samInterface, result, samTypeParameters, unsubstitutedSamType, samResolver, samConversionOracle);
return result;
}
@@ -112,11 +68,13 @@ public class SingleAbstractMethodUtils {
@NotNull SimpleFunctionDescriptorImpl samConstructor,
@NotNull List<TypeParameterDescriptor> samTypeParameters,
@NotNull KotlinType unsubstitutedSamType,
@NotNull SamConversionResolver samResolver
@NotNull SamConversionResolver samResolver,
@NotNull SamConversionOracle samConversionOracle
) {
TypeParameters typeParameters = recreateAndInitializeTypeParameters(samTypeParameters, samConstructor);
KotlinType parameterTypeUnsubstituted = getFunctionTypeForSamType(unsubstitutedSamType, samResolver);
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 +
@@ -146,14 +104,15 @@ public class SingleAbstractMethodUtils {
public static SamConstructorDescriptor createTypeAliasSamConstructorFunction(
@NotNull TypeAliasDescriptor typeAliasDescriptor,
@NotNull SamConstructorDescriptor underlyingSamConstructor,
@NotNull SamConversionResolver samResolver
@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);
initializeSamConstructorDescriptor(samInterface, result, samTypeParameters, unsubstitutedSamType, samResolver, samConversionOracle);
return result;
}
@@ -169,7 +128,9 @@ public class SingleAbstractMethodUtils {
ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
if (descriptor instanceof ClassDescriptor && ((ClassDescriptor) descriptor).isFun()) return true;
return getFunctionTypeForSamType(type, JavaBasedSamConversionResolver.INSTANCE) != null;
return SamConversionResolverImplKt.getFunctionTypeForSamType(
type, JavaBasedSamConversionResolver.INSTANCE, JavaBasedSamConversionOracle.INSTANCE
) != null;
}
public static boolean isSamAdapterNecessary(@NotNull FunctionDescriptor fun) {
@@ -184,7 +145,8 @@ public class SingleAbstractMethodUtils {
@NotNull
public static SamAdapterDescriptor<JavaMethodDescriptor> createSamAdapterFunction(
@NotNull JavaMethodDescriptor original,
@NotNull SamConversionResolver samResolver
@NotNull SamConversionResolver samResolver,
@NotNull SamConversionOracle samConversionOracle
) {
SamAdapterFunctionDescriptor result = new SamAdapterFunctionDescriptor(original);
return initSamAdapter(original, result, new FunctionInitializer() {
@@ -204,13 +166,14 @@ public class SingleAbstractMethodUtils {
original.getVisibility()
);
}
}, samResolver);
}, samResolver, samConversionOracle);
}
@NotNull
public static SamAdapterDescriptor<JavaClassConstructorDescriptor> createSamAdapterConstructor(
@NotNull JavaClassConstructorDescriptor original,
@NotNull SamConversionResolver samResolver
@NotNull SamConversionResolver samResolver,
@NotNull SamConversionOracle samConversionOracle
) {
SamAdapterClassConstructorDescriptor result = new SamAdapterClassConstructorDescriptor(original);
return initSamAdapter(original, result, new FunctionInitializer() {
@@ -223,7 +186,7 @@ public class SingleAbstractMethodUtils {
result.initialize(valueParameters, original.getVisibility());
result.setReturnType(returnType);
}
}, samResolver);
}, samResolver, samConversionOracle);
}
@NotNull
@@ -231,7 +194,8 @@ public class SingleAbstractMethodUtils {
@NotNull F original,
@NotNull SamAdapterDescriptor<F> adapter,
@NotNull FunctionInitializer initializer,
@NotNull SamConversionResolver samResolver
@NotNull SamConversionResolver samResolver,
@NotNull SamConversionOracle samConversionOracle
) {
TypeParameters typeParameters = recreateAndInitializeTypeParameters(original.getTypeParameters(), adapter);
@@ -244,7 +208,8 @@ public class SingleAbstractMethodUtils {
", substitutor = " + substitutor;
List<ValueParameterDescriptor> valueParameters = createValueParametersForSamAdapter(original, adapter, substitutor, samResolver);
List<ValueParameterDescriptor> valueParameters =
createValueParametersForSamAdapter(original, adapter, substitutor, samResolver, samConversionOracle);
initializer.initialize(typeParameters.descriptors, valueParameters, returnType);
@@ -255,13 +220,14 @@ public class SingleAbstractMethodUtils {
@NotNull FunctionDescriptor original,
@NotNull FunctionDescriptor samAdapter,
@NotNull TypeSubstitutor substitutor,
@NotNull SamConversionResolver samResolver
@NotNull SamConversionResolver samResolver,
@NotNull SamConversionOracle samConversionOracle
) {
List<ValueParameterDescriptor> originalValueParameters = original.getValueParameters();
List<ValueParameterDescriptor> valueParameters = new ArrayList<>(originalValueParameters.size());
for (ValueParameterDescriptor originalParam : originalValueParameters) {
KotlinType originalType = originalParam.getType();
KotlinType functionType = getFunctionTypeForSamType(originalType, samResolver);
KotlinType functionType = SamConversionResolverImplKt.getFunctionTypeForSamType(originalType, samResolver, samConversionOracle);
KotlinType newTypeUnsubstituted = functionType != null ? functionType : originalType;
KotlinType newType = substitutor.substitute(newTypeUnsubstituted, Variance.IN_VARIANCE);
assert newType != null : "couldn't substitute type: " + newTypeUnsubstituted + ", substitutor = " + substitutor;
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.resolve.sam.SamConversionResolver
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
import org.jetbrains.kotlin.resolve.sam.SamConversionOracle
import org.jetbrains.kotlin.resolve.scopes.SyntheticScope
import org.jetbrains.kotlin.resolve.scopes.SyntheticScopes
import org.jetbrains.kotlin.storage.StorageManager
@@ -35,6 +36,7 @@ class JavaSyntheticScopes(
lookupTracker: LookupTracker,
languageVersionSettings: LanguageVersionSettings,
samConventionResolver: SamConversionResolver,
samConversionOracle: SamConversionOracle,
deprecationResolver: DeprecationResolver
) : SyntheticScopes {
override val scopes: Collection<SyntheticScope>
@@ -57,6 +59,7 @@ class JavaSyntheticScopes(
val samAdapterFunctionsScope = SamAdapterFunctionsScope(
storageManager,
samConventionResolver,
samConversionOracle,
deprecationResolver,
lookupTracker,
samViaSyntheticScopeDisabled = samConversionPerArgumentIsEnabled,
@@ -71,6 +74,7 @@ class JavaSyntheticScopes(
val forceEnabledSamAdapterFunctionsScope = SamAdapterFunctionsScope(
storageManager,
samConventionResolver,
samConversionOracle,
deprecationResolver,
lookupTracker,
samViaSyntheticScopeDisabled = false,
@@ -37,6 +37,7 @@ 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.SamConversionOracle
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.ResolutionScope
import org.jetbrains.kotlin.resolve.scopes.SyntheticScope
@@ -54,6 +55,7 @@ val SAM_LOOKUP_NAME = Name.special("<SAM-CONSTRUCTOR>")
class SamAdapterFunctionsScope(
storageManager: StorageManager,
private val samResolver: SamConversionResolver,
private val samConversionOracle: SamConversionOracle,
private val deprecationResolver: DeprecationResolver,
private val lookupTracker: LookupTracker,
private val samViaSyntheticScopeDisabled: Boolean,
@@ -68,17 +70,17 @@ class SamAdapterFunctionsScope(
private val samAdapterForStaticFunction =
storageManager.createMemoizedFunction<JavaMethodDescriptor, SamAdapterDescriptor<JavaMethodDescriptor>> { function ->
SingleAbstractMethodUtils.createSamAdapterFunction(function, samResolver)
SingleAbstractMethodUtils.createSamAdapterFunction(function, samResolver, samConversionOracle)
}
private val samConstructorForClassifier =
storageManager.createMemoizedFunction<ClassDescriptor, SamConstructorDescriptor> { classifier ->
SingleAbstractMethodUtils.createSamConstructorFunction(classifier.containingDeclaration, classifier, samResolver)
SingleAbstractMethodUtils.createSamConstructorFunction(classifier.containingDeclaration, classifier, samResolver, samConversionOracle)
}
private val samConstructorForJavaConstructor =
storageManager.createMemoizedFunction<JavaClassConstructorDescriptor, ClassConstructorDescriptor> { constructor ->
SingleAbstractMethodUtils.createSamAdapterConstructor(constructor, samResolver) as ClassConstructorDescriptor
SingleAbstractMethodUtils.createSamAdapterConstructor(constructor, samResolver, samConversionOracle) as ClassConstructorDescriptor
}
private val samConstructorForTypeAliasConstructor =
@@ -93,7 +95,7 @@ class SamAdapterFunctionsScope(
if (!SingleAbstractMethodUtils.isSamAdapterNecessary(function)) return null
if (function.returnType == null) return null
if (deprecationResolver.isHiddenInResolution(function)) return null
return SamAdapterExtensionFunctionDescriptorImpl.create(function, samResolver)
return SamAdapterExtensionFunctionDescriptorImpl.create(function, samResolver, samConversionOracle)
}
override fun getSyntheticMemberFunctions(
@@ -269,7 +271,8 @@ class SamAdapterFunctionsScope(
if (!SingleAbstractMethodUtils.isSamClassDescriptor(classDescriptor)) return null
return SingleAbstractMethodUtils.createTypeAliasSamConstructorFunction(
classifier, samConstructorForClassifier(classDescriptor), samResolver)
classifier, samConstructorForClassifier(classDescriptor), samResolver, samConversionOracle
)
}
private class SamAdapterExtensionFunctionDescriptorImpl(
@@ -289,7 +292,11 @@ class SamAdapterFunctionsScope(
}
companion object {
fun create(sourceFunction: FunctionDescriptor, samResolver: SamConversionResolver): SamAdapterExtensionFunctionDescriptorImpl {
fun create(
sourceFunction: FunctionDescriptor,
samResolver: SamConversionResolver,
samConversionOracle: SamConversionOracle
): SamAdapterExtensionFunctionDescriptorImpl {
val descriptor = SamAdapterExtensionFunctionDescriptorImpl(
sourceFunction.containingDeclaration,
null,
@@ -307,7 +314,8 @@ class SamAdapterFunctionsScope(
val returnType = typeSubstitutor.safeSubstitute(sourceFunction.returnType!!, Variance.INVARIANT)
val valueParameters = SingleAbstractMethodUtils.createValueParametersForSamAdapter(
sourceFunction, descriptor, typeSubstitutor, samResolver)
sourceFunction, descriptor, typeSubstitutor, samResolver, samConversionOracle
)
val visibility = syntheticVisibility(sourceFunction, isUsedForExtension = false)
@@ -312,7 +312,10 @@ private fun KotlinResolutionCandidate.getExpectedTypeWithSAMConversion(
!callComponents.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitVarargAsArrayAfterSamArgument)
if (generatingAdditionalSamCandidateIsEnabled) return null
if (!callComponents.samConversionOracle.shouldRunSamConversionForFunction(resolvedCall.candidateDescriptor)) return null
val samConversionOracle = callComponents.samConversionOracle
if (!callComponents.languageVersionSettings.supportsFeature(LanguageFeature.SamConversionForKotlinFunctions)) {
if (!samConversionOracle.shouldRunSamConversionForFunction(resolvedCall.candidateDescriptor)) return null
}
val argumentIsFunctional = when (argument) {
is SimpleKotlinCallArgument -> argument.receiver.stableType.isFunctionType
@@ -323,13 +326,12 @@ private fun KotlinResolutionCandidate.getExpectedTypeWithSAMConversion(
val originalExpectedType = argument.getExpectedType(candidateParameter.original, callComponents.languageVersionSettings)
if (!callComponents.samConversionOracle.isPossibleSamType(originalExpectedType)) return null
val convertedTypeByOriginal =
callComponents.samConversionResolver.getFunctionTypeForPossibleSamType(originalExpectedType) ?: return null
callComponents.samConversionResolver.getFunctionTypeForPossibleSamType(originalExpectedType, samConversionOracle) ?: return null
val candidateExpectedType = argument.getExpectedType(candidateParameter, callComponents.languageVersionSettings)
val convertedTypeByCandidate = callComponents.samConversionResolver.getFunctionTypeForPossibleSamType(candidateExpectedType)
val convertedTypeByCandidate =
callComponents.samConversionResolver.getFunctionTypeForPossibleSamType(candidateExpectedType, samConversionOracle)
assert(candidateExpectedType.constructor == originalExpectedType.constructor && convertedTypeByCandidate != null) {
"If original type is SAM type, then candidate should have same type constructor and corresponding function type\n" +
@@ -95,14 +95,20 @@ fun getFunctionTypeForAbstractMethod(
)
}
fun SamConversionResolver.getFunctionTypeForPossibleSamType(possibleSamType: UnwrappedType): UnwrappedType? =
getFunctionTypeForSamType(possibleSamType, this)?.unwrap()
fun SamConversionResolver.getFunctionTypeForPossibleSamType(
possibleSamType: UnwrappedType,
samConversionOracle: SamConversionOracle
): UnwrappedType? = getFunctionTypeForSamType(possibleSamType, this, samConversionOracle)?.unwrap()
fun getFunctionTypeForSamType(samType: KotlinType, samResolver: SamConversionResolver): KotlinType? {
fun getFunctionTypeForSamType(
samType: KotlinType,
samResolver: SamConversionResolver,
samConversionOracle: SamConversionOracle
): KotlinType? {
val unwrappedType = samType.unwrap()
if (unwrappedType is FlexibleType) {
val lower = getFunctionTypeForSamType(unwrappedType.lowerBound, samResolver)
val upper = getFunctionTypeForSamType(unwrappedType.upperBound, samResolver)
val lower = getFunctionTypeForSamType(unwrappedType.lowerBound, samResolver, samConversionOracle)
val upper = getFunctionTypeForSamType(unwrappedType.upperBound, samResolver, samConversionOracle)
assert((lower == null) == (upper == null)) { "Illegal flexible type: $unwrappedType" }
@@ -110,15 +116,21 @@ fun getFunctionTypeForSamType(samType: KotlinType, samResolver: SamConversionRes
return KotlinTypeFactory.flexibleType(lower, upper)
} else {
return getFunctionTypeForSamType(unwrappedType as SimpleType, samResolver)
return getFunctionTypeForSamType(unwrappedType as SimpleType, samResolver, samConversionOracle)
}
}
private fun getFunctionTypeForSamType(samType: SimpleType, samResolver: SamConversionResolver): SimpleType? {
private fun getFunctionTypeForSamType(
samType: SimpleType,
samResolver: SamConversionResolver,
samConversionOracle: SamConversionOracle
): SimpleType? {
// e.g. samType == Comparator<String>?
val classifier = samType.constructor.declarationDescriptor
if (classifier !is ClassDescriptor) return null
if (!samConversionOracle.isPossibleSamType(samType)) return null
// Function2<T, T, Int>
val functionTypeDefault = samResolver.resolveFunctionTypeIfSamInterface(classifier) ?: return null
val noProjectionsSamType = nonProjectionParametrization(samType) ?: return null
@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.callUtil.getValueArgumentsInParentheses
import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.resolve.sam.SamConversionOracle
import org.jetbrains.kotlin.resolve.sam.SamConversionResolver
import org.jetbrains.kotlin.resolve.sam.getFunctionTypeForPossibleSamType
import org.jetbrains.kotlin.types.KotlinType
@@ -129,6 +130,7 @@ fun KtCallExpression.canMoveLambdaOutsideParentheses(): Boolean {
val resolutionFacade = getResolutionFacade()
val samConversionTransformer = resolutionFacade.frontendService<SamConversionResolver>()
val samConversionOracle = resolutionFacade.frontendService<SamConversionOracle>()
val languageVersionSettings = resolutionFacade.frontendService<LanguageVersionSettings>()
val bindingContext = analyze(resolutionFacade, BodyResolveMode.PARTIAL)
@@ -143,6 +145,7 @@ fun KtCallExpression.canMoveLambdaOutsideParentheses(): Boolean {
it.allowsMoveOfLastParameterOutsideParentheses(
lambdaArgumentCount + referenceArgumentCount,
samConversionTransformer,
samConversionOracle,
languageVersionSettings.supportsFeature(LanguageFeature.NewInference)
)
}
@@ -156,6 +159,7 @@ fun KtCallExpression.canMoveLambdaOutsideParentheses(): Boolean {
private fun FunctionDescriptor.allowsMoveOfLastParameterOutsideParentheses(
lambdaAndCallableReferencesInOriginalCallCount: Int,
samConversionTransformer: SamConversionResolver,
samConversionOracle: SamConversionOracle,
newInferenceEnabled: Boolean
): Boolean {
fun KotlinType.allowsMoveOutsideParentheses(): Boolean {
@@ -167,7 +171,7 @@ private fun FunctionDescriptor.allowsMoveOfLastParameterOutsideParentheses(
// converted types, but in NI it is performed by conversions, so we check it explicitly
// Also note that 'newInferenceEnabled' is essentially a micro-optimization, as there are no
// harm in just calling 'samConversionTransformer' on all candidates.
return newInferenceEnabled && samConversionTransformer.getFunctionTypeForPossibleSamType(this.unwrap()) != null
return newInferenceEnabled && samConversionTransformer.getFunctionTypeForPossibleSamType(this.unwrap(), samConversionOracle) != null
}
val params = valueParameters