Collect sam adapters for constructors in synthetic scope

Also place computation of synthetic constructors under one function
This commit is contained in:
Mikhail Zarechenskiy
2017-05-25 15:58:28 +03:00
parent 0adc8d9bfa
commit 011231f2ab
21 changed files with 174 additions and 77 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,35 +16,12 @@
package org.jetbrains.kotlin.load.java.sam
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.load.java.components.SamConversionResolver
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
import org.jetbrains.kotlin.load.java.descriptors.JavaClassConstructorDescriptor
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.storage.StorageManager
import org.jetbrains.kotlin.types.SimpleType
class SamConversionResolverImpl(val storageManager: StorageManager, val samWithReceiverResolver: SamWithReceiverResolver): SamConversionResolver {
override fun resolveSamConstructor(constructorOwner: DeclarationDescriptor, classifier: () -> ClassifierDescriptor?): SamConstructorDescriptor? {
val classifierDescriptor = classifier()
if (classifierDescriptor !is LazyJavaClassDescriptor || classifierDescriptor.functionTypeForSamInterface == null) return null
return SingleAbstractMethodUtils.createSamConstructorFunction(constructorOwner, classifierDescriptor)
}
@Suppress("UNCHECKED_CAST")
override fun <D : FunctionDescriptor> resolveSamAdapter(original: D): D? {
return when {
!SingleAbstractMethodUtils.isSamAdapterNecessary(original) -> null
original is JavaClassConstructorDescriptor -> SingleAbstractMethodUtils.createSamAdapterConstructor(original) as D
original is JavaMethodDescriptor -> SingleAbstractMethodUtils.createSamAdapterFunction(original) as D
else -> null
}
}
private val functionTypesForSamInterfaces = storageManager.createCacheWithNullableValues<JavaClassDescriptor, SimpleType>()
override fun resolveFunctionTypeIfSamInterface(classDescriptor: JavaClassDescriptor): SimpleType? {
@@ -180,9 +180,18 @@ class JavaSyntheticPropertiesScope(storageManager: StorageManager, private val l
override fun getSyntheticStaticFunctions(scope: ResolutionScope, name: Name, location: LookupLocation): Collection<FunctionDescriptor>
= emptyList()
override fun getSyntheticConstructors(scope: ResolutionScope, name: Name, location: LookupLocation): Collection<FunctionDescriptor>
= emptyList()
override fun getSyntheticStaticFunctions(scope: ResolutionScope): Collection<FunctionDescriptor>
= emptyList()
override fun getSyntheticConstructors(scope: ResolutionScope): Collection<FunctionDescriptor>
= emptyList()
override fun getSyntheticConstructor(constructor: ConstructorDescriptor): ConstructorDescriptor?
= null
private fun collectSyntheticPropertiesByName(result: SmartList<PropertyDescriptor>?, type: TypeConstructor, name: Name, processedTypes: MutableSet<TypeConstructor>?, location: LookupLocation): SmartList<PropertyDescriptor>? {
if (processedTypes != null && !processedTypes.add(type)) return result
@@ -21,12 +21,11 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings
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.TypeAliasConstructorDescriptor
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptorImpl
import org.jetbrains.kotlin.descriptors.synthetic.SyntheticMemberDescriptor
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor
import org.jetbrains.kotlin.load.java.descriptors.SamAdapterDescriptor
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor
import org.jetbrains.kotlin.load.java.descriptors.*
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaClassDescriptor
import org.jetbrains.kotlin.load.java.sam.SingleAbstractMethodUtils
import org.jetbrains.kotlin.name.Name
@@ -38,8 +37,6 @@ import org.jetbrains.kotlin.resolve.scopes.SyntheticScope
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.findCorrespondingSupertype
import java.util.*
import kotlin.collections.LinkedHashSet
import kotlin.properties.Delegates
interface SamAdapterExtensionFunctionDescriptor : FunctionDescriptor, SyntheticMemberDescriptor<FunctionDescriptor> {
@@ -61,7 +58,18 @@ class SamAdapterFunctionsScope(
private val samConstructorForClassifier =
storageManager.createMemoizedFunction<JavaClassDescriptor, SamConstructorDescriptor> { classifier ->
samConstructorForClassifierNotCached(classifier)
SingleAbstractMethodUtils.createSamConstructorFunction(classifier.containingDeclaration, classifier)
}
private val samConstructorForJavaConstructor =
storageManager.createMemoizedFunction<JavaClassConstructorDescriptor, ClassConstructorDescriptor> { constructor ->
SingleAbstractMethodUtils.createSamAdapterConstructor(constructor) as ClassConstructorDescriptor
}
private val samConstructorForTypeAliasConstructor =
storageManager.createMemoizedFunctionWithNullableValues<Pair<ClassConstructorDescriptor, TypeAliasDescriptor>, TypeAliasConstructorDescriptor> {
(constructor, typeAliasDescriptor) ->
TypeAliasConstructorDescriptorImpl.createIfAvailable(storageManager, typeAliasDescriptor, constructor)
}
private fun extensionForFunctionNotCached(function: FunctionDescriptor): FunctionDescriptor? {
@@ -73,10 +81,6 @@ class SamAdapterFunctionsScope(
return MyFunctionDescriptor.create(function)
}
private fun samConstructorForClassifierNotCached(classifier: JavaClassDescriptor): SamConstructorDescriptor {
return SingleAbstractMethodUtils.createSamConstructorFunction(classifier.containingDeclaration, classifier)
}
override fun getSyntheticMemberFunctions(receiverTypes: Collection<KotlinType>, name: Name, location: LookupLocation): Collection<FunctionDescriptor> {
var result: SmartList<FunctionDescriptor>? = null
for (type in receiverTypes) {
@@ -124,18 +128,41 @@ class SamAdapterFunctionsScope(
override fun getSyntheticExtensionProperties(receiverTypes: Collection<KotlinType>): Collection<PropertyDescriptor> = emptyList()
override fun getSyntheticStaticFunctions(scope: ResolutionScope, name: Name, location: LookupLocation): Collection<FunctionDescriptor> {
val classifier = scope.getContributedClassifier(name, location)
val samConstructor = classifier?.let { getSamConstructor(it) }
return getSamFunctions(scope.getContributedFunctions(name, location)) + listOfNotNull(samConstructor)
return getSamFunctions(scope.getContributedFunctions(name, location))
}
override fun getSyntheticConstructors(scope: ResolutionScope, name: Name, location: LookupLocation): Collection<FunctionDescriptor> {
val classifier = scope.getContributedClassifier(name, location) ?: return emptyList()
return getAllSamConstructors(classifier)
}
override fun getSyntheticStaticFunctions(scope: ResolutionScope): Collection<FunctionDescriptor> {
val samConstructors =
scope.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS)
.filterIsInstance<ClassifierDescriptor>()
.mapNotNull{ getSamConstructor(it) }
return getSamFunctions(scope.getContributedDescriptors(DescriptorKindFilter.FUNCTIONS))
}
return getSamFunctions(scope.getContributedDescriptors(DescriptorKindFilter.FUNCTIONS)) + samConstructors
override fun getSyntheticConstructors(scope: ResolutionScope): Collection<FunctionDescriptor> {
return scope.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS)
.filterIsInstance<ClassifierDescriptor>()
.flatMap { getAllSamConstructors(it) }
}
override fun getSyntheticConstructor(constructor: ConstructorDescriptor): ConstructorDescriptor? {
return when (constructor) {
is JavaClassConstructorDescriptor -> createJavaSamAdapterConstructor(constructor)
is TypeAliasConstructorDescriptor -> {
val underlyingConstructor = constructor.underlyingConstructorDescriptor
if (underlyingConstructor !is JavaClassConstructorDescriptor) return null
val underlyingSamConstructor = createJavaSamAdapterConstructor(underlyingConstructor) ?: return null
samConstructorForTypeAliasConstructor(Pair(underlyingSamConstructor, constructor.typeAliasDescriptor))
}
else -> null
}
}
private fun createJavaSamAdapterConstructor(constructor: JavaClassConstructorDescriptor): ClassConstructorDescriptor? {
if (!SingleAbstractMethodUtils.isSamAdapterNecessary(constructor)) return null
return samConstructorForJavaConstructor(constructor)
}
private fun getSamFunctions(functions: Collection<DeclarationDescriptor>): List<SamAdapterDescriptor<JavaMethodDescriptor>> {
@@ -148,6 +175,21 @@ class SamAdapterFunctionsScope(
}
}
private fun getAllSamConstructors(classifier: ClassifierDescriptor): List<FunctionDescriptor> {
return getSamAdaptersFromConstructors(classifier) + listOfNotNull(getSamConstructor(classifier))
}
private fun getSamAdaptersFromConstructors(classifier: ClassifierDescriptor): List<FunctionDescriptor> {
if (classifier !is JavaClassDescriptor) return emptyList()
return arrayListOf<FunctionDescriptor>().apply {
for (constructor in classifier.constructors) {
val samConstructor = getSyntheticConstructor(constructor) ?: continue
add(samConstructor)
}
}
}
private fun getSamConstructor(classifier: ClassifierDescriptor): SamConstructorDescriptor? {
if (classifier is TypeAliasDescriptor) {
return getTypeAliasSamConstructor(classifier)