JS: prohibit dynamic values as handlers of property delegates. Prohibit delegation of classes by dynamic values. See KT-15283
This commit is contained in:
+13
@@ -0,0 +1,13 @@
|
||||
val x: dynamic = 23
|
||||
|
||||
interface I {
|
||||
fun foo(): String
|
||||
}
|
||||
|
||||
class C : I by <!DELEGATION_BY_DYNAMIC!>x<!>
|
||||
|
||||
object O : I by <!DELEGATION_BY_DYNAMIC!>x<!>
|
||||
|
||||
fun box(): String {
|
||||
return object : I by <!DELEGATION_BY_DYNAMIC!>x<!> {}.foo()
|
||||
}
|
||||
+16
-5
@@ -1,16 +1,27 @@
|
||||
package
|
||||
|
||||
public final class C : Tr {
|
||||
public constructor C(/*0*/ d: dynamic)
|
||||
public val x: dynamic = 23
|
||||
public fun box(): kotlin.String
|
||||
|
||||
public final class C : I {
|
||||
public constructor C()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*delegation*/ fun foo(): kotlin.Unit
|
||||
public open override /*1*/ /*delegation*/ fun foo(): kotlin.String
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface Tr {
|
||||
public interface I {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public abstract fun foo(): kotlin.Unit
|
||||
public abstract fun foo(): kotlin.String
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public object O : I {
|
||||
private constructor O()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*delegation*/ fun foo(): kotlin.String
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
-3
@@ -52,6 +52,3 @@ public final fun get(/*0*/ p0: dynamic): dynamic
|
||||
public final fun divAssign(/*0*/ p0: dynamic): dynamic
|
||||
public final fun get(/*0*/ p0: dynamic): dynamic
|
||||
public final fun remAssign(/*0*/ p0: dynamic): dynamic
|
||||
public final fun getValue(/*0*/ p0: dynamic, /*1*/ p1: dynamic): dynamic
|
||||
public final fun getValue(/*0*/ p0: dynamic, /*1*/ p1: dynamic): dynamic
|
||||
public final fun setValue(/*0*/ p0: dynamic, /*1*/ p1: dynamic, /*2*/ p2: dynamic): dynamic
|
||||
|
||||
@@ -81,6 +81,3 @@ fun test(d: dynamic) {
|
||||
<!DEBUG_INFO_DYNAMIC!>d[1]<!> <!DEBUG_INFO_DYNAMIC!>%=<!> 1
|
||||
}
|
||||
|
||||
val dyn: dynamic = null
|
||||
val foo : Int <!DEBUG_INFO_DYNAMIC!>by dyn<!>
|
||||
var bar : Int <!DEBUG_INFO_DYNAMIC, DEBUG_INFO_DYNAMIC!>by dyn<!>
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
package
|
||||
|
||||
public var bar: kotlin.Int
|
||||
public val dyn: dynamic = null
|
||||
public val foo: kotlin.Int
|
||||
public fun test(/*0*/ d: dynamic): kotlin.Unit
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
interface Tr {
|
||||
fun foo()
|
||||
}
|
||||
|
||||
class C(d: dynamic) : Tr by d
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
public final fun getValue(/*0*/ p0: dynamic, /*1*/ p1: dynamic): dynamic
|
||||
public final fun setValue(/*0*/ p0: dynamic, /*1*/ p1: dynamic, /*2*/ p2: dynamic): dynamic
|
||||
public final fun getValue(/*0*/ p0: dynamic, /*1*/ p1: dynamic): dynamic
|
||||
public final fun getValue(/*0*/ p0: dynamic, /*1*/ p1: dynamic): dynamic
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE
|
||||
|
||||
external val x: dynamic
|
||||
|
||||
var y: Any? by <!PROPERTY_DELEGATION_BY_DYNAMIC!>x<!>
|
||||
|
||||
fun foo() {
|
||||
val a: Any by <!PROPERTY_DELEGATION_BY_DYNAMIC!>x<!>
|
||||
}
|
||||
|
||||
class C {
|
||||
val a: dynamic by <!PROPERTY_DELEGATION_BY_DYNAMIC!>x<!>
|
||||
}
|
||||
|
||||
class A {
|
||||
operator fun provideDelegate(host: Any?, p: Any): dynamic = TODO("")
|
||||
}
|
||||
|
||||
val z: Any? by <!PROPERTY_DELEGATION_BY_DYNAMIC!>A()<!>
|
||||
|
||||
class DynamicHandler {
|
||||
operator fun getValue(thisRef: Any?, property: kotlin.reflect.KProperty<*>): dynamic = 23
|
||||
}
|
||||
|
||||
class B {
|
||||
val x: dynamic by DynamicHandler()
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package
|
||||
|
||||
public external val x: dynamic
|
||||
public var y: kotlin.Any?
|
||||
public val z: kotlin.Any?
|
||||
public fun foo(): kotlin.Unit
|
||||
|
||||
public final class A {
|
||||
public constructor A()
|
||||
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 provideDelegate(/*0*/ host: kotlin.Any?, /*1*/ p: kotlin.Any): dynamic
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class B {
|
||||
public constructor B()
|
||||
public final val x: dynamic
|
||||
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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class C {
|
||||
public constructor C()
|
||||
public final val a: dynamic
|
||||
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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class DynamicHandler {
|
||||
public constructor DynamicHandler()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final operator fun getValue(/*0*/ thisRef: kotlin.Any?, /*1*/ property: kotlin.reflect.KProperty<*>): dynamic
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
+12
-6
@@ -86,6 +86,12 @@ public class DiagnosticsTestWithJsStdLibGenerated extends AbstractDiagnosticsTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("classDelegateBy.kt")
|
||||
public void testClassDelegateBy() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/classDelegateBy.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("comparisonToNull.kt")
|
||||
public void testComparisonToNull() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/comparisonToNull.kt");
|
||||
@@ -104,12 +110,6 @@ public class DiagnosticsTestWithJsStdLibGenerated extends AbstractDiagnosticsTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("delegationBy.kt")
|
||||
public void testDelegationBy() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/delegationBy.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("destructuring.kt")
|
||||
public void testDestructuring() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/destructuring.kt");
|
||||
@@ -242,6 +242,12 @@ public class DiagnosticsTestWithJsStdLibGenerated extends AbstractDiagnosticsTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("propertyDelegateBy.kt")
|
||||
public void testPropertyDelegateBy() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/propertyDelegateBy.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("protected.kt")
|
||||
public void testProtected() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/dynamicTypes/protected.kt");
|
||||
|
||||
@@ -39,6 +39,7 @@ object JsPlatformConfigurator : PlatformConfigurator(
|
||||
JsNameChecker, JsModuleChecker,
|
||||
JsExternalChecker, JsInheritanceChecker,
|
||||
JsRuntimeAnnotationChecker,
|
||||
JsDynamicDeclarationChecker,
|
||||
HeaderImplDeclarationChecker()
|
||||
),
|
||||
additionalCallCheckers = listOf(ReifiedTypeParameterSubstitutionChecker(), JsModuleCallChecker, JsDynamicCallChecker),
|
||||
|
||||
+2
@@ -71,6 +71,8 @@ private val DIAGNOSTIC_FACTORY_TO_RENDERER by lazy {
|
||||
|
||||
put(ErrorsJs.WRONG_OPERATION_WITH_DYNAMIC, "Wrong operation with dynamic value: {0}", Renderers.STRING)
|
||||
put(ErrorsJs.SPREAD_OPERATOR_IN_DYNAMIC_CALL, "Can't apply spread operator in dynamic call")
|
||||
put(ErrorsJs.DELEGATION_BY_DYNAMIC, "Can't delegate to dynamic value")
|
||||
put(ErrorsJs.PROPERTY_DELEGATION_BY_DYNAMIC, "Can't apply property delegation by dynamic handler")
|
||||
|
||||
put(ErrorsJs.RUNTIME_ANNOTATION_ON_EXTERNAL_DECLARATION, "Runtime annotation can't be put on external declaration")
|
||||
put(ErrorsJs.RUNTIME_ANNOTATION_NOT_SUPPORTED, "Reflection is not supported in JavaScript target, therefore you won't be able " +
|
||||
|
||||
@@ -71,6 +71,8 @@ public interface ErrorsJs {
|
||||
|
||||
DiagnosticFactory1<PsiElement, String> WRONG_OPERATION_WITH_DYNAMIC = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> SPREAD_OPERATOR_IN_DYNAMIC_CALL = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> DELEGATION_BY_DYNAMIC = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> PROPERTY_DELEGATION_BY_DYNAMIC = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
DiagnosticFactory0<PsiElement> RUNTIME_ANNOTATION_ON_EXTERNAL_DECLARATION = DiagnosticFactory0.create(
|
||||
ERROR, DECLARATION_SIGNATURE_OR_DEFAULT);
|
||||
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.js.resolve.diagnostics
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptorWithAccessors
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry
|
||||
import org.jetbrains.kotlin.psi.KtProperty
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.checkers.SimpleDeclarationChecker
|
||||
import org.jetbrains.kotlin.types.isDynamic
|
||||
|
||||
object JsDynamicDeclarationChecker : SimpleDeclarationChecker {
|
||||
override fun check(
|
||||
declaration: KtDeclaration, descriptor: DeclarationDescriptor,
|
||||
diagnosticHolder: DiagnosticSink, bindingContext: BindingContext
|
||||
) {
|
||||
if (declaration is KtProperty && descriptor is VariableDescriptorWithAccessors) {
|
||||
declaration.delegateExpression?.let { delegateExpression ->
|
||||
val provideDelegateCall = bindingContext[BindingContext.PROVIDE_DELEGATE_RESOLVED_CALL, descriptor]
|
||||
if (provideDelegateCall != null && provideDelegateCall.resultingDescriptor.returnType?.isDynamic() == true ||
|
||||
bindingContext.getType(delegateExpression)?.isDynamic() == true
|
||||
) {
|
||||
diagnosticHolder.report(ErrorsJs.PROPERTY_DELEGATION_BY_DYNAMIC.on(delegateExpression))
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (declaration is KtClassOrObject) {
|
||||
for (delegateDecl in declaration.superTypeListEntries.filterIsInstance<KtDelegatedSuperTypeEntry>()) {
|
||||
val delegateExpr = delegateDecl.delegateExpression ?: continue
|
||||
if (bindingContext.getType(delegateExpr)?.isDynamic() == true) {
|
||||
diagnosticHolder.report(ErrorsJs.DELEGATION_BY_DYNAMIC.on(delegateExpr))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user