Corrected usages of isNullableType/isMarkedNullable

This commit is contained in:
Valentin Kipyatkov
2014-12-03 22:09:01 +03:00
parent 9f845f0de4
commit 191d3e2766
6 changed files with 29 additions and 7 deletions
@@ -61,6 +61,11 @@ public trait Flexibility : TypeCapability, SubtypingRepresentatives {
public fun JetType.isFlexible(): Boolean = this.getCapability(javaClass<Flexibility>()) != null
public fun JetType.flexibility(): Flexibility = this.getCapability(javaClass<Flexibility>())!!
public fun JetType.isNullabilityFlexible(): Boolean {
val flexibility = this.getCapability(javaClass<Flexibility>()) ?: return false
return TypeUtils.isNullableType(flexibility.lowerBound) != TypeUtils.isNullableType(flexibility.upperBound)
}
// This function is intended primarily for sets: since JetType.equals() represents _syntactical_ equality of types,
// whereas JetTypeChecker.DEFAULT.equalsTypes() represents semantical equality
// A set of types (e.g. exact bounds etc) may contain, for example, X, X? and X!
@@ -42,7 +42,7 @@ fun CallableDescriptor.fuzzyExtensionReceiverType(): FuzzyType? {
fun FuzzyType.makeNotNullable() = FuzzyType(type.makeNotNullable(), freeParameters)
fun FuzzyType.makeNullable() = FuzzyType(type.makeNullable(), freeParameters)
fun FuzzyType.isNullable() = type.isMarkedNullable()
fun FuzzyType.nullability() = type.nullability()
class FuzzyType(
val type: JetType,
@@ -29,6 +29,7 @@ import org.jetbrains.jet.lang.types.isFlexible
import org.jetbrains.jet.lang.types.flexibility
import java.util.LinkedHashSet
import org.jetbrains.jet.lang.types.isDynamic
import org.jetbrains.jet.lang.types.isNullabilityFlexible
fun JetType.makeNullable() = TypeUtils.makeNullable(this)
fun JetType.makeNotNullable() = TypeUtils.makeNotNullable(this)
@@ -78,4 +79,18 @@ public fun JetType.getAllReferencedTypes(): Set<JetType> {
addType(this)
return types
}
public enum class TypeNullability {
NOT_NULL
NULLABLE
FLEXIBLE
}
public fun JetType.nullability(): TypeNullability {
return when {
isNullabilityFlexible() -> TypeNullability.FLEXIBLE
TypeUtils.isNullableType(this) -> TypeNullability.NULLABLE
else -> TypeNullability.NOT_NULL
}
}
@@ -23,7 +23,6 @@ import org.jetbrains.jet.lang.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.jet.lang.resolve.scopes.JetScope
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor
import org.jetbrains.jet.lang.resolve.calls.smartcasts.SmartCastUtils
import org.jetbrains.jet.lang.types.TypeUtils
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor
public enum class CallType {
@@ -79,7 +78,7 @@ public fun CallableDescriptor.substituteExtensionIfCallable(
.map {
var substitutor = extensionReceiverType.checkIsSuperTypeOf(it)
// check if we may fail due to receiver expression being nullable
if (substitutor == null && TypeUtils.isNullableType(it) && !TypeUtils.isNullableType(extensionReceiverType.type)) {
if (substitutor == null && it.nullability() == TypeNullability.NULLABLE && extensionReceiverType.nullability() == TypeNullability.NOT_NULL) {
substitutor = extensionReceiverType.checkIsSuperTypeOf(it.makeNotNullable())
}
substitutor
@@ -38,6 +38,8 @@ import org.jetbrains.jet.plugin.caches.resolve.ResolutionFacade
import com.intellij.codeInsight.lookup.DefaultLookupItemRenderer
import org.jetbrains.jet.lang.types.TypeUtils
import com.intellij.codeInsight.lookup.impl.LookupCellRenderer
import org.jetbrains.jet.plugin.util.nullability
import org.jetbrains.jet.plugin.util.TypeNullability
public class LookupElementFactory(
private val receiverTypes: Collection<JetType>
@@ -207,12 +209,12 @@ public class LookupElementFactory(
private fun callableWeight(descriptor: DeclarationDescriptor): CallableWeight? {
if (descriptor !is CallableDescriptor) return null
val isReceiverNullable = receiverTypes.isNotEmpty() && receiverTypes.all { it.isMarkedNullable() }
val isReceiverNullable = receiverTypes.isNotEmpty() && receiverTypes.all { it.nullability() == TypeNullability.NULLABLE }
val receiverParameter = descriptor.getExtensionReceiverParameter()
if (receiverParameter != null) {
val receiverParamType = receiverParameter.getType()
return if (isReceiverNullable && !receiverParamType.isMarkedNullable())
return if (isReceiverNullable && receiverParamType.nullability() == TypeNullability.NOT_NULL)
CallableWeight.notApplicableReceiverNullable
else if (receiverTypes.any { TypeUtils.equalTypes(it, receiverParamType) })
CallableWeight.thisTypeExtension
@@ -41,8 +41,9 @@ import org.jetbrains.jet.lang.types.TypeSubstitutor
import java.util.ArrayList
import java.util.HashMap
import org.jetbrains.jet.plugin.util.FuzzyType
import org.jetbrains.jet.plugin.util.isNullable
import org.jetbrains.jet.plugin.util.makeNotNullable
import org.jetbrains.jet.plugin.util.nullability
import org.jetbrains.jet.plugin.util.TypeNullability
class ArtificialElementInsertHandler(
val textBeforeCaret: String, val textAfterCaret: String, val shortenRefs: Boolean) : InsertHandler<LookupElement>{
@@ -117,7 +118,7 @@ fun Collection<FuzzyType>.classifyExpectedInfo(expectedInfo: ExpectedInfo): Expe
return ExpectedInfoClassification.matches(substitutor)
}
if (stream.any { it.isNullable() }) {
if (stream.any { it.nullability() == TypeNullability.NULLABLE }) {
val substitutor2 = stream.map { it.makeNotNullable().checkIsSubtypeOf(expectedInfo.type) }.firstOrNull()
if (substitutor2 != null) {
return ExpectedInfoClassification.matchesIfNotNullable(substitutor2)