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? {
|
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
|
if (descriptor == this) return descriptor
|
||||||
|
|
||||||
val classTypeParameters = (getMethod.containingDeclaration as ClassDescriptor).typeConstructor.parameters
|
val classTypeParameters = (getMethod.containingDeclaration as ClassDescriptor).typeConstructor.parameters
|
||||||
@@ -362,7 +362,10 @@ class JavaSyntheticPropertiesScope(storageManager: StorageManager, private val l
|
|||||||
substitutionMap[classTypeParameter.typeConstructor] = typeProjection
|
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.getMethod = getMethod.substitute(classParametersSubstitutor) ?: return null
|
||||||
descriptor.setMethod = setMethod?.substitute(classParametersSubstitutor)
|
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.*
|
||||||
import org.jetbrains.kotlin.types.checker.StrictEqualityTypeChecker
|
import org.jetbrains.kotlin.types.checker.StrictEqualityTypeChecker
|
||||||
import org.jetbrains.kotlin.types.typeUtil.*
|
import org.jetbrains.kotlin.types.typeUtil.*
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
fun CallableDescriptor.fuzzyReturnType() = returnType?.toFuzzyType(typeParameters)
|
fun CallableDescriptor.fuzzyReturnType() = returnType?.toFuzzyType(typeParameters)
|
||||||
@@ -170,13 +171,20 @@ class FuzzyType(
|
|||||||
if (otherSubstitutedType.isError) return TypeSubstitutor.EMPTY
|
if (otherSubstitutedType.isError) return TypeSubstitutor.EMPTY
|
||||||
if (!substitutedType.checkInheritance(otherSubstitutedType)) return null
|
if (!substitutedType.checkInheritance(otherSubstitutedType)) return null
|
||||||
|
|
||||||
val substitution = constraintSystem.typeVariables.map { it.originalTypeParameter }.associateBy({ it.typeConstructor }) {
|
val substitutorToKeepCapturedTypes = object : DelegatedTypeSubstitution(substitutor.substitution) {
|
||||||
val type = it.defaultType
|
override fun approximateCapturedTypes() = false
|
||||||
val solution = substitutor.substitute(type, Variance.INVARIANT)
|
}.buildSubstitutor()
|
||||||
TypeProjectionImpl(if (solution != null && !ErrorUtils.containsUninferredParameter(solution)) solution else type)
|
|
||||||
}
|
|
||||||
|
|
||||||
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.calls.smartcasts.SmartCastManager
|
||||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
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.ImplicitReceiver
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.TypeNullability
|
import org.jetbrains.kotlin.types.typeUtil.TypeNullability
|
||||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||||
@@ -95,7 +95,9 @@ fun <TCallable : CallableDescriptor> TCallable.substituteExtensionIfCallable(
|
|||||||
return if (substitutors.any()) listOf(this) else listOf()
|
return if (substitutors.any()) listOf(this) else listOf()
|
||||||
}
|
}
|
||||||
else {
|
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>
|
klass.<caret>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <T> Class<T>.extFun(): Class<in T> = TODO()
|
||||||
|
|
||||||
// EXIST: simpleName
|
// EXIST: simpleName
|
||||||
// ABSENT: getSimpleName
|
// ABSENT: getSimpleName
|
||||||
// EXIST: enclosingClass
|
// EXIST: enclosingClass
|
||||||
// ABSENT: getEnclosingClass
|
// ABSENT: getEnclosingClass
|
||||||
// EXIST: annotations
|
// EXIST: annotations
|
||||||
// ABSENT: getAnnotations
|
// 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);
|
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")
|
@TestMetadata("NonPredictableSmartCast.kt")
|
||||||
public void testNonPredictableSmartCast() throws Exception {
|
public void testNonPredictableSmartCast() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/boldOrGrayed/NonPredictableSmartCast.kt");
|
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);
|
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")
|
@TestMetadata("NonPredictableSmartCast.kt")
|
||||||
public void testNonPredictableSmartCast() throws Exception {
|
public void testNonPredictableSmartCast() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/boldOrGrayed/NonPredictableSmartCast.kt");
|
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);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("KT9835")
|
||||||
|
public void testKT9835() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/multifile/KT9835/");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("MoreSpecificExtensionGeneric")
|
@TestMetadata("MoreSpecificExtensionGeneric")
|
||||||
public void testMoreSpecificExtensionGeneric() throws Exception {
|
public void testMoreSpecificExtensionGeneric() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/multifile/MoreSpecificExtensionGeneric/");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/multifile/MoreSpecificExtensionGeneric/");
|
||||||
|
|||||||
Reference in New Issue
Block a user