diff --git a/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/DataClassMethodGenerator.kt b/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/DataClassMethodGenerator.kt index 497e853b78b..46327bec12c 100644 --- a/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/DataClassMethodGenerator.kt +++ b/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/DataClassMethodGenerator.kt @@ -33,32 +33,22 @@ import org.jetbrains.kotlin.resolve.BindingContextUtils * TODO: data class with zero components gets no toString/equals/hashCode methods. This is inconsistent and should be * changed here with the platform backends adopted. */ -abstract class DataClassMethodGenerator(protected val declaration: KtClassOrObject, private val bindingContext: BindingContext) { - protected val classDescriptor: ClassDescriptor = BindingContextUtils.getNotNull(bindingContext, BindingContext.CLASS, declaration) +abstract class DataClassMethodGenerator( + declaration: KtClassOrObject, + bindingContext: BindingContext +) : FunctionsFromAnyGenerator(declaration, bindingContext) { - fun generate() { + override fun generate() { generateComponentFunctionsForDataClasses() - generateCopyFunctionForDataClasses(primaryConstructorParameters) - val properties = dataProperties - if (properties.isNotEmpty()) { - generateDataClassToStringIfNeeded(properties) - generateDataClassHashCodeIfNeeded(properties) - generateDataClassEqualsIfNeeded(properties) - } + super.generate() } protected abstract fun generateComponentFunction(function: FunctionDescriptor, parameter: ValueParameterDescriptor) protected abstract fun generateCopyFunction(function: FunctionDescriptor, constructorParameters: List) - protected abstract fun generateToStringMethod(function: FunctionDescriptor, properties: List) - - protected abstract fun generateHashCodeMethod(function: FunctionDescriptor, properties: List) - - protected abstract fun generateEqualsMethod(function: FunctionDescriptor, properties: List) - private fun generateComponentFunctionsForDataClasses() { // primary constructor should exist for data classes // but when generating light-classes still need to check we have one @@ -76,38 +66,4 @@ abstract class DataClassMethodGenerator(protected val declaration: KtClassOrObje val copyFunction = bindingContext.get(BindingContext.DATA_CLASS_COPY_FUNCTION, classDescriptor) ?: return generateCopyFunction(copyFunction, constructorParameters) } - - private fun generateDataClassToStringIfNeeded(properties: List) { - val function = getMemberToGenerate( - classDescriptor, "toString", - KotlinBuiltIns::isString, List::isEmpty - ) ?: return - generateToStringMethod(function, properties) - } - - private fun generateDataClassHashCodeIfNeeded(properties: List) { - val function = getMemberToGenerate( - classDescriptor, "hashCode", - KotlinBuiltIns::isInt, List::isEmpty - ) ?: return - generateHashCodeMethod(function, properties) - } - - private fun generateDataClassEqualsIfNeeded(properties: List) { - val function = getMemberToGenerate( - classDescriptor, "equals", - KotlinBuiltIns::isBoolean - ) { parameters -> - parameters.size == 1 && KotlinBuiltIns.isNullableAny(parameters.first().type) - } ?: return - generateEqualsMethod(function, properties) - } - - private val dataProperties: List - get() = primaryConstructorParameters - .filter { it.hasValOrVar() } - .map { bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, it)!! } - - private val primaryConstructorParameters: List - get() = (declaration as? KtClass)?.primaryConstructorParameters.orEmpty() } diff --git a/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/FunctionsFromAnyGenerator.kt b/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/FunctionsFromAnyGenerator.kt new file mode 100644 index 00000000000..f44ae11e293 --- /dev/null +++ b/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/FunctionsFromAnyGenerator.kt @@ -0,0 +1,70 @@ +/* + * 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.backend.common + +import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.PropertyDescriptor +import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor +import org.jetbrains.kotlin.psi.KtClass +import org.jetbrains.kotlin.psi.KtClassOrObject +import org.jetbrains.kotlin.psi.KtParameter +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.BindingContextUtils + +abstract class FunctionsFromAnyGenerator(protected val declaration: KtClassOrObject, protected val bindingContext: BindingContext) { + protected val classDescriptor: ClassDescriptor = BindingContextUtils.getNotNull(bindingContext, BindingContext.CLASS, declaration) + + open fun generate() { + val properties = primaryConstructorProperties + if (properties.isNotEmpty()) { + generateToStringIfNeeded(properties) + generateHashCodeIfNeeded(properties) + generateEqualsIfNeeded(properties) + } + } + + protected abstract fun generateToStringMethod(function: FunctionDescriptor, properties: List) + + protected abstract fun generateHashCodeMethod(function: FunctionDescriptor, properties: List) + + protected abstract fun generateEqualsMethod(function: FunctionDescriptor, properties: List) + + private fun generateToStringIfNeeded(properties: List) { + val function = CodegenUtil.getMemberToGenerate( + classDescriptor, "toString", + KotlinBuiltIns::isString, List::isEmpty + ) ?: return + generateToStringMethod(function, properties) + } + + private fun generateHashCodeIfNeeded(properties: List) { + val function = CodegenUtil.getMemberToGenerate( + classDescriptor, "hashCode", + KotlinBuiltIns::isInt, List::isEmpty + ) ?: return + generateHashCodeMethod(function, properties) + } + + private fun generateEqualsIfNeeded(properties: List) { + val function = CodegenUtil.getMemberToGenerate( + classDescriptor, "equals", + KotlinBuiltIns::isBoolean + ) { parameters -> + parameters.size == 1 && KotlinBuiltIns.isNullableAny(parameters.first().type) + } ?: return + generateEqualsMethod(function, properties) + } + + private val primaryConstructorProperties: List + get() = primaryConstructorParameters + .filter { it.hasValOrVar() } + .map { bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, it)!! } + + protected val primaryConstructorParameters: List + get() = (declaration as? KtClass)?.primaryConstructorParameters.orEmpty() +}