KT-9835 Completion thinks receiver is nullable when it is not
#KT-9835 Fixed
This commit is contained in:
+5
-2
@@ -352,7 +352,7 @@ class JavaSyntheticPropertiesScope(storageManager: StorageManager, private val l
|
||||
}
|
||||
|
||||
override fun substitute(originalSubstitutor: TypeSubstitutor): PropertyDescriptor? {
|
||||
val descriptor = super.substitute(originalSubstitutor) as MyPropertyDescriptor
|
||||
val descriptor = super.substitute(originalSubstitutor) as MyPropertyDescriptor? ?: return null
|
||||
if (descriptor == this) return descriptor
|
||||
|
||||
val classTypeParameters = (getMethod.containingDeclaration as ClassDescriptor).typeConstructor.parameters
|
||||
@@ -362,7 +362,10 @@ class JavaSyntheticPropertiesScope(storageManager: StorageManager, private val l
|
||||
substitutionMap[classTypeParameter.typeConstructor] = typeProjection
|
||||
|
||||
}
|
||||
val classParametersSubstitutor = TypeSubstitutor.create(substitutionMap)
|
||||
val classParametersSubstitutor = TypeConstructorSubstitution.createByConstructorsMap(
|
||||
substitutionMap,
|
||||
approximateCapturedTypes = true
|
||||
).buildSubstitutor()
|
||||
|
||||
descriptor.getMethod = getMethod.substitute(classParametersSubstitutor) ?: return null
|
||||
descriptor.setMethod = setMethod?.substitute(classParametersSubstitutor)
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.Constrain
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.StrictEqualityTypeChecker
|
||||
import org.jetbrains.kotlin.types.typeUtil.*
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||
import java.util.*
|
||||
|
||||
fun CallableDescriptor.fuzzyReturnType() = returnType?.toFuzzyType(typeParameters)
|
||||
@@ -170,13 +171,20 @@ class FuzzyType(
|
||||
if (otherSubstitutedType.isError) return TypeSubstitutor.EMPTY
|
||||
if (!substitutedType.checkInheritance(otherSubstitutedType)) return null
|
||||
|
||||
val substitution = constraintSystem.typeVariables.map { it.originalTypeParameter }.associateBy({ it.typeConstructor }) {
|
||||
val type = it.defaultType
|
||||
val solution = substitutor.substitute(type, Variance.INVARIANT)
|
||||
TypeProjectionImpl(if (solution != null && !ErrorUtils.containsUninferredParameter(solution)) solution else type)
|
||||
}
|
||||
val substitutorToKeepCapturedTypes = object : DelegatedTypeSubstitution(substitutor.substitution) {
|
||||
override fun approximateCapturedTypes() = false
|
||||
}.buildSubstitutor()
|
||||
|
||||
return TypeSubstitutor.create(TypeConstructorSubstitution.createByConstructorsMap(substitution))
|
||||
val substitutionMap: Map<TypeConstructor, TypeProjection> = constraintSystem.typeVariables
|
||||
.map { it.originalTypeParameter }
|
||||
.associateBy(
|
||||
keySelector = { it.typeConstructor },
|
||||
valueTransform = {
|
||||
val typeProjection = TypeProjectionImpl(Variance.INVARIANT, it.defaultType)
|
||||
val substitutedProjection = substitutorToKeepCapturedTypes.substitute(typeProjection)
|
||||
substitutedProjection?.check { !ErrorUtils.containsUninferredParameter(it.type) } ?: typeProjection
|
||||
})
|
||||
return TypeConstructorSubstitution.createByConstructorsMap(substitutionMap, approximateCapturedTypes = true).buildSubstitutor()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,8 +27,8 @@ import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastManager
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.TypeNullability
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||
@@ -95,7 +95,9 @@ fun <TCallable : CallableDescriptor> TCallable.substituteExtensionIfCallable(
|
||||
return if (substitutors.any()) listOf(this) else listOf()
|
||||
}
|
||||
else {
|
||||
return substitutors.map { @Suppress("UNCHECKED_CAST") (substitute(it) as TCallable) }.toList()
|
||||
return substitutors
|
||||
.mapNotNull { @Suppress("UNCHECKED_CAST") (substitute(it) as TCallable?) }
|
||||
.toList()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
interface R<T>
|
||||
|
||||
val <T> R<T>.prop: Int get() = TODO()
|
||||
fun <T> R<T>.extFun(): Int = TODO()
|
||||
|
||||
interface I
|
||||
|
||||
fun foo(r: R<out I>) {
|
||||
r.<caret>
|
||||
}
|
||||
|
||||
// EXIST: { itemText: "prop", typeText: "Int", attributes: "bold" }
|
||||
// EXIST: { itemText: "extFun", typeText: "Int", attributes: "bold" }
|
||||
|
||||
|
||||
+5
@@ -2,9 +2,14 @@ fun foo(klass: Class<*>) {
|
||||
klass.<caret>
|
||||
}
|
||||
|
||||
fun <T> Class<T>.extFun(): Class<in T> = TODO()
|
||||
|
||||
// EXIST: simpleName
|
||||
// ABSENT: getSimpleName
|
||||
// EXIST: enclosingClass
|
||||
// ABSENT: getEnclosingClass
|
||||
// EXIST: annotations
|
||||
// ABSENT: getAnnotations
|
||||
// EXIST: superclass
|
||||
// ABSENT: getSuperclass
|
||||
// EXIST: extFun
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
public interface R<D extends I> {
|
||||
int getFoo();
|
||||
int f();
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
interface I
|
||||
|
||||
fun foo(r: R<out I>) {
|
||||
r.<caret>
|
||||
}
|
||||
|
||||
// EXIST: { itemText: "foo", tailText: " (from getFoo())", typeText: "Int", attributes: "bold" }
|
||||
// EXIST: { itemText: "f", tailText: "()", typeText: "Int", attributes: "bold" }
|
||||
+6
@@ -1197,6 +1197,12 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("KT9835.kt")
|
||||
public void testKT9835() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/boldOrGrayed/KT9835.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("NonPredictableSmartCast.kt")
|
||||
public void testNonPredictableSmartCast() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/boldOrGrayed/NonPredictableSmartCast.kt");
|
||||
|
||||
+6
@@ -1197,6 +1197,12 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("KT9835.kt")
|
||||
public void testKT9835() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/boldOrGrayed/KT9835.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("NonPredictableSmartCast.kt")
|
||||
public void testNonPredictableSmartCast() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/boldOrGrayed/NonPredictableSmartCast.kt");
|
||||
|
||||
+6
@@ -209,6 +209,12 @@ public class MultiFileJvmBasicCompletionTestGenerated extends AbstractMultiFileJ
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("KT9835")
|
||||
public void testKT9835() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/multifile/KT9835/");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("MoreSpecificExtensionGeneric")
|
||||
public void testMoreSpecificExtensionGeneric() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/multifile/MoreSpecificExtensionGeneric/");
|
||||
|
||||
Reference in New Issue
Block a user