Smart completion works for cases when no exact type known (generic parameter substitution is not known)

This commit is contained in:
Valentin Kipyatkov
2015-07-21 01:20:50 +03:00
parent 7b0b2d38c5
commit a5384cdc28
12 changed files with 93 additions and 49 deletions
@@ -78,20 +78,26 @@ class FuzzyType(
}
}
public fun checkIsSubtypeOf(otherType: JetType): TypeSubstitutor?
public fun checkIsSubtypeOf(otherType: FuzzyType): TypeSubstitutor?
= matchedSubstitutor(otherType, MatchKind.IS_SUBTYPE)
public fun checkIsSuperTypeOf(otherType: JetType): TypeSubstitutor?
public fun checkIsSuperTypeOf(otherType: FuzzyType): TypeSubstitutor?
= matchedSubstitutor(otherType, MatchKind.IS_SUPERTYPE)
public fun checkIsSubtypeOf(otherType: JetType): TypeSubstitutor?
= checkIsSubtypeOf(FuzzyType(otherType, emptyList()))
public fun checkIsSuperTypeOf(otherType: JetType): TypeSubstitutor?
= checkIsSuperTypeOf(FuzzyType(otherType, emptyList()))
private enum class MatchKind {
IS_SUBTYPE,
IS_SUPERTYPE
}
private fun matchedSubstitutor(otherType: JetType, matchKind: MatchKind): TypeSubstitutor? {
private fun matchedSubstitutor(otherType: FuzzyType, matchKind: MatchKind): TypeSubstitutor? {
if (type.isError()) return null
if (otherType.isError()) return null
if (otherType.type.isError()) return null
fun JetType.checkInheritance(otherType: JetType): Boolean {
return when (matchKind) {
@@ -100,16 +106,17 @@ class FuzzyType(
}
}
if (freeParameters.isEmpty()) {
return if (type.checkInheritance(otherType)) TypeSubstitutor.EMPTY else null
if (freeParameters.isEmpty() && otherType.freeParameters.isEmpty()) {
return if (type.checkInheritance(otherType.type)) TypeSubstitutor.EMPTY else null
}
val constraintSystem = ConstraintSystemImpl()
constraintSystem.registerTypeVariables(freeParameters, { Variance.INVARIANT })
constraintSystem.registerTypeVariables(otherType.freeParameters, { Variance.INVARIANT })
when (matchKind) {
MatchKind.IS_SUBTYPE -> constraintSystem.addSubtypeConstraint(type, otherType, ConstraintPositionKind.RECEIVER_POSITION.position())
MatchKind.IS_SUPERTYPE -> constraintSystem.addSubtypeConstraint(otherType, type, ConstraintPositionKind.RECEIVER_POSITION.position())
MatchKind.IS_SUBTYPE -> constraintSystem.addSubtypeConstraint(type, otherType.type, ConstraintPositionKind.RECEIVER_POSITION.position())
MatchKind.IS_SUPERTYPE -> constraintSystem.addSubtypeConstraint(otherType.type, type, ConstraintPositionKind.RECEIVER_POSITION.position())
}
constraintSystem.fixVariables()
@@ -119,7 +126,11 @@ class FuzzyType(
// that's why we have to check subtyping manually
val substitutor = constraintSystem.getResultingSubstitutor()
val substitutedType = substitutor.substitute(type, Variance.INVARIANT)
return if (substitutedType != null && substitutedType.checkInheritance(otherType)) substitutor else null
val otherSubstitutedType = substitutor.substitute(otherType.type, Variance.INVARIANT)
return if (substitutedType != null && otherSubstitutedType != null && substitutedType.checkInheritance(otherSubstitutedType))
substitutor
else
null
}
else {
return null