From f42be4aea29c58b5cdb5c662c1ba16c7c0aa1321 Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Fri, 11 Aug 2017 12:17:25 +0300 Subject: [PATCH] [NI] Fix exception explicit qualified receiver and dispatch receiver --- .../resolve/calls/tower/PSICallResolver.kt | 2 +- .../kotlin/resolve/calls/tower/PSIKotlinCalls.kt | 16 ++++++++++++---- .../kotlin/resolve/calls/model/KotlinCall.kt | 9 +++++---- .../resolve/calls/model/KotlinCallArguments.kt | 6 ++++-- .../propertyWithExtensionTypeInvoke.kt | 7 +++++++ .../propertyWithExtensionTypeInvoke.txt | 16 ++++++++++++++++ .../checkers/DiagnosticsTestGenerated.java | 6 ++++++ 7 files changed, 51 insertions(+), 11 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/regressions/propertyWithExtensionTypeInvoke.kt create mode 100644 compiler/testData/diagnostics/tests/regressions/propertyWithExtensionTypeInvoke.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt index 3d3a5002edb..2ae266ff383 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSICallResolver.kt @@ -313,7 +313,7 @@ class PSICallResolver( val variableCallArgument = createReceiverCallArgument(variable) val explicitReceiver = kotlinCall.explicitReceiver - val callForInvoke = if (useExplicitReceiver && explicitReceiver is SimpleKotlinCallArgument) { + val callForInvoke = if (useExplicitReceiver && explicitReceiver != null) { PSIKotlinCallForInvoke(kotlinCall, variable, explicitReceiver, variableCallArgument) } else { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSIKotlinCalls.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSIKotlinCalls.kt index b462afabd2f..6abd09d0178 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSIKotlinCalls.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/PSIKotlinCalls.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategyForInvoke import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver +import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue import org.jetbrains.kotlin.util.OperatorNameConventions val KotlinCall.psiKotlinCall: PSIKotlinCall get() { @@ -80,7 +81,7 @@ class PSIKotlinCallForVariable( class PSIKotlinCallForInvoke( val baseCall: PSIKotlinCallImpl, val variableCall: KotlinResolutionCandidate, - override val explicitReceiver: SimpleKotlinCallArgument, + override val explicitReceiver: ReceiverKotlinCallArgument, override val dispatchReceiverForInvokeExtension: SimpleKotlinCallArgument? ) : PSIKotlinCall() { override val callKind: KotlinCallKind get() = KotlinCallKind.FUNCTION @@ -101,8 +102,15 @@ class PSIKotlinCallForInvoke( val calleeExpression = baseCall.psiCall.calleeExpression!! psiCall = CallTransformer.CallForImplicitInvoke( - explicitExtensionReceiver?.receiver?.receiverValue, - variableReceiver.receiver.receiverValue as ExpressionReceiver, baseCall.psiCall, true) - tracingStrategy = TracingStrategyForInvoke(calleeExpression, psiCall, variableReceiver.receiver.receiverValue.type) + explicitExtensionReceiver?.receiverValue, + variableReceiver.receiverValue as ExpressionReceiver, baseCall.psiCall, true) + tracingStrategy = TracingStrategyForInvoke(calleeExpression, psiCall, variableReceiver.receiverValue!!.type) // check for type parameters } } + +val ReceiverKotlinCallArgument.receiverValue: ReceiverValue? + get() = when (this) { + is SimpleKotlinCallArgument -> this.receiver.receiverValue + is QualifierReceiverKotlinCallArgument -> this.receiver.classValueReceiver + else -> null + } \ No newline at end of file diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCall.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCall.kt index ea537253d01..0fa8f0b91fb 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCall.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCall.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2016 JetBrains s.r.o. + * Copyright 2010-2017 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. @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.resolve.calls.model import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.utils.addToStdlib.safeAs interface KotlinCall : ResolutionAtom { @@ -25,7 +26,7 @@ interface KotlinCall : ResolutionAtom { val explicitReceiver: ReceiverKotlinCallArgument? // a.(foo)() -- (foo) is dispatchReceiverForInvoke - val dispatchReceiverForInvokeExtension: SimpleKotlinCallArgument? get() = null + val dispatchReceiverForInvokeExtension: ReceiverKotlinCallArgument? get() = null val name: Name @@ -62,8 +63,8 @@ fun KotlinCall.checkCallInvariants() { "Lambda argument or callable reference is not allowed as explicit receiver: $explicitReceiver" } - (explicitReceiver as? SimpleKotlinCallArgument)?.checkReceiverInvariants() - dispatchReceiverForInvokeExtension?.checkReceiverInvariants() + explicitReceiver.safeAs()?.checkReceiverInvariants() + dispatchReceiverForInvokeExtension.safeAs()?.checkReceiverInvariants() argumentsInParenthesis.forEach(KotlinCallArgument::checkArgumentInvariants) externalArgument?.checkArgumentInvariants() diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCallArguments.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCallArguments.kt index 600678a0239..16029a38435 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCallArguments.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCallArguments.kt @@ -28,9 +28,13 @@ import org.jetbrains.kotlin.types.UnwrappedType interface ReceiverKotlinCallArgument : KotlinCallArgument { val receiver: DetailedReceiver + val isSafeCall: Boolean } class QualifierReceiverKotlinCallArgument(override val receiver: QualifierReceiver) : ReceiverKotlinCallArgument { + override val isSafeCall: Boolean + get() = false // TODO: add warning + override fun toString() = "$receiver" override val isSpread get() = false @@ -46,8 +50,6 @@ interface PostponableKotlinCallArgument : KotlinCallArgument, ResolutionAtom interface SimpleKotlinCallArgument : KotlinCallArgument, ReceiverKotlinCallArgument { override val receiver: ReceiverValueWithSmartCastInfo - - val isSafeCall: Boolean } interface ExpressionKotlinCallArgument : SimpleKotlinCallArgument, ResolutionAtom diff --git a/compiler/testData/diagnostics/tests/regressions/propertyWithExtensionTypeInvoke.kt b/compiler/testData/diagnostics/tests/regressions/propertyWithExtensionTypeInvoke.kt new file mode 100644 index 00000000000..e3b2daf88eb --- /dev/null +++ b/compiler/testData/diagnostics/tests/regressions/propertyWithExtensionTypeInvoke.kt @@ -0,0 +1,7 @@ +object X + +class Y { + fun f(op: X.() -> Unit) { + X.op() + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/regressions/propertyWithExtensionTypeInvoke.txt b/compiler/testData/diagnostics/tests/regressions/propertyWithExtensionTypeInvoke.txt new file mode 100644 index 00000000000..2de4946fe00 --- /dev/null +++ b/compiler/testData/diagnostics/tests/regressions/propertyWithExtensionTypeInvoke.txt @@ -0,0 +1,16 @@ +package + +public object X { + private constructor X() + 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 Y { + public constructor Y() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun f(/*0*/ op: X.() -> kotlin.Unit): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 0a13c4b0f06..39025b8ddce 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -17470,6 +17470,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("propertyWithExtensionTypeInvoke.kt") + public void testPropertyWithExtensionTypeInvoke() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/regressions/propertyWithExtensionTypeInvoke.kt"); + doTest(fileName); + } + @TestMetadata("resolveSubclassOfList.kt") public void testResolveSubclassOfList() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/regressions/resolveSubclassOfList.kt");