Pluggable Synthetic Objects
This commit is contained in:
@@ -20,6 +20,7 @@ import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.backend.common.bridges.findInterfaceImplementation
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
@@ -162,4 +163,23 @@ object CodegenUtil {
|
||||
val document = file.viewProvider.document
|
||||
return document?.getLineNumber(if (markEndOffset) statement.textRange.endOffset else statement.textOffset)?.plus(1)
|
||||
}
|
||||
|
||||
// Returns the descriptor for a function (whose parameters match the given predicate) which should be generated in the class.
|
||||
// Note that we always generate equals/hashCode/toString in data classes, unless that would lead to a JVM signature clash with
|
||||
// another method, which can only happen if the method is declared in the data class (manually or via delegation).
|
||||
// Also there are no hard asserts or assumptions because such methods are generated for erroneous code as well (in light classes mode).
|
||||
fun getMemberToGenerate(
|
||||
classDescriptor: ClassDescriptor,
|
||||
name: String,
|
||||
isReturnTypeOk: (KotlinType) -> Boolean,
|
||||
areParametersOk: (List<ValueParameterDescriptor>) -> Boolean
|
||||
): FunctionDescriptor? =
|
||||
classDescriptor.unsubstitutedMemberScope.getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND)
|
||||
.singleOrNull { function ->
|
||||
function.kind.let { kind -> kind == CallableMemberDescriptor.Kind.SYNTHESIZED || kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE } &&
|
||||
function.modality != Modality.FINAL &&
|
||||
areParametersOk(function.valueParameters) &&
|
||||
function.returnType != null &&
|
||||
isReturnTypeOk(function.returnType!!)
|
||||
}
|
||||
}
|
||||
|
||||
+11
-27
@@ -16,18 +16,17 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.common
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.CodegenUtil.getMemberToGenerate
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.FAKE_OVERRIDE
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
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
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
/**
|
||||
* A platform-independent logic for generating data class synthetic methods.
|
||||
@@ -79,17 +78,20 @@ abstract class DataClassMethodGenerator(private val declaration: KtClassOrObject
|
||||
}
|
||||
|
||||
private fun generateDataClassToStringIfNeeded(properties: List<PropertyDescriptor>) {
|
||||
val function = getMemberToGenerate("toString", KotlinBuiltIns::isString, List<ValueParameterDescriptor>::isEmpty) ?: return
|
||||
val function = getMemberToGenerate(classDescriptor, "toString",
|
||||
KotlinBuiltIns::isString, List<ValueParameterDescriptor>::isEmpty) ?: return
|
||||
generateToStringMethod(function, properties)
|
||||
}
|
||||
|
||||
private fun generateDataClassHashCodeIfNeeded(properties: List<PropertyDescriptor>) {
|
||||
val function = getMemberToGenerate("hashCode", KotlinBuiltIns::isInt, List<ValueParameterDescriptor>::isEmpty) ?: return
|
||||
val function = getMemberToGenerate(classDescriptor, "hashCode",
|
||||
KotlinBuiltIns::isInt, List<ValueParameterDescriptor>::isEmpty) ?: return
|
||||
generateHashCodeMethod(function, properties)
|
||||
}
|
||||
|
||||
private fun generateDataClassEqualsIfNeeded(properties: List<PropertyDescriptor>) {
|
||||
val function = getMemberToGenerate("equals", KotlinBuiltIns::isBoolean) { parameters ->
|
||||
val function = getMemberToGenerate(classDescriptor, "equals",
|
||||
KotlinBuiltIns::isBoolean) { parameters ->
|
||||
parameters.size == 1 && KotlinBuiltIns.isNullableAny(parameters.first().type)
|
||||
} ?: return
|
||||
generateEqualsMethod(function, properties)
|
||||
@@ -102,22 +104,4 @@ abstract class DataClassMethodGenerator(private val declaration: KtClassOrObject
|
||||
|
||||
private val primaryConstructorParameters: List<KtParameter>
|
||||
get() = (declaration as? KtClass)?.getPrimaryConstructorParameters().orEmpty()
|
||||
|
||||
// Returns the descriptor for a function (whose parameters match the given predicate) which should be generated in the data class.
|
||||
// Note that we always generate equals/hashCode/toString in data classes, unless that would lead to a JVM signature clash with
|
||||
// another method, which can only happen if the method is declared in the data class (manually or via delegation).
|
||||
// Also there are no hard asserts or assumptions because such methods are generated for erroneous code as well (in light classes mode).
|
||||
private fun getMemberToGenerate(
|
||||
name: String,
|
||||
isReturnTypeOk: (KotlinType) -> Boolean,
|
||||
areParametersOk: (List<ValueParameterDescriptor>) -> Boolean
|
||||
): FunctionDescriptor? =
|
||||
classDescriptor.unsubstitutedMemberScope.getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND)
|
||||
.singleOrNull { function ->
|
||||
function.kind.let { kind -> kind == SYNTHESIZED || kind == FAKE_OVERRIDE } &&
|
||||
function.modality != Modality.FINAL &&
|
||||
areParametersOk(function.valueParameters) &&
|
||||
function.returnType != null &&
|
||||
isReturnTypeOk(function.returnType!!)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user