[JS IR] Support external delegation in case of JS in psi2ir
- fix FE delegation resolver - fix critical KT-40650
This commit is contained in:
@@ -26,12 +26,14 @@ import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry
|
|||||||
import org.jetbrains.kotlin.psi.KtPureClassOrObject
|
import org.jetbrains.kotlin.psi.KtPureClassOrObject
|
||||||
import org.jetbrains.kotlin.psi.KtTypeReference
|
import org.jetbrains.kotlin.psi.KtTypeReference
|
||||||
import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE
|
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.isTypeRefinementEnabled
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
import org.jetbrains.kotlin.resolve.lazy.DelegationFilter
|
import org.jetbrains.kotlin.resolve.lazy.DelegationFilter
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.isDynamic
|
import org.jetbrains.kotlin.types.isDynamic
|
||||||
import org.jetbrains.kotlin.types.isError
|
import org.jetbrains.kotlin.types.isError
|
||||||
|
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
||||||
import org.jetbrains.kotlin.utils.keysToMapExceptNulls
|
import org.jetbrains.kotlin.utils.keysToMapExceptNulls
|
||||||
|
|
||||||
class DelegationResolver<T : CallableMemberDescriptor> private constructor(
|
class DelegationResolver<T : CallableMemberDescriptor> private constructor(
|
||||||
@@ -163,14 +165,17 @@ class DelegationResolver<T : CallableMemberDescriptor> private constructor(
|
|||||||
.asIterable()
|
.asIterable()
|
||||||
.sortedWith(MemberComparator.INSTANCE)
|
.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
|
return delegatedMembers
|
||||||
.keysToMapExceptNulls { delegatingMember ->
|
.keysToMapExceptNulls { delegatingMember ->
|
||||||
val actualDelegates = DescriptorUtils.getAllOverriddenDescriptors(delegatingMember)
|
val actualDelegates = DescriptorUtils.getAllOverriddenDescriptors(delegatingMember)
|
||||||
.filter { it.containingDeclaration == toInterface }
|
.filter { it.containingDeclaration == toInterface }
|
||||||
.map { overriddenDescriptor ->
|
.map { overriddenDescriptor ->
|
||||||
val scope = (delegateExpressionType ?: toInterface.defaultType).memberScope
|
|
||||||
val name = overriddenDescriptor.name
|
val name = overriddenDescriptor.name
|
||||||
|
|
||||||
// this is the actual member of delegateExpressionType that we are delegating to
|
// this is the actual member of delegateExpressionType that we are delegating to
|
||||||
(scope.getContributedFunctions(name, NoLookupLocation.WHEN_CHECK_OVERRIDES) +
|
(scope.getContributedFunctions(name, NoLookupLocation.WHEN_CHECK_OVERRIDES) +
|
||||||
scope.getContributedVariables(name, NoLookupLocation.WHEN_CHECK_OVERRIDES))
|
scope.getContributedVariables(name, NoLookupLocation.WHEN_CHECK_OVERRIDES))
|
||||||
|
|||||||
+5
@@ -1211,6 +1211,11 @@ public class IrBoxJsES6TestGenerated extends AbstractIrBoxJsES6Test {
|
|||||||
runTest("js/js.translator/testData/box/delegation/delegationByArg.kt");
|
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")
|
@TestMetadata("delegationByExprWithArgs.kt")
|
||||||
public void testDelegationByExprWithArgs() throws Exception {
|
public void testDelegationByExprWithArgs() throws Exception {
|
||||||
runTest("js/js.translator/testData/box/delegation/delegationByExprWithArgs.kt");
|
runTest("js/js.translator/testData/box/delegation/delegationByExprWithArgs.kt");
|
||||||
|
|||||||
+5
@@ -1211,6 +1211,11 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
|||||||
runTest("js/js.translator/testData/box/delegation/delegationByArg.kt");
|
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")
|
@TestMetadata("delegationByExprWithArgs.kt")
|
||||||
public void testDelegationByExprWithArgs() throws Exception {
|
public void testDelegationByExprWithArgs() throws Exception {
|
||||||
runTest("js/js.translator/testData/box/delegation/delegationByExprWithArgs.kt");
|
runTest("js/js.translator/testData/box/delegation/delegationByExprWithArgs.kt");
|
||||||
|
|||||||
+5
@@ -1211,6 +1211,11 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
|||||||
runTest("js/js.translator/testData/box/delegation/delegationByArg.kt");
|
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")
|
@TestMetadata("delegationByExprWithArgs.kt")
|
||||||
public void testDelegationByExprWithArgs() throws Exception {
|
public void testDelegationByExprWithArgs() throws Exception {
|
||||||
runTest("js/js.translator/testData/box/delegation/delegationByExprWithArgs.kt");
|
runTest("js/js.translator/testData/box/delegation/delegationByExprWithArgs.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"
|
||||||
|
}
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
// EXPECTED_REACHABLE_NODES: 1236
|
// EXPECTED_REACHABLE_NODES: 1236
|
||||||
// KJS_WITH_FULL_RUNTIME
|
// KJS_WITH_FULL_RUNTIME
|
||||||
// KT-40126
|
// KT-40126
|
||||||
|
|
||||||
|
// MODULE: lib
|
||||||
|
// FILE: l.kt
|
||||||
@file:Suppress("EXTERNAL_DELEGATION")
|
@file:Suppress("EXTERNAL_DELEGATION")
|
||||||
|
|
||||||
@Suppress("NESTED_CLASS_IN_EXTERNAL_INTERFACE")
|
@Suppress("NESTED_CLASS_IN_EXTERNAL_INTERFACE")
|
||||||
@@ -12,4 +15,9 @@ external interface MySymbolConstructor {
|
|||||||
operator fun invoke(description: String = definedExternally): Any
|
operator fun invoke(description: String = definedExternally): Any
|
||||||
}
|
}
|
||||||
|
|
||||||
fun box() = "OK"
|
// MODULE: main(lib)
|
||||||
|
// FILE: f.kt
|
||||||
|
|
||||||
|
fun foo(ee: MySymbol?) = "OK"
|
||||||
|
|
||||||
|
fun box() = foo(null)
|
||||||
Reference in New Issue
Block a user