KT-9835 Completion thinks receiver is nullable when it is not

#KT-9835 Fixed
This commit is contained in:
Valentin Kipyatkov
2016-10-11 17:12:41 +03:00
parent 7b12dd498f
commit 0399772ee6
10 changed files with 73 additions and 10 deletions
@@ -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" }
@@ -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" }
@@ -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");
@@ -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");
@@ -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/");