[Wasm] K2 js(code) constant checker (KT-56849)

Reuse K/JS FirJsCodeConstantArgumentChecker by moving it to web.common
This commit is contained in:
Svyatoslav Kuzmich
2023-11-16 15:06:12 +01:00
committed by Space Team
parent 5973951f71
commit 7092541e34
14 changed files with 54 additions and 44 deletions
@@ -5641,12 +5641,6 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirJsErrors.JSCODE_ARGUMENT_NON_CONST_EXPRESSION) { firDiagnostic ->
JscodeArgumentNonConstExpressionImpl(
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirSyntaxErrors.SYNTAX) { firDiagnostic ->
SyntaxImpl(
firDiagnostic.a,
@@ -5727,4 +5721,10 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirWebCommonErrors.JSCODE_ARGUMENT_NON_CONST_EXPRESSION) { firDiagnostic ->
JscodeArgumentNonConstExpressionImpl(
firDiagnostic as KtPsiDiagnostic,
token,
)
}
}
@@ -3924,10 +3924,6 @@ sealed interface KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
val operation: String
}
interface JscodeArgumentNonConstExpression : KtFirDiagnostic<KtElement> {
override val diagnosticClass get() = JscodeArgumentNonConstExpression::class
}
interface Syntax : KtFirDiagnostic<PsiElement> {
override val diagnosticClass get() = Syntax::class
val message: String
@@ -3982,4 +3978,8 @@ sealed interface KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
override val diagnosticClass get() = WrongDefaultValueForExternalFunParameter::class
}
interface JscodeArgumentNonConstExpression : KtFirDiagnostic<KtElement> {
override val diagnosticClass get() = JscodeArgumentNonConstExpression::class
}
}
@@ -4739,11 +4739,6 @@ internal class WrongOperationWithDynamicImpl(
token: KtLifetimeToken,
) : KtAbstractFirDiagnostic<KtElement>(firDiagnostic, token), KtFirDiagnostic.WrongOperationWithDynamic
internal class JscodeArgumentNonConstExpressionImpl(
firDiagnostic: KtPsiDiagnostic,
token: KtLifetimeToken,
) : KtAbstractFirDiagnostic<KtElement>(firDiagnostic, token), KtFirDiagnostic.JscodeArgumentNonConstExpression
internal class SyntaxImpl(
override val message: String,
firDiagnostic: KtPsiDiagnostic,
@@ -4811,3 +4806,8 @@ internal class WrongDefaultValueForExternalFunParameterImpl(
token: KtLifetimeToken,
) : KtAbstractFirDiagnostic<KtElement>(firDiagnostic, token), KtFirDiagnostic.WrongDefaultValueForExternalFunParameter
internal class JscodeArgumentNonConstExpressionImpl(
firDiagnostic: KtPsiDiagnostic,
token: KtLifetimeToken,
) : KtAbstractFirDiagnostic<KtElement>(firDiagnostic, token), KtFirDiagnostic.JscodeArgumentNonConstExpression
@@ -136,8 +136,4 @@ object JS_DIAGNOSTICS_LIST : DiagnosticList("FirJsErrors") {
parameter<String>("operation")
}
}
val JSCODE by object : DiagnosticGroup("JsCode") {
val JSCODE_ARGUMENT_NON_CONST_EXPRESSION by error<KtElement>()
}
}
@@ -5,10 +5,8 @@
package org.jetbrains.kotlin.fir.checkers.generator.diagnostics
import com.intellij.psi.PsiElement
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
@@ -31,4 +29,8 @@ object WEB_COMMON_DIAGNOSTICS_LIST : DiagnosticList("FirWebCommonErrors") {
val WRONG_INITIALIZER_OF_EXTERNAL_DECLARATION by error<KtElement>()
val WRONG_DEFAULT_VALUE_FOR_EXTERNAL_FUN_PARAMETER by error<KtElement>()
}
val JSCODE by object : DiagnosticGroup("JsCode") {
val JSCODE_ARGUMENT_NON_CONST_EXPRESSION by error<KtElement>()
}
}
@@ -87,9 +87,6 @@ object FirJsErrors {
val SPREAD_OPERATOR_IN_DYNAMIC_CALL by error0<KtElement>(SourceElementPositioningStrategies.SPREAD_OPERATOR)
val WRONG_OPERATION_WITH_DYNAMIC by error1<KtElement, String>()
// JsCode
val JSCODE_ARGUMENT_NON_CONST_EXPRESSION by error0<KtElement>()
init {
RootDiagnosticRendererFactory.registerFactory(FirJsErrorsDefaultMessages)
}
@@ -25,7 +25,6 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.EXTERNAL_TYP
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
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.INLINE_CLASS_IN_EXTERNAL_DECLARATION_WARNING
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.JSCODE_ARGUMENT_NON_CONST_EXPRESSION
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.JS_BUILTIN_NAME_CLASH
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.JS_EXTERNAL_ARGUMENT
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.JS_EXTERNAL_INHERITORS_ONLY
@@ -215,6 +214,5 @@ object FirJsErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
"Exported declaration contains non-consumable identifier ''{0}'', which cannot be represented inside TS definitions and ESM.",
CommonRenderers.STRING,
)
map.put(JSCODE_ARGUMENT_NON_CONST_EXPRESSION, "An argument for the 'js()' function must be a constant string expression.")
}
}
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.analysis.js.checkers
import org.jetbrains.kotlin.fir.analysis.checkers.expression.*
import org.jetbrains.kotlin.fir.analysis.js.checkers.expression.*
import org.jetbrains.kotlin.fir.analysis.web.common.checkers.expression.FirJsCodeConstantArgumentChecker
object JsExpressionCheckers : ExpressionCheckers() {
override val annotationCallCheckers: Set<FirAnnotationCallChecker>
@@ -7,10 +7,16 @@ 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.web.common.checkers.expression.FirJsCodeConstantArgumentChecker
object WasmExpressionCheckers : ExpressionCheckers() {
override val basicExpressionCheckers: Set<FirBasicExpressionChecker>
get() = setOf(
FirWasmDefinedExternallyCallChecker,
)
override val functionCallCheckers: Set<FirFunctionCallChecker>
get() = setOf(
FirJsCodeConstantArgumentChecker,
)
}
@@ -33,6 +33,9 @@ object FirWebCommonErrors {
val WRONG_INITIALIZER_OF_EXTERNAL_DECLARATION by error0<KtElement>()
val WRONG_DEFAULT_VALUE_FOR_EXTERNAL_FUN_PARAMETER by error0<KtElement>()
// JsCode
val JSCODE_ARGUMENT_NON_CONST_EXPRESSION by error0<KtElement>()
init {
RootDiagnosticRendererFactory.registerFactory(FirWebCommonErrorsDefaultMessages)
}
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.web.common.FirWebCommonErro
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.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.NON_ABSTRACT_MEMBER_OF_EXTERNAL_INTERFACE
@@ -45,5 +46,7 @@ object FirWebCommonErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
WRONG_DEFAULT_VALUE_FOR_EXTERNAL_FUN_PARAMETER,
"Wrong default value for parameter of external function. Must be ' = definedExternally'."
)
map.put(JSCODE_ARGUMENT_NON_CONST_EXPRESSION, "An argument for the 'js()' function must be a constant string expression.")
}
}
@@ -3,7 +3,7 @@
* 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.expression
package org.jetbrains.kotlin.fir.analysis.web.common.checkers.expression
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
@@ -11,7 +11,7 @@ import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.analysis.checkers.canBeEvaluatedAtCompileTime
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.diagnostics.web.common.FirWebCommonErrors
import org.jetbrains.kotlin.fir.declarations.utils.isConst
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
@@ -21,17 +21,21 @@ import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol
import org.jetbrains.kotlin.fir.types.isString
import org.jetbrains.kotlin.fir.types.resolvedType
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
import org.jetbrains.kotlin.name.JsStandardClassIds
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
object FirJsCodeConstantArgumentChecker : FirFunctionCallChecker() {
private val jsCodeCallableId = CallableId(FqName("kotlin.js"), Name.identifier("js"))
override fun check(expression: FirFunctionCall, context: CheckerContext, reporter: DiagnosticReporter) {
if (expression.calleeReference.toResolvedCallableSymbol()?.callableId != JsStandardClassIds.Callables.JsCode) {
if (expression.calleeReference.toResolvedCallableSymbol()?.callableId != jsCodeCallableId) {
return
}
val jsCodeExpression = expression.arguments.firstOrNull()
if (jsCodeExpression == null || !jsCodeExpression.resolvedType.isString) {
reporter.reportOn(jsCodeExpression?.source ?: expression.source, FirJsErrors.JSCODE_ARGUMENT_NON_CONST_EXPRESSION, context)
reporter.reportOn(jsCodeExpression?.source ?: expression.source, FirWebCommonErrors.JSCODE_ARGUMENT_NON_CONST_EXPRESSION, context)
return
}
@@ -44,7 +48,7 @@ object FirJsCodeConstantArgumentChecker : FirFunctionCallChecker() {
if (lastReported == lastReportedElement && !canBeEvaluatedAtCompileTime(element as? FirExpression, context.session)) {
lastReportedElement = element
val source = element.source ?: jsCodeExpression.source
reporter.reportOn(source, FirJsErrors.JSCODE_ARGUMENT_NON_CONST_EXPRESSION, context)
reporter.reportOn(source, FirWebCommonErrors.JSCODE_ARGUMENT_NON_CONST_EXPRESSION, context)
}
}
@@ -639,7 +639,6 @@ val FIR_NON_SUPPRESSIBLE_ERROR_NAMES: Set<String> = setOf(
"PROPERTY_DELEGATION_BY_DYNAMIC",
"SPREAD_OPERATOR_IN_DYNAMIC_CALL",
"WRONG_OPERATION_WITH_DYNAMIC",
"JSCODE_ARGUMENT_NON_CONST_EXPRESSION",
"THROWS_LIST_EMPTY",
"INCOMPATIBLE_THROWS_OVERRIDE",
"INCOMPATIBLE_THROWS_INHERITED",
@@ -677,5 +676,6 @@ 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",
"JSCODE_ARGUMENT_NON_CONST_EXPRESSION",
"SYNTAX",
)
@@ -14,14 +14,14 @@ fun <!IMPLICIT_NOTHING_RETURN_TYPE!>returnTypeNotSepcified<!>() = js("1")
val a = "1"
fun nonConst(): String = "1"
val p0: Int = js(a)
val p0: Int = js(<!JSCODE_ARGUMENT_NON_CONST_EXPRESSION!>a<!>)
val p1: Int = js(("1"))
val p2: Int = js("$a")
val p2: Int = js("$<!JSCODE_ARGUMENT_NON_CONST_EXPRESSION!>a<!>")
val p3: Int = js("${1}")
val p4: Int = js("${a}${a}")
val p5: Int = js(a + a)
val p4: Int = js("${<!JSCODE_ARGUMENT_NON_CONST_EXPRESSION!>a<!>}${<!JSCODE_ARGUMENT_NON_CONST_EXPRESSION!>a<!>}")
val p5: Int = js(<!JSCODE_ARGUMENT_NON_CONST_EXPRESSION!>a<!> + <!JSCODE_ARGUMENT_NON_CONST_EXPRESSION!>a<!>)
val p6: Int = js("1" + "1")
val p7: Int = js(nonConst())
val p7: Int = js(<!JSCODE_ARGUMENT_NON_CONST_EXPRESSION!>nonConst()<!>)
val propWithGetter: String
get() = "1"
@@ -41,16 +41,16 @@ const val constProp = "1"
val delegatedVal: String by lazy { "1" }
val p8: Int = js(propWithGetter)
val p8: Int = js(<!JSCODE_ARGUMENT_NON_CONST_EXPRESSION!>propWithGetter<!>)
// TODO: This should be an error as property getters are no different to functions
val p9: Int = js(propWithSimpleGetterAndInitializer)
val p10: Int = js(propWithComplexGetterAndInitializer)
val p9: Int = js(<!JSCODE_ARGUMENT_NON_CONST_EXPRESSION!>propWithSimpleGetterAndInitializer<!>)
val p10: Int = js(<!JSCODE_ARGUMENT_NON_CONST_EXPRESSION!>propWithComplexGetterAndInitializer<!>)
val p11: Int = js(varProp)
val p12: Int = js(varPropWithSetter)
val p11: Int = js(<!JSCODE_ARGUMENT_NON_CONST_EXPRESSION!>varProp<!>)
val p12: Int = js(<!JSCODE_ARGUMENT_NON_CONST_EXPRESSION!>varPropWithSetter<!>)
val p13: Int = js(constProp)
val p14: Int = js(delegatedVal)
val p14: Int = js(<!JSCODE_ARGUMENT_NON_CONST_EXPRESSION!>delegatedVal<!>)
fun foo0(b: Boolean): Int =