FIR: add equality call checker
Added checker for FirEqualityOperatorCall. It's surfaced as one of the following diagnostics depending on the PSI structure and types under comparison: * INCOMPATIBLE_TYPES(_WARNING) * EQUALITY_NOT_APPLICABLE(_WARNING) * INCOMPATIBLE_ENUM_COMPARISON_ERROR Comparing with FE1.0, the current implementation is more conservative and only highlights error if the types are known to follow certain contracts with `equals` method. Otherwise, the checker reports warnings instead. However, the current checker is more strict in the following situations: 1. it now rejects incompatible enum types like `Enum<E1>` and `Enum<E2>`, which was previously accepted 2. it now rejects incompatible class types like `Class<String>` and `Class<Int>`, which was previously accepted 3. the check now takes smart cast into consideration, so `if (x is String) x == 3` is now rejected
This commit is contained in:
committed by
teamcityserver
parent
787c743333
commit
7bb81ef157
@@ -5,11 +5,13 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir
|
||||
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||
import org.jetbrains.kotlin.fir.declarations.classId
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl
|
||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
|
||||
object PrimitiveTypes {
|
||||
val Boolean: ConeClassLikeType = StandardClassIds.Boolean.createType()
|
||||
@@ -34,11 +36,27 @@ fun ConeClassLikeType.isByte(): Boolean = lookupTag.classId == StandardClassIds.
|
||||
fun ConeClassLikeType.isBoolean(): Boolean = lookupTag.classId == StandardClassIds.Boolean
|
||||
fun ConeClassLikeType.isChar(): Boolean = lookupTag.classId == StandardClassIds.Char
|
||||
|
||||
fun ConeClassLikeType.isPrimitiveType(): Boolean = isPrimitiveNumberOrUnsignedNumberType() || isBoolean() || isByte() || isShort() || isChar()
|
||||
fun ConeClassLikeType.isPrimitiveType(): Boolean =
|
||||
isPrimitiveNumberOrUnsignedNumberType() || isBoolean() || isByte() || isShort() || isChar()
|
||||
|
||||
fun ConeClassLikeType.isPrimitiveNumberType(): Boolean = lookupTag.classId in PRIMITIVE_NUMBER_CLASS_IDS
|
||||
fun ConeClassLikeType.isPrimitiveUnsignedNumberType(): Boolean = lookupTag.classId in PRIMITIVE_UNSIGNED_NUMBER_CLASS_IDS
|
||||
fun ConeClassLikeType.isPrimitiveNumberOrUnsignedNumberType(): Boolean = isPrimitiveNumberType() || isPrimitiveUnsignedNumberType()
|
||||
|
||||
fun FirClass<*>.isDouble(): Boolean = classId == StandardClassIds.Double
|
||||
fun FirClass<*>.isFloat(): Boolean = classId == StandardClassIds.Float
|
||||
fun FirClass<*>.isLong(): Boolean = classId == StandardClassIds.Long
|
||||
fun FirClass<*>.isInt(): Boolean = classId == StandardClassIds.Int
|
||||
fun FirClass<*>.isShort(): Boolean = classId == StandardClassIds.Short
|
||||
fun FirClass<*>.isByte(): Boolean = classId == StandardClassIds.Byte
|
||||
fun FirClass<*>.isBoolean(): Boolean = classId == StandardClassIds.Boolean
|
||||
fun FirClass<*>.isChar(): Boolean = classId == StandardClassIds.Char
|
||||
|
||||
fun FirClass<*>.isPrimitiveType(): Boolean = isPrimitiveNumberOrUnsignedNumberType() || isBoolean() || isByte() || isShort() || isChar()
|
||||
fun FirClass<*>.isPrimitiveNumberType(): Boolean = classId in PRIMITIVE_NUMBER_CLASS_IDS
|
||||
fun FirClass<*>.isPrimitiveUnsignedNumberType(): Boolean = classId in PRIMITIVE_UNSIGNED_NUMBER_CLASS_IDS
|
||||
fun FirClass<*>.isPrimitiveNumberOrUnsignedNumberType(): Boolean = isPrimitiveNumberType() || isPrimitiveUnsignedNumberType()
|
||||
|
||||
private val PRIMITIVE_NUMBER_CLASS_IDS: Set<ClassId> = setOf(
|
||||
StandardClassIds.Double, StandardClassIds.Float, StandardClassIds.Long, StandardClassIds.Int,
|
||||
StandardClassIds.Short, StandardClassIds.Byte
|
||||
|
||||
@@ -35,10 +35,10 @@ fun FirTypeParameterBuilder.addDefaultBoundIfNecessary(isFlexible: Boolean = fal
|
||||
}
|
||||
}
|
||||
|
||||
inline val FirRegularClass.isInterface: Boolean
|
||||
inline val FirClass<*>.isInterface: Boolean
|
||||
get() = classKind == ClassKind.INTERFACE
|
||||
|
||||
inline val FirRegularClass.isEnumClass: Boolean
|
||||
inline val FirClass<*>.isEnumClass: Boolean
|
||||
get() = classKind == ClassKind.ENUM_CLASS
|
||||
|
||||
inline val FirRegularClass.modality get() = status.modality
|
||||
|
||||
Reference in New Issue
Block a user