Track lookups in JavaSyntheticPropertiesScope
This commit is contained in:
+4
-3
@@ -16,9 +16,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.synthetic
|
||||
|
||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||
import org.jetbrains.kotlin.resolve.lazy.FileScopeProvider
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
|
||||
class AdditionalScopesWithJavaSyntheticExtensions(storageManager: StorageManager) : FileScopeProvider.AdditionalScopes {
|
||||
override val scopes = listOf(JavaSyntheticPropertiesScope(storageManager), SamAdapterFunctionsScope(storageManager))
|
||||
}
|
||||
class AdditionalScopesWithJavaSyntheticExtensions(storageManager: StorageManager, lookupTracker: LookupTracker) : FileScopeProvider.AdditionalScopes {
|
||||
override val scopes = listOf(JavaSyntheticPropertiesScope(storageManager, lookupTracker), SamAdapterFunctionsScope(storageManager))
|
||||
}
|
||||
|
||||
+59
-20
@@ -23,7 +23,9 @@ import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.PropertyGetterDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.PropertySetterDescriptorImpl
|
||||
import org.jetbrains.kotlin.incremental.components.LookupLocation
|
||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.incremental.record
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
@@ -42,6 +44,8 @@ import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import java.util.*
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
private val POSSIBLE_GETTER_NAMES_CAPACITY = 3
|
||||
|
||||
interface SyntheticJavaPropertyDescriptor : PropertyDescriptor {
|
||||
val getMethod: FunctionDescriptor
|
||||
val setMethod: FunctionDescriptor?
|
||||
@@ -69,31 +73,62 @@ interface SyntheticJavaPropertyDescriptor : PropertyDescriptor {
|
||||
}
|
||||
}
|
||||
|
||||
class JavaSyntheticPropertiesScope(storageManager: StorageManager) : BaseImportingScope(null) {
|
||||
private val syntheticPropertyInClass = storageManager.createMemoizedFunctionWithNullableValues<Pair<ClassDescriptor, Name>, PropertyDescriptor> { pair ->
|
||||
class JavaSyntheticPropertiesScope(storageManager: StorageManager, private val lookupTracker: LookupTracker) : BaseImportingScope(null) {
|
||||
private val syntheticPropertyInClass = storageManager.createMemoizedFunction<Pair<ClassDescriptor, Name>, SyntheticPropertyHolder> { pair ->
|
||||
syntheticPropertyInClassNotCached(pair.first, pair.second)
|
||||
}
|
||||
|
||||
private fun syntheticPropertyInClassNotCached(ownerClass: ClassDescriptor, name: Name): PropertyDescriptor? {
|
||||
if (name.isSpecial()) return null
|
||||
private fun getSyntheticPropertyAndRecordLookups(classifier: ClassDescriptor, name: Name, location: LookupLocation): PropertyDescriptor? {
|
||||
val (descriptor, lookedNames) = syntheticPropertyInClass(Pair(classifier, name))
|
||||
|
||||
if (location !is NoLookupLocation) {
|
||||
lookedNames.forEach { lookupTracker.record(location, classifier.unsubstitutedMemberScope, it) }
|
||||
}
|
||||
|
||||
return descriptor
|
||||
}
|
||||
|
||||
private fun syntheticPropertyInClassNotCached(ownerClass: ClassDescriptor, name: Name): SyntheticPropertyHolder {
|
||||
|
||||
fun result(descriptor: PropertyDescriptor?, getterNames: Sequence<Name>, setterName: Name? = null): SyntheticPropertyHolder {
|
||||
if (lookupTracker == LookupTracker.DO_NOTHING) {
|
||||
return if (descriptor == null) SyntheticPropertyHolder.EMPTY else SyntheticPropertyHolder(descriptor, emptyList())
|
||||
}
|
||||
|
||||
val names = ArrayList<Name>(POSSIBLE_GETTER_NAMES_CAPACITY + (setterName?.let { 1 } ?: 0))
|
||||
|
||||
names.addAll(getterNames)
|
||||
names.addIfNotNull(setterName)
|
||||
|
||||
return SyntheticPropertyHolder(descriptor, names)
|
||||
}
|
||||
|
||||
if (name.isSpecial) return SyntheticPropertyHolder.EMPTY
|
||||
|
||||
val identifier = name.identifier
|
||||
if (identifier.isEmpty()) return null
|
||||
if (identifier.isEmpty()) return SyntheticPropertyHolder.EMPTY
|
||||
|
||||
val firstChar = identifier[0]
|
||||
if (!firstChar.isJavaIdentifierStart() || firstChar in 'A'..'Z') return null
|
||||
if (!firstChar.isJavaIdentifierStart() || firstChar in 'A'..'Z') return SyntheticPropertyHolder.EMPTY
|
||||
|
||||
val memberScope = ownerClass.unsubstitutedMemberScope
|
||||
val getMethod = possibleGetMethodNames(name)
|
||||
.flatMap { memberScope.getFunctions(it, NoLookupLocation.UNSORTED).asSequence() }
|
||||
|
||||
val possibleGetMethodNames = possibleGetMethodNames(name)
|
||||
val getMethod = possibleGetMethodNames
|
||||
.flatMap { memberScope.getFunctions(it, NoLookupLocation.FROM_SYNTHETIC_SCOPE).asSequence() }
|
||||
.singleOrNull {
|
||||
isGoodGetMethod(it) && it.hasJavaOriginInHierarchy()
|
||||
} ?: return null
|
||||
} ?: return result(null, possibleGetMethodNames)
|
||||
|
||||
|
||||
val setMethod = memberScope.getFunctions(setMethodName(getMethod.name), NoLookupLocation.UNSORTED)
|
||||
val setMethodName = setMethodName(getMethod.name)
|
||||
val setMethod = memberScope.getFunctions(setMethodName, NoLookupLocation.FROM_SYNTHETIC_SCOPE)
|
||||
.singleOrNull { isGoodSetMethod(it, getMethod) }
|
||||
|
||||
val propertyType = getMethod.returnType ?: return null
|
||||
return MyPropertyDescriptor.create(ownerClass, getMethod.original, setMethod?.original, name, propertyType)
|
||||
val propertyType = getMethod.returnType!!
|
||||
|
||||
val descriptor = MyPropertyDescriptor.create(ownerClass, getMethod.original, setMethod?.original, name, propertyType)
|
||||
return result(descriptor, possibleGetMethodNames, setMethodName);
|
||||
}
|
||||
|
||||
private fun isGoodGetMethod(descriptor: FunctionDescriptor): Boolean {
|
||||
@@ -131,12 +166,10 @@ class JavaSyntheticPropertiesScope(storageManager: StorageManager) : BaseImporti
|
||||
}
|
||||
|
||||
override fun getContributedSyntheticExtensionProperties(receiverTypes: Collection<KotlinType>, name: Name, location: LookupLocation): Collection<PropertyDescriptor> {
|
||||
//TODO: use location parameter!
|
||||
|
||||
var result: SmartList<PropertyDescriptor>? = null
|
||||
val processedTypes: MutableSet<TypeConstructor>? = if (receiverTypes.size() > 1) HashSet<TypeConstructor>() else null
|
||||
for (type in receiverTypes) {
|
||||
result = collectSyntheticPropertiesByName(result, type.constructor, name, processedTypes)
|
||||
result = collectSyntheticPropertiesByName(result, type.constructor, name, processedTypes, location)
|
||||
}
|
||||
return when {
|
||||
result == null -> emptyList()
|
||||
@@ -145,7 +178,7 @@ class JavaSyntheticPropertiesScope(storageManager: StorageManager) : BaseImporti
|
||||
}
|
||||
}
|
||||
|
||||
private fun collectSyntheticPropertiesByName(result: SmartList<PropertyDescriptor>?, type: TypeConstructor, name: Name, processedTypes: MutableSet<TypeConstructor>?): SmartList<PropertyDescriptor>? {
|
||||
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
|
||||
|
||||
@Suppress("NAME_SHADOWING")
|
||||
@@ -153,10 +186,10 @@ class JavaSyntheticPropertiesScope(storageManager: StorageManager) : BaseImporti
|
||||
|
||||
val classifier = type.declarationDescriptor
|
||||
if (classifier is ClassDescriptor) {
|
||||
result = result.add(syntheticPropertyInClass(Pair(classifier, name)))
|
||||
result = result.add(getSyntheticPropertyAndRecordLookups(classifier, name, location))
|
||||
}
|
||||
else {
|
||||
type.supertypes.forEach { result = collectSyntheticPropertiesByName(result, it.constructor, name, processedTypes) }
|
||||
type.supertypes.forEach { result = collectSyntheticPropertiesByName(result, it.constructor, name, processedTypes, location) }
|
||||
}
|
||||
|
||||
return result
|
||||
@@ -177,7 +210,7 @@ class JavaSyntheticPropertiesScope(storageManager: StorageManager) : BaseImporti
|
||||
for (descriptor in classifier.getUnsubstitutedMemberScope().getDescriptors(DescriptorKindFilter.FUNCTIONS)) {
|
||||
if (descriptor is FunctionDescriptor) {
|
||||
val propertyName = SyntheticJavaPropertyDescriptor.propertyNameByGetMethodName(descriptor.getName()) ?: continue
|
||||
addIfNotNull(syntheticPropertyInClass(Pair(classifier, propertyName)))
|
||||
addIfNotNull(syntheticPropertyInClass(Pair(classifier, propertyName)).descriptor)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -196,7 +229,7 @@ class JavaSyntheticPropertiesScope(storageManager: StorageManager) : BaseImporti
|
||||
//TODO: reuse code with generation?
|
||||
|
||||
private fun possibleGetMethodNames(propertyName: Name): Sequence<Name> {
|
||||
val result = ArrayList<Name>(3)
|
||||
val result = ArrayList<Name>(POSSIBLE_GETTER_NAMES_CAPACITY)
|
||||
val identifier = propertyName.identifier
|
||||
|
||||
if (JvmAbi.startsWithIsPrefix(identifier)) {
|
||||
@@ -228,6 +261,12 @@ class JavaSyntheticPropertiesScope(storageManager: StorageManager) : BaseImporti
|
||||
p.println(javaClass.simpleName)
|
||||
}
|
||||
|
||||
private data class SyntheticPropertyHolder(val descriptor: PropertyDescriptor?, val lookedNames: List<Name>) {
|
||||
companion object {
|
||||
val EMPTY = SyntheticPropertyHolder(null, emptyList())
|
||||
}
|
||||
}
|
||||
|
||||
private class MyPropertyDescriptor(
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
original: PropertyDescriptor?,
|
||||
|
||||
Reference in New Issue
Block a user