From 619df3a53e757ee2da3ee8f9791b326ded241ed4 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Thu, 9 Oct 2014 18:18:41 +0400 Subject: [PATCH] Use semantic equality in Create From Usage --- .../callableBuilder/CallableBuilder.kt | 30 +++++++++++++------ .../callableBuilder/typeUtils.kt | 4 +-- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/createFromUsage/callableBuilder/CallableBuilder.kt b/idea/src/org/jetbrains/jet/plugin/quickfix/createFromUsage/callableBuilder/CallableBuilder.kt index 9b07b9781a4..cbe83bb9cfa 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/createFromUsage/callableBuilder/CallableBuilder.kt +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/createFromUsage/callableBuilder/CallableBuilder.kt @@ -55,10 +55,10 @@ import com.intellij.util.ArrayUtil import com.intellij.psi.PsiWhiteSpace import com.intellij.psi.PsiElement import org.jetbrains.jet.lexer.JetTokens -import org.jetbrains.jet.plugin.quickfix.createFromUsage.createFunction import org.jetbrains.jet.plugin.util.application.runWriteAction import org.jetbrains.jet.plugin.refactoring.isMultiLine -import org.jetbrains.jet.plugin.intentions.declarations.DeclarationUtils +import org.jetbrains.kotlin.util.printAndReturn +import org.jetbrains.jet.lang.types.checker.JetTypeChecker private val TYPE_PARAMETER_LIST_VARIABLE_NAME = "typeParameterList" private val TEMPLATE_FROM_USAGE_FUNCTION_BODY = "New Kotlin Function Body.kt" @@ -89,6 +89,8 @@ class TypeCandidate(val theType: JetType, scope: JetScope? = null) { typeParameters = getTypeParameterNamesNotInScope(typeParametersInType, scope).copyToArray(); } } + + override fun toString() = theType.toString() } class CallableBuilderConfiguration( @@ -130,22 +132,29 @@ class CallableBuilder(val config: CallableBuilderConfiguration) { return typeCandidates.getOrPut(typeInfo) { val types = typeInfo.getPossibleTypes(this).reverse() - val newTypes = LinkedHashSet(types) + // We have to use semantic equality here + [data] class EqWrapper(val _type: JetType) { + override fun equals(other: Any?) = this === other + || other is EqWrapper && JetTypeChecker.DEFAULT.equalTypes(_type, other._type) + override fun hashCode() = 0 // no good way to compute hashCode() that would agree with our equals() + } + + val newTypes = LinkedHashSet(types.map { EqWrapper(it) }) for (substitution in substitutions) { // each substitution can be applied or not, so we offer all options - val toAdd = newTypes.map { theType -> theType.substitute(substitution, typeInfo.variance) } + val toAdd = newTypes.map { it._type.substitute(substitution, typeInfo.variance) } // substitution.byType are type arguments, but they cannot already occur in the type before substitution - val toRemove = newTypes.filter { theType -> substitution.byType in theType } + val toRemove = newTypes.filter { substitution.byType in it._type } - newTypes.addAll(toAdd) + newTypes.addAll(toAdd.map { EqWrapper(it) }) newTypes.removeAll(toRemove) } if (newTypes.empty) { - newTypes.add(KotlinBuiltIns.getInstance().getAnyType()) + newTypes.add(EqWrapper(KotlinBuiltIns.getInstance().getAnyType())) } - newTypes.map { TypeCandidate(it, scope) }.reverse() + newTypes.map { TypeCandidate(it._type, scope) }.reverse() } } @@ -217,7 +226,10 @@ class CallableBuilder(val config: CallableBuilderConfiguration) { val substitutions = ownerTypeArguments.zip(classTypeParameters).map { JetTypeSubstitution(it.first.getType(), it.second.getType()) }.copyToArray() - config.callableInfo.parameterInfos.forEach { parameter -> computeTypeCandidates(parameter.typeInfo, substitutions, scope) } + config.callableInfo.parameterInfos.forEach { + parameter -> + computeTypeCandidates(parameter.typeInfo, substitutions, scope) + } if (!isUnit) { computeTypeCandidates(config.callableInfo.returnTypeInfo, substitutions, scope) } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/createFromUsage/callableBuilder/typeUtils.kt b/idea/src/org/jetbrains/jet/plugin/quickfix/createFromUsage/callableBuilder/typeUtils.kt index 47c9e622be8..87eb3f6e5d3 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/createFromUsage/callableBuilder/typeUtils.kt +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/createFromUsage/callableBuilder/typeUtils.kt @@ -25,7 +25,7 @@ import org.jetbrains.jet.lang.types.JetTypeImpl import org.jetbrains.jet.lang.psi.psiUtil.getAssignmentByLHS private fun JetType.contains(inner: JetType): Boolean { - return this == inner || getArguments().any { inner in it.getType() } + return JetTypeChecker.DEFAULT.equalTypes(this, inner) || getArguments().any { inner in it.getType() } } private fun DeclarationDescriptor.render( @@ -167,7 +167,7 @@ private class JetTypeSubstitution(public val forType: JetType, public val byType private fun JetType.substitute(substitution: JetTypeSubstitution, variance: Variance): JetType { if (when (variance) { - Variance.INVARIANT -> this == substitution.forType + Variance.INVARIANT -> JetTypeChecker.DEFAULT.equalTypes(this, substitution.forType) Variance.IN_VARIANCE -> JetTypeChecker.DEFAULT.isSubtypeOf(this, substitution.forType) Variance.OUT_VARIANCE -> JetTypeChecker.DEFAULT.isSubtypeOf(substitution.forType, this) }) {