From 720fe2ac899b876bc130b60b01637ee205cc11df Mon Sep 17 00:00:00 2001 From: Alexander Korepanov Date: Tue, 17 Oct 2023 14:26:50 +0200 Subject: [PATCH] [JS PSI] Deprecate using not constant variables in js() calls Added JSCODE_ARGUMENT_NON_CONST_EXPRESSION warning which checks non constant variable usages in js() argument expressions. The fix is related to KT-57156. --- .../diagnostics/DefaultErrorMessagesJs.kt | 1 + .../js/resolve/diagnostics/ErrorsJs.java | 1 + .../js/resolve/diagnostics/JsCallChecker.kt | 21 +++++++++++++++---- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/DefaultErrorMessagesJs.kt b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/DefaultErrorMessagesJs.kt index bdd589f171a..0412442b46a 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/DefaultErrorMessagesJs.kt +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/DefaultErrorMessagesJs.kt @@ -24,6 +24,7 @@ private val DIAGNOSTIC_FACTORY_TO_RENDERER by lazy { put(ErrorsJs.JSCODE_ERROR, "JavaScript: {0}", JsCallDataTextRenderer) put(ErrorsJs.JSCODE_WARNING, "JavaScript: {0}", JsCallDataTextRenderer) put(ErrorsJs.JSCODE_ARGUMENT_SHOULD_BE_CONSTANT, "Argument must be string constant") + put(ErrorsJs.JSCODE_ARGUMENT_NON_CONST_EXPRESSION, "Using not constant variables in js() argument expression becomes deprecated and will be an error in future releases") put(ErrorsJs.NOT_SUPPORTED, "Cannot translate (not supported yet): ''{0}''", RenderFirstLineOfElementText) put(ErrorsJs.JSCODE_NO_JAVASCRIPT_PRODUCED, "Argument must be non-empty JavaScript code") put(ErrorsJs.NESTED_EXTERNAL_DECLARATION, "Non top-level `external` declaration") diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/ErrorsJs.java b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/ErrorsJs.java index 57af1520796..13ca6de58f4 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/ErrorsJs.java +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/ErrorsJs.java @@ -27,6 +27,7 @@ public interface ErrorsJs { DiagnosticFactory1 JSCODE_ERROR = DiagnosticFactory1.create(ERROR, JsCodePositioningStrategy.INSTANCE); DiagnosticFactory1 JSCODE_WARNING = DiagnosticFactory1.create(WARNING, JsCodePositioningStrategy.INSTANCE); DiagnosticFactory0 JSCODE_ARGUMENT_SHOULD_BE_CONSTANT = DiagnosticFactory0.create(ERROR, DEFAULT); + DiagnosticFactory0 JSCODE_ARGUMENT_NON_CONST_EXPRESSION = DiagnosticFactory0.create(WARNING, DEFAULT); DiagnosticFactory1 NOT_SUPPORTED = DiagnosticFactory1.create(ERROR, DEFAULT); DiagnosticFactory0 JSCODE_NO_JAVASCRIPT_PRODUCED = DiagnosticFactory0.create(ERROR, DEFAULT); DiagnosticFactory1 WRONG_EXTERNAL_DECLARATION = DiagnosticFactory1.create(ERROR, DECLARATION_SIGNATURE_OR_DEFAULT); diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/JsCallChecker.kt b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/JsCallChecker.kt index 8cceef76020..33960a502c9 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/JsCallChecker.kt +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/JsCallChecker.kt @@ -25,6 +25,7 @@ import com.intellij.psi.PsiElement import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor +import org.jetbrains.kotlin.descriptors.VariableDescriptor import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1 import org.jetbrains.kotlin.js.backend.ast.JsFunctionScope import org.jetbrains.kotlin.js.backend.ast.JsProgram @@ -33,15 +34,13 @@ import org.jetbrains.kotlin.js.parser.parseExpressionOrStatement import org.jetbrains.kotlin.js.patterns.DescriptorPredicate import org.jetbrains.kotlin.js.patterns.PatternBuilder import org.jetbrains.kotlin.js.resolve.LEXICAL_SCOPE_FOR_JS -import org.jetbrains.kotlin.psi.KtCallExpression -import org.jetbrains.kotlin.psi.KtExpression -import org.jetbrains.kotlin.psi.KtLiteralStringTemplateEntry -import org.jetbrains.kotlin.psi.KtStringTemplateExpression +import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.BindingTrace import org.jetbrains.kotlin.resolve.TemporaryBindingTrace import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.resolve.calls.util.getResolvedCall import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant import org.jetbrains.kotlin.resolve.constants.StringValue import org.jetbrains.kotlin.resolve.constants.TypedCompileTimeConstant @@ -84,6 +83,20 @@ class JsCallChecker( return } + argument.accept(object : KtVisitor() { + override fun visitElement(element: PsiElement) { + element.acceptChildren(this) + } + + override fun visitSimpleNameExpression(expression: KtSimpleNameExpression, data: Nothing?): Nothing? { + val variableAccessing = (expression.getResolvedCall(trace.bindingContext)?.resultingDescriptor as? VariableDescriptor) + if (variableAccessing?.isConst == false) { + context.trace.report(ErrorsJs.JSCODE_ARGUMENT_NON_CONST_EXPRESSION.on(expression)) + } + return super.visitSimpleNameExpression(expression, data) + } + }) + trace.commit() val errorReporter = JsCodeErrorReporter(argument, code, context.trace)