[Wasm] Move external RTT checkers to web.common and reuse in Wasm

#KT-56849
This commit is contained in:
Svyatoslav Kuzmich
2023-11-21 14:29:28 +01:00
committed by Space Team
parent d219d5380b
commit cf3b293072
24 changed files with 360 additions and 121 deletions
@@ -67,12 +67,8 @@ object FirJsErrors {
val INLINE_CLASS_IN_EXTERNAL_DECLARATION by error0<KtElement>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
val EXTENSION_FUNCTION_IN_EXTERNAL_DECLARATION by error0<KtElement>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
val NON_EXTERNAL_DECLARATION_IN_INAPPROPRIATE_FILE by error1<KtElement, ConeKotlinType>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
val CANNOT_CHECK_FOR_EXTERNAL_INTERFACE by error1<KtElement, ConeKotlinType>()
val UNCHECKED_CAST_TO_EXTERNAL_INTERFACE by warning2<KtElement, ConeKotlinType, ConeKotlinType>()
val EXTERNAL_INTERFACE_AS_CLASS_LITERAL by error0<KtElement>()
val JS_EXTERNAL_INHERITORS_ONLY by error2<KtDeclaration, FirClassLikeSymbol<*>, FirClassLikeSymbol<*>>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
val JS_EXTERNAL_ARGUMENT by error1<KtExpression, ConeKotlinType>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
val EXTERNAL_INTERFACE_AS_REIFIED_TYPE_ARGUMENT by error1<KtElement, ConeKotlinType>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
// Export
val WRONG_EXPORTED_DECLARATION by error1<KtElement, String>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
@@ -14,13 +14,10 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.CALL_FROM_UM
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.CALL_TO_DEFINED_EXTERNALLY_FROM_NON_EXTERNAL_DECLARATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.CALL_TO_JS_MODULE_WITHOUT_MODULE_SYSTEM
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.CALL_TO_JS_NON_MODULE_WITH_MODULE_SYSTEM
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.CANNOT_CHECK_FOR_EXTERNAL_INTERFACE
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.DELEGATION_BY_DYNAMIC
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.ENUM_CLASS_IN_EXTERNAL_DECLARATION_WARNING
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.EXTENSION_FUNCTION_IN_EXTERNAL_DECLARATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.EXTERNAL_ENUM_ENTRY_WITH_BODY
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.EXTERNAL_INTERFACE_AS_CLASS_LITERAL
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.EXTERNAL_INTERFACE_AS_REIFIED_TYPE_ARGUMENT
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.IMPLEMENTING_FUNCTION_INTERFACE
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.INLINE_CLASS_IN_EXTERNAL_DECLARATION
@@ -55,7 +52,6 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.PROPERTY_DEL
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.RUNTIME_ANNOTATION_NOT_SUPPORTED
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.RUNTIME_ANNOTATION_ON_EXTERNAL_DECLARATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.SPREAD_OPERATOR_IN_DYNAMIC_CALL
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.UNCHECKED_CAST_TO_EXTERNAL_INTERFACE
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.WRONG_EXPORTED_DECLARATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.WRONG_MULTIPLE_INHERITANCE
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.WRONG_OPERATION_WITH_DYNAMIC
@@ -155,11 +151,6 @@ object FirJsErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
"Expected argument with external type, but type ''{0}'' is non-external.",
FirDiagnosticRenderers.RENDER_TYPE
)
map.put(
EXTERNAL_INTERFACE_AS_REIFIED_TYPE_ARGUMENT,
"Cannot pass external interface ''{0}'' for reified type parameter.",
FirDiagnosticRenderers.RENDER_TYPE
)
map.put(JS_NAME_PROHIBITED_FOR_EXTENSION_PROPERTY, "'@JsName' is prohibited for extension properties.")
map.put(
JS_BUILTIN_NAME_CLASH,
@@ -186,18 +177,6 @@ object FirJsErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
map.put(JS_NAME_PROHIBITED_FOR_OVERRIDE, "'@JsName' is prohibited for overridden members.")
map.put(JS_NAME_ON_PRIMARY_CONSTRUCTOR_PROHIBITED, "'@JsName' annotation is prohibited for primary constructors.")
map.put(JS_NAME_ON_ACCESSOR_AND_PROPERTY, "'@JsName' can be either on a property or its accessors, not both of them.")
map.put(
CANNOT_CHECK_FOR_EXTERNAL_INTERFACE,
"Cannot check for external interface: ''{0}''",
FirDiagnosticRenderers.RENDER_TYPE,
)
map.put(
UNCHECKED_CAST_TO_EXTERNAL_INTERFACE,
"Unchecked cast to external interface: ''{0}'' to ''{1}''.",
FirDiagnosticRenderers.RENDER_TYPE,
FirDiagnosticRenderers.RENDER_TYPE,
)
map.put(EXTERNAL_INTERFACE_AS_CLASS_LITERAL, "Cannot refer to external interface from class literal.")
map.put(WRONG_EXPORTED_DECLARATION, "Declaration of such kind ({0}) cannot be exported to JavaScript.", CommonRenderers.STRING)
map.put(
NON_EXPORTABLE_TYPE,
@@ -0,0 +1,16 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.js.checkers
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.web.common.checkers.FirAbstractWebCheckerUtils
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
object FirJsWebCheckerUtils : FirAbstractWebCheckerUtils() {
override fun isNativeOrExternalInterface(symbol: FirBasedSymbol<*>, session: FirSession): Boolean {
return symbol.isNativeInterface(session)
}
}
@@ -5,62 +5,7 @@
package org.jetbrains.kotlin.fir.analysis.js.checkers.expression
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirBasicExpressionChecker
import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClassSymbol
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors
import org.jetbrains.kotlin.fir.analysis.js.checkers.isNativeInterface
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.resolvedType
import org.jetbrains.kotlin.fir.types.toRegularClassSymbol
import org.jetbrains.kotlin.fir.analysis.js.checkers.FirJsWebCheckerUtils
import org.jetbrains.kotlin.fir.analysis.web.common.checkers.expression.FirAbstractNativeRttiChecker
object FirJsNativeRttiChecker : FirBasicExpressionChecker() {
override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) {
when (expression) {
is FirGetClassCall -> checkGetClassCall(expression, context, reporter)
is FirTypeOperatorCall -> checkTypeOperatorCall(expression, context, reporter)
else -> {}
}
}
private fun checkGetClassCall(expression: FirGetClassCall, context: CheckerContext, reporter: DiagnosticReporter) {
val declarationToCheck = expression.argument.resolvedType.toRegularClassSymbol(context.session) ?: return
if (expression.arguments.firstOrNull() !is FirResolvedQualifier) {
return
}
if (declarationToCheck.isNativeInterface(context)) {
reporter.reportOn(expression.source, FirJsErrors.EXTERNAL_INTERFACE_AS_CLASS_LITERAL, context)
}
}
private fun checkTypeOperatorCall(expression: FirTypeOperatorCall, context: CheckerContext, reporter: DiagnosticReporter) {
val targetTypeRef = expression.conversionTypeRef
val declarationToCheck = targetTypeRef.toRegularClassSymbol(context.session) ?: return
if (!declarationToCheck.isNativeInterface(context)) {
return
}
when (expression.operation) {
FirOperation.AS, FirOperation.SAFE_AS -> reporter.reportOn(
expression.source,
FirJsErrors.UNCHECKED_CAST_TO_EXTERNAL_INTERFACE,
expression.argument.resolvedType,
targetTypeRef.coneType,
context,
)
FirOperation.IS, FirOperation.NOT_IS -> reporter.reportOn(
expression.source,
FirJsErrors.CANNOT_CHECK_FOR_EXTERNAL_INTERFACE,
targetTypeRef.coneType,
context,
)
else -> {}
}
}
}
object FirJsNativeRttiChecker : FirAbstractNativeRttiChecker(FirJsWebCheckerUtils)
@@ -5,28 +5,7 @@
package org.jetbrains.kotlin.fir.analysis.js.checkers.expression
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirFunctionCallChecker
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.expressions.forAllReifiedTypeParameters
import org.jetbrains.kotlin.fir.types.toSymbol
import org.jetbrains.kotlin.fir.analysis.js.checkers.FirJsWebCheckerUtils
import org.jetbrains.kotlin.fir.analysis.web.common.checkers.expression.FirAbstractReifiedExternalChecker
object FirJsReifiedExternalChecker : FirFunctionCallChecker() {
override fun check(expression: FirFunctionCall, context: CheckerContext, reporter: DiagnosticReporter) {
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
)
}
}
}
}
object FirJsReifiedExternalChecker : FirAbstractReifiedExternalChecker(FirJsWebCheckerUtils)