From 07ca355af8c1a2fc517920a6b04a4442620a7de0 Mon Sep 17 00:00:00 2001 From: Pavel Kirpichenkov Date: Wed, 19 Feb 2020 20:22:57 +0300 Subject: [PATCH] [NI] Fix smartcasts for conventional contains in when Call argument for conventional `contains` after expanding `in` may come from a `when` subject during its branch analysis. In this case data flow info from a previous when branch was not considered, because data flow info for subject had been used instead of data flow before argument. Use of the latter one for the conventional `contains` solves the issue. The old FE uses `isExternal` property of value arguments to skip smartcast reporting on `when` subject, if they come from branches. To prevent undesired smartcasts on `when` subject after branch analysis in the new FE, `isExternal` arguments are skipped in diagnostic reporter and during recorded type update. Also, the new FE interprets `isExternal` completely differently from the old FE. In the old FE this property is used exclusively by `when` with subject. In the new FE it is also used for parially resolved calls, lambda return arguments and receivers. This may be preventing the use of data flow info before argument in the first place, but this assumption requires additional investigation. ^KT-36818 Fixed --- ...endDiagnosticsTestWithStdlibGenerated.java | 10 +++++ .../DiagnosticReporterByTrackingStrategy.kt | 10 +++-- .../tower/KotlinResolutionCallbacksImpl.kt | 2 +- .../tower/KotlinToResolvedCallTransformer.kt | 16 ++++---- .../resolve/calls/tower/NewCallArguments.kt | 10 +++-- .../BasicExpressionTypingVisitor.java | 7 +++- .../src/org/jetbrains/kotlin/psi/Call.java | 2 +- .../smartcasts/externalArguments.fir.kt | 37 +++++++++++++++++++ .../contracts/smartcasts/externalArguments.kt | 37 +++++++++++++++++++ .../smartcasts/externalArguments.txt | 14 +++++++ .../contracts/smartcasts/when/kt36818.fir.kt | 11 ++++++ .../contracts/smartcasts/when/kt36818.kt | 11 ++++++ .../contracts/smartcasts/when/kt36818.txt | 3 ++ .../testData/ir/irText/expressions/when.txt | 5 ++- .../DiagnosticsTestWithStdLibGenerated.java | 10 +++++ ...ticsTestWithStdLibUsingJavacGenerated.java | 10 +++++ .../callTranslator/FunctionCallCases.kt | 10 ++++- 17 files changed, 183 insertions(+), 22 deletions(-) create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/externalArguments.fir.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/externalArguments.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/externalArguments.txt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/kt36818.fir.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/kt36818.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/kt36818.txt diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestWithStdlibGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestWithStdlibGenerated.java index ba62289ffd5..928fda2a2bb 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestWithStdlibGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestWithStdlibGenerated.java @@ -1360,6 +1360,11 @@ public class FirOldFrontendDiagnosticsTestWithStdlibGenerated extends AbstractFi runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/extensionReceiver_after.kt"); } + @TestMetadata("externalArguments.kt") + public void testExternalArguments() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/externalArguments.kt"); + } + @TestMetadata("intersectingInfo.kt") public void testIntersectingInfo() throws Exception { runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/intersectingInfo.kt"); @@ -1508,6 +1513,11 @@ public class FirOldFrontendDiagnosticsTestWithStdlibGenerated extends AbstractFi KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true); } + @TestMetadata("kt36818.kt") + public void testKt36818() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/kt36818.kt"); + } + @TestMetadata("withSubject.kt") public void testWithSubject() throws Exception { runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withSubject.kt"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt index 69e005ab4c4..a3047b46541 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt @@ -251,10 +251,12 @@ class DiagnosticReporterByTrackingStrategy( ) val dataFlowValue = dataFlowValueFactory.createDataFlowValue(expressionArgument.receiver.receiverValue, context) val call = if (call.callElement is KtBinaryExpression) null else call - smartCastManager.checkAndRecordPossibleCast( - dataFlowValue, smartCastDiagnostic.smartCastType, argumentExpression, context, call, - recordExpressionType = false - ) + if (!expressionArgument.valueArgument.isExternal()) { + smartCastManager.checkAndRecordPossibleCast( + dataFlowValue, smartCastDiagnostic.smartCastType, argumentExpression, context, call, + recordExpressionType = false + ) + } else null } is ReceiverExpressionKotlinCallArgument -> { trace.markAsReported() diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt index b67f5d86775..576485155a2 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt @@ -130,7 +130,7 @@ class KotlinResolutionCallbacksImpl( return createSimplePSICallArgument( trace.bindingContext, outerCallContext.statementFilter, outerCallContext.scope.ownerDescriptor, CallMaker.makeExternalValueArgument(ktExpression), DataFlowInfo.EMPTY, typeInfo, languageVersionSettings, - dataFlowValueFactory + dataFlowValueFactory, outerCallContext.call ) } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt index bd1de7dc5eb..d58f10a1cec 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt @@ -318,13 +318,15 @@ class KotlinToResolvedCallTransformer( ) } - updateRecordedType( - argumentExpression, - parameter, - newContext, - constantConvertedArgument?.unknownIntegerType?.unwrap(), - resolvedCall.isReallySuccess() - ) + if (!valueArgument.isExternal()) { + updateRecordedType( + argumentExpression, + parameter, + newContext, + constantConvertedArgument?.unknownIntegerType?.unwrap(), + resolvedCall.isReallySuccess() + ) + } } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewCallArguments.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewCallArguments.kt index 8a5bfecd665..6a294effd75 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewCallArguments.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/NewCallArguments.kt @@ -303,7 +303,8 @@ internal fun createSimplePSICallArgument( contextForArgument.scope.ownerDescriptor, valueArgument, contextForArgument.dataFlowInfo, typeInfoForArgument, contextForArgument.languageVersionSettings, - contextForArgument.dataFlowValueFactory + contextForArgument.dataFlowValueFactory, + contextForArgument.call, ) internal fun createSimplePSICallArgument( @@ -314,7 +315,8 @@ internal fun createSimplePSICallArgument( dataFlowInfoBeforeThisArgument: DataFlowInfo, typeInfoForArgument: KotlinTypeInfo, languageVersionSettings: LanguageVersionSettings, - dataFlowValueFactory: DataFlowValueFactory + dataFlowValueFactory: DataFlowValueFactory, + call: Call ): SimplePSIKotlinCallArgument? { val ktExpression = KtPsiUtil.getLastElementDeparenthesized(valueArgument.getArgumentExpression(), statementFilter) ?: return null @@ -331,10 +333,10 @@ internal fun createSimplePSICallArgument( // so we use a fast-path here to avoid calling transformToReceiverWithSmartCastInfo function ReceiverValueWithSmartCastInfo(expressionReceiver, emptySet(), isStable = true) } else { + val useDataFlowInfoBeforeArgument = call.callType == Call.CallType.CONTAINS transformToReceiverWithSmartCastInfo( ownerDescriptor, bindingContext, - // dataFlowInfoBeforeThisArgument cannot be used here, because of if() { if (x != null) return; x } - typeInfoForArgument.dataFlowInfo, + if (useDataFlowInfoBeforeArgument) dataFlowInfoBeforeThisArgument else typeInfoForArgument.dataFlowInfo, expressionReceiver, languageVersionSettings, dataFlowValueFactory diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java index b59ec9ca5ac..51a7124e2d1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java @@ -1402,9 +1402,14 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { ExpressionReceiver receiver = safeGetExpressionReceiver(facade, right, contextWithNoExpectedType); ExpressionTypingContext contextWithDataFlow = context.replaceDataFlowInfo(dataFlowInfo); + Call containsCall = CallMaker.makeCall( + callElement, receiver, null, operationSign, + Collections.singletonList(leftArgument), Call.CallType.CONTAINS + ); + OverloadResolutionResults resolutionResult = components.callResolver.resolveCallWithGivenName( contextWithDataFlow, - CallMaker.makeCall(callElement, receiver, null, operationSign, Collections.singletonList(leftArgument)), + containsCall, operationSign, OperatorNameConventions.CONTAINS); KotlinType containsType = OverloadResolutionResultsUtil.getResultingType(resolutionResult, context); diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/Call.java b/compiler/psi/src/org/jetbrains/kotlin/psi/Call.java index a535b4fb8e8..8e1d8dafb97 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/psi/Call.java +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/Call.java @@ -67,7 +67,7 @@ public interface Call { KtElement getCallElement(); enum CallType { - DEFAULT, ARRAY_GET_METHOD, ARRAY_SET_METHOD, INVOKE + DEFAULT, ARRAY_GET_METHOD, ARRAY_SET_METHOD, INVOKE, CONTAINS } @NotNull diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/externalArguments.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/externalArguments.fir.kt new file mode 100644 index 00000000000..de95bc6b4e1 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/externalArguments.fir.kt @@ -0,0 +1,37 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE +// !WITH_NEW_INFERENCE + +import kotlin.reflect.KProperty + +fun testLambdaArgumentSmartCast(foo: Int?) { + val v = run { + if (foo != null) + return@run foo + 15 + } +} + +class D { + operator fun getValue(ref: Any?, property: KProperty<*>): Int = 42 +} + +fun testSmartCastInDelegate(d: D?) { + if (d == null) return + val v: Int by d +} + +fun testFunctionCallSmartcast(fn: (() -> Unit)?) { + if (fn == null) return + + fn() +} + +fun testCallableRefernceSmartCast() { + fun forReference() {} + + val refernece = if (true) ::forReference else null + if (refernece == null) + return + + refernece() +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/externalArguments.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/externalArguments.kt new file mode 100644 index 00000000000..29b5a273c70 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/externalArguments.kt @@ -0,0 +1,37 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE +// !WITH_NEW_INFERENCE + +import kotlin.reflect.KProperty + +fun testLambdaArgumentSmartCast(foo: Int?) { + val v = run { + if (foo != null) + return@run foo + 15 + } +} + +class D { + operator fun getValue(ref: Any?, property: KProperty<*>): Int = 42 +} + +fun testSmartCastInDelegate(d: D?) { + if (d == null) return + val v: Int by d +} + +fun testFunctionCallSmartcast(fn: (() -> Unit)?) { + if (fn == null) return + + fn() +} + +fun testCallableRefernceSmartCast() { + fun forReference() {} + + val refernece = if (true) ::forReference else null + if (refernece == null) + return + + refernece() +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/externalArguments.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/externalArguments.txt new file mode 100644 index 00000000000..ecd0195fc1d --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/externalArguments.txt @@ -0,0 +1,14 @@ +package + +public fun testCallableRefernceSmartCast(): kotlin.Unit +public fun testFunctionCallSmartcast(/*0*/ fn: (() -> kotlin.Unit)?): kotlin.Unit +public fun testLambdaArgumentSmartCast(/*0*/ foo: kotlin.Int?): kotlin.Unit +public fun testSmartCastInDelegate(/*0*/ d: D?): kotlin.Unit + +public final class D { + public constructor D() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final operator fun getValue(/*0*/ ref: kotlin.Any?, /*1*/ property: kotlin.reflect.KProperty<*>): kotlin.Int + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/kt36818.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/kt36818.fir.kt new file mode 100644 index 00000000000..100afc833b4 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/kt36818.fir.kt @@ -0,0 +1,11 @@ +fun main(x1: Double?, range: ClosedRange) { + when (x1) { + null -> throw Exception() + in range -> {} // error, no smartcast from previous branch, OK in OI + } + + when { + x1 == null -> throw Exception() + x1 in range -> {} + } +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/kt36818.kt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/kt36818.kt new file mode 100644 index 00000000000..f4f31f677c4 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/kt36818.kt @@ -0,0 +1,11 @@ +fun main(x1: Double?, range: ClosedRange) { + when (x1) { + null -> throw Exception() + in range -> {} // error, no smartcast from previous branch, OK in OI + } + + when { + x1 == null -> throw Exception() + x1 in range -> {} + } +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/kt36818.txt b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/kt36818.txt new file mode 100644 index 00000000000..e847e6ea490 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/kt36818.txt @@ -0,0 +1,3 @@ +package + +public fun main(/*0*/ x1: kotlin.Double?, /*1*/ range: kotlin.ranges.ClosedRange): kotlin.Unit diff --git a/compiler/testData/ir/irText/expressions/when.txt b/compiler/testData/ir/irText/expressions/when.txt index 4414cd610fb..e09bfd0cf88 100644 --- a/compiler/testData/ir/irText/expressions/when.txt +++ b/compiler/testData/ir/irText/expressions/when.txt @@ -47,10 +47,11 @@ FILE fqName: fileName:/when.kt then: CONST String type=kotlin.String value="!Number" BRANCH if: CALL 'public final fun contains (element: T of kotlin.collections.contains): kotlin.Boolean [operator] declared in kotlin.collections' type=kotlin.Boolean origin=IN - : kotlin.Any? + : kotlin.Number $receiver: CALL 'public final fun setOf (): kotlin.collections.Set [inline] declared in kotlin.collections' type=kotlin.collections.Set origin=null : kotlin.Nothing - element: GET_VAR 'val tmp_0: kotlin.Any? [val] declared in .testWithSubject' type=kotlin.Any? origin=null + element: TYPE_OP type=kotlin.Number origin=IMPLICIT_CAST typeOperand=kotlin.Number + GET_VAR 'val tmp_0: kotlin.Any? [val] declared in .testWithSubject' type=kotlin.Any? origin=null then: CONST String type=kotlin.String value="nothingness?" BRANCH if: CONST Boolean type=kotlin.Boolean value=true diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java index 950135d3129..ed0eb5d1f0e 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java @@ -1361,6 +1361,11 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/extensionReceiver_after.kt"); } + @TestMetadata("externalArguments.kt") + public void testExternalArguments() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/externalArguments.kt"); + } + @TestMetadata("intersectingInfo.kt") public void testIntersectingInfo() throws Exception { runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/intersectingInfo.kt"); @@ -1509,6 +1514,11 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true); } + @TestMetadata("kt36818.kt") + public void testKt36818() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/kt36818.kt"); + } + @TestMetadata("withSubject.kt") public void testWithSubject() throws Exception { runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withSubject.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java index cc4342d157a..7db0fb9e672 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java @@ -1361,6 +1361,11 @@ public class DiagnosticsTestWithStdLibUsingJavacGenerated extends AbstractDiagno runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/extensionReceiver_after.kt"); } + @TestMetadata("externalArguments.kt") + public void testExternalArguments() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/externalArguments.kt"); + } + @TestMetadata("intersectingInfo.kt") public void testIntersectingInfo() throws Exception { runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/intersectingInfo.kt"); @@ -1509,6 +1514,11 @@ public class DiagnosticsTestWithStdLibUsingJavacGenerated extends AbstractDiagno KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true); } + @TestMetadata("kt36818.kt") + public void testKt36818() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/kt36818.kt"); + } + @TestMetadata("withSubject.kt") public void testWithSubject() throws Exception { runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/when/withSubject.kt"); diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/FunctionCallCases.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/FunctionCallCases.kt index 151337cd95e..50eafe54d5f 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/FunctionCallCases.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/callTranslator/FunctionCallCases.kt @@ -257,8 +257,14 @@ object SuperCallCase : FunctionCallCase() { } object DynamicInvokeAndBracketAccessCallCase : FunctionCallCase() { - fun canApply(callInfo: FunctionCallInfo): Boolean = - callInfo.resolvedCall.call.callType != Call.CallType.DEFAULT && callInfo.callableDescriptor.isDynamic() + fun canApply(callInfo: FunctionCallInfo): Boolean { + if (!callInfo.callableDescriptor.isDynamic()) + return false + val callType = callInfo.resolvedCall.call.callType + return callType == Call.CallType.ARRAY_GET_METHOD + || callType == Call.CallType.ARRAY_SET_METHOD + || callType == Call.CallType.INVOKE + } override fun FunctionCallInfo.dispatchReceiver(): JsExpression { val arguments = argumentsInfo.translateArguments