From 0559e192ee7bfbe8f2cc5fbc6b99d002a0e72e0e Mon Sep 17 00:00:00 2001 From: Roman Artemev Date: Tue, 28 Jul 2020 14:18:57 +0300 Subject: [PATCH] [JS IR] Support external delegation in case of JS in psi2ir - fix FE delegation resolver - fix critical KT-40650 --- .../kotlin/resolve/DelegationResolver.kt | 9 ++++++-- .../semantics/IrBoxJsES6TestGenerated.java | 5 +++++ .../ir/semantics/IrBoxJsTestGenerated.java | 5 +++++ .../js/test/semantics/BoxJsTestGenerated.java | 5 +++++ .../delegationByCompanionToNothing.kt | 22 +++++++++++++++++++ .../delegationToExternaInterface.kt | 10 ++++++++- 6 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 js/js.translator/testData/box/delegation/delegationByCompanionToNothing.kt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegationResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegationResolver.kt index 62952b4a7cc..d372c5fbbf1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegationResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegationResolver.kt @@ -26,12 +26,14 @@ import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry import org.jetbrains.kotlin.psi.KtPureClassOrObject import org.jetbrains.kotlin.psi.KtTypeReference import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE +import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal import org.jetbrains.kotlin.resolve.descriptorUtil.isTypeRefinementEnabled import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.lazy.DelegationFilter import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.isDynamic import org.jetbrains.kotlin.types.isError +import org.jetbrains.kotlin.types.typeUtil.isNothing import org.jetbrains.kotlin.utils.keysToMapExceptNulls class DelegationResolver private constructor( @@ -163,14 +165,17 @@ class DelegationResolver private constructor( .asIterable() .sortedWith(MemberComparator.INSTANCE) + // If delegate type is Nothing interface declarations could be missed so + // to make it work propagate nothing type into delegating interface type + val scopeType = delegateExpressionType?.takeUnless { it.isNothing() } ?: toInterface.defaultType + val scope = scopeType.memberScope + return delegatedMembers .keysToMapExceptNulls { delegatingMember -> val actualDelegates = DescriptorUtils.getAllOverriddenDescriptors(delegatingMember) .filter { it.containingDeclaration == toInterface } .map { overriddenDescriptor -> - val scope = (delegateExpressionType ?: toInterface.defaultType).memberScope val name = overriddenDescriptor.name - // this is the actual member of delegateExpressionType that we are delegating to (scope.getContributedFunctions(name, NoLookupLocation.WHEN_CHECK_OVERRIDES) + scope.getContributedVariables(name, NoLookupLocation.WHEN_CHECK_OVERRIDES)) diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrBoxJsES6TestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrBoxJsES6TestGenerated.java index 29a500c4fa1..7ace160c728 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrBoxJsES6TestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrBoxJsES6TestGenerated.java @@ -1211,6 +1211,11 @@ public class IrBoxJsES6TestGenerated extends AbstractIrBoxJsES6Test { runTest("js/js.translator/testData/box/delegation/delegationByArg.kt"); } + @TestMetadata("delegationByCompanionToNothing.kt") + public void testDelegationByCompanionToNothing() throws Exception { + runTest("js/js.translator/testData/box/delegation/delegationByCompanionToNothing.kt"); + } + @TestMetadata("delegationByExprWithArgs.kt") public void testDelegationByExprWithArgs() throws Exception { runTest("js/js.translator/testData/box/delegation/delegationByExprWithArgs.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrBoxJsTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrBoxJsTestGenerated.java index 3cc11dd6719..977e89e4ee0 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrBoxJsTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrBoxJsTestGenerated.java @@ -1211,6 +1211,11 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest { runTest("js/js.translator/testData/box/delegation/delegationByArg.kt"); } + @TestMetadata("delegationByCompanionToNothing.kt") + public void testDelegationByCompanionToNothing() throws Exception { + runTest("js/js.translator/testData/box/delegation/delegationByCompanionToNothing.kt"); + } + @TestMetadata("delegationByExprWithArgs.kt") public void testDelegationByExprWithArgs() throws Exception { runTest("js/js.translator/testData/box/delegation/delegationByExprWithArgs.kt"); 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 b3411f05640..40621cad108 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 @@ -1211,6 +1211,11 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest { runTest("js/js.translator/testData/box/delegation/delegationByArg.kt"); } + @TestMetadata("delegationByCompanionToNothing.kt") + public void testDelegationByCompanionToNothing() throws Exception { + runTest("js/js.translator/testData/box/delegation/delegationByCompanionToNothing.kt"); + } + @TestMetadata("delegationByExprWithArgs.kt") public void testDelegationByExprWithArgs() throws Exception { runTest("js/js.translator/testData/box/delegation/delegationByExprWithArgs.kt"); diff --git a/js/js.translator/testData/box/delegation/delegationByCompanionToNothing.kt b/js/js.translator/testData/box/delegation/delegationByCompanionToNothing.kt new file mode 100644 index 00000000000..05ce5eb9e46 --- /dev/null +++ b/js/js.translator/testData/box/delegation/delegationByCompanionToNothing.kt @@ -0,0 +1,22 @@ +// EXPECTED_REACHABLE_NODES: 1253 +// MODULE: lib +// FILE: lib.kt +interface II { + companion object : DDD by error("OK") +} + +interface DDD { + fun bar(d: String = error("FAIL4")): String +} + +// MODULE: main(lib) +// FILE: main.kt +fun box() : String { + try { + return II.bar() + } catch (e: IllegalStateException) { + return e.message ?: "FAIL 2" + } + + return "FAIL" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/delegation/delegationToExternaInterface.kt b/js/js.translator/testData/box/delegation/delegationToExternaInterface.kt index 05909b67207..8a6268516e3 100644 --- a/js/js.translator/testData/box/delegation/delegationToExternaInterface.kt +++ b/js/js.translator/testData/box/delegation/delegationToExternaInterface.kt @@ -1,6 +1,9 @@ // EXPECTED_REACHABLE_NODES: 1236 // KJS_WITH_FULL_RUNTIME // KT-40126 + +// MODULE: lib +// FILE: l.kt @file:Suppress("EXTERNAL_DELEGATION") @Suppress("NESTED_CLASS_IN_EXTERNAL_INTERFACE") @@ -12,4 +15,9 @@ external interface MySymbolConstructor { operator fun invoke(description: String = definedExternally): Any } -fun box() = "OK" \ No newline at end of file +// MODULE: main(lib) +// FILE: f.kt + +fun foo(ee: MySymbol?) = "OK" + +fun box() = foo(null) \ No newline at end of file