diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/illegalName.dynamic.txt b/compiler/testData/diagnostics/testsWithJsStdLib/name/illegalName.dynamic.txt new file mode 100644 index 00000000000..38217666d46 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJsStdLib/name/illegalName.dynamic.txt @@ -0,0 +1,4 @@ +public final fun `foo-bar`(): dynamic +public final var `ba-z`: dynamic + public final fun (): dynamic + public final fun (/*0*/ : dynamic): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/illegalName.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/illegalName.kt index c0529ded3d3..d22f9aaa8d3 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/illegalName.kt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/name/illegalName.kt @@ -17,4 +17,9 @@ private class ` .private class ` { val x: Int @JsName(".") - get() = TODO("") \ No newline at end of file + get() = TODO("") + +fun box(x: dynamic) { + x.`foo-bar`() + x.`ba-z` +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/illegalName.txt b/compiler/testData/diagnostics/testsWithJsStdLib/name/illegalName.txt index bdfdc841ee7..e546680d26a 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/name/illegalName.txt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/name/illegalName.txt @@ -5,6 +5,7 @@ private fun ` .private `(): kotlin.String @kotlin.js.JsName(name = "validName") private fun ` .private with @JsName `(): kotlin.String public fun ` .public `(): kotlin.String @kotlin.js.JsName(name = " ___ ") private fun bar(): kotlin.String +public fun box(/*0*/ x: dynamic): kotlin.Unit @kotlin.js.JsName(name = " __ ") public fun foo(): kotlin.String private final class ` .private class ` { diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/JsDynamicCallChecker.kt b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/JsDynamicCallChecker.kt index 59804ce1161..23789634e0a 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/JsDynamicCallChecker.kt +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/diagnostics/JsDynamicCallChecker.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.js.resolve.diagnostics import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.js.naming.NameSuggestion import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker @@ -62,6 +63,15 @@ object JsDynamicCallChecker : CallChecker { context.trace.report(ErrorsJs.WRONG_OPERATION_WITH_DYNAMIC.on(element.parent, "destructuring declaration")) } } + + is KtSimpleNameExpression -> checkIdentifier(element.getReferencedName(), element, context) + + is KtCallExpression -> { + val calleePsi = element.calleeExpression + if (calleePsi is KtSimpleNameExpression) { + checkIdentifier(calleePsi.getReferencedName(), calleePsi, context) + } + } } for (argument in resolvedCall.call.valueArguments) { @@ -71,6 +81,13 @@ object JsDynamicCallChecker : CallChecker { } } + private fun checkIdentifier(name: String?, reportOn: PsiElement, context: CallCheckerContext) { + if (name == null) return + if (NameSuggestion.sanitizeName(name) != name) { + context.trace.report(ErrorsJs.NAME_CONTAINS_ILLEGAL_CHARS.on(reportOn)) + } + } + private fun checkSpreadOperator(resolvedCall: ResolvedCall<*>, context: CallCheckerContext) { for (arg in resolvedCall.call.valueArguments) { val argExpression = arg.getArgumentExpression() ?: continue