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.isFlexible(): Boolean = this.getCapability(javaClass<Flexibility>()) != null
public fun JetType.flexibility(): Flexibility = this.getCapability(javaClass<Flexibility>())!! 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, // This function is intended primarily for sets: since JetType.equals() represents _syntactical_ equality of types,
// whereas JetTypeChecker.DEFAULT.equalsTypes() represents semantical equality // whereas JetTypeChecker.DEFAULT.equalsTypes() represents semantical equality
// A set of types (e.g. exact bounds etc) may contain, for example, X, X? and X! // 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.makeNotNullable() = FuzzyType(type.makeNotNullable(), freeParameters)
fun FuzzyType.makeNullable() = FuzzyType(type.makeNullable(), freeParameters) fun FuzzyType.makeNullable() = FuzzyType(type.makeNullable(), freeParameters)
fun FuzzyType.isNullable() = type.isMarkedNullable() fun FuzzyType.nullability() = type.nullability()
class FuzzyType( class FuzzyType(
val type: JetType, val type: JetType,
@@ -29,6 +29,7 @@ import org.jetbrains.jet.lang.types.isFlexible
import org.jetbrains.jet.lang.types.flexibility import org.jetbrains.jet.lang.types.flexibility
import java.util.LinkedHashSet import java.util.LinkedHashSet
import org.jetbrains.jet.lang.types.isDynamic import org.jetbrains.jet.lang.types.isDynamic
import org.jetbrains.jet.lang.types.isNullabilityFlexible
fun JetType.makeNullable() = TypeUtils.makeNullable(this) fun JetType.makeNullable() = TypeUtils.makeNullable(this)
fun JetType.makeNotNullable() = TypeUtils.makeNotNullable(this) fun JetType.makeNotNullable() = TypeUtils.makeNotNullable(this)
@@ -79,3 +80,17 @@ public fun JetType.getAllReferencedTypes(): Set<JetType> {
addType(this) addType(this)
return types 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.resolve.scopes.JetScope
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor
import org.jetbrains.jet.lang.resolve.calls.smartcasts.SmartCastUtils import org.jetbrains.jet.lang.resolve.calls.smartcasts.SmartCastUtils
import org.jetbrains.jet.lang.types.TypeUtils
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor
public enum class CallType { public enum class CallType {
@@ -79,7 +78,7 @@ public fun CallableDescriptor.substituteExtensionIfCallable(
.map { .map {
var substitutor = extensionReceiverType.checkIsSuperTypeOf(it) var substitutor = extensionReceiverType.checkIsSuperTypeOf(it)
// check if we may fail due to receiver expression being nullable // 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 = extensionReceiverType.checkIsSuperTypeOf(it.makeNotNullable())
} }
substitutor substitutor
@@ -38,6 +38,8 @@ import org.jetbrains.jet.plugin.caches.resolve.ResolutionFacade
import com.intellij.codeInsight.lookup.DefaultLookupItemRenderer import com.intellij.codeInsight.lookup.DefaultLookupItemRenderer
import org.jetbrains.jet.lang.types.TypeUtils import org.jetbrains.jet.lang.types.TypeUtils
import com.intellij.codeInsight.lookup.impl.LookupCellRenderer import com.intellij.codeInsight.lookup.impl.LookupCellRenderer
import org.jetbrains.jet.plugin.util.nullability
import org.jetbrains.jet.plugin.util.TypeNullability
public class LookupElementFactory( public class LookupElementFactory(
private val receiverTypes: Collection<JetType> private val receiverTypes: Collection<JetType>
@@ -207,12 +209,12 @@ public class LookupElementFactory(
private fun callableWeight(descriptor: DeclarationDescriptor): CallableWeight? { private fun callableWeight(descriptor: DeclarationDescriptor): CallableWeight? {
if (descriptor !is CallableDescriptor) return null 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() val receiverParameter = descriptor.getExtensionReceiverParameter()
if (receiverParameter != null) { if (receiverParameter != null) {
val receiverParamType = receiverParameter.getType() val receiverParamType = receiverParameter.getType()
return if (isReceiverNullable && !receiverParamType.isMarkedNullable()) return if (isReceiverNullable && receiverParamType.nullability() == TypeNullability.NOT_NULL)
CallableWeight.notApplicableReceiverNullable CallableWeight.notApplicableReceiverNullable
else if (receiverTypes.any { TypeUtils.equalTypes(it, receiverParamType) }) else if (receiverTypes.any { TypeUtils.equalTypes(it, receiverParamType) })
CallableWeight.thisTypeExtension CallableWeight.thisTypeExtension
@@ -41,8 +41,9 @@ import org.jetbrains.jet.lang.types.TypeSubstitutor
import java.util.ArrayList import java.util.ArrayList
import java.util.HashMap import java.util.HashMap
import org.jetbrains.jet.plugin.util.FuzzyType 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.makeNotNullable
import org.jetbrains.jet.plugin.util.nullability
import org.jetbrains.jet.plugin.util.TypeNullability
class ArtificialElementInsertHandler( class ArtificialElementInsertHandler(
val textBeforeCaret: String, val textAfterCaret: String, val shortenRefs: Boolean) : InsertHandler<LookupElement>{ 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) 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() val substitutor2 = stream.map { it.makeNotNullable().checkIsSubtypeOf(expectedInfo.type) }.firstOrNull()
if (substitutor2 != null) { if (substitutor2 != null) {
return ExpectedInfoClassification.matchesIfNotNullable(substitutor2) return ExpectedInfoClassification.matchesIfNotNullable(substitutor2)