Use semantic equality in Create From Usage
This commit is contained in:
+21
-9
@@ -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)
|
||||
}
|
||||
|
||||
+2
-2
@@ -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)
|
||||
}) {
|
||||
|
||||
Reference in New Issue
Block a user