Code Insight: "Generate equals/hashCode" action
This commit is contained in:
@@ -45,6 +45,7 @@ import org.jetbrains.kotlin.idea.actions.AbstractGotoTestOrCodeActionTest
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.AbstractIdeLightClassTest
|
||||
import org.jetbrains.kotlin.idea.codeInsight.*
|
||||
import org.jetbrains.kotlin.idea.codeInsight.generate.AbstractGenerateActionTest
|
||||
import org.jetbrains.kotlin.idea.codeInsight.generate.AbstractGenerateHashCodeAndEqualsActionTest
|
||||
import org.jetbrains.kotlin.idea.codeInsight.generate.AbstractGenerateTestSupportMethodActionTest
|
||||
import org.jetbrains.kotlin.idea.codeInsight.moveUpDown.AbstractCodeMoverTest
|
||||
import org.jetbrains.kotlin.idea.codeInsight.surroundWith.AbstractSurroundWithTest
|
||||
@@ -741,6 +742,10 @@ fun main(args: Array<String>) {
|
||||
model("codeInsight/generate/testFrameworkSupport")
|
||||
}
|
||||
|
||||
testClass<AbstractGenerateHashCodeAndEqualsActionTest>() {
|
||||
model("codeInsight/generate/equalsWithHashCode")
|
||||
}
|
||||
|
||||
testClass<AbstractGenerateActionTest>() {
|
||||
model("codeInsight/generate/secondaryConstructors")
|
||||
}
|
||||
|
||||
@@ -173,6 +173,9 @@
|
||||
<action id="KotlinGenerateSecondaryConstructor"
|
||||
class="org.jetbrains.kotlin.idea.actions.generate.KotlinGenerateSecondaryConstructorAction"
|
||||
text="Secondary Constructor" />
|
||||
<action id="KotlinGenerateEqualsAndHashCode"
|
||||
class="org.jetbrains.kotlin.idea.actions.generate.KotlinGenerateEqualsAndHashcodeAction"
|
||||
text="equals() and hashCode()" />
|
||||
|
||||
<add-to-group group-id="GenerateGroup" anchor="first"/>
|
||||
</group>
|
||||
|
||||
+286
@@ -0,0 +1,286 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.actions.generate
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightBundle
|
||||
import com.intellij.codeInsight.CodeInsightSettings
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.Messages
|
||||
import com.intellij.util.IncorrectOperationException
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyzeFully
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||
import org.jetbrains.kotlin.idea.core.CollectingNameValidator
|
||||
import org.jetbrains.kotlin.idea.core.KotlinNameSuggester
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.OverrideMemberChooserObject
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.generateMember
|
||||
import org.jetbrains.kotlin.idea.core.refactoring.quoteIfNeeded
|
||||
import org.jetbrains.kotlin.idea.quickfix.insertMembersAfter
|
||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.lexer.JetTokens
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
|
||||
import org.jetbrains.kotlin.renderer.ParameterNameRenderingPolicy
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
|
||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.lastIsInstanceOrNull
|
||||
import java.util.*
|
||||
|
||||
class KotlinGenerateEqualsAndHashcodeAction : KotlinGenerateMemberActionBase<KotlinGenerateEqualsAndHashcodeAction.Info>() {
|
||||
companion object {
|
||||
private val LOG = Logger.getInstance(KotlinGenerateEqualsAndHashcodeAction::class.java)
|
||||
|
||||
private val MEMBER_RENDERER = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.withOptions {
|
||||
modifiers = emptySet()
|
||||
startFromName = true
|
||||
parameterNameRenderingPolicy = ParameterNameRenderingPolicy.NONE
|
||||
}
|
||||
}
|
||||
|
||||
class Info(
|
||||
val needEquals: Boolean,
|
||||
val needHashCode: Boolean,
|
||||
val classDescriptor: ClassDescriptor,
|
||||
val variablesForEquals: List<VariableDescriptor>,
|
||||
val variablesForHashCode: List<VariableDescriptor>
|
||||
)
|
||||
|
||||
override fun isValidForClass(targetClass: JetClassOrObject): Boolean {
|
||||
return targetClass is JetClass && targetClass !is JetEnumEntry && !targetClass.isAnnotation()
|
||||
&& !targetClass.hasModifier(JetTokens.DATA_KEYWORD)
|
||||
&& targetClass.getPropertiesToUse().isNotEmpty()
|
||||
}
|
||||
|
||||
private tailrec fun ClassDescriptor.findDeclaredFunction(
|
||||
name: String,
|
||||
checkSuperClasses: Boolean,
|
||||
filter: (FunctionDescriptor) -> Boolean
|
||||
): FunctionDescriptor? {
|
||||
unsubstitutedMemberScope
|
||||
.getFunctions(Name.identifier(name), NoLookupLocation.FROM_IDE)
|
||||
.firstOrNull { it.containingDeclaration == this && it.kind == CallableMemberDescriptor.Kind.DECLARATION && filter(it) }
|
||||
?.let { return it }
|
||||
|
||||
return if (checkSuperClasses) getSuperClassOrAny().findDeclaredFunction(name, checkSuperClasses, filter) else null
|
||||
}
|
||||
|
||||
private fun ClassDescriptor.findDeclaredEquals(checkSupers: Boolean): FunctionDescriptor? {
|
||||
return findDeclaredFunction("equals", checkSupers) {
|
||||
it.valueParameters.singleOrNull()?.type == it.builtIns.nullableAnyType && it.typeParameters.isEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
private fun ClassDescriptor.findDeclaredHashCode(checkSupers: Boolean): FunctionDescriptor? {
|
||||
return findDeclaredFunction("hashCode", checkSupers) { it.valueParameters.isEmpty() && it.typeParameters.isEmpty() }
|
||||
}
|
||||
|
||||
private fun JetClassOrObject.getPropertiesToUse(): List<JetNamedDeclaration> {
|
||||
return ArrayList<JetNamedDeclaration>().apply {
|
||||
getPrimaryConstructorParameters().filterTo(this) { it.hasValOrVar() }
|
||||
declarations.filterIsInstance<JetProperty>().filterTo(this) f@ {
|
||||
val descriptor = it.resolveToDescriptor()
|
||||
when (descriptor) {
|
||||
is ValueParameterDescriptor -> true
|
||||
is PropertyDescriptor -> descriptor.accessors.all { it.isDefault }
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun confirmRewrite(
|
||||
targetClass: JetClass,
|
||||
equalsDescriptor: FunctionDescriptor,
|
||||
hashCodeDescriptor: FunctionDescriptor
|
||||
): Boolean {
|
||||
if (ApplicationManager.getApplication().isUnitTestMode) return true
|
||||
val functionsText = "'${MEMBER_RENDERER.render(equalsDescriptor)}' and '${MEMBER_RENDERER.render(hashCodeDescriptor)}'"
|
||||
val message = "Functions $functionsText are already defined\nfor class ${targetClass.name}. Do you want to delete them and proceed?"
|
||||
return Messages.showYesNoDialog(targetClass.project, message,
|
||||
CodeInsightBundle.message("generate.equals.and.hashcode.already.defined.title"),
|
||||
Messages.getQuestionIcon()) == Messages.YES
|
||||
}
|
||||
|
||||
override fun prepareMembersInfo(klass: JetClassOrObject, project: Project, editor: Editor): Info? {
|
||||
if (klass !is JetClass) throw AssertionError("Not a class: ${klass.getElementTextWithContext()}")
|
||||
|
||||
val context = klass.analyzeFully()
|
||||
val classDescriptor = context.get(BindingContext.CLASS, klass) ?: return null
|
||||
|
||||
val equalsDescriptor = classDescriptor.findDeclaredEquals(false)
|
||||
val hashCodeDescriptor = classDescriptor.findDeclaredHashCode(false)
|
||||
|
||||
var needEquals = equalsDescriptor == null
|
||||
var needHashCode = hashCodeDescriptor == null
|
||||
if (!needEquals && !needHashCode) {
|
||||
if (!confirmRewrite(klass, equalsDescriptor!!, hashCodeDescriptor!!)) return null
|
||||
|
||||
runWriteAction {
|
||||
try {
|
||||
equalsDescriptor.source.getPsi()?.delete()
|
||||
hashCodeDescriptor.source.getPsi()?.delete()
|
||||
needEquals = true
|
||||
needHashCode = true
|
||||
} catch(e: IncorrectOperationException) {
|
||||
LOG.error(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val properties = klass.getPropertiesToUse()
|
||||
|
||||
if (properties.isEmpty() || ApplicationManager.getApplication().isUnitTestMode) {
|
||||
val descriptors = properties.map { context[BindingContext.DECLARATION_TO_DESCRIPTOR, it] as VariableDescriptor }
|
||||
return Info(needEquals, needHashCode, classDescriptor, descriptors, descriptors)
|
||||
}
|
||||
|
||||
return with(KotlinGenerateEqualsWizard(project, klass, properties, needEquals, needHashCode)) {
|
||||
if (!showAndGet()) return null
|
||||
|
||||
Info(needEquals,
|
||||
needHashCode,
|
||||
classDescriptor,
|
||||
getPropertiesForEquals().map { context[BindingContext.DECLARATION_TO_DESCRIPTOR, it] as VariableDescriptor },
|
||||
getPropertiesForHashCode().map { context[BindingContext.DECLARATION_TO_DESCRIPTOR, it] as VariableDescriptor })
|
||||
}
|
||||
}
|
||||
|
||||
private fun FunctionDescriptor.isMemberOfAny() = containingDeclaration == builtIns.any
|
||||
|
||||
private fun generateFunctionSkeleton(descriptor: FunctionDescriptor, project: Project): JetNamedFunction {
|
||||
return OverrideMemberChooserObject
|
||||
.create(project, descriptor, descriptor, OverrideMemberChooserObject.BodyType.EMPTY)
|
||||
.generateMember(project) as JetNamedFunction
|
||||
}
|
||||
|
||||
private fun generateEquals(project: Project, info: Info): JetNamedFunction? {
|
||||
with(info) {
|
||||
if (!needEquals) return null
|
||||
|
||||
val superEquals = classDescriptor.getSuperClassOrAny().findDeclaredEquals(true)!!
|
||||
val equalsFun = generateFunctionSkeleton(superEquals, project)
|
||||
|
||||
val paramName = equalsFun.valueParameters.first().name!!.quoteIfNeeded()
|
||||
var typeForCast = IdeDescriptorRenderers.SOURCE_CODE.renderClassifierName(classDescriptor)
|
||||
val typeParams = classDescriptor.defaultType.constructor.parameters
|
||||
if (typeParams.isNotEmpty()) {
|
||||
typeForCast += typeParams.map { "*" }.joinToString(prefix = "<", postfix = ">")
|
||||
}
|
||||
|
||||
val useIsCheck = CodeInsightSettings.getInstance().USE_INSTANCEOF_ON_EQUALS_PARAMETER
|
||||
val isNotInstanceCondition = if (useIsCheck) "$paramName !is $typeForCast" else "$paramName?.javaClass != javaClass"
|
||||
val bodyText = StringBuilder().apply {
|
||||
append("if (this === $paramName) return true\n")
|
||||
append("if ($isNotInstanceCondition) return false\n")
|
||||
if (!superEquals.isMemberOfAny()) {
|
||||
append("if (!super.equals($paramName)) return false\n")
|
||||
}
|
||||
|
||||
if (variablesForEquals.isNotEmpty()) {
|
||||
if (!useIsCheck) {
|
||||
append("\n$paramName as $typeForCast\n")
|
||||
}
|
||||
|
||||
append('\n')
|
||||
|
||||
variablesForEquals.forEach {
|
||||
val propName = it.name.asString()
|
||||
append("if ($propName != $paramName.$propName) return false\n")
|
||||
}
|
||||
|
||||
append('\n')
|
||||
}
|
||||
|
||||
append("return true")
|
||||
}
|
||||
|
||||
equalsFun.bodyExpression!!.replace(JetPsiFactory(project).createExpression("{\n$bodyText\n}"))
|
||||
|
||||
return equalsFun
|
||||
}
|
||||
}
|
||||
private fun generateHashCode(project: Project, info: Info): JetNamedFunction? {
|
||||
fun VariableDescriptor.genVariableHashCode(parenthesesNeeded: Boolean): String {
|
||||
val ref = name.asString().quoteIfNeeded()
|
||||
val isNullable = TypeUtils.isNullableType(type)
|
||||
|
||||
val builtIns = builtIns
|
||||
|
||||
var text = when (type.constructor.declarationDescriptor) {
|
||||
builtIns.byte, builtIns.short, builtIns.int -> ref
|
||||
else -> if (isNullable) "$ref?.hashCode()" else "$ref.hashCode()"
|
||||
}
|
||||
if (isNullable) {
|
||||
text += " ?: 0"
|
||||
if (parenthesesNeeded) {
|
||||
text = "($text)"
|
||||
}
|
||||
}
|
||||
|
||||
return text
|
||||
}
|
||||
|
||||
with(info) {
|
||||
if (!needHashCode) return null
|
||||
|
||||
val superHashCode = classDescriptor.getSuperClassOrAny().findDeclaredHashCode(true)!!
|
||||
val hashCodeFun = generateFunctionSkeleton(superHashCode, project)
|
||||
|
||||
val propertyIterator = variablesForHashCode.iterator()
|
||||
val initialValue = when {
|
||||
!superHashCode.isMemberOfAny() -> "super.hashCode()"
|
||||
propertyIterator.hasNext() -> propertyIterator.next().genVariableHashCode(false)
|
||||
else -> "0"
|
||||
}
|
||||
|
||||
val bodyText = if (propertyIterator.hasNext()) {
|
||||
val validator = CollectingNameValidator(variablesForEquals.map { it.name.asString().quoteIfNeeded() })
|
||||
val resultVarName = KotlinNameSuggester.suggestNameByName("result", validator)
|
||||
StringBuilder().apply {
|
||||
append("var $resultVarName = $initialValue\n")
|
||||
propertyIterator.forEach { append("$resultVarName += 31 * $resultVarName + ${it.genVariableHashCode(true)}\n") }
|
||||
append("return $resultVarName")
|
||||
}.toString()
|
||||
} else "return $initialValue"
|
||||
|
||||
hashCodeFun.bodyExpression!!.replace(JetPsiFactory(project).createExpression("{\n$bodyText\n}"))
|
||||
|
||||
return hashCodeFun
|
||||
}
|
||||
}
|
||||
|
||||
override fun generateMembers(project: Project, editor: Editor, info: Info): List<JetDeclaration> {
|
||||
val targetClass = info.classDescriptor.source.getPsi() as JetClass
|
||||
val prototypes = ArrayList<JetDeclaration>(2)
|
||||
.apply {
|
||||
addIfNotNull(generateEquals(project, info))
|
||||
addIfNotNull(generateHashCode(project, info))
|
||||
}
|
||||
val anchor = with(targetClass.declarations) { lastIsInstanceOrNull<JetNamedFunction>() ?: lastOrNull() }
|
||||
return insertMembersAfter(editor, targetClass, prototypes, anchor)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.actions.generate
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightBundle
|
||||
import com.intellij.codeInsight.CodeInsightSettings
|
||||
import com.intellij.codeInsight.generation.ui.AbstractGenerateEqualsWizard
|
||||
import com.intellij.ide.wizard.StepAdapter
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.VerticalFlowLayout
|
||||
import com.intellij.refactoring.classMembers.AbstractMemberInfoModel
|
||||
import com.intellij.ui.NonFocusableCheckBox
|
||||
import com.intellij.util.containers.HashMap
|
||||
import org.jetbrains.kotlin.idea.refactoring.memberInfo.KotlinMemberInfo
|
||||
import org.jetbrains.kotlin.idea.refactoring.memberInfo.KotlinMemberSelectionPanel
|
||||
import org.jetbrains.kotlin.psi.JetClass
|
||||
import org.jetbrains.kotlin.psi.JetNamedDeclaration
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isInheritable
|
||||
import org.jetbrains.kotlin.utils.keysToMap
|
||||
import javax.swing.JLabel
|
||||
import javax.swing.JPanel
|
||||
|
||||
class KotlinGenerateEqualsWizard(
|
||||
project: Project,
|
||||
klass: JetClass,
|
||||
properties: List<JetNamedDeclaration>,
|
||||
needEquals: Boolean,
|
||||
needHashCode: Boolean
|
||||
) : AbstractGenerateEqualsWizard<JetClass, JetNamedDeclaration, KotlinMemberInfo>(
|
||||
project, KotlinGenerateEqualsWizard.BuilderImpl(klass, properties, needEquals, needHashCode)
|
||||
) {
|
||||
private object MemberInfoModelImpl : AbstractMemberInfoModel<JetNamedDeclaration, KotlinMemberInfo>()
|
||||
|
||||
private class BuilderImpl(
|
||||
private val klass: JetClass,
|
||||
properties: List<JetNamedDeclaration>,
|
||||
needEquals: Boolean,
|
||||
needHashCode: Boolean
|
||||
) : AbstractGenerateEqualsWizard.Builder<JetClass, JetNamedDeclaration, KotlinMemberInfo>() {
|
||||
private val equalsPanel: KotlinMemberSelectionPanel?
|
||||
private val hashCodePanel: KotlinMemberSelectionPanel?
|
||||
|
||||
private val memberInfos = properties.map { createMemberInfo(it) }
|
||||
|
||||
private val membersToHashCode = HashMap(properties.keysToMap { createMemberInfo(it) })
|
||||
|
||||
init {
|
||||
equalsPanel = if (needEquals) {
|
||||
KotlinMemberSelectionPanel("Choose p&roperties to be included in equals()", memberInfos, null).apply {
|
||||
table.memberInfoModel = MemberInfoModelImpl
|
||||
}
|
||||
} else null
|
||||
|
||||
hashCodePanel = if (needHashCode) {
|
||||
KotlinMemberSelectionPanel("Choose p&roperties to be included in hashCode()", memberInfos, null).apply {
|
||||
table.memberInfoModel = MemberInfoModelImpl
|
||||
}
|
||||
} else null
|
||||
}
|
||||
|
||||
private fun createMemberInfo(it: JetNamedDeclaration) = KotlinMemberInfo(it).apply { isChecked = true }
|
||||
|
||||
override fun getPsiClass() = klass
|
||||
|
||||
override fun getClassFields() = memberInfos
|
||||
|
||||
override fun getFieldsToHashCode() = membersToHashCode
|
||||
|
||||
override fun getFieldsToNonNull() = HashMap<JetNamedDeclaration, KotlinMemberInfo>()
|
||||
|
||||
override fun getEqualsPanel() = equalsPanel
|
||||
|
||||
override fun getHashCodePanel() = hashCodePanel
|
||||
|
||||
override fun getNonNullPanel() = null
|
||||
|
||||
override fun updateHashCodeMemberInfos(equalsMemberInfos: MutableCollection<KotlinMemberInfo>) {
|
||||
hashCodePanel?.table?.setMemberInfos(equalsMemberInfos.map { membersToHashCode[it.member] })
|
||||
}
|
||||
|
||||
override fun updateNonNullMemberInfos(equalsMemberInfos: MutableCollection<KotlinMemberInfo>?) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private object OptionsStep : StepAdapter() {
|
||||
private val panel = JPanel(VerticalFlowLayout())
|
||||
|
||||
init {
|
||||
with(NonFocusableCheckBox(CodeInsightBundle.message("generate.equals.hashcode.accept.sublcasses"))) {
|
||||
isSelected = CodeInsightSettings.getInstance().USE_INSTANCEOF_ON_EQUALS_PARAMETER
|
||||
addActionListener { CodeInsightSettings.getInstance().USE_INSTANCEOF_ON_EQUALS_PARAMETER = isSelected }
|
||||
panel.add(this)
|
||||
}
|
||||
panel.add(JLabel(CodeInsightBundle.message("generate.equals.hashcode.accept.sublcasses.explanation")))
|
||||
}
|
||||
|
||||
override fun getComponent() = panel
|
||||
}
|
||||
|
||||
override fun addSteps() {
|
||||
if (myEqualsPanel != null && myClass.isInheritable()) {
|
||||
addStep(OptionsStep)
|
||||
}
|
||||
super.addSteps()
|
||||
}
|
||||
|
||||
override fun doOKAction() {
|
||||
myEqualsPanel?.let { updateHashCodeMemberInfos(it.table.selectedMemberInfos) }
|
||||
super.doOKAction()
|
||||
}
|
||||
|
||||
fun getPropertiesForEquals() = myEqualsPanel?.table?.selectedMemberInfos?.map { it.member } ?: emptyList()
|
||||
|
||||
fun getPropertiesForHashCode() = myHashCodePanel?.table?.selectedMemberInfos?.map { it.member } ?: emptyList()
|
||||
}
|
||||
+4
-4
@@ -28,18 +28,18 @@ import org.jetbrains.kotlin.psi.JetClassOrObject
|
||||
import org.jetbrains.kotlin.psi.JetDeclaration
|
||||
|
||||
abstract class KotlinGenerateMemberActionBase<Info : Any> : KotlinGenerateActionBase() {
|
||||
protected abstract fun prepareMembersInfo(klass: JetClassOrObject, project: Project): Info?
|
||||
protected abstract fun prepareMembersInfo(klass: JetClassOrObject, project: Project, editor: Editor): Info?
|
||||
|
||||
protected abstract fun generateMembers(editor: Editor, info: Info): List<JetDeclaration>
|
||||
protected abstract fun generateMembers(project: Project, editor: Editor, info: Info): List<JetDeclaration>
|
||||
|
||||
override fun invoke(project: Project, editor: Editor, file: PsiFile) {
|
||||
if (!CodeInsightUtilBase.prepareEditorForWrite(editor)) return
|
||||
if (!FileDocumentManager.getInstance().requestWriting(editor.document, project)) return
|
||||
val klass = getTargetClass(editor, file) ?: return
|
||||
val membersInfo = prepareMembersInfo(klass, project) ?: return
|
||||
val membersInfo = prepareMembersInfo(klass, project, editor) ?: return
|
||||
|
||||
project.executeWriteCommand(commandName, this) {
|
||||
val newMembers = generateMembers(editor, membersInfo)
|
||||
val newMembers = generateMembers(project, editor, membersInfo)
|
||||
GlobalInspectionContextBase.cleanupElements(project, null, *newMembers.toTypedArray())
|
||||
newMembers.firstOrNull()?.let { GenerateMembersUtil.positionCaret(editor, it, false) }
|
||||
}
|
||||
|
||||
+2
-2
@@ -100,7 +100,7 @@ class KotlinGenerateSecondaryConstructorAction : KotlinGenerateMemberActionBase<
|
||||
}
|
||||
}
|
||||
|
||||
override fun prepareMembersInfo(klass: JetClassOrObject, project: Project): Info? {
|
||||
override fun prepareMembersInfo(klass: JetClassOrObject, project: Project, editor: Editor): Info? {
|
||||
val context = klass.analyzeFully()
|
||||
val classDescriptor = context.get(BindingContext.CLASS, klass) ?: return null
|
||||
val superConstructors = chooseSuperConstructors(klass, classDescriptor).map { it.descriptor as ConstructorDescriptor }
|
||||
@@ -108,7 +108,7 @@ class KotlinGenerateSecondaryConstructorAction : KotlinGenerateMemberActionBase<
|
||||
return Info(propertiesToInitialize, superConstructors, classDescriptor)
|
||||
}
|
||||
|
||||
override fun generateMembers(editor: Editor, info: Info): List<JetDeclaration> {
|
||||
override fun generateMembers(project: Project, editor: Editor, info: Info): List<JetDeclaration> {
|
||||
val targetClass = info.classDescriptor.source.getPsi() as? JetClass ?: return emptyList()
|
||||
|
||||
fun Info.findAnchor(): PsiElement? {
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
// NOT_APPLICABLE
|
||||
annotation class A<caret>()
|
||||
@@ -0,0 +1,2 @@
|
||||
// NOT_APPLICABLE
|
||||
data class A<caret>(val n: Int)
|
||||
@@ -0,0 +1,6 @@
|
||||
// NOT_APPLICABLE
|
||||
enum class A {<caret>
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class A<T>(val n: T) {<caret>
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
class A<T>(val n: T) {
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
|
||||
<caret>override fun equals(other: Any?): Boolean{
|
||||
if (this === other) return true
|
||||
if (other?.javaClass != javaClass) return false
|
||||
|
||||
other as A<*>
|
||||
|
||||
if (n != other.n) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int{
|
||||
return n?.hashCode() ?: 0
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// USE_IS_CHECK
|
||||
class A<T>(val n: T) {<caret>
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// USE_IS_CHECK
|
||||
class A<T>(val n: T) {
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
|
||||
<caret>override fun equals(other: Any?): Boolean{
|
||||
if (this === other) return true
|
||||
if (other !is A<*>) return false
|
||||
|
||||
if (n != other.n) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int{
|
||||
return n?.hashCode() ?: 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
// NOT_APPLICABLE
|
||||
interface A {<caret>
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
class A(val n: Int, val s: String) {<caret>
|
||||
val f: Float = 1.0f
|
||||
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
class A(val n: Int, val s: String) {
|
||||
val f: Float = 1.0f
|
||||
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
|
||||
<caret>override fun equals(other: Any?): Boolean{
|
||||
if (this === other) return true
|
||||
if (other?.javaClass != javaClass) return false
|
||||
|
||||
other as A
|
||||
|
||||
if (n != other.n) return false
|
||||
if (s != other.s) return false
|
||||
if (f != other.f) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int{
|
||||
var result = n
|
||||
result += 31 * result + s.hashCode()
|
||||
result += 31 * result + f.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
class A(val n: Int?, val s: String) {<caret>
|
||||
val f: Float? = null
|
||||
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
class A(val n: Int?, val s: String) {
|
||||
val f: Float? = null
|
||||
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
|
||||
<caret>override fun equals(other: Any?): Boolean{
|
||||
if (this === other) return true
|
||||
if (other?.javaClass != javaClass) return false
|
||||
|
||||
other as A
|
||||
|
||||
if (n != other.n) return false
|
||||
if (s != other.s) return false
|
||||
if (f != other.f) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int{
|
||||
var result = n ?: 0
|
||||
result += 31 * result + s.hashCode()
|
||||
result += 31 * result + (f?.hashCode() ?: 0)
|
||||
return result
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
open class X {
|
||||
override fun equals(other: Any?) = super.equals(other)
|
||||
override fun hashCode() = super.hashCode()
|
||||
}
|
||||
|
||||
class A(val n: Int, val s: String) : X() {<caret>
|
||||
val f: Float = 1.0f
|
||||
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
open class X {
|
||||
override fun equals(other: Any?) = super.equals(other)
|
||||
override fun hashCode() = super.hashCode()
|
||||
}
|
||||
|
||||
class A(val n: Int, val s: String) : X() {
|
||||
val f: Float = 1.0f
|
||||
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
|
||||
<caret>override fun equals(other: Any?): Boolean{
|
||||
if (this === other) return true
|
||||
if (other?.javaClass != javaClass) return false
|
||||
if (!super.equals(other)) return false
|
||||
|
||||
other as A
|
||||
|
||||
if (n != other.n) return false
|
||||
if (s != other.s) return false
|
||||
if (f != other.f) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int{
|
||||
var result = super.hashCode()
|
||||
result += 31 * result + n
|
||||
result += 31 * result + s.hashCode()
|
||||
result += 31 * result + f.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class A(val result: Int, val s: String) {<caret>
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
class A(val result: Int, val s: String) {
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
|
||||
<caret>override fun equals(other: Any?): Boolean{
|
||||
if (this === other) return true
|
||||
if (other?.javaClass != javaClass) return false
|
||||
|
||||
other as A
|
||||
|
||||
if (result != other.result) return false
|
||||
if (s != other.s) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int{
|
||||
var result1 = result
|
||||
result1 += 31 * result1 + s.hashCode()
|
||||
return result1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
// NOT_APPLICABLE
|
||||
class A {<caret>
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
// FORCED
|
||||
class A {<caret>
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// FORCED
|
||||
class A {
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
|
||||
<caret>override fun equals(other: Any?): Boolean{
|
||||
if (this === other) return true
|
||||
if (other?.javaClass != javaClass) return false
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int{
|
||||
return 0
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// FORCED
|
||||
open class X {
|
||||
override fun equals(other: Any?) = super.equals(other)
|
||||
override fun hashCode() = super.hashCode()
|
||||
}
|
||||
|
||||
class A : X() {<caret>
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
// FORCED
|
||||
open class X {
|
||||
override fun equals(other: Any?) = super.equals(other)
|
||||
override fun hashCode() = super.hashCode()
|
||||
}
|
||||
|
||||
class A : X() {
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
|
||||
<caret>override fun equals(other: Any?): Boolean{
|
||||
if (this === other) return true
|
||||
if (other?.javaClass != javaClass) return false
|
||||
if (!super.equals(other)) return false
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int{
|
||||
return super.hashCode()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
// NOT_APPLICABLE
|
||||
object A {<caret>
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class A(val n: Int) {<caret>
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
class A(val n: Int) {
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
|
||||
<caret>override fun equals(other: Any?): Boolean{
|
||||
if (this === other) return true
|
||||
if (other?.javaClass != javaClass) return false
|
||||
|
||||
other as A
|
||||
|
||||
if (n != other.n) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int{
|
||||
return n
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class A(val n: Int?) {<caret>
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
class A(val n: Int?) {
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
|
||||
<caret>override fun equals(other: Any?): Boolean{
|
||||
if (this === other) return true
|
||||
if (other?.javaClass != javaClass) return false
|
||||
|
||||
other as A
|
||||
|
||||
if (n != other.n) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int{
|
||||
return n ?: 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
// USE_IS_CHECK
|
||||
class A(val n: Int) {<caret>
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// USE_IS_CHECK
|
||||
class A(val n: Int) {
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
|
||||
<caret>override fun equals(other: Any?): Boolean{
|
||||
if (this === other) return true
|
||||
if (other !is A) return false
|
||||
|
||||
if (n != other.n) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int{
|
||||
return n
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
public class X {
|
||||
public boolean equals(Object object) {
|
||||
return super.equals(object);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return super.hashCode();
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
class A(val n: Int) : X() {<caret>
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
class A(val n: Int) : X() {
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
|
||||
<caret>override fun equals(other: Any?): Boolean{
|
||||
if (this === other) return true
|
||||
if (other?.javaClass != javaClass) return false
|
||||
if (!super.equals(other)) return false
|
||||
|
||||
other as A
|
||||
|
||||
if (n != other.n) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int{
|
||||
var result = super.hashCode()
|
||||
result += 31 * result + n
|
||||
return result
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
open class X {
|
||||
override fun equals(other: Any?) = super.equals(other)
|
||||
override fun hashCode() = super.hashCode()
|
||||
}
|
||||
|
||||
class A(val n: Int) : X() {<caret>
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
open class X {
|
||||
override fun equals(other: Any?) = super.equals(other)
|
||||
override fun hashCode() = super.hashCode()
|
||||
}
|
||||
|
||||
class A(val n: Int) : X() {
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
|
||||
<caret>override fun equals(other: Any?): Boolean{
|
||||
if (this === other) return true
|
||||
if (other?.javaClass != javaClass) return false
|
||||
if (!super.equals(other)) return false
|
||||
|
||||
other as A
|
||||
|
||||
if (n != other.n) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int{
|
||||
var result = super.hashCode()
|
||||
result += 31 * result + n
|
||||
return result
|
||||
}
|
||||
}
|
||||
+24
-5
@@ -17,9 +17,12 @@
|
||||
package org.jetbrains.kotlin.idea.codeInsight.generate
|
||||
|
||||
import com.intellij.codeInsight.actions.CodeInsightAction
|
||||
import com.intellij.openapi.actionSystem.AnAction
|
||||
import com.intellij.openapi.actionSystem.Presentation
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.refactoring.util.CommonRefactoringUtil
|
||||
import com.intellij.testFramework.PlatformTestUtil
|
||||
import com.intellij.testFramework.TestActionEvent
|
||||
import junit.framework.TestCase
|
||||
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil
|
||||
import org.jetbrains.kotlin.idea.test.JetLightCodeInsightFixtureTestCase
|
||||
@@ -29,6 +32,20 @@ import org.jetbrains.kotlin.test.JetTestUtils
|
||||
import java.io.File
|
||||
|
||||
abstract class AbstractGenerateActionTest : JetLightCodeInsightFixtureTestCase() {
|
||||
protected open fun createAction(fileText: String): CodeInsightAction {
|
||||
val actionClassName = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// ACTION_CLASS: ")
|
||||
return Class.forName(actionClassName).newInstance() as CodeInsightAction
|
||||
}
|
||||
|
||||
private fun testAction(action: AnAction, forced: Boolean): Presentation {
|
||||
val e = TestActionEvent(action)
|
||||
action.beforeActionPerformedUpdate(e)
|
||||
if (forced || (e.presentation.isEnabled && e.presentation.isVisible)) {
|
||||
action.actionPerformed(e)
|
||||
}
|
||||
return e.presentation
|
||||
}
|
||||
|
||||
protected open fun doTest(path: String) {
|
||||
val fileText = FileUtil.loadFile(File(path), true)
|
||||
|
||||
@@ -50,17 +67,19 @@ abstract class AbstractGenerateActionTest : JetLightCodeInsightFixtureTestCase()
|
||||
}
|
||||
myFixture.configureByFile(path)
|
||||
|
||||
val actionClassName = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// ACTION_CLASS: ")
|
||||
val action = Class.forName(actionClassName).newInstance() as CodeInsightAction
|
||||
val action = createAction(fileText)
|
||||
|
||||
val isApplicableExpected = !InTextDirectivesUtils.isDirectiveDefined(fileText, "// NOT_APPLICABLE")
|
||||
val isForced = InTextDirectivesUtils.isDirectiveDefined(fileText, "// FORCED")
|
||||
|
||||
val presentation = myFixture.testAction(action)
|
||||
TestCase.assertEquals(isApplicableExpected, presentation.isEnabled)
|
||||
val presentation = testAction(action, isForced)
|
||||
if (!isForced) {
|
||||
TestCase.assertEquals(isApplicableExpected, presentation.isEnabled)
|
||||
}
|
||||
|
||||
assert(!conflictFile.exists()) { "Conflict file $conflictFile should not exist" }
|
||||
|
||||
if (isApplicableExpected) {
|
||||
if (isForced || isApplicableExpected) {
|
||||
val afterFile = File("$path.after")
|
||||
TestCase.assertTrue(afterFile.exists())
|
||||
myFixture.checkResult(FileUtil.loadFile(afterFile, true))
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.codeInsight.generate
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightSettings
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import org.jetbrains.kotlin.idea.actions.generate.KotlinGenerateEqualsAndHashcodeAction
|
||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||
import java.io.File
|
||||
|
||||
abstract class AbstractGenerateHashCodeAndEqualsActionTest : AbstractGenerateActionTest() {
|
||||
override fun createAction(fileText: String) = KotlinGenerateEqualsAndHashcodeAction()
|
||||
|
||||
override fun doTest(path: String) {
|
||||
val fileText = FileUtil.loadFile(File(path), true)
|
||||
|
||||
val codeInsightSettings = CodeInsightSettings.getInstance()
|
||||
val useInstanceOfOnEqualsParameterOld = codeInsightSettings.USE_INSTANCEOF_ON_EQUALS_PARAMETER
|
||||
|
||||
try {
|
||||
codeInsightSettings.USE_INSTANCEOF_ON_EQUALS_PARAMETER =
|
||||
InTextDirectivesUtils.isDirectiveDefined(fileText, "// USE_IS_CHECK")
|
||||
super.doTest(path)
|
||||
} finally {
|
||||
codeInsightSettings.USE_INSTANCEOF_ON_EQUALS_PARAMETER = useInstanceOfOnEqualsParameterOld
|
||||
}
|
||||
}
|
||||
}
|
||||
+151
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.codeInsight.generate;
|
||||
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
|
||||
import org.jetbrains.kotlin.test.JetTestUtils;
|
||||
import org.jetbrains.kotlin.test.TestMetadata;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("idea/testData/codeInsight/generate/equalsWithHashCode")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public class GenerateHashCodeAndEqualsActionTestGenerated extends AbstractGenerateHashCodeAndEqualsActionTest {
|
||||
public void testAllFilesPresentInEqualsWithHashCode() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/codeInsight/generate/equalsWithHashCode"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("annotation.kt")
|
||||
public void testAnnotation() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/generate/equalsWithHashCode/annotation.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("dataClass.kt")
|
||||
public void testDataClass() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/generate/equalsWithHashCode/dataClass.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enum.kt")
|
||||
public void testEnum() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/generate/equalsWithHashCode/enum.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("genericClass.kt")
|
||||
public void testGenericClass() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/generate/equalsWithHashCode/genericClass.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("genericClassWithIsCheck.kt")
|
||||
public void testGenericClassWithIsCheck() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/generate/equalsWithHashCode/genericClassWithIsCheck.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("interface.kt")
|
||||
public void testInterface() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/generate/equalsWithHashCode/interface.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("multipleVars.kt")
|
||||
public void testMultipleVars() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/generate/equalsWithHashCode/multipleVars.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("multipleVarsNullable.kt")
|
||||
public void testMultipleVarsNullable() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/generate/equalsWithHashCode/multipleVarsNullable.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("multipleVarsWithSuperClass.kt")
|
||||
public void testMultipleVarsWithSuperClass() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/generate/equalsWithHashCode/multipleVarsWithSuperClass.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("nameClash.kt")
|
||||
public void testNameClash() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/generate/equalsWithHashCode/nameClash.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("noVars.kt")
|
||||
public void testNoVars() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/generate/equalsWithHashCode/noVars.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("noVarsForced.kt")
|
||||
public void testNoVarsForced() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/generate/equalsWithHashCode/noVarsForced.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("noVarsForcedWithSuperClass.kt")
|
||||
public void testNoVarsForcedWithSuperClass() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/generate/equalsWithHashCode/noVarsForcedWithSuperClass.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("object.kt")
|
||||
public void testObject() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/generate/equalsWithHashCode/object.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("singleVar.kt")
|
||||
public void testSingleVar() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/generate/equalsWithHashCode/singleVar.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("singleVarNullable.kt")
|
||||
public void testSingleVarNullable() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/generate/equalsWithHashCode/singleVarNullable.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("singleVarWithIsCheck.kt")
|
||||
public void testSingleVarWithIsCheck() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/generate/equalsWithHashCode/singleVarWithIsCheck.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("singleVarWithJavaSuperClass.kt")
|
||||
public void testSingleVarWithJavaSuperClass() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/generate/equalsWithHashCode/singleVarWithJavaSuperClass.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("singleVarWithSuperClass.kt")
|
||||
public void testSingleVarWithSuperClass() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/codeInsight/generate/equalsWithHashCode/singleVarWithSuperClass.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user