[Wasm] Move external RTT checkers to web.common and reuse in Wasm
#KT-56849
This commit is contained in:
committed by
Space Team
parent
d219d5380b
commit
cf3b293072
-11
@@ -93,14 +93,6 @@ object JS_DIAGNOSTICS_LIST : DiagnosticList("FirJsErrors") {
|
||||
val NON_EXTERNAL_DECLARATION_IN_INAPPROPRIATE_FILE by error<KtElement>(PositioningStrategy.DECLARATION_SIGNATURE_OR_DEFAULT) {
|
||||
parameter<ConeKotlinType>("type")
|
||||
}
|
||||
val CANNOT_CHECK_FOR_EXTERNAL_INTERFACE by error<KtElement> {
|
||||
parameter<ConeKotlinType>("targetType")
|
||||
}
|
||||
val UNCHECKED_CAST_TO_EXTERNAL_INTERFACE by warning<KtElement> {
|
||||
parameter<ConeKotlinType>("sourceType")
|
||||
parameter<ConeKotlinType>("targetType")
|
||||
}
|
||||
val EXTERNAL_INTERFACE_AS_CLASS_LITERAL by error<KtElement>()
|
||||
val JS_EXTERNAL_INHERITORS_ONLY by error<KtDeclaration>(PositioningStrategy.DECLARATION_SIGNATURE_OR_DEFAULT) {
|
||||
parameter<FirClassLikeSymbol<*>>("parent")
|
||||
parameter<FirClassLikeSymbol<*>>("kid")
|
||||
@@ -108,9 +100,6 @@ object JS_DIAGNOSTICS_LIST : DiagnosticList("FirJsErrors") {
|
||||
val JS_EXTERNAL_ARGUMENT by error<KtExpression>(PositioningStrategy.DECLARATION_SIGNATURE_OR_DEFAULT) {
|
||||
parameter<ConeKotlinType>("argType")
|
||||
}
|
||||
val EXTERNAL_INTERFACE_AS_REIFIED_TYPE_ARGUMENT by error<KtElement>(PositioningStrategy.DECLARATION_SIGNATURE_OR_DEFAULT) {
|
||||
parameter<ConeKotlinType>("typeArgument")
|
||||
}
|
||||
}
|
||||
|
||||
val EXPORT by object : DiagnosticGroup("Export") {
|
||||
|
||||
+12
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.checkers.generator.diagnostics
|
||||
|
||||
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.DiagnosticList
|
||||
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.PositioningStrategy
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.util.PrivateForInline
|
||||
|
||||
@@ -32,6 +33,17 @@ object WEB_COMMON_DIAGNOSTICS_LIST : DiagnosticList("FirWebCommonErrors") {
|
||||
val WRONG_BODY_OF_EXTERNAL_DECLARATION by error<KtElement>()
|
||||
val WRONG_INITIALIZER_OF_EXTERNAL_DECLARATION by error<KtElement>()
|
||||
val WRONG_DEFAULT_VALUE_FOR_EXTERNAL_FUN_PARAMETER by error<KtElement>()
|
||||
val CANNOT_CHECK_FOR_EXTERNAL_INTERFACE by error<KtElement> {
|
||||
parameter<ConeKotlinType>("targetType")
|
||||
}
|
||||
val UNCHECKED_CAST_TO_EXTERNAL_INTERFACE by warning<KtElement> {
|
||||
parameter<ConeKotlinType>("sourceType")
|
||||
parameter<ConeKotlinType>("targetType")
|
||||
}
|
||||
val EXTERNAL_INTERFACE_AS_CLASS_LITERAL by error<KtElement>()
|
||||
val EXTERNAL_INTERFACE_AS_REIFIED_TYPE_ARGUMENT by error<KtElement>(PositioningStrategy.DECLARATION_SIGNATURE_OR_DEFAULT) {
|
||||
parameter<ConeKotlinType>("typeArgument")
|
||||
}
|
||||
}
|
||||
|
||||
val EXPORT by object : DiagnosticGroup("Export") {
|
||||
|
||||
-4
@@ -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)
|
||||
|
||||
-21
@@ -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,
|
||||
|
||||
+16
@@ -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)
|
||||
}
|
||||
}
|
||||
+3
-58
@@ -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)
|
||||
|
||||
+3
-24
@@ -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)
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* 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.wasm.checkers
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.web.common.checkers.FirAbstractWebCheckerUtils
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isEffectivelyExternal
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isInterface
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||
|
||||
object FirWasmWebCheckerUtils : FirAbstractWebCheckerUtils() {
|
||||
@OptIn(SymbolInternals::class)
|
||||
override fun isNativeOrExternalInterface(symbol: FirBasedSymbol<*>, session: FirSession): Boolean =
|
||||
symbol.isEffectivelyExternal(session) && (symbol.fir as? FirClass)?.isInterface == true
|
||||
}
|
||||
+4
@@ -7,7 +7,9 @@ package org.jetbrains.kotlin.fir.analysis.wasm.checkers
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.*
|
||||
import org.jetbrains.kotlin.fir.analysis.wasm.checkers.expression.FirWasmDefinedExternallyCallChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.wasm.checkers.expression.FirWasmExternalRttiChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.wasm.checkers.expression.FirWasmJsCodeCallChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.wasm.checkers.expression.FirWasmReifiedExternalChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.web.common.checkers.expression.FirJsCodeConstantArgumentChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.web.common.checkers.expression.FirJsQualifierChecker
|
||||
|
||||
@@ -20,11 +22,13 @@ object WasmExpressionCheckers : ExpressionCheckers() {
|
||||
override val basicExpressionCheckers: Set<FirBasicExpressionChecker>
|
||||
get() = setOf(
|
||||
FirWasmDefinedExternallyCallChecker,
|
||||
FirWasmExternalRttiChecker,
|
||||
)
|
||||
|
||||
override val functionCallCheckers: Set<FirFunctionCallChecker>
|
||||
get() = setOf(
|
||||
FirJsCodeConstantArgumentChecker,
|
||||
FirWasmJsCodeCallChecker,
|
||||
FirWasmReifiedExternalChecker
|
||||
)
|
||||
}
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* 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.wasm.checkers.expression
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.wasm.checkers.FirWasmWebCheckerUtils
|
||||
import org.jetbrains.kotlin.fir.analysis.web.common.checkers.expression.FirAbstractNativeRttiChecker
|
||||
|
||||
object FirWasmExternalRttiChecker : FirAbstractNativeRttiChecker(FirWasmWebCheckerUtils)
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* 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.wasm.checkers.expression
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.wasm.checkers.FirWasmWebCheckerUtils
|
||||
import org.jetbrains.kotlin.fir.analysis.web.common.checkers.expression.FirAbstractReifiedExternalChecker
|
||||
|
||||
object FirWasmReifiedExternalChecker : FirAbstractReifiedExternalChecker(FirWasmWebCheckerUtils)
|
||||
+5
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.diagnostics.*
|
||||
import org.jetbrains.kotlin.diagnostics.SourceElementPositioningStrategies
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.RootDiagnosticRendererFactory
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.psi.KtAnonymousInitializer
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
@@ -35,6 +36,10 @@ object FirWebCommonErrors {
|
||||
val WRONG_BODY_OF_EXTERNAL_DECLARATION by error0<KtElement>()
|
||||
val WRONG_INITIALIZER_OF_EXTERNAL_DECLARATION by error0<KtElement>()
|
||||
val WRONG_DEFAULT_VALUE_FOR_EXTERNAL_FUN_PARAMETER by error0<KtElement>()
|
||||
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 EXTERNAL_INTERFACE_AS_REIFIED_TYPE_ARGUMENT by error1<KtElement, ConeKotlinType>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
|
||||
|
||||
// Export
|
||||
val NESTED_JS_EXPORT by error0<KtElement>()
|
||||
|
||||
+23
@@ -8,16 +8,21 @@ package org.jetbrains.kotlin.fir.analysis.diagnostics.web.common
|
||||
import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactoryToRendererMap
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.BaseDiagnosticRendererFactory
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.CommonRenderers
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.web.common.FirWebCommonErrors.CANNOT_CHECK_FOR_EXTERNAL_INTERFACE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.web.common.FirWebCommonErrors.EXTERNAL_ANONYMOUS_INITIALIZER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.web.common.FirWebCommonErrors.EXTERNAL_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.web.common.FirWebCommonErrors.EXTERNAL_DELEGATED_CONSTRUCTOR_CALL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.web.common.FirWebCommonErrors.EXTERNAL_DELEGATION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.web.common.FirWebCommonErrors.EXTERNAL_INTERFACE_AS_CLASS_LITERAL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.web.common.FirWebCommonErrors.EXTERNAL_INTERFACE_AS_REIFIED_TYPE_ARGUMENT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.web.common.FirWebCommonErrors.INLINE_EXTERNAL_DECLARATION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.web.common.FirWebCommonErrors.JSCODE_ARGUMENT_NON_CONST_EXPRESSION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.web.common.FirWebCommonErrors.NESTED_CLASS_IN_EXTERNAL_INTERFACE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.web.common.FirWebCommonErrors.NESTED_EXTERNAL_DECLARATION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.web.common.FirWebCommonErrors.NESTED_JS_EXPORT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.web.common.FirWebCommonErrors.NON_ABSTRACT_MEMBER_OF_EXTERNAL_INTERFACE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.web.common.FirWebCommonErrors.UNCHECKED_CAST_TO_EXTERNAL_INTERFACE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.web.common.FirWebCommonErrors.WRONG_BODY_OF_EXTERNAL_DECLARATION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.web.common.FirWebCommonErrors.WRONG_DEFAULT_VALUE_FOR_EXTERNAL_FUN_PARAMETER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.web.common.FirWebCommonErrors.WRONG_EXTERNAL_DECLARATION
|
||||
@@ -49,6 +54,24 @@ object FirWebCommonErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
||||
WRONG_DEFAULT_VALUE_FOR_EXTERNAL_FUN_PARAMETER,
|
||||
"Wrong default value for parameter of external function. Must be ' = definedExternally'."
|
||||
)
|
||||
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(
|
||||
EXTERNAL_INTERFACE_AS_REIFIED_TYPE_ARGUMENT,
|
||||
"Cannot pass external interface ''{0}'' for reified type parameter.",
|
||||
FirDiagnosticRenderers.RENDER_TYPE
|
||||
)
|
||||
|
||||
|
||||
map.put(NESTED_JS_EXPORT, "'@JsExport' is only allowed on files and top-level declarations.")
|
||||
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* 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.web.common.checkers
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
|
||||
abstract class FirAbstractWebCheckerUtils {
|
||||
abstract fun isNativeOrExternalInterface(symbol: FirBasedSymbol<*>, session: FirSession): Boolean
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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.web.common.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.web.common.FirWebCommonErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.web.common.checkers.FirAbstractWebCheckerUtils
|
||||
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
|
||||
|
||||
abstract class FirAbstractNativeRttiChecker(
|
||||
private val webCheckerUtils: FirAbstractWebCheckerUtils
|
||||
) : 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 (webCheckerUtils.isNativeOrExternalInterface(declarationToCheck, context.session)) {
|
||||
reporter.reportOn(expression.source, FirWebCommonErrors.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 (!webCheckerUtils.isNativeOrExternalInterface(declarationToCheck, context.session)) {
|
||||
return
|
||||
}
|
||||
|
||||
when (expression.operation) {
|
||||
FirOperation.AS, FirOperation.SAFE_AS -> reporter.reportOn(
|
||||
expression.source,
|
||||
FirWebCommonErrors.UNCHECKED_CAST_TO_EXTERNAL_INTERFACE,
|
||||
expression.argument.resolvedType,
|
||||
targetTypeRef.coneType,
|
||||
context,
|
||||
)
|
||||
FirOperation.IS, FirOperation.NOT_IS -> reporter.reportOn(
|
||||
expression.source,
|
||||
FirWebCommonErrors.CANNOT_CHECK_FOR_EXTERNAL_INTERFACE,
|
||||
targetTypeRef.coneType,
|
||||
context,
|
||||
)
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.web.common.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.web.common.FirWebCommonErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.web.common.checkers.FirAbstractWebCheckerUtils
|
||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||
import org.jetbrains.kotlin.fir.expressions.forAllReifiedTypeParameters
|
||||
import org.jetbrains.kotlin.fir.types.toSymbol
|
||||
|
||||
abstract class FirAbstractReifiedExternalChecker(
|
||||
private val webCheckerUtils: FirAbstractWebCheckerUtils
|
||||
) : FirFunctionCallChecker() {
|
||||
override fun check(expression: FirFunctionCall, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
expression.forAllReifiedTypeParameters { type, typeArgument ->
|
||||
val typeSymbol = type.toSymbol(context.session)
|
||||
if (typeSymbol != null && webCheckerUtils.isNativeOrExternalInterface(typeSymbol, context.session)) {
|
||||
reporter.reportOn(
|
||||
typeArgument.source ?: expression.source,
|
||||
FirWebCommonErrors.EXTERNAL_INTERFACE_AS_REIFIED_TYPE_ARGUMENT,
|
||||
type,
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -628,11 +628,8 @@ val FIR_NON_SUPPRESSIBLE_ERROR_NAMES: Set<String> = setOf(
|
||||
"INLINE_CLASS_IN_EXTERNAL_DECLARATION",
|
||||
"EXTENSION_FUNCTION_IN_EXTERNAL_DECLARATION",
|
||||
"NON_EXTERNAL_DECLARATION_IN_INAPPROPRIATE_FILE",
|
||||
"CANNOT_CHECK_FOR_EXTERNAL_INTERFACE",
|
||||
"EXTERNAL_INTERFACE_AS_CLASS_LITERAL",
|
||||
"JS_EXTERNAL_INHERITORS_ONLY",
|
||||
"JS_EXTERNAL_ARGUMENT",
|
||||
"EXTERNAL_INTERFACE_AS_REIFIED_TYPE_ARGUMENT",
|
||||
"WRONG_EXPORTED_DECLARATION",
|
||||
"NESTED_JS_EXPORT",
|
||||
"DELEGATION_BY_DYNAMIC",
|
||||
@@ -676,6 +673,9 @@ val FIR_NON_SUPPRESSIBLE_ERROR_NAMES: Set<String> = setOf(
|
||||
"WRONG_BODY_OF_EXTERNAL_DECLARATION",
|
||||
"WRONG_INITIALIZER_OF_EXTERNAL_DECLARATION",
|
||||
"WRONG_DEFAULT_VALUE_FOR_EXTERNAL_FUN_PARAMETER",
|
||||
"CANNOT_CHECK_FOR_EXTERNAL_INTERFACE",
|
||||
"EXTERNAL_INTERFACE_AS_CLASS_LITERAL",
|
||||
"EXTERNAL_INTERFACE_AS_REIFIED_TYPE_ARGUMENT",
|
||||
"JSCODE_ARGUMENT_NON_CONST_EXPRESSION",
|
||||
"SYNTAX",
|
||||
)
|
||||
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// FIR_IDENTICAL
|
||||
// DIAGNOSTICS: +UNCHECKED_CAST_TO_EXTERNAL_INTERFACE
|
||||
|
||||
external interface I
|
||||
|
||||
fun box(a: Any, b: Any): Pair<I, I?> {
|
||||
return Pair(<!UNCHECKED_CAST_TO_EXTERNAL_INTERFACE!>a as I<!>, <!UNCHECKED_CAST_TO_EXTERNAL_INTERFACE!>b as? I<!>)
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// FIR_IDENTICAL
|
||||
external interface I
|
||||
|
||||
fun box(a: Any, b: Any): Boolean {
|
||||
return <!CANNOT_CHECK_FOR_EXTERNAL_INTERFACE!>a is I<!> && <!CANNOT_CHECK_FOR_EXTERNAL_INTERFACE!>b !is I<!>
|
||||
}
|
||||
Vendored
+22
@@ -0,0 +1,22 @@
|
||||
// FIR_IDENTICAL
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
inline fun <reified T> foo(x: T) {
|
||||
println(x)
|
||||
}
|
||||
|
||||
external interface I
|
||||
|
||||
external class C : I
|
||||
|
||||
operator inline fun <reified T> C.plus(other: T) = this
|
||||
|
||||
fun bar() {
|
||||
foo(C())
|
||||
|
||||
val c: I = C()
|
||||
<!EXTERNAL_INTERFACE_AS_REIFIED_TYPE_ARGUMENT!>foo(c)<!>
|
||||
foo<<!EXTERNAL_INTERFACE_AS_REIFIED_TYPE_ARGUMENT!>I<!>>(C())
|
||||
|
||||
<!EXTERNAL_INTERFACE_AS_REIFIED_TYPE_ARGUMENT!>C() + c<!>
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// FIR_IDENTICAL
|
||||
external interface I
|
||||
|
||||
typealias TA = I
|
||||
fun box() {
|
||||
println(<!EXTERNAL_INTERFACE_AS_CLASS_LITERAL!>I::class<!>)
|
||||
println(<!EXTERNAL_INTERFACE_AS_CLASS_LITERAL!>TA::class<!>)
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// FIR_IDENTICAL
|
||||
external interface I
|
||||
|
||||
external interface J
|
||||
|
||||
fun box(a: Any) = when (a) {
|
||||
<!CANNOT_CHECK_FOR_EXTERNAL_INTERFACE!>is I<!> -> 0
|
||||
<!CANNOT_CHECK_FOR_EXTERNAL_INTERFACE!>!is J<!> -> 1
|
||||
else -> 2
|
||||
}
|
||||
+40
@@ -128,6 +128,46 @@ public class DiagnosticsFirWasmTestGenerated extends AbstractDiagnosticsFirWasmT
|
||||
public void testWrongQualifier() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/wasmTests/jsInterop/wrongQualifier.kt");
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/wasmTests/jsInterop/rtti")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class Rtti {
|
||||
@Test
|
||||
public void testAllFilesPresentInRtti() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/wasmTests/jsInterop/rtti"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("castToNativeInterface.kt")
|
||||
public void testCastToNativeInterface() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/wasmTests/jsInterop/rtti/castToNativeInterface.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("checkForNativeInterface.kt")
|
||||
public void testCheckForNativeInterface() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/wasmTests/jsInterop/rtti/checkForNativeInterface.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nativeInterfaceAsReifiedTypeArgument.kt")
|
||||
public void testNativeInterfaceAsReifiedTypeArgument() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/wasmTests/jsInterop/rtti/nativeInterfaceAsReifiedTypeArgument.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nativeInterfaceClassLiteral.kt")
|
||||
public void testNativeInterfaceClassLiteral() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/wasmTests/jsInterop/rtti/nativeInterfaceClassLiteral.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("whenIsNativeInterface.kt")
|
||||
public void testWhenIsNativeInterface() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/wasmTests/jsInterop/rtti/whenIsNativeInterface.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
|
||||
+40
@@ -128,6 +128,46 @@ public class DiagnosticsWasmTestGenerated extends AbstractDiagnosticsWasmTest {
|
||||
public void testWrongQualifier() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/wasmTests/jsInterop/wrongQualifier.kt");
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/wasmTests/jsInterop/rtti")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class Rtti {
|
||||
@Test
|
||||
public void testAllFilesPresentInRtti() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/wasmTests/jsInterop/rtti"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("castToNativeInterface.kt")
|
||||
public void testCastToNativeInterface() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/wasmTests/jsInterop/rtti/castToNativeInterface.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("checkForNativeInterface.kt")
|
||||
public void testCheckForNativeInterface() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/wasmTests/jsInterop/rtti/checkForNativeInterface.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nativeInterfaceAsReifiedTypeArgument.kt")
|
||||
public void testNativeInterfaceAsReifiedTypeArgument() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/wasmTests/jsInterop/rtti/nativeInterfaceAsReifiedTypeArgument.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nativeInterfaceClassLiteral.kt")
|
||||
public void testNativeInterfaceClassLiteral() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/wasmTests/jsInterop/rtti/nativeInterfaceClassLiteral.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("whenIsNativeInterface.kt")
|
||||
public void testWhenIsNativeInterface() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/wasmTests/jsInterop/rtti/whenIsNativeInterface.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
|
||||
Reference in New Issue
Block a user