Transform CharSequence.length to property

This commit is contained in:
Denis Zharkov
2015-10-11 17:32:31 +03:00
committed by Mikhail Glukhikh
parent 6c0d55e4ed
commit 1305d9755a
14 changed files with 83 additions and 50 deletions
@@ -25,8 +25,7 @@ import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.load.java.*
import org.jetbrains.kotlin.load.java.BuiltinSpecialProperties.isBuiltinSpecialPropertyName
import org.jetbrains.kotlin.load.java.BuiltinSpecialProperties.getBuiltinSpecialPropertyAccessorName
import org.jetbrains.kotlin.load.java.BuiltinSpecialProperties.getBuiltinSpecialPropertyGetterName
import org.jetbrains.kotlin.load.java.BuiltinSpecialMethods.sameAsRenamedInJvmBuiltin
import org.jetbrains.kotlin.load.java.BuiltinSpecialMethods.isRemoveAtByIndex
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialJvmSignature.sameAsBuiltinMethodWithErasedValueParameters
@@ -86,25 +85,13 @@ public class LazyJavaClassMemberScope(
}
override fun JavaMethodDescriptor.isVisibleAsFunction(): Boolean {
val nameAsString = name.asString()
if (JvmAbi.isGetterName(nameAsString)) {
val propertyName = propertyNameByGetMethodName(name) ?: return true
return !doesClassOverrideAnyProperty(getPropertiesFromSupertypes(propertyName))
}
if (JvmAbi.isSetterName(nameAsString)) {
return propertyNamesBySetMethodName(name).none {
propertyName ->
getPropertiesFromSupertypes(propertyName).any {
property -> property.isVar && doesClassOverridesProperty(property)
}
if (getPropertyNamesCandidatesByAccessorName(name).any {
propertyName ->
getPropertiesFromSupertypes(propertyName).any {
property ->
doesClassOverridesProperty(property) && (property.isVar || !JvmAbi.isSetterName(name.asString()))
}
}
if (name.isBuiltinSpecialPropertyName) {
return !doesClassOverrideAnyProperty(getPropertiesFromSupertypes(name))
}
}) return false
val javaMethod = (source as? JavaSourceElement)?.javaElement as? JavaMethod
if (javaMethod?.doesOverrideRenamedBuiltins() ?: false) {
@@ -136,11 +123,8 @@ public class LazyJavaClassMemberScope(
).result == OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE
}
private fun doesClassOverrideAnyProperty(properties: Collection<PropertyDescriptor>)
= properties.any { property -> doesClassOverridesProperty(property) }
private fun PropertyDescriptor.findGetterOverride(): JavaMethodDescriptor? {
val getterName = getter?.getBuiltinSpecialOverridden()?.getBuiltinSpecialPropertyAccessorName() ?: JvmAbi.getterName(name.asString())
val getterName = getter?.getBuiltinSpecialOverridden()?.getBuiltinSpecialPropertyGetterName() ?: JvmAbi.getterName(name.asString())
return memberIndex().findMethodsByName(Name.identifier(getterName)).firstNotNullResult factory@{
javaMethod ->
val descriptor = resolveMethodToFunctionDescriptor(javaMethod)
@@ -18,6 +18,9 @@ package org.jetbrains.kotlin.load.java
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.util.capitalizeDecapitalize.decapitalizeSmart
import org.jetbrains.kotlin.utils.singletonOrEmptyList
import org.jetbrains.kotlin.load.java.BuiltinSpecialProperties.getPropertyNameCandidatesBySpecialGetterName
fun propertyNameByGetMethodName(methodName: Name): Name?
= propertyNameFromAccessorMethodName(methodName, "get") ?: propertyNameFromAccessorMethodName(methodName, "is", removePrefix = false)
@@ -45,3 +48,17 @@ private fun propertyNameFromAccessorMethodName(methodName: Name, prefix: String,
if (!Name.isValidIdentifier(name)) return null
return Name.identifier(name)
}
fun getPropertyNamesCandidatesByAccessorName(name: Name): List<Name> {
val nameAsString = name.asString()
if (JvmAbi.isGetterName(nameAsString)) {
return propertyNameByGetMethodName(name).singletonOrEmptyList()
}
if (JvmAbi.isSetterName(nameAsString)) {
return propertyNamesBySetMethodName(name)
}
return getPropertyNameCandidatesBySpecialGetterName(name)
}
@@ -28,10 +28,20 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.utils.DFS
import org.jetbrains.kotlin.utils.addToStdlib.check
import org.jetbrains.kotlin.load.java.BuiltinSpecialProperties.getBuiltinSpecialPropertyAccessorName
import org.jetbrains.kotlin.load.java.BuiltinSpecialProperties.getBuiltinSpecialPropertyGetterName
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
object BuiltinSpecialProperties {
private val FQ_NAMES = setOf(FqName("kotlin.Collection.size"), FqName("kotlin.Map.size"))
private val PROPERTY_FQ_NAME_TO_JVM_GETTER_NAME_MAP = mapOf(
FqName("kotlin.Collection.size") to Name.identifier("size"),
FqName("kotlin.Map.size") to Name.identifier("size"),
FqName("kotlin.CharSequence.length") to Name.identifier("length")
)
private val GETTER_JVM_NAME_TO_PROPERTIES_SHORT_NAME_MAP: Map<Name, List<Name>> =
PROPERTY_FQ_NAME_TO_JVM_GETTER_NAME_MAP.getInversedShortNamesMap()
private val FQ_NAMES = PROPERTY_FQ_NAME_TO_JVM_GETTER_NAME_MAP.keySet()
private val SHORT_NAMES = FQ_NAMES.map { it.shortName() }.toSet()
fun hasBuiltinSpecialPropertyFqName(callableMemberDescriptor: CallableMemberDescriptor): Boolean {
@@ -47,12 +57,14 @@ object BuiltinSpecialProperties {
return overriddenDescriptors.any { hasBuiltinSpecialPropertyFqName(it) }
}
val Name.isBuiltinSpecialPropertyName: Boolean get() = this in SHORT_NAMES
fun getPropertyNameCandidatesBySpecialGetterName(name1: Name): List<Name> =
GETTER_JVM_NAME_TO_PROPERTIES_SHORT_NAME_MAP[name1] ?: emptyList()
fun CallableMemberDescriptor.getBuiltinSpecialPropertyAccessorName(): String? {
return propertyIfAccessor.check {
hasBuiltinSpecialPropertyFqName(it)
}?.name?.asString()
fun CallableMemberDescriptor.getBuiltinSpecialPropertyGetterName(): String? {
assert(isFromBuiltins()) { "This method is defined only for builtin members, but $this found" }
val descriptor = propertyIfAccessor.firstOverridden { hasBuiltinSpecialPropertyFqName(it) } ?: return null
return PROPERTY_FQ_NAME_TO_JVM_GETTER_NAME_MAP[descriptor.fqNameSafe]?.asString()
}
}
@@ -115,11 +127,7 @@ object BuiltinSpecialMethods {
val ORIGINAL_SHORT_NAMES: List<Name> = FQ_NAMES_TO_JVM_MAP.keySet().map { it.shortName() }
private val JVM_SHORT_NAME_TO_BUILTIN_FQ_NAMES_MAP: Map<Name, List<FqName>> =
FQ_NAMES_TO_JVM_MAP.entrySet().groupBy { it.value }.mapValues { entry -> entry.value.map { it.key } }
val JVM_SHORT_NAME_TO_BUILTIN_SHORT_NAMES_MAP: Map<Name, List<Name>> =
JVM_SHORT_NAME_TO_BUILTIN_FQ_NAMES_MAP.mapValues { it.value.map { it.shortName() } }
val JVM_SHORT_NAME_TO_BUILTIN_SHORT_NAMES_MAP: Map<Name, List<Name>> = FQ_NAMES_TO_JVM_MAP.getInversedShortNamesMap()
val Name.sameAsRenamedInJvmBuiltin: Boolean
get() = this in ORIGINAL_SHORT_NAMES
@@ -157,7 +165,7 @@ fun getJvmMethodNameIfSpecial(callableMemberDescriptor: CallableMemberDescriptor
val builtinOverridden = getBuiltinOverriddenThatAffectsJvmName(callableMemberDescriptor)?.propertyIfAccessor
?: return null
return when (builtinOverridden) {
is PropertyDescriptor -> builtinOverridden.getBuiltinSpecialPropertyAccessorName()
is PropertyDescriptor -> builtinOverridden.getBuiltinSpecialPropertyGetterName()
else -> BuiltinSpecialMethods.getSpecialJvmName(builtinOverridden)?.asString()
}
}
@@ -209,3 +217,6 @@ private fun CallableMemberDescriptor.firstOverridden(
}
private fun CallableMemberDescriptor.isFromJavaOrBuiltins() = isFromJava || isFromBuiltins()
private fun Map<FqName, Name>.getInversedShortNamesMap(): Map<Name, List<Name>> =
entrySet().groupBy { it.value }.mapValues { entry -> entry.value.map { it.key.shortName() } }