Refactoring: extract logic about methods from Any for scopes out
This commit is contained in:
@@ -26,10 +26,6 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
object DataClassDescriptorResolver {
|
||||
val EQUALS_METHOD_NAME = OperatorNameConventions.EQUALS
|
||||
val HASH_CODE_METHOD_NAME = Name.identifier("hashCode")
|
||||
val TO_STRING_METHOD_NAME = Name.identifier("toString")
|
||||
|
||||
val COPY_METHOD_NAME = Name.identifier("copy")
|
||||
|
||||
private val COMPONENT_FUNCTION_NAME_PREFIX = "component"
|
||||
@@ -52,36 +48,6 @@ object DataClassDescriptorResolver {
|
||||
return true
|
||||
}
|
||||
|
||||
fun createEqualsFunctionDescriptor(classDescriptor: ClassDescriptor): SimpleFunctionDescriptor =
|
||||
doCreateFunctionFromAny(classDescriptor, EQUALS_METHOD_NAME)
|
||||
|
||||
fun createHashCodeFunctionDescriptor(classDescriptor: ClassDescriptor): SimpleFunctionDescriptor =
|
||||
doCreateFunctionFromAny(classDescriptor, HASH_CODE_METHOD_NAME)
|
||||
|
||||
fun createToStringFunctionDescriptor(classDescriptor: ClassDescriptor): SimpleFunctionDescriptor =
|
||||
doCreateFunctionFromAny(classDescriptor, TO_STRING_METHOD_NAME)
|
||||
|
||||
private fun doCreateFunctionFromAny(classDescriptor: ClassDescriptor, name: Name): SimpleFunctionDescriptor {
|
||||
val functionDescriptor = SimpleFunctionDescriptorImpl.create(
|
||||
classDescriptor, Annotations.EMPTY, name, CallableMemberDescriptor.Kind.SYNTHESIZED, classDescriptor.source
|
||||
)
|
||||
|
||||
val functionFromAny = classDescriptor.builtIns.any.getMemberScope(emptyList())
|
||||
.getContributedFunctions(name, NoLookupLocation.FROM_BUILTINS).single()
|
||||
|
||||
functionDescriptor.initialize(
|
||||
null,
|
||||
classDescriptor.thisAsReceiverParameter,
|
||||
functionFromAny.typeParameters,
|
||||
functionFromAny.valueParameters.map { it.copy(functionDescriptor, it.name, it.index) },
|
||||
functionFromAny.returnType,
|
||||
Modality.OPEN,
|
||||
Visibilities.PUBLIC
|
||||
)
|
||||
|
||||
return functionDescriptor
|
||||
}
|
||||
|
||||
fun createComponentFunctionDescriptor(
|
||||
parameterIndex: Int,
|
||||
property: PropertyDescriptor,
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. 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
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
object FunctionsFromAny {
|
||||
val EQUALS_METHOD_NAME = OperatorNameConventions.EQUALS
|
||||
val HASH_CODE_METHOD_NAME = Name.identifier("hashCode")
|
||||
val TO_STRING_METHOD_NAME = Name.identifier("toString")
|
||||
|
||||
fun shouldAddEquals(
|
||||
name: Name,
|
||||
declaredFunctions: Collection<SimpleFunctionDescriptor>,
|
||||
fromSupertypes: List<SimpleFunctionDescriptor>
|
||||
): Boolean {
|
||||
return name == EQUALS_METHOD_NAME && shouldAddFunctionFromAny(
|
||||
declaredFunctions,
|
||||
fromSupertypes
|
||||
) { function ->
|
||||
val parameters = function.valueParameters
|
||||
parameters.size == 1 && KotlinBuiltIns.isNullableAny(parameters.first().type)
|
||||
}
|
||||
}
|
||||
|
||||
fun shouldAddHashCode(
|
||||
name: Name,
|
||||
declaredFunctions: Collection<SimpleFunctionDescriptor>,
|
||||
fromSupertypes: List<SimpleFunctionDescriptor>
|
||||
): Boolean {
|
||||
return name == HASH_CODE_METHOD_NAME && shouldAddFunctionFromAny(
|
||||
declaredFunctions,
|
||||
fromSupertypes
|
||||
) {
|
||||
it.valueParameters.isEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
fun shouldAddToString(
|
||||
name: Name,
|
||||
declaredFunctions: Collection<SimpleFunctionDescriptor>,
|
||||
fromSupertypes: List<SimpleFunctionDescriptor>
|
||||
): Boolean {
|
||||
return name == TO_STRING_METHOD_NAME && shouldAddFunctionFromAny(
|
||||
declaredFunctions,
|
||||
fromSupertypes
|
||||
) {
|
||||
it.valueParameters.isEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
fun createEqualsFunctionDescriptor(classDescriptor: ClassDescriptor): SimpleFunctionDescriptor =
|
||||
doCreateFunctionFromAny(classDescriptor, EQUALS_METHOD_NAME)
|
||||
|
||||
fun createHashCodeFunctionDescriptor(classDescriptor: ClassDescriptor): SimpleFunctionDescriptor =
|
||||
doCreateFunctionFromAny(classDescriptor, HASH_CODE_METHOD_NAME)
|
||||
|
||||
fun createToStringFunctionDescriptor(classDescriptor: ClassDescriptor): SimpleFunctionDescriptor =
|
||||
doCreateFunctionFromAny(classDescriptor, TO_STRING_METHOD_NAME)
|
||||
|
||||
private fun doCreateFunctionFromAny(classDescriptor: ClassDescriptor, name: Name): SimpleFunctionDescriptor {
|
||||
val functionDescriptor = SimpleFunctionDescriptorImpl.create(
|
||||
classDescriptor, Annotations.EMPTY, name, CallableMemberDescriptor.Kind.SYNTHESIZED, classDescriptor.source
|
||||
)
|
||||
|
||||
val functionFromAny = classDescriptor.builtIns.any.getMemberScope(emptyList())
|
||||
.getContributedFunctions(name, NoLookupLocation.FROM_BUILTINS).single()
|
||||
|
||||
functionDescriptor.initialize(
|
||||
null,
|
||||
classDescriptor.thisAsReceiverParameter,
|
||||
functionFromAny.typeParameters,
|
||||
functionFromAny.valueParameters.map { it.copy(functionDescriptor, it.name, it.index) },
|
||||
functionFromAny.returnType,
|
||||
Modality.OPEN,
|
||||
Visibilities.PUBLIC
|
||||
)
|
||||
|
||||
return functionDescriptor
|
||||
}
|
||||
|
||||
private fun shouldAddFunctionFromAny(
|
||||
declaredFunctions: Collection <SimpleFunctionDescriptor>,
|
||||
fromSupertypes: List<SimpleFunctionDescriptor>,
|
||||
checkParameters: (FunctionDescriptor) -> Boolean
|
||||
): Boolean {
|
||||
// Add 'equals', 'hashCode', 'toString' iff there is no such declared member AND there is no such final member in supertypes
|
||||
return declaredFunctions.none(checkParameters) &&
|
||||
fromSupertypes.none { checkParameters(it) && it.modality == Modality.FINAL }
|
||||
}
|
||||
}
|
||||
+6
-16
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.lazy.descriptors
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DELEGATION
|
||||
@@ -256,25 +255,16 @@ open class LazyClassMemberScope(
|
||||
}
|
||||
|
||||
if (c.languageVersionSettings.supportsFeature(LanguageFeature.DataClassInheritance)) {
|
||||
fun shouldAddFunctionFromAny(checkParameters: (FunctionDescriptor) -> Boolean): Boolean {
|
||||
// Add 'equals', 'hashCode', 'toString' iff there is no such declared member AND there is no such final member in supertypes
|
||||
return result.none(checkParameters) &&
|
||||
fromSupertypes.none { checkParameters(it) && it.modality == Modality.FINAL }
|
||||
if (FunctionsFromAny.shouldAddEquals(name, result, fromSupertypes)) {
|
||||
result.add(FunctionsFromAny.createEqualsFunctionDescriptor(thisDescriptor))
|
||||
}
|
||||
|
||||
if (name == DataClassDescriptorResolver.EQUALS_METHOD_NAME && shouldAddFunctionFromAny { function ->
|
||||
val parameters = function.valueParameters
|
||||
parameters.size == 1 && KotlinBuiltIns.isNullableAny(parameters.first().type)
|
||||
}) {
|
||||
result.add(DataClassDescriptorResolver.createEqualsFunctionDescriptor(thisDescriptor))
|
||||
if (FunctionsFromAny.shouldAddHashCode(name, result, fromSupertypes)) {
|
||||
result.add(FunctionsFromAny.createHashCodeFunctionDescriptor(thisDescriptor))
|
||||
}
|
||||
|
||||
if (name == DataClassDescriptorResolver.HASH_CODE_METHOD_NAME && shouldAddFunctionFromAny { it.valueParameters.isEmpty() }) {
|
||||
result.add(DataClassDescriptorResolver.createHashCodeFunctionDescriptor(thisDescriptor))
|
||||
}
|
||||
|
||||
if (name == DataClassDescriptorResolver.TO_STRING_METHOD_NAME && shouldAddFunctionFromAny { it.valueParameters.isEmpty() }) {
|
||||
result.add(DataClassDescriptorResolver.createToStringFunctionDescriptor(thisDescriptor))
|
||||
if (FunctionsFromAny.shouldAddToString(name, result, fromSupertypes)) {
|
||||
result.add(FunctionsFromAny.createToStringFunctionDescriptor(thisDescriptor))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -191,11 +191,11 @@ internal object IDELightClassContexts {
|
||||
}
|
||||
|
||||
private fun isGeneratedForDataClass(name: Name): Boolean {
|
||||
return name == DataClassDescriptorResolver.EQUALS_METHOD_NAME ||
|
||||
return name == FunctionsFromAny.EQUALS_METHOD_NAME ||
|
||||
// known failure is related to equals override, checking for other methods 'just in case'
|
||||
name == DataClassDescriptorResolver.COPY_METHOD_NAME ||
|
||||
name == DataClassDescriptorResolver.HASH_CODE_METHOD_NAME ||
|
||||
name == DataClassDescriptorResolver.TO_STRING_METHOD_NAME ||
|
||||
name == FunctionsFromAny.HASH_CODE_METHOD_NAME ||
|
||||
name == FunctionsFromAny.TO_STRING_METHOD_NAME ||
|
||||
DataClassDescriptorResolver.isComponentLike(name)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user