Generate equals and hashCode: enable for data classes #KT-17502 Fixed
This commit is contained in:
committed by
asedunov
parent
b5664755c8
commit
6971ca44e7
+19
-31
@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.config.LanguageFeature
|
|||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyzeWithContent
|
import org.jetbrains.kotlin.idea.caches.resolve.analyzeWithContent
|
||||||
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
||||||
import org.jetbrains.kotlin.idea.core.CollectingNameValidator
|
import org.jetbrains.kotlin.idea.core.CollectingNameValidator
|
||||||
@@ -47,7 +46,6 @@ import org.jetbrains.kotlin.resolve.BindingContext
|
|||||||
import org.jetbrains.kotlin.resolve.TargetPlatform
|
import org.jetbrains.kotlin.resolve.TargetPlatform
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
|
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
|
||||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
|
||||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
@@ -70,30 +68,19 @@ class KotlinGenerateEqualsAndHashcodeAction : KotlinGenerateMemberActionBase<Kot
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Info(
|
class Info(
|
||||||
val needEquals: Boolean,
|
val needEquals: Boolean,
|
||||||
val needHashCode: Boolean,
|
val needHashCode: Boolean,
|
||||||
val classDescriptor: ClassDescriptor,
|
val classDescriptor: ClassDescriptor,
|
||||||
val variablesForEquals: List<VariableDescriptor>,
|
val variablesForEquals: List<VariableDescriptor>,
|
||||||
val variablesForHashCode: List<VariableDescriptor>
|
val variablesForHashCode: List<VariableDescriptor>
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun isValidForClass(targetClass: KtClassOrObject): Boolean {
|
override fun isValidForClass(targetClass: KtClassOrObject): Boolean {
|
||||||
return targetClass is KtClass
|
return targetClass is KtClass
|
||||||
&& targetClass !is KtEnumEntry
|
&& targetClass !is KtEnumEntry
|
||||||
&& !targetClass.isEnum()
|
&& !targetClass.isEnum()
|
||||||
&& !targetClass.isAnnotation()
|
&& !targetClass.isAnnotation()
|
||||||
&& !targetClass.isInterface()
|
&& !targetClass.isInterface()
|
||||||
&& (!targetClass.isData() || isValidForDataClass(targetClass))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun isValidForDataClass(targetClass: KtClass): Boolean {
|
|
||||||
val constructor = targetClass.primaryConstructor ?: return false
|
|
||||||
val context = constructor.analyze(BodyResolveMode.PARTIAL)
|
|
||||||
return constructor.valueParameters.any { parameter ->
|
|
||||||
parameter.hasValOrVar() && context.get(BindingContext.TYPE, parameter.typeReference)?.let { type ->
|
|
||||||
KotlinBuiltIns.isArray(type) || KotlinBuiltIns.isPrimitiveArray(type)
|
|
||||||
} ?: false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun prepareMembersInfo(klass: KtClassOrObject, project: Project, editor: Editor?): Info? {
|
override fun prepareMembersInfo(klass: KtClassOrObject, project: Project, editor: Editor?): Info? {
|
||||||
@@ -116,7 +103,7 @@ class KotlinGenerateEqualsAndHashcodeAction : KotlinGenerateMemberActionBase<Kot
|
|||||||
hashCodeDescriptor.source.getPsi()?.delete()
|
hashCodeDescriptor.source.getPsi()?.delete()
|
||||||
needEquals = true
|
needEquals = true
|
||||||
needHashCode = true
|
needHashCode = true
|
||||||
} catch(e: IncorrectOperationException) {
|
} catch (e: IncorrectOperationException) {
|
||||||
LOG.error(e)
|
LOG.error(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -213,8 +200,7 @@ class KotlinGenerateEqualsAndHashcodeAction : KotlinGenerateMemberActionBase<Kot
|
|||||||
val useIsCheck = CodeInsightSettings.getInstance().USE_INSTANCEOF_ON_EQUALS_PARAMETER
|
val useIsCheck = CodeInsightSettings.getInstance().USE_INSTANCEOF_ON_EQUALS_PARAMETER
|
||||||
val isNotInstanceCondition = if (useIsCheck) {
|
val isNotInstanceCondition = if (useIsCheck) {
|
||||||
"$paramName !is $typeForCast"
|
"$paramName !is $typeForCast"
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
generateClassLiteralsNotEqual(paramName, targetClass)
|
generateClassLiteralsNotEqual(paramName, targetClass)
|
||||||
}
|
}
|
||||||
val bodyText = buildString {
|
val bodyText = buildString {
|
||||||
@@ -237,11 +223,13 @@ class KotlinGenerateEqualsAndHashcodeAction : KotlinGenerateMemberActionBase<Kot
|
|||||||
val isNullable = TypeUtils.isNullableType(it.type)
|
val isNullable = TypeUtils.isNullableType(it.type)
|
||||||
val isArray = KotlinBuiltIns.isArrayOrPrimitiveArray(it.type)
|
val isArray = KotlinBuiltIns.isArrayOrPrimitiveArray(it.type)
|
||||||
val canUseArrayContentFunctions = targetClass.canUseArrayContentFunctions()
|
val canUseArrayContentFunctions = targetClass.canUseArrayContentFunctions()
|
||||||
val propName = (DescriptorToSourceUtilsIde.getAnyDeclaration(project, it) as PsiNameIdentifierOwner).nameIdentifier!!.text
|
val propName =
|
||||||
|
(DescriptorToSourceUtilsIde.getAnyDeclaration(project, it) as PsiNameIdentifierOwner).nameIdentifier!!.text
|
||||||
val notEquals = when {
|
val notEquals = when {
|
||||||
isArray -> {
|
isArray -> {
|
||||||
"!${generateArraysEqualsCall(it, canUseArrayContentFunctions, propName, "$paramName.$propName")}"
|
"!${generateArraysEqualsCall(it, canUseArrayContentFunctions, propName, "$paramName.$propName")}"
|
||||||
} else -> {
|
}
|
||||||
|
else -> {
|
||||||
"$propName != $paramName.$propName"
|
"$propName != $paramName.$propName"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -332,10 +320,10 @@ class KotlinGenerateEqualsAndHashcodeAction : KotlinGenerateMemberActionBase<Kot
|
|||||||
override fun generateMembers(project: Project, editor: Editor?, info: Info): List<KtDeclaration> {
|
override fun generateMembers(project: Project, editor: Editor?, info: Info): List<KtDeclaration> {
|
||||||
val targetClass = info.classDescriptor.source.getPsi() as KtClass
|
val targetClass = info.classDescriptor.source.getPsi() as KtClass
|
||||||
val prototypes = ArrayList<KtDeclaration>(2)
|
val prototypes = ArrayList<KtDeclaration>(2)
|
||||||
.apply {
|
.apply {
|
||||||
addIfNotNull(generateEquals(project, info, targetClass))
|
addIfNotNull(generateEquals(project, info, targetClass))
|
||||||
addIfNotNull(generateHashCode(project, info, targetClass))
|
addIfNotNull(generateHashCode(project, info, targetClass))
|
||||||
}
|
}
|
||||||
val anchor = with(targetClass.declarations) { lastIsInstanceOrNull<KtNamedFunction>() ?: lastOrNull() }
|
val anchor = with(targetClass.declarations) { lastIsInstanceOrNull<KtNamedFunction>() ?: lastOrNull() }
|
||||||
return insertMembersAfter(editor, targetClass, prototypes, anchor)
|
return insertMembersAfter(editor, targetClass, prototypes, anchor)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,2 +1 @@
|
|||||||
// NOT_APPLICABLE
|
|
||||||
data class A<caret>(val n: Int)
|
data class A<caret>(val n: Int)
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
data class A(val n: Int) {
|
||||||
|
<caret>override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as A
|
||||||
|
|
||||||
|
if (n != other.n) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user