Checking for conflicting substitutors in completion after "by"
This commit is contained in:
@@ -184,3 +184,18 @@ class FuzzyType(
|
||||
return TypeSubstitutor.create(TypeConstructorSubstitution.createByConstructorsMap(substitution))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun TypeSubstitution.hasConflictWith(other: TypeSubstitution, freeParameters: Collection<TypeParameterDescriptor>): Boolean {
|
||||
return freeParameters.any { parameter ->
|
||||
val type = parameter.defaultType
|
||||
val substituted1 = this[type] ?: return@any false
|
||||
val substituted2 = other[type] ?: return@any false
|
||||
!KotlinTypeChecker.FLEXIBLE_UNEQUAL_TO_INFLEXIBLE.equalTypes(substituted1.type, substituted2.type) || substituted1.projectionKind != substituted2.projectionKind
|
||||
}
|
||||
}
|
||||
|
||||
fun TypeSubstitutor.combineIfNoConflicts(other: TypeSubstitutor, freeParameters: Collection<TypeParameterDescriptor>): TypeSubstitutor? {
|
||||
if (this.substitution.hasConflictWith(other.substitution, freeParameters)) return null
|
||||
return TypeSubstitutor.createChainedSubstitutor(this.substitution, other.substitution)
|
||||
}
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class X<T> {
|
||||
operator fun getValue(thisRef: T, property: KProperty<*>): T = throw Exception()
|
||||
}
|
||||
|
||||
class C<T> {
|
||||
val property: Int by <caret>
|
||||
}
|
||||
|
||||
// ABSENT: X
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class X<T>(t: T) {
|
||||
operator fun getValue(thisRef: T, property: KProperty<*>): T = throw Exception()
|
||||
}
|
||||
|
||||
class C<T> {
|
||||
val property: C<T> by <caret>
|
||||
}
|
||||
|
||||
// EXIST: { itemText: "X", tailText: "(t: C<T>) (<root>)" }
|
||||
+12
@@ -1450,6 +1450,12 @@ public class JvmSmartCompletionTestGenerated extends AbstractJvmSmartCompletionT
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/smart/propertyDelegate"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("ConflictingSubstitutors.kt")
|
||||
public void testConflictingSubstitutors() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/smart/propertyDelegate/ConflictingSubstitutors.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("DelegatesDot.kt")
|
||||
public void testDelegatesDot() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/smart/propertyDelegate/DelegatesDot.kt");
|
||||
@@ -1522,6 +1528,12 @@ public class JvmSmartCompletionTestGenerated extends AbstractJvmSmartCompletionT
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("NonConflictingSubstitutors.kt")
|
||||
public void testNonConflictingSubstitutors() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/smart/propertyDelegate/NonConflictingSubstitutors.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("Order.kt")
|
||||
public void testOrder() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/smart/propertyDelegate/Order.kt");
|
||||
|
||||
@@ -22,10 +22,7 @@ import org.jetbrains.kotlin.builtins.isFunctionType
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.resolve.ideService
|
||||
import org.jetbrains.kotlin.idea.util.FuzzyType
|
||||
import org.jetbrains.kotlin.idea.util.fuzzyExtensionReceiverType
|
||||
import org.jetbrains.kotlin.idea.util.fuzzyReturnType
|
||||
import org.jetbrains.kotlin.idea.util.getResolutionScope
|
||||
import org.jetbrains.kotlin.idea.util.*
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
@@ -632,9 +629,9 @@ class ExpectedInfos(
|
||||
val propertyType = explicitPropertyType ?: getValueOperator.fuzzyReturnType()!!
|
||||
val setParamType = FuzzyType(setValueOperator.valueParameters.last().type, setValueOperator.typeParameters)
|
||||
val setParamTypeSubstitutor = setParamType.checkIsSuperTypeOf(propertyType) ?: return null
|
||||
return TypeSubstitutor.createChainedSubstitutor(getOperatorSubstitutor.substitution,
|
||||
TypeSubstitutor.createChainedSubstitutor(setOperatorSubstitutor.substitution,
|
||||
setParamTypeSubstitutor.substitution).substitution)
|
||||
return getOperatorSubstitutor
|
||||
.combineIfNoConflicts(setOperatorSubstitutor, descriptorType.freeParameters)
|
||||
?.combineIfNoConflicts(setParamTypeSubstitutor, descriptorType.freeParameters)
|
||||
}
|
||||
|
||||
override val multipleFuzzyTypes: Collection<FuzzyType> by lazy {
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.idea.util.FuzzyType
|
||||
import org.jetbrains.kotlin.idea.util.combineIfNoConflicts
|
||||
import org.jetbrains.kotlin.idea.util.fuzzyExtensionReceiverType
|
||||
import org.jetbrains.kotlin.idea.util.nullability
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
@@ -138,7 +139,7 @@ class TypesWithGetValueDetector(
|
||||
|
||||
val fuzzyReturnType = FuzzyType(operator.returnType ?: return null, freeTypeParams)
|
||||
val substitutorFromPropertyType = fuzzyReturnType.checkIsSubtypeOf(propertyType) ?: return null
|
||||
return TypeSubstitutor.createChainedSubstitutor(substitutor.substitution, substitutorFromPropertyType.substitution)
|
||||
return substitutor.combineIfNoConflicts(substitutorFromPropertyType, freeTypeParams)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user