From 51c59e5634328c43c4ab8d078b026685e5ebd4b5 Mon Sep 17 00:00:00 2001 From: Roman Golyshev Date: Wed, 30 Dec 2020 13:58:23 +0300 Subject: [PATCH] FIR IDE: Check function call before trying to drop the receiver --- .../FirShortenRefsTestGenerated.java | 20 +++++++++++++++++++ .../fir/components/KtFirReferenceShortener.kt | 18 ++++++++++++++--- ...plicitlyImportedFunctionFromLocalObject.kt | 12 +++++++++++ ...lyImportedFunctionFromLocalObject.kt.after | 12 +++++++++++ ...onOnCompanionObjectReceiverNotShortened.kt | 12 +++++++++++ ...mpanionObjectReceiverNotShortened.kt.after | 12 +++++++++++ ...ionFunctionOnObjectReceiverNotShortened.kt | 10 ++++++++++ ...ctionOnObjectReceiverNotShortened.kt.after | 10 ++++++++++ .../extenstionFunctionReceiverNotShortened.kt | 10 ++++++++++ ...stionFunctionReceiverNotShortened.kt.after | 10 ++++++++++ 10 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 idea/testData/shortenRefsFir/calls/explicitlyImportedFunctionFromLocalObject.kt create mode 100644 idea/testData/shortenRefsFir/calls/explicitlyImportedFunctionFromLocalObject.kt.after create mode 100644 idea/testData/shortenRefsFir/calls/extenstionFunctionOnCompanionObjectReceiverNotShortened.kt create mode 100644 idea/testData/shortenRefsFir/calls/extenstionFunctionOnCompanionObjectReceiverNotShortened.kt.after create mode 100644 idea/testData/shortenRefsFir/calls/extenstionFunctionOnObjectReceiverNotShortened.kt create mode 100644 idea/testData/shortenRefsFir/calls/extenstionFunctionOnObjectReceiverNotShortened.kt.after create mode 100644 idea/testData/shortenRefsFir/calls/extenstionFunctionReceiverNotShortened.kt create mode 100644 idea/testData/shortenRefsFir/calls/extenstionFunctionReceiverNotShortened.kt.after diff --git a/idea/idea-fir/tests/org/jetbrains/kotlin/shortenRefs/FirShortenRefsTestGenerated.java b/idea/idea-fir/tests/org/jetbrains/kotlin/shortenRefs/FirShortenRefsTestGenerated.java index bc2474535e7..e1e234f7941 100644 --- a/idea/idea-fir/tests/org/jetbrains/kotlin/shortenRefs/FirShortenRefsTestGenerated.java +++ b/idea/idea-fir/tests/org/jetbrains/kotlin/shortenRefs/FirShortenRefsTestGenerated.java @@ -46,6 +46,26 @@ public class FirShortenRefsTestGenerated extends AbstractFirShortenRefsTest { runTest("idea/testData/shortenRefsFir/calls/classInSameFile.kt"); } + @TestMetadata("explicitlyImportedFunctionFromLocalObject.kt") + public void testExplicitlyImportedFunctionFromLocalObject() throws Exception { + runTest("idea/testData/shortenRefsFir/calls/explicitlyImportedFunctionFromLocalObject.kt"); + } + + @TestMetadata("extenstionFunctionOnCompanionObjectReceiverNotShortened.kt") + public void testExtenstionFunctionOnCompanionObjectReceiverNotShortened() throws Exception { + runTest("idea/testData/shortenRefsFir/calls/extenstionFunctionOnCompanionObjectReceiverNotShortened.kt"); + } + + @TestMetadata("extenstionFunctionOnObjectReceiverNotShortened.kt") + public void testExtenstionFunctionOnObjectReceiverNotShortened() throws Exception { + runTest("idea/testData/shortenRefsFir/calls/extenstionFunctionOnObjectReceiverNotShortened.kt"); + } + + @TestMetadata("extenstionFunctionReceiverNotShortened.kt") + public void testExtenstionFunctionReceiverNotShortened() throws Exception { + runTest("idea/testData/shortenRefsFir/calls/extenstionFunctionReceiverNotShortened.kt"); + } + @TestMetadata("functionInSameFile.kt") public void testFunctionInSameFile() throws Exception { runTest("idea/testData/shortenRefsFir/calls/functionInSameFile.kt"); diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirReferenceShortener.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirReferenceShortener.kt index b67d28a0224..25e88f6fa24 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirReferenceShortener.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirReferenceShortener.kt @@ -11,11 +11,11 @@ import com.intellij.psi.SmartPsiElementPointer import com.intellij.util.containers.addIfNotNull import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.fir.FirElement -import org.jetbrains.kotlin.fir.declarations.FirClass -import org.jetbrains.kotlin.fir.declarations.FirFile -import org.jetbrains.kotlin.fir.declarations.FirResolvedImport +import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClass +import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.expressions.FirFunctionCall import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier +import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression import org.jetbrains.kotlin.fir.psi import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.resolve.ScopeSession @@ -247,6 +247,8 @@ internal class KtFirReferenceShortener( override fun visitFunctionCall(functionCall: FirFunctionCall) { super.visitFunctionCall(functionCall) + if (!canBePossibleToDropReceiver(functionCall)) return + val callExpression = functionCall.psi as? KtCallExpression ?: return val qualifiedCallExpression = callExpression.getDotQualifiedExpressionForSelector() ?: return @@ -261,6 +263,16 @@ internal class KtFirReferenceShortener( } } + private fun canBePossibleToDropReceiver(functionCall: FirFunctionCall): Boolean { + // we can remove receiver only if it is a qualifier + val explicitReceiver = functionCall.explicitReceiver as? FirResolvedQualifier ?: return false + + // if there is no extension receiver necessary, then it can be removed + if (functionCall.extensionReceiver is FirNoReceiverExpression) return true + + val receiverType = explicitReceiver.typeRef.toRegularClass(firResolveState.rootModuleSession) ?: return true + return receiverType.classKind != ClassKind.OBJECT + } override fun visitResolvedQualifier(resolvedQualifier: FirResolvedQualifier) { super.visitResolvedQualifier(resolvedQualifier) diff --git a/idea/testData/shortenRefsFir/calls/explicitlyImportedFunctionFromLocalObject.kt b/idea/testData/shortenRefsFir/calls/explicitlyImportedFunctionFromLocalObject.kt new file mode 100644 index 00000000000..4daebabe693 --- /dev/null +++ b/idea/testData/shortenRefsFir/calls/explicitlyImportedFunctionFromLocalObject.kt @@ -0,0 +1,12 @@ +// FIR_COMPARISON +package test + +import test.Obj.funFromObj + +object Obj { + fun funFromObj() {} +} + +fun usage() { + Obj.funFromObj() +} \ No newline at end of file diff --git a/idea/testData/shortenRefsFir/calls/explicitlyImportedFunctionFromLocalObject.kt.after b/idea/testData/shortenRefsFir/calls/explicitlyImportedFunctionFromLocalObject.kt.after new file mode 100644 index 00000000000..4c45aa7a3b7 --- /dev/null +++ b/idea/testData/shortenRefsFir/calls/explicitlyImportedFunctionFromLocalObject.kt.after @@ -0,0 +1,12 @@ +// FIR_COMPARISON +package test + +import test.Obj.funFromObj + +object Obj { + fun funFromObj() {} +} + +fun usage() { + funFromObj() +} \ No newline at end of file diff --git a/idea/testData/shortenRefsFir/calls/extenstionFunctionOnCompanionObjectReceiverNotShortened.kt b/idea/testData/shortenRefsFir/calls/extenstionFunctionOnCompanionObjectReceiverNotShortened.kt new file mode 100644 index 00000000000..6e42faf1623 --- /dev/null +++ b/idea/testData/shortenRefsFir/calls/extenstionFunctionOnCompanionObjectReceiverNotShortened.kt @@ -0,0 +1,12 @@ +// FIR_COMPARISON +package test + +class T { + companion object +} + +fun T.Companion.ext() {} + +fun usage() { + T.ext() +} \ No newline at end of file diff --git a/idea/testData/shortenRefsFir/calls/extenstionFunctionOnCompanionObjectReceiverNotShortened.kt.after b/idea/testData/shortenRefsFir/calls/extenstionFunctionOnCompanionObjectReceiverNotShortened.kt.after new file mode 100644 index 00000000000..d0a9331bdbf --- /dev/null +++ b/idea/testData/shortenRefsFir/calls/extenstionFunctionOnCompanionObjectReceiverNotShortened.kt.after @@ -0,0 +1,12 @@ +// FIR_COMPARISON +package test + +class T { + companion object +} + +fun T.Companion.ext() {} + +fun usage() { + T.ext() +} \ No newline at end of file diff --git a/idea/testData/shortenRefsFir/calls/extenstionFunctionOnObjectReceiverNotShortened.kt b/idea/testData/shortenRefsFir/calls/extenstionFunctionOnObjectReceiverNotShortened.kt new file mode 100644 index 00000000000..c1b04717494 --- /dev/null +++ b/idea/testData/shortenRefsFir/calls/extenstionFunctionOnObjectReceiverNotShortened.kt @@ -0,0 +1,10 @@ +// FIR_COMPARISON +package test + +object T + +fun T.ext() {} + +fun usage() { + T.ext() +} \ No newline at end of file diff --git a/idea/testData/shortenRefsFir/calls/extenstionFunctionOnObjectReceiverNotShortened.kt.after b/idea/testData/shortenRefsFir/calls/extenstionFunctionOnObjectReceiverNotShortened.kt.after new file mode 100644 index 00000000000..52fdbb62ddb --- /dev/null +++ b/idea/testData/shortenRefsFir/calls/extenstionFunctionOnObjectReceiverNotShortened.kt.after @@ -0,0 +1,10 @@ +// FIR_COMPARISON +package test + +object T + +fun T.ext() {} + +fun usage() { + T.ext() +} \ No newline at end of file diff --git a/idea/testData/shortenRefsFir/calls/extenstionFunctionReceiverNotShortened.kt b/idea/testData/shortenRefsFir/calls/extenstionFunctionReceiverNotShortened.kt new file mode 100644 index 00000000000..fbfb363c1b3 --- /dev/null +++ b/idea/testData/shortenRefsFir/calls/extenstionFunctionReceiverNotShortened.kt @@ -0,0 +1,10 @@ +// FIR_COMPARISON +package test + +class T + +fun T.ext() {} + +fun usage(t: T) { + t.ext() +} \ No newline at end of file diff --git a/idea/testData/shortenRefsFir/calls/extenstionFunctionReceiverNotShortened.kt.after b/idea/testData/shortenRefsFir/calls/extenstionFunctionReceiverNotShortened.kt.after new file mode 100644 index 00000000000..1c3c4c8afbd --- /dev/null +++ b/idea/testData/shortenRefsFir/calls/extenstionFunctionReceiverNotShortened.kt.after @@ -0,0 +1,10 @@ +// FIR_COMPARISON +package test + +class T + +fun T.ext() {} + +fun usage(t: T) { + t.ext() +}