[FIR] Implement warnings for java nullability type mismatch

#KT-56989
This commit is contained in:
Kirill Rakhman
2023-09-20 15:34:48 +02:00
committed by Space Team
parent 1ecbc094ec
commit a6fdeeb7df
158 changed files with 741 additions and 2021 deletions
@@ -5,10 +5,9 @@
package org.jetbrains.kotlin.fir.java.enhancement
import org.jetbrains.kotlin.fir.types.ConeAttributeWithConeType
import org.jetbrains.kotlin.fir.types.ConeAttributes
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.renderForDebugging
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
import org.jetbrains.kotlin.fir.resolve.substitution.AbstractConeSubstitutor
import org.jetbrains.kotlin.fir.types.*
import kotlin.reflect.KClass
class EnhancedTypeForWarningAttribute(
@@ -31,4 +30,37 @@ class EnhancedTypeForWarningAttribute(
val ConeAttributes.enhancedTypeForWarning: EnhancedTypeForWarningAttribute? by ConeAttributes.attributeAccessor<EnhancedTypeForWarningAttribute>()
val ConeKotlinType.enhancedTypeForWarning: ConeKotlinType?
get() = attributes.enhancedTypeForWarning?.coneType
get() = attributes.enhancedTypeForWarning?.coneType
/**
* Substitutor that substitutes types with their [ConeKotlinType.enhancedTypeForWarning] recursively.
*/
class EnhancedForWarningConeSubstitutor(typeContext: ConeTypeContext) : AbstractConeSubstitutor(typeContext) {
override fun substituteType(type: ConeKotlinType): ConeKotlinType? {
// The attribute is usually taken from the lower bound of flexible types.
// However, if the type has flexible mutability, we don't want to accidentally enhance the mutability to the lower bound.
if (type is ConeFlexibleType && type.hasFlexibleMutability()) {
val lowerSubstituted = substituteOrNull(type.lowerBound)
return if (lowerSubstituted is ConeSimpleKotlinType) {
ConeFlexibleType(
lowerBound = lowerSubstituted,
upperBound = substituteOrNull(type.upperBound) as? ConeSimpleKotlinType ?: type.upperBound
)
} else {
null
}
}
// If the top-level type can be enhanced, this will only enhance the top-level type but not its arguments: Foo<Bar!>! -> Foo<Bar!>?
// Otherwise, it will enhance recursively until the first possible enhancement.
val enhancedTopLevel = type.enhancedTypeForWarning
// This will also enhance type arguments if the top-level type was enhanced, otherwise it will continue enhancing recursively.
return enhancedTopLevel?.let(::substituteOrSelf)
}
private fun ConeFlexibleType.hasFlexibleMutability(): Boolean {
return JavaToKotlinClassMap.isMutable(lowerBound.classId) && JavaToKotlinClassMap.isReadOnly(upperBound.classId)
}
}