From a2d45153bab47674acea5d1acdcc52a8626b1983 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Thu, 8 Dec 2016 17:31:20 +0300 Subject: [PATCH] JS: prohibit dynamic on RHS of `in` and `!in` operators (see KT-6579) --- .../dynamicTypes/conventions.dynamic.txt | 4 -- .../dynamicTypes/conventions.kt | 6 -- .../dynamicTypes/inExpression.dynamic.txt | 4 ++ .../dynamicTypes/inExpression.kt | 12 ++++ .../dynamicTypes/inExpression.txt | 3 + .../DiagnosticsTestWithJsStdLibGenerated.java | 6 ++ .../diagnostics/JsDynamicCallChecker.kt | 9 +++ .../js/test/semantics/BoxJsTestGenerated.java | 6 -- js/js.translator/testData/box/dynamic/in.kt | 57 ------------------- 9 files changed, 34 insertions(+), 73 deletions(-) create mode 100644 compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/inExpression.dynamic.txt create mode 100644 compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/inExpression.kt create mode 100644 compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/inExpression.txt delete mode 100644 js/js.translator/testData/box/dynamic/in.kt diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/conventions.dynamic.txt b/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/conventions.dynamic.txt index 986d3a77e00..595a558567b 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/conventions.dynamic.txt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/conventions.dynamic.txt @@ -9,10 +9,6 @@ public final fun div(/*0*/ p0: dynamic): dynamic public final fun mod(/*0*/ p0: dynamic): dynamic public final fun rangeTo(/*0*/ p0: dynamic): dynamic public final fun and(/*0*/ p0: dynamic): dynamic -public final fun contains(/*0*/ p0: dynamic): dynamic -public final fun contains(/*0*/ p0: dynamic): dynamic -public final fun contains(/*0*/ p0: dynamic): dynamic -public final fun contains(/*0*/ p0: dynamic): dynamic public final fun get(/*0*/ p0: dynamic): dynamic public final fun set(/*0*/ p0: dynamic, /*1*/ p1: dynamic): dynamic public final fun get(/*0*/ p0: dynamic): dynamic diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/conventions.kt b/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/conventions.kt index d42298fdf5d..4196e5ab04d 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/conventions.kt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/conventions.kt @@ -20,12 +20,6 @@ fun test(d: dynamic) { d and d - d in d - d !in d - - 1 in d - 1 !in d - d[1] d[1] = 2 diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/inExpression.dynamic.txt b/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/inExpression.dynamic.txt new file mode 100644 index 00000000000..c6cfd9456e6 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/inExpression.dynamic.txt @@ -0,0 +1,4 @@ +public final fun contains(/*0*/ p0: dynamic): dynamic +public final fun contains(/*0*/ p0: dynamic): dynamic +public final fun contains(/*0*/ p0: dynamic): dynamic +public final fun contains(/*0*/ p0: dynamic): dynamic diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/inExpression.kt b/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/inExpression.kt new file mode 100644 index 00000000000..864c00b8ff5 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/inExpression.kt @@ -0,0 +1,12 @@ +fun foo() { + val a: dynamic = Any() + println(a in setOf(1, 2)) + println(1 in a) + println(1 !in a) + when (2) { + in a -> println("ok") + } + when (3) { + !in a -> println("ok") + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/inExpression.txt b/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/inExpression.txt new file mode 100644 index 00000000000..65a6ac47e1f --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/inExpression.txt @@ -0,0 +1,3 @@ +package + +public fun foo(): kotlin.Unit diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithJsStdLibGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithJsStdLibGenerated.java index f1804ea5bee..9aecea11635 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithJsStdLibGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithJsStdLibGenerated.java @@ -146,6 +146,12 @@ public class DiagnosticsTestWithJsStdLibGenerated extends AbstractDiagnosticsTes doTest(fileName); } + @TestMetadata("inExpression.kt") + public void testInExpression() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/inExpression.kt"); + doTest(fileName); + } + @TestMetadata("indexedAccess.kt") public void testIndexedAccess() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/indexedAccess.kt"); 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 8408081a19a..4efd0c057c5 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 @@ -18,9 +18,12 @@ package org.jetbrains.kotlin.js.resolve.diagnostics import com.intellij.psi.PsiElement import org.jetbrains.kotlin.psi.KtArrayAccessExpression +import org.jetbrains.kotlin.psi.KtBinaryExpression +import org.jetbrains.kotlin.psi.KtWhenConditionInRange 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.types.expressions.OperatorConventions import org.jetbrains.kotlin.types.isDynamic object JsDynamicCallChecker : CallChecker { @@ -32,5 +35,11 @@ object JsDynamicCallChecker : CallChecker { if (element is KtArrayAccessExpression && element.indexExpressions.size > 1) { context.trace.report(ErrorsJs.WRONG_OPERATION_WITH_DYNAMIC.on(reportOn, "indexed access with more than one index")) } + + if (element is KtBinaryExpression && element.operationToken in OperatorConventions.IN_OPERATIONS || + element is KtWhenConditionInRange + ) { + context.trace.report(ErrorsJs.WRONG_OPERATION_WITH_DYNAMIC.on(reportOn, "`in` operation")) + } } } \ No newline at end of file diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java index ee8911fb8a3..29beaa4a625 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java @@ -1328,12 +1328,6 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest { doTest(fileName); } - @TestMetadata("in.kt") - public void testIn() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/dynamic/in.kt"); - doTest(fileName); - } - @TestMetadata("incrementAndDecrement.kt") public void testIncrementAndDecrement() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/dynamic/incrementAndDecrement.kt"); diff --git a/js/js.translator/testData/box/dynamic/in.kt b/js/js.translator/testData/box/dynamic/in.kt deleted file mode 100644 index 1e70f7be96f..00000000000 --- a/js/js.translator/testData/box/dynamic/in.kt +++ /dev/null @@ -1,57 +0,0 @@ -package foo - -fun box(): String { - testTrue { "num" in bar } - testTrue { "str" in bar } - testTrue { "obj" in bar } - testTrue { 0 in bar } - testTrue { 5 in bar } - testTrue { 1 in bar } - testTrue { "name" in bar.obj } - testTrue { "name" in baz } - testTrue { "length" in baz } - testTrue { "0" in arr } - testTrue { 0 in arr } - testTrue { 2 in arr } - testTrue { 3 in arr } - testTrue { "length" in arr } - - testFalse { "num" !in bar } - testFalse { "str" !in bar } - testFalse { "obj" !in bar } - testFalse { 0 !in bar } - testFalse { 5 !in bar } - testFalse { 1 !in bar } - testFalse { "name" !in bar.obj } - testFalse { "name" !in baz } - testFalse { "length" !in baz } - testFalse { "0" !in arr } - testFalse { 0 !in arr } - testFalse { 2 !in arr } - testFalse { 3 !in arr } - testFalse { "length" !in arr } - - testFalse { "num0" in bar } - testFalse { "STR" in bar } - testFalse { 2 in bar } - testFalse { "foo" in bar.obj } - testFalse { 3 in baz } - testFalse { "function" in baz } - testFalse { "6" in arr } - testFalse { 7 in arr } - testFalse { 10 in arr } - testFalse { "name" in arr } - - testTrue { "num0" !in bar } - testTrue { "STR" !in bar } - testTrue { 2 !in bar } - testTrue { "foo" !in bar.obj } - testTrue { 3 !in baz } - testTrue { "function" !in baz } - testTrue { "6" !in arr } - testTrue { 7 !in arr } - testTrue { 10 !in arr } - testTrue { "name" !in arr } - - return "OK" -} \ No newline at end of file