HL API: add nullability property to every KtType

This commit is contained in:
Ilya Kirillov
2021-08-17 14:57:19 +03:00
parent c940972674
commit a1497b13c9
5 changed files with 32 additions and 17 deletions
@@ -25,7 +25,7 @@ public interface KtTypeInfoProviderMixIn : KtAnalysisSessionMixIn {
public val KtType.canBeNull: Boolean get() = analysisSession.typeInfoProvider.canBeNull(this) public val KtType.canBeNull: Boolean get() = analysisSession.typeInfoProvider.canBeNull(this)
/** Returns true if the type is explicitly marked as nullable. This means it's safe to assign `null` to a variable with this type. */ /** Returns true if the type is explicitly marked as nullable. This means it's safe to assign `null` to a variable with this type. */
public val KtType.isMarkedNullable: Boolean get() = (this as? KtTypeWithNullability)?.nullability == KtTypeNullability.NULLABLE public val KtType.isMarkedNullable: Boolean get() = this.nullability == KtTypeNullability.NULLABLE
public val KtType.isUnit: Boolean get() = isClassTypeWithClassId(DefaultTypeClassIds.UNIT) public val KtType.isUnit: Boolean get() = isClassTypeWithClassId(DefaultTypeClassIds.UNIT)
public val KtType.isInt: Boolean get() = isClassTypeWithClassId(DefaultTypeClassIds.INT) public val KtType.isInt: Boolean get() = isClassTypeWithClassId(DefaultTypeClassIds.INT)
@@ -13,15 +13,14 @@ import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
public sealed interface KtType : ValidityTokenOwner { public sealed interface KtType : ValidityTokenOwner {
public val nullability: KtTypeNullability
public fun asStringForDebugging(): String public fun asStringForDebugging(): String
} }
public interface KtTypeWithNullability : KtType {
public val nullability: KtTypeNullability
}
public enum class KtTypeNullability(public val isNullable: Boolean) { public enum class KtTypeNullability(public val isNullable: Boolean) {
NULLABLE(true), NON_NULLABLE(false); NULLABLE(true),
NON_NULLABLE(false),
UNKNOWN(false);
public companion object { public companion object {
public fun create(isNullable: Boolean): KtTypeNullability = if (isNullable) NULLABLE else NON_NULLABLE public fun create(isNullable: Boolean): KtTypeNullability = if (isNullable) NULLABLE else NON_NULLABLE
@@ -32,7 +31,7 @@ public sealed class KtClassType : KtType {
override fun toString(): String = asStringForDebugging() override fun toString(): String = asStringForDebugging()
} }
public sealed class KtNonErrorClassType : KtClassType(), KtTypeWithNullability { public sealed class KtNonErrorClassType : KtClassType() {
public abstract val classId: ClassId public abstract val classId: ClassId
public abstract val classSymbol: KtClassLikeSymbol public abstract val classSymbol: KtClassLikeSymbol
public abstract val typeArguments: List<KtTypeArgument> public abstract val typeArguments: List<KtTypeArgument>
@@ -53,7 +52,7 @@ public abstract class KtClassErrorType : KtClassType() {
public abstract val error: String public abstract val error: String
} }
public abstract class KtTypeParameterType : KtTypeWithNullability { public abstract class KtTypeParameterType : KtType {
public abstract val name: Name public abstract val name: Name
public abstract val symbol: KtTypeParameterSymbol public abstract val symbol: KtTypeParameterSymbol
} }
@@ -62,7 +61,7 @@ public abstract class KtCapturedType : KtType {
override fun toString(): String = asStringForDebugging() override fun toString(): String = asStringForDebugging()
} }
public abstract class KtDefinitelyNotNullType : KtType, KtTypeWithNullability { public abstract class KtDefinitelyNotNullType : KtType {
public abstract val original: KtType public abstract val original: KtType
final override val nullability: KtTypeNullability get() = KtTypeNullability.NON_NULLABLE final override val nullability: KtTypeNullability get() = KtTypeNullability.NON_NULLABLE
@@ -33,7 +33,6 @@ import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtTypeAndAnnotatio
import org.jetbrains.kotlin.idea.frontend.api.types.KtNonErrorClassType import org.jetbrains.kotlin.idea.frontend.api.types.KtNonErrorClassType
import org.jetbrains.kotlin.idea.frontend.api.types.KtType import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.idea.frontend.api.types.KtTypeNullability import org.jetbrains.kotlin.idea.frontend.api.types.KtTypeNullability
import org.jetbrains.kotlin.idea.frontend.api.types.KtTypeWithNullability
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.name.SpecialNames
@@ -71,11 +70,13 @@ internal enum class NullabilityType {
Unknown Unknown
} }
//todo get rid of NullabilityType as it corresponds to KtTypeNullability
internal val KtType.nullabilityType: NullabilityType internal val KtType.nullabilityType: NullabilityType
get() = get() = when (nullability) {
(this as? KtTypeWithNullability)?.let { KtTypeNullability.NULLABLE -> NullabilityType.Nullable
if (it.nullability == KtTypeNullability.NULLABLE) NullabilityType.Nullable else NullabilityType.NotNull KtTypeNullability.NON_NULLABLE -> NullabilityType.NotNull
} ?: NullabilityType.Unknown KtTypeNullability.UNKNOWN -> NullabilityType.Unknown
}
internal fun FirMemberDeclaration.computeSimpleModality(): Set<String> { internal fun FirMemberDeclaration.computeSimpleModality(): Set<String> {
@@ -54,7 +54,7 @@ internal class KtFirUsualClassType(
} }
} }
override val nullability: KtTypeNullability get() = withValidityAssertion { KtTypeNullability.create(coneType.canBeNull) } override val nullability: KtTypeNullability get() = withValidityAssertion { coneType.nullability.asKtNullability() }
override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() } override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
override fun equals(other: Any?) = typeEquals(other) override fun equals(other: Any?) = typeEquals(other)
override fun hashCode() = typeHashcode() override fun hashCode() = typeHashcode()
@@ -79,7 +79,7 @@ internal class KtFirFunctionalType(
} }
} }
override val nullability: KtTypeNullability get() = withValidityAssertion { KtTypeNullability.create(coneType.canBeNull) } override val nullability: KtTypeNullability get() = withValidityAssertion { coneType.nullability.asKtNullability() }
override val isSuspend: Boolean get() = withValidityAssertion { coneType.isSuspendFunctionType(builder.rootSession) } override val isSuspend: Boolean get() = withValidityAssertion { coneType.isSuspendFunctionType(builder.rootSession) }
override val arity: Int override val arity: Int
@@ -120,6 +120,7 @@ internal class KtFirClassErrorType(
override val coneType by weakRef(_coneType) override val coneType by weakRef(_coneType)
override val error: String get() = withValidityAssertion { coneType.diagnostic.reason } override val error: String get() = withValidityAssertion { coneType.diagnostic.reason }
override val nullability: KtTypeNullability get() = withValidityAssertion { coneType.nullability.asKtNullability() }
override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() } override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
override fun equals(other: Any?) = typeEquals(other) override fun equals(other: Any?) = typeEquals(other)
override fun hashCode() = typeHashcode() override fun hashCode() = typeHashcode()
@@ -130,6 +131,7 @@ internal class KtFirCapturedType(
override val token: ValidityToken, override val token: ValidityToken,
) : KtCapturedType(), KtFirType { ) : KtCapturedType(), KtFirType {
override val coneType by weakRef(_coneType) override val coneType by weakRef(_coneType)
override val nullability: KtTypeNullability get() = withValidityAssertion { coneType.nullability.asKtNullability() }
override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() } override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
override fun equals(other: Any?) = typeEquals(other) override fun equals(other: Any?) = typeEquals(other)
override fun hashCode() = typeHashcode() override fun hashCode() = typeHashcode()
@@ -164,7 +166,8 @@ internal class KtFirTypeParameterType(
?: error("Type parameter ${coneType.lookupTag} was not found") ?: error("Type parameter ${coneType.lookupTag} was not found")
} }
override val nullability: KtTypeNullability get() = withValidityAssertion { KtTypeNullability.create(coneType.canBeNull) } override val nullability: KtTypeNullability get() = withValidityAssertion { coneType.nullability.asKtNullability() }
override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() } override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
override fun equals(other: Any?) = typeEquals(other) override fun equals(other: Any?) = typeEquals(other)
override fun hashCode() = typeHashcode() override fun hashCode() = typeHashcode()
@@ -180,6 +183,9 @@ internal class KtFirFlexibleType(
override val lowerBound: KtType by cached { builder.typeBuilder.buildKtType(coneType.lowerBound) } override val lowerBound: KtType by cached { builder.typeBuilder.buildKtType(coneType.lowerBound) }
override val upperBound: KtType by cached { builder.typeBuilder.buildKtType(coneType.upperBound) } override val upperBound: KtType by cached { builder.typeBuilder.buildKtType(coneType.upperBound) }
override val nullability: KtTypeNullability get() = withValidityAssertion { coneType.nullability.asKtNullability() }
override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() } override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
override fun equals(other: Any?) = typeEquals(other) override fun equals(other: Any?) = typeEquals(other)
override fun hashCode() = typeHashcode() override fun hashCode() = typeHashcode()
@@ -197,7 +203,15 @@ internal class KtFirIntersectionType(
coneType.intersectedTypes.map { conjunct -> builder.typeBuilder.buildKtType(conjunct) } coneType.intersectedTypes.map { conjunct -> builder.typeBuilder.buildKtType(conjunct) }
} }
override val nullability: KtTypeNullability get() = withValidityAssertion { coneType.nullability.asKtNullability() }
override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() } override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
override fun equals(other: Any?) = typeEquals(other) override fun equals(other: Any?) = typeEquals(other)
override fun hashCode() = typeHashcode() override fun hashCode() = typeHashcode()
} }
private fun ConeNullability.asKtNullability(): KtTypeNullability = when (this) {
ConeNullability.NULLABLE -> KtTypeNullability.NULLABLE
ConeNullability.UNKNOWN -> KtTypeNullability.UNKNOWN
ConeNullability.NOT_NULL -> KtTypeNullability.NON_NULLABLE
}
@@ -95,4 +95,5 @@ internal fun FirExpression.convertConstantExpression(): KtConstantValue =
internal fun KtTypeNullability.toConeNullability() = when (this) { internal fun KtTypeNullability.toConeNullability() = when (this) {
KtTypeNullability.NULLABLE -> ConeNullability.NULLABLE KtTypeNullability.NULLABLE -> ConeNullability.NULLABLE
KtTypeNullability.NON_NULLABLE -> ConeNullability.NOT_NULL KtTypeNullability.NON_NULLABLE -> ConeNullability.NOT_NULL
KtTypeNullability.UNKNOWN -> ConeNullability.UNKNOWN
} }