diff --git a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt index eaf863a8388..c8a64bc9a0e 100644 --- a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt +++ b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt @@ -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) { model("codeInsight/generate/testFrameworkSupport") } + testClass() { + model("codeInsight/generate/equalsWithHashCode") + } + testClass() { model("codeInsight/generate/secondaryConstructors") } diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index f190b1d6813..173ab8c93c9 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -173,6 +173,9 @@ + diff --git a/idea/src/org/jetbrains/kotlin/idea/actions/generate/KotlinGenerateEqualsAndHashcodeAction.kt b/idea/src/org/jetbrains/kotlin/idea/actions/generate/KotlinGenerateEqualsAndHashcodeAction.kt new file mode 100644 index 00000000000..3b47c3df178 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/actions/generate/KotlinGenerateEqualsAndHashcodeAction.kt @@ -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() { + 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, + val variablesForHashCode: List + ) + + 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 { + return ArrayList().apply { + getPrimaryConstructorParameters().filterTo(this) { it.hasValOrVar() } + declarations.filterIsInstance().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 { + val targetClass = info.classDescriptor.source.getPsi() as JetClass + val prototypes = ArrayList(2) + .apply { + addIfNotNull(generateEquals(project, info)) + addIfNotNull(generateHashCode(project, info)) + } + val anchor = with(targetClass.declarations) { lastIsInstanceOrNull() ?: lastOrNull() } + return insertMembersAfter(editor, targetClass, prototypes, anchor) + } +} diff --git a/idea/src/org/jetbrains/kotlin/idea/actions/generate/KotlinGenerateEqualsWizard.kt b/idea/src/org/jetbrains/kotlin/idea/actions/generate/KotlinGenerateEqualsWizard.kt new file mode 100644 index 00000000000..da9588bd2d4 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/actions/generate/KotlinGenerateEqualsWizard.kt @@ -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, + needEquals: Boolean, + needHashCode: Boolean +) : AbstractGenerateEqualsWizard( + project, KotlinGenerateEqualsWizard.BuilderImpl(klass, properties, needEquals, needHashCode) +) { + private object MemberInfoModelImpl : AbstractMemberInfoModel() + + private class BuilderImpl( + private val klass: JetClass, + properties: List, + needEquals: Boolean, + needHashCode: Boolean + ) : AbstractGenerateEqualsWizard.Builder() { + 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() + + override fun getEqualsPanel() = equalsPanel + + override fun getHashCodePanel() = hashCodePanel + + override fun getNonNullPanel() = null + + override fun updateHashCodeMemberInfos(equalsMemberInfos: MutableCollection) { + hashCodePanel?.table?.setMemberInfos(equalsMemberInfos.map { membersToHashCode[it.member] }) + } + + override fun updateNonNullMemberInfos(equalsMemberInfos: MutableCollection?) { + + } + } + + 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() +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/actions/generate/KotlinGenerateMemberActionBase.kt b/idea/src/org/jetbrains/kotlin/idea/actions/generate/KotlinGenerateMemberActionBase.kt index c4874deccad..5e607448729 100644 --- a/idea/src/org/jetbrains/kotlin/idea/actions/generate/KotlinGenerateMemberActionBase.kt +++ b/idea/src/org/jetbrains/kotlin/idea/actions/generate/KotlinGenerateMemberActionBase.kt @@ -28,18 +28,18 @@ import org.jetbrains.kotlin.psi.JetClassOrObject import org.jetbrains.kotlin.psi.JetDeclaration abstract class KotlinGenerateMemberActionBase : 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 + protected abstract fun generateMembers(project: Project, editor: Editor, info: Info): List 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) } } diff --git a/idea/src/org/jetbrains/kotlin/idea/actions/generate/KotlinGenerateSecondaryConstructorAction.kt b/idea/src/org/jetbrains/kotlin/idea/actions/generate/KotlinGenerateSecondaryConstructorAction.kt index 5c4efb91dd4..c39f76ee03c 100644 --- a/idea/src/org/jetbrains/kotlin/idea/actions/generate/KotlinGenerateSecondaryConstructorAction.kt +++ b/idea/src/org/jetbrains/kotlin/idea/actions/generate/KotlinGenerateSecondaryConstructorAction.kt @@ -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 { + override fun generateMembers(project: Project, editor: Editor, info: Info): List { val targetClass = info.classDescriptor.source.getPsi() as? JetClass ?: return emptyList() fun Info.findAnchor(): PsiElement? { diff --git a/idea/testData/codeInsight/generate/equalsWithHashCode/annotation.kt b/idea/testData/codeInsight/generate/equalsWithHashCode/annotation.kt new file mode 100644 index 00000000000..881d85168d3 --- /dev/null +++ b/idea/testData/codeInsight/generate/equalsWithHashCode/annotation.kt @@ -0,0 +1,2 @@ +// NOT_APPLICABLE +annotation class A() \ No newline at end of file diff --git a/idea/testData/codeInsight/generate/equalsWithHashCode/dataClass.kt b/idea/testData/codeInsight/generate/equalsWithHashCode/dataClass.kt new file mode 100644 index 00000000000..9cc91f7fdc9 --- /dev/null +++ b/idea/testData/codeInsight/generate/equalsWithHashCode/dataClass.kt @@ -0,0 +1,2 @@ +// NOT_APPLICABLE +data class A(val n: Int) \ No newline at end of file diff --git a/idea/testData/codeInsight/generate/equalsWithHashCode/enum.kt b/idea/testData/codeInsight/generate/equalsWithHashCode/enum.kt new file mode 100644 index 00000000000..fdc70a815e4 --- /dev/null +++ b/idea/testData/codeInsight/generate/equalsWithHashCode/enum.kt @@ -0,0 +1,6 @@ +// NOT_APPLICABLE +enum class A { + fun foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/generate/equalsWithHashCode/genericClass.kt b/idea/testData/codeInsight/generate/equalsWithHashCode/genericClass.kt new file mode 100644 index 00000000000..31ae3477b0f --- /dev/null +++ b/idea/testData/codeInsight/generate/equalsWithHashCode/genericClass.kt @@ -0,0 +1,5 @@ +class A(val n: T) { + fun foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/generate/equalsWithHashCode/genericClass.kt.after b/idea/testData/codeInsight/generate/equalsWithHashCode/genericClass.kt.after new file mode 100644 index 00000000000..c43cd486488 --- /dev/null +++ b/idea/testData/codeInsight/generate/equalsWithHashCode/genericClass.kt.after @@ -0,0 +1,20 @@ +class A(val n: T) { + fun foo() { + + } + + 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 + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/generate/equalsWithHashCode/genericClassWithIsCheck.kt b/idea/testData/codeInsight/generate/equalsWithHashCode/genericClassWithIsCheck.kt new file mode 100644 index 00000000000..c9450af1105 --- /dev/null +++ b/idea/testData/codeInsight/generate/equalsWithHashCode/genericClassWithIsCheck.kt @@ -0,0 +1,6 @@ +// USE_IS_CHECK +class A(val n: T) { + fun foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/generate/equalsWithHashCode/genericClassWithIsCheck.kt.after b/idea/testData/codeInsight/generate/equalsWithHashCode/genericClassWithIsCheck.kt.after new file mode 100644 index 00000000000..e8ec46e8636 --- /dev/null +++ b/idea/testData/codeInsight/generate/equalsWithHashCode/genericClassWithIsCheck.kt.after @@ -0,0 +1,19 @@ +// USE_IS_CHECK +class A(val n: T) { + fun foo() { + + } + + 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 + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/generate/equalsWithHashCode/interface.kt b/idea/testData/codeInsight/generate/equalsWithHashCode/interface.kt new file mode 100644 index 00000000000..f430c6033fc --- /dev/null +++ b/idea/testData/codeInsight/generate/equalsWithHashCode/interface.kt @@ -0,0 +1,6 @@ +// NOT_APPLICABLE +interface A { + fun foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/generate/equalsWithHashCode/multipleVars.kt b/idea/testData/codeInsight/generate/equalsWithHashCode/multipleVars.kt new file mode 100644 index 00000000000..88b879d570f --- /dev/null +++ b/idea/testData/codeInsight/generate/equalsWithHashCode/multipleVars.kt @@ -0,0 +1,7 @@ +class A(val n: Int, val s: String) { + val f: Float = 1.0f + + fun foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/generate/equalsWithHashCode/multipleVars.kt.after b/idea/testData/codeInsight/generate/equalsWithHashCode/multipleVars.kt.after new file mode 100644 index 00000000000..ae50339c5d1 --- /dev/null +++ b/idea/testData/codeInsight/generate/equalsWithHashCode/multipleVars.kt.after @@ -0,0 +1,27 @@ +class A(val n: Int, val s: String) { + val f: Float = 1.0f + + fun foo() { + + } + + 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 + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/generate/equalsWithHashCode/multipleVarsNullable.kt b/idea/testData/codeInsight/generate/equalsWithHashCode/multipleVarsNullable.kt new file mode 100644 index 00000000000..373c84cc70e --- /dev/null +++ b/idea/testData/codeInsight/generate/equalsWithHashCode/multipleVarsNullable.kt @@ -0,0 +1,7 @@ +class A(val n: Int?, val s: String) { + val f: Float? = null + + fun foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/generate/equalsWithHashCode/multipleVarsNullable.kt.after b/idea/testData/codeInsight/generate/equalsWithHashCode/multipleVarsNullable.kt.after new file mode 100644 index 00000000000..32f1d9b67d1 --- /dev/null +++ b/idea/testData/codeInsight/generate/equalsWithHashCode/multipleVarsNullable.kt.after @@ -0,0 +1,27 @@ +class A(val n: Int?, val s: String) { + val f: Float? = null + + fun foo() { + + } + + 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 + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/generate/equalsWithHashCode/multipleVarsWithSuperClass.kt b/idea/testData/codeInsight/generate/equalsWithHashCode/multipleVarsWithSuperClass.kt new file mode 100644 index 00000000000..53d4bd486a4 --- /dev/null +++ b/idea/testData/codeInsight/generate/equalsWithHashCode/multipleVarsWithSuperClass.kt @@ -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() { + val f: Float = 1.0f + + fun foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/generate/equalsWithHashCode/multipleVarsWithSuperClass.kt.after b/idea/testData/codeInsight/generate/equalsWithHashCode/multipleVarsWithSuperClass.kt.after new file mode 100644 index 00000000000..e409bb30dc8 --- /dev/null +++ b/idea/testData/codeInsight/generate/equalsWithHashCode/multipleVarsWithSuperClass.kt.after @@ -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() { + + } + + 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 + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/generate/equalsWithHashCode/nameClash.kt b/idea/testData/codeInsight/generate/equalsWithHashCode/nameClash.kt new file mode 100644 index 00000000000..23cf333d62e --- /dev/null +++ b/idea/testData/codeInsight/generate/equalsWithHashCode/nameClash.kt @@ -0,0 +1,5 @@ +class A(val result: Int, val s: String) { + fun foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/generate/equalsWithHashCode/nameClash.kt.after b/idea/testData/codeInsight/generate/equalsWithHashCode/nameClash.kt.after new file mode 100644 index 00000000000..0520eb4d71b --- /dev/null +++ b/idea/testData/codeInsight/generate/equalsWithHashCode/nameClash.kt.after @@ -0,0 +1,23 @@ +class A(val result: Int, val s: String) { + fun foo() { + + } + + 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 + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/generate/equalsWithHashCode/noVars.kt b/idea/testData/codeInsight/generate/equalsWithHashCode/noVars.kt new file mode 100644 index 00000000000..a3beae64071 --- /dev/null +++ b/idea/testData/codeInsight/generate/equalsWithHashCode/noVars.kt @@ -0,0 +1,6 @@ +// NOT_APPLICABLE +class A { + fun foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/generate/equalsWithHashCode/noVarsForced.kt b/idea/testData/codeInsight/generate/equalsWithHashCode/noVarsForced.kt new file mode 100644 index 00000000000..fd189b60ebb --- /dev/null +++ b/idea/testData/codeInsight/generate/equalsWithHashCode/noVarsForced.kt @@ -0,0 +1,6 @@ +// FORCED +class A { + fun foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/generate/equalsWithHashCode/noVarsForced.kt.after b/idea/testData/codeInsight/generate/equalsWithHashCode/noVarsForced.kt.after new file mode 100644 index 00000000000..3b43fc11f22 --- /dev/null +++ b/idea/testData/codeInsight/generate/equalsWithHashCode/noVarsForced.kt.after @@ -0,0 +1,16 @@ +// FORCED +class A { + fun foo() { + + } + + 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 + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/generate/equalsWithHashCode/noVarsForcedWithSuperClass.kt b/idea/testData/codeInsight/generate/equalsWithHashCode/noVarsForcedWithSuperClass.kt new file mode 100644 index 00000000000..664503f1ebe --- /dev/null +++ b/idea/testData/codeInsight/generate/equalsWithHashCode/noVarsForcedWithSuperClass.kt @@ -0,0 +1,11 @@ +// FORCED +open class X { + override fun equals(other: Any?) = super.equals(other) + override fun hashCode() = super.hashCode() +} + +class A : X() { + fun foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/generate/equalsWithHashCode/noVarsForcedWithSuperClass.kt.after b/idea/testData/codeInsight/generate/equalsWithHashCode/noVarsForcedWithSuperClass.kt.after new file mode 100644 index 00000000000..fd8cfdc9756 --- /dev/null +++ b/idea/testData/codeInsight/generate/equalsWithHashCode/noVarsForcedWithSuperClass.kt.after @@ -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() { + + } + + 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() + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/generate/equalsWithHashCode/object.kt b/idea/testData/codeInsight/generate/equalsWithHashCode/object.kt new file mode 100644 index 00000000000..692699c6ad3 --- /dev/null +++ b/idea/testData/codeInsight/generate/equalsWithHashCode/object.kt @@ -0,0 +1,6 @@ +// NOT_APPLICABLE +object A { + fun foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/generate/equalsWithHashCode/singleVar.kt b/idea/testData/codeInsight/generate/equalsWithHashCode/singleVar.kt new file mode 100644 index 00000000000..53550d65203 --- /dev/null +++ b/idea/testData/codeInsight/generate/equalsWithHashCode/singleVar.kt @@ -0,0 +1,5 @@ +class A(val n: Int) { + fun foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/generate/equalsWithHashCode/singleVar.kt.after b/idea/testData/codeInsight/generate/equalsWithHashCode/singleVar.kt.after new file mode 100644 index 00000000000..22a86c7565c --- /dev/null +++ b/idea/testData/codeInsight/generate/equalsWithHashCode/singleVar.kt.after @@ -0,0 +1,20 @@ +class A(val n: Int) { + fun foo() { + + } + + 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 + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/generate/equalsWithHashCode/singleVarNullable.kt b/idea/testData/codeInsight/generate/equalsWithHashCode/singleVarNullable.kt new file mode 100644 index 00000000000..14edb9cd411 --- /dev/null +++ b/idea/testData/codeInsight/generate/equalsWithHashCode/singleVarNullable.kt @@ -0,0 +1,5 @@ +class A(val n: Int?) { + fun foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/generate/equalsWithHashCode/singleVarNullable.kt.after b/idea/testData/codeInsight/generate/equalsWithHashCode/singleVarNullable.kt.after new file mode 100644 index 00000000000..4814af485d2 --- /dev/null +++ b/idea/testData/codeInsight/generate/equalsWithHashCode/singleVarNullable.kt.after @@ -0,0 +1,20 @@ +class A(val n: Int?) { + fun foo() { + + } + + 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 + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/generate/equalsWithHashCode/singleVarWithIsCheck.kt b/idea/testData/codeInsight/generate/equalsWithHashCode/singleVarWithIsCheck.kt new file mode 100644 index 00000000000..11d18193faa --- /dev/null +++ b/idea/testData/codeInsight/generate/equalsWithHashCode/singleVarWithIsCheck.kt @@ -0,0 +1,6 @@ +// USE_IS_CHECK +class A(val n: Int) { + fun foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/generate/equalsWithHashCode/singleVarWithIsCheck.kt.after b/idea/testData/codeInsight/generate/equalsWithHashCode/singleVarWithIsCheck.kt.after new file mode 100644 index 00000000000..0a00aea5095 --- /dev/null +++ b/idea/testData/codeInsight/generate/equalsWithHashCode/singleVarWithIsCheck.kt.after @@ -0,0 +1,19 @@ +// USE_IS_CHECK +class A(val n: Int) { + fun foo() { + + } + + 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 + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/generate/equalsWithHashCode/singleVarWithJavaSuperClass.java b/idea/testData/codeInsight/generate/equalsWithHashCode/singleVarWithJavaSuperClass.java new file mode 100644 index 00000000000..c2316c12695 --- /dev/null +++ b/idea/testData/codeInsight/generate/equalsWithHashCode/singleVarWithJavaSuperClass.java @@ -0,0 +1,9 @@ +public class X { + public boolean equals(Object object) { + return super.equals(object); + } + + public int hashCode() { + return super.hashCode(); + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/generate/equalsWithHashCode/singleVarWithJavaSuperClass.kt b/idea/testData/codeInsight/generate/equalsWithHashCode/singleVarWithJavaSuperClass.kt new file mode 100644 index 00000000000..13c22c28c90 --- /dev/null +++ b/idea/testData/codeInsight/generate/equalsWithHashCode/singleVarWithJavaSuperClass.kt @@ -0,0 +1,5 @@ +class A(val n: Int) : X() { + fun foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/generate/equalsWithHashCode/singleVarWithJavaSuperClass.kt.after b/idea/testData/codeInsight/generate/equalsWithHashCode/singleVarWithJavaSuperClass.kt.after new file mode 100644 index 00000000000..6f530d7417e --- /dev/null +++ b/idea/testData/codeInsight/generate/equalsWithHashCode/singleVarWithJavaSuperClass.kt.after @@ -0,0 +1,23 @@ +class A(val n: Int) : X() { + fun foo() { + + } + + 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 + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/generate/equalsWithHashCode/singleVarWithSuperClass.kt b/idea/testData/codeInsight/generate/equalsWithHashCode/singleVarWithSuperClass.kt new file mode 100644 index 00000000000..9b9b2e13347 --- /dev/null +++ b/idea/testData/codeInsight/generate/equalsWithHashCode/singleVarWithSuperClass.kt @@ -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() { + fun foo() { + + } +} \ No newline at end of file diff --git a/idea/testData/codeInsight/generate/equalsWithHashCode/singleVarWithSuperClass.kt.after b/idea/testData/codeInsight/generate/equalsWithHashCode/singleVarWithSuperClass.kt.after new file mode 100644 index 00000000000..0ec827ce992 --- /dev/null +++ b/idea/testData/codeInsight/generate/equalsWithHashCode/singleVarWithSuperClass.kt.after @@ -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() { + + } + + 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 + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/generate/AbstractGenerateActionTest.kt b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/generate/AbstractGenerateActionTest.kt index dd5d108cc0f..b84edf33e9b 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/generate/AbstractGenerateActionTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/generate/AbstractGenerateActionTest.kt @@ -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)) diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/generate/AbstractGenerateHashCodeAndEqualsActionTest.kt b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/generate/AbstractGenerateHashCodeAndEqualsActionTest.kt new file mode 100644 index 00000000000..2b202d48264 --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/generate/AbstractGenerateHashCodeAndEqualsActionTest.kt @@ -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 + } + } +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/generate/GenerateHashCodeAndEqualsActionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/generate/GenerateHashCodeAndEqualsActionTestGenerated.java new file mode 100644 index 00000000000..5ae6765f70b --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/generate/GenerateHashCodeAndEqualsActionTestGenerated.java @@ -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); + } +}