From 31d0e0b7c4fa8c475e8ff54091ad6d6689297002 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Mon, 26 Dec 2016 16:42:50 +0300 Subject: [PATCH] JS: prohibit `..` operation on dynamic type. See KT-15184 --- .../dynamicTypes/conventions.dynamic.txt | 1 - .../dynamicTypes/conventions.kt | 2 -- .../dynamicTypes/rangeExpression.dynamic.txt | 2 ++ .../dynamicTypes/rangeExpression.kt | 14 ++++++++++++ .../dynamicTypes/rangeExpression.txt | 11 ++++++++++ .../DiagnosticsTestWithJsStdLibGenerated.java | 6 +++++ .../diagnostics/JsDynamicCallChecker.kt | 22 +++++++++++++++---- 7 files changed, 51 insertions(+), 7 deletions(-) create mode 100644 compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/rangeExpression.dynamic.txt create mode 100644 compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/rangeExpression.kt create mode 100644 compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/rangeExpression.txt diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/conventions.dynamic.txt b/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/conventions.dynamic.txt index 17a25cee9ba..c22b8457729 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/conventions.dynamic.txt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/conventions.dynamic.txt @@ -7,7 +7,6 @@ public final fun minus(/*0*/ p0: dynamic): dynamic public final fun times(/*0*/ p0: dynamic): dynamic public final fun div(/*0*/ p0: dynamic): dynamic public final fun rem(/*0*/ p0: dynamic): dynamic -public final fun rangeTo(/*0*/ p0: dynamic): dynamic public final fun and(/*0*/ p0: dynamic): dynamic public final fun get(/*0*/ p0: dynamic): dynamic public final fun set(/*0*/ p0: dynamic, /*1*/ p1: dynamic): dynamic diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/conventions.kt b/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/conventions.kt index 45dffb2860e..d9283cf5a8c 100644 --- a/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/conventions.kt +++ b/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/conventions.kt @@ -16,8 +16,6 @@ fun test(d: dynamic) { d / d d % d - d..d - d and d d[1] diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/rangeExpression.dynamic.txt b/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/rangeExpression.dynamic.txt new file mode 100644 index 00000000000..37eada3ccc3 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/rangeExpression.dynamic.txt @@ -0,0 +1,2 @@ +public final fun rangeTo(/*0*/ p0: dynamic): dynamic +public final fun rangeTo(/*0*/ p0: dynamic): dynamic diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/rangeExpression.kt b/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/rangeExpression.kt new file mode 100644 index 00000000000..ca58339073b --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/rangeExpression.kt @@ -0,0 +1,14 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +fun foo() { + val a: dynamic = Any() + val b: dynamic = Any() + val c = C() + println(a..b) + println(c..a) + println(a.rangeTo(b)) +} + +class C { + operator fun rangeTo(other: dynamic): ClosedRange = TODO("not implemented") +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/rangeExpression.txt b/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/rangeExpression.txt new file mode 100644 index 00000000000..4ae18c41546 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/rangeExpression.txt @@ -0,0 +1,11 @@ +package + +public fun foo(): kotlin.Unit + +public final class C { + public constructor C() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final operator fun rangeTo(/*0*/ other: dynamic): kotlin.ranges.ClosedRange + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithJsStdLibGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithJsStdLibGenerated.java index e83d3bfb8bf..2a36feefc81 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithJsStdLibGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithJsStdLibGenerated.java @@ -242,6 +242,12 @@ public class DiagnosticsTestWithJsStdLibGenerated extends AbstractDiagnosticsTes doTest(fileName); } + @TestMetadata("rangeExpression.kt") + public void testRangeExpression() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/rangeExpression.kt"); + doTest(fileName); + } + @TestMetadata("reified.kt") public void testReified() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/reified.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 4efd0c057c5..963f3e05321 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.lexer.KtTokens import org.jetbrains.kotlin.psi.KtArrayAccessExpression import org.jetbrains.kotlin.psi.KtBinaryExpression import org.jetbrains.kotlin.psi.KtWhenConditionInRange @@ -36,10 +37,23 @@ object JsDynamicCallChecker : CallChecker { 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")) + if (element is KtWhenConditionInRange) { + reportInOperation(context, reportOn) + } + else if (element is KtBinaryExpression) { + val token = element.operationToken + when (token) { + in OperatorConventions.IN_OPERATIONS -> { + reportInOperation(context, reportOn) + } + KtTokens.RANGE -> { + context.trace.report(ErrorsJs.WRONG_OPERATION_WITH_DYNAMIC.on(reportOn, "`..` operation")) + } + } } } + + private fun reportInOperation(context: CallCheckerContext, reportOn: PsiElement) { + context.trace.report(ErrorsJs.WRONG_OPERATION_WITH_DYNAMIC.on(reportOn, "`in` operation")) + } } \ No newline at end of file