[JS FIR] Fix review comments

This commit is contained in:
Alexander Korepanov
2023-07-18 13:23:30 +02:00
committed by Space Team
parent 08d158f901
commit e61a11f0a3
7 changed files with 46 additions and 60 deletions
@@ -11,7 +11,7 @@ dependencies {
api(project(":compiler:fir:checkers"))
// FE checks for modules use ModuleKind
// This dependency can be removed when we stop supporting PLANE and UMD module systems
// This dependency can be removed when we stop supporting PLAIN and UMD module systems
implementation(project(":js:js.serializer"))
/*
@@ -157,10 +157,7 @@ internal fun FirClass.superClassNotAny(session: FirSession) = superConeTypes
.filterNot { it.isAny || it.isNullableAny }
.find { it.toSymbol(session)?.classKind == ClassKind.CLASS }
internal fun getRootDeclarationSymbol(symbol: FirBasedSymbol<*>, session: FirSession): FirBasedSymbol<*> {
return generateSequence(symbol) { it.getContainingClassSymbol(session) }.last()
internal fun getRootClassLikeSymbolOrSelf(symbol: FirBasedSymbol<*>, session: FirSession): FirBasedSymbol<*> {
return symbol.getContainingClassSymbol(session)?.let { getRootClassLikeSymbolOrSelf(it, session) } ?: symbol
}
internal fun isTopLevelSymbol(symbol: FirBasedSymbol<*>, session: FirSession): Boolean {
return symbol.getContainingClassSymbol(session) == null
}
@@ -37,7 +37,7 @@ internal fun checkJsModuleUsage(
val moduleKind = context.session.jsModuleKind
val calleeSession = callee.moduleData.session
val calleeRoot = getRootDeclarationSymbol(callee, calleeSession)
val calleeRoot = getRootClassLikeSymbolOrSelf(callee, calleeSession)
val calleeContainingFile = calleeRoot.getContainingFile(calleeSession)
val callToModule = calleeRoot.getAnnotationStringParameter(JsStandardClassIds.Annotations.JsModule, calleeSession) != null ||
@@ -9,15 +9,12 @@ import org.jetbrains.kotlin.AbstractKtSourceElement
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirQualifiedAccessExpressionChecker
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol
import org.jetbrains.kotlin.fir.analysis.js.checkers.checkJsModuleUsage
import org.jetbrains.kotlin.fir.analysis.js.checkers.isTopLevelSymbol
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
import org.jetbrains.kotlin.fir.references.toResolvedBaseSymbol
import org.jetbrains.kotlin.fir.references.toResolvedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.types.FirTypeProjectionWithVariance
import org.jetbrains.kotlin.fir.types.coneTypeOrNull
import org.jetbrains.kotlin.fir.types.toRegularClassSymbol
object FirJsModuleQualifiedAccessChecker : FirQualifiedAccessExpressionChecker() {
@@ -34,7 +31,7 @@ object FirJsModuleQualifiedAccessChecker : FirQualifiedAccessExpressionChecker()
expression: FirQualifiedAccessExpression
): List<Pair<FirBasedSymbol<*>, AbstractKtSourceElement?>> {
val calleeSymbol = expression.calleeReference.toResolvedBaseSymbol()
if (calleeSymbol != null && isTopLevelSymbol(calleeSymbol, calleeSymbol.moduleData.session)) {
if (calleeSymbol != null && calleeSymbol.getContainingClassSymbol(calleeSymbol.moduleData.session) == null) {
return listOf(calleeSymbol to expression.calleeReference.source)
}
@@ -53,14 +50,10 @@ object FirJsModuleQualifiedAccessChecker : FirQualifiedAccessExpressionChecker()
}
private fun checkReifiedTypeParameters(expr: FirQualifiedAccessExpression, context: CheckerContext, reporter: DiagnosticReporter) {
val functionSymbol = (expr as? FirFunctionCall)?.calleeReference?.toResolvedFunctionSymbol() ?: return
for ((typeParameterSymbol, typeArgument) in functionSymbol.typeParameterSymbols.zip(expr.typeArguments)) {
if (typeParameterSymbol.isReified) {
val type = (typeArgument as? FirTypeProjectionWithVariance)?.typeRef?.coneTypeOrNull ?: continue
val typeArgumentClass = type.toRegularClassSymbol(context.session) ?: continue
val source = typeArgument.source ?: expr.calleeReference.source ?: expr.source
checkJsModuleUsage(typeArgumentClass, context, reporter, source)
}
(expr as? FirFunctionCall)?.forAllReifiedTypeParameters { type, typeArgument ->
val typeArgumentClass = type.toRegularClassSymbol(context.session) ?: return@forAllReifiedTypeParameters
val source = typeArgument.source ?: expr.calleeReference.source ?: expr.source
checkJsModuleUsage(typeArgumentClass, context, reporter, source)
}
}
}
@@ -12,28 +12,21 @@ import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirFunctionCallChec
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors
import org.jetbrains.kotlin.fir.analysis.js.checkers.isNativeInterface
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.references.toResolvedFunctionSymbol
import org.jetbrains.kotlin.fir.types.FirTypeProjectionWithVariance
import org.jetbrains.kotlin.fir.types.coneTypeOrNull
import org.jetbrains.kotlin.fir.expressions.forAllReifiedTypeParameters
import org.jetbrains.kotlin.fir.types.toSymbol
object FirJsReifiedExternalChecker : FirFunctionCallChecker() {
override fun check(expression: FirFunctionCall, context: CheckerContext, reporter: DiagnosticReporter) {
val functionSymbol = expression.calleeReference.toResolvedFunctionSymbol() ?: return
for ((typeParameterSymbol, typeArgument) in functionSymbol.typeParameterSymbols.zip(expression.typeArguments)) {
if (typeParameterSymbol.isReified) {
val type = (typeArgument as? FirTypeProjectionWithVariance)?.typeRef?.coneTypeOrNull ?: continue
val typeSymbol = type.toSymbol(context.session) ?: continue
if (typeSymbol.isNativeInterface(context)) {
reporter.reportOn(
typeArgument.source ?: expression.source,
FirJsErrors.EXTERNAL_INTERFACE_AS_REIFIED_TYPE_ARGUMENT,
type,
context
)
}
expression.forAllReifiedTypeParameters { type, typeArgument ->
val typeSymbol = type.toSymbol(context.session)
if (typeSymbol?.isNativeInterface(context) == true) {
reporter.reportOn(
typeArgument.source ?: expression.source,
FirJsErrors.EXTERNAL_INTERFACE_AS_REIFIED_TYPE_ARGUMENT,
type,
context
)
}
}
}
}
@@ -28,35 +28,28 @@ object FirCastOperatorsChecker : FirTypeOperatorCallChecker() {
val conversionTypeRef = expression.conversionTypeRef
val targetType = conversionTypeRef.coneType.fullyExpandedType(session)
if (expression.operation in FirOperation.TYPES && targetType is ConeDynamicType) {
reporter.reportOn(conversionTypeRef.source, FirErrors.DYNAMIC_NOT_ALLOWED, context)
}
val isSafeAs = expression.operation == FirOperation.SAFE_AS
if (expression.operation == FirOperation.AS || isSafeAs) {
if (targetType is ConeDynamicType) {
reporter.reportOn(conversionTypeRef.source, FirErrors.DYNAMIC_NOT_ALLOWED, context)
} else {
val castType = checkCasting(actualType, targetType, isSafeAs, context)
if (castType == CastingType.Impossible) {
if (context.languageVersionSettings.supportsFeature(LanguageFeature.EnableDfaWarningsInK2)) {
reporter.reportOn(expression.source, FirErrors.CAST_NEVER_SUCCEEDS, context)
}
} else if (castType == CastingType.Always) {
if (context.languageVersionSettings.supportsFeature(LanguageFeature.EnableDfaWarningsInK2)) {
reporter.reportOn(expression.source, FirErrors.USELESS_CAST, context)
}
} else if (isCastErased(actualType, targetType, context)) {
reporter.reportOn(expression.source, FirErrors.UNCHECKED_CAST, actualType, targetType, context)
val castType = checkCasting(actualType, targetType, isSafeAs, context)
if (castType == CastingType.Impossible) {
if (context.languageVersionSettings.supportsFeature(LanguageFeature.EnableDfaWarningsInK2)) {
reporter.reportOn(expression.source, FirErrors.CAST_NEVER_SUCCEEDS, context)
}
} else if (castType == CastingType.Always) {
if (context.languageVersionSettings.supportsFeature(LanguageFeature.EnableDfaWarningsInK2)) {
reporter.reportOn(expression.source, FirErrors.USELESS_CAST, context)
}
} else if (isCastErased(actualType, targetType, context)) {
reporter.reportOn(expression.source, FirErrors.UNCHECKED_CAST, actualType, targetType, context)
}
} else if (expression.operation == FirOperation.IS) {
if (targetType is ConeDynamicType) {
reporter.reportOn(conversionTypeRef.source, FirErrors.DYNAMIC_NOT_ALLOWED, context)
}
if (!context.isContractBody && isCastErased(actualType, targetType, context)) {
reporter.reportOn(conversionTypeRef.source, FirErrors.CANNOT_CHECK_FOR_ERASED, targetType, context)
}
} else if (expression.operation == FirOperation.NOT_IS) {
if (targetType is ConeDynamicType) {
reporter.reportOn(conversionTypeRef.source, FirErrors.DYNAMIC_NOT_ALLOWED, context)
}
}
}
}
@@ -20,8 +20,7 @@ import org.jetbrains.kotlin.fir.expressions.impl.FirResolvedArgumentList
import org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock
import org.jetbrains.kotlin.fir.references.*
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef
import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.fir.visitors.TransformData
@@ -177,3 +176,14 @@ val FirQualifiedAccessExpression.allReceiverExpressions: List<FirExpression>
addIfNotNull(extensionReceiver)
addAll(contextReceiverArguments)
}
inline fun FirFunctionCall.forAllReifiedTypeParameters(block: (ConeKotlinType, FirTypeProjectionWithVariance) -> Unit) {
val functionSymbol = calleeReference.toResolvedFunctionSymbol() ?: return
for ((typeParameterSymbol, typeArgument) in functionSymbol.typeParameterSymbols.zip(typeArguments)) {
if (typeParameterSymbol.isReified && typeArgument is FirTypeProjectionWithVariance) {
val type = typeArgument.typeRef.coneTypeOrNull ?: continue
block(type, typeArgument)
}
}
}