From ea7fac07c4a52b1aa1f9cd7a8a9b854170abf0d7 Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Fri, 13 Jan 2017 18:40:21 +0300 Subject: [PATCH] Ban import member intentions from import directives (KT-13710) #KT-13710 Fixed --- .../jetbrains/kotlin/psi/psiUtil/ktPsiUtil.kt | 4 ++++ .../intentions/ImportAllMembersIntention.kt | 9 ++++++--- .../idea/intentions/ImportMemberIntention.kt | 11 +++++------ ...lassFromReferenceExpressionActionFactory.kt | 9 ++------- .../ImportAllMembersInImport.kt | 4 ++++ .../importMember/ImportMemberInImport.kt | 4 ++++ .../ImportMemberInMiddleOfImport.kt | 4 ++++ .../intentions/IntentionTestGenerated.java | 18 ++++++++++++++++++ 8 files changed, 47 insertions(+), 16 deletions(-) create mode 100644 idea/testData/intentions/importAllMembers/ImportAllMembersInImport.kt create mode 100644 idea/testData/intentions/importMember/ImportMemberInImport.kt create mode 100644 idea/testData/intentions/importMember/ImportMemberInMiddleOfImport.kt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/psiUtil/ktPsiUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/psiUtil/ktPsiUtil.kt index 1fa807c111f..433e3606fd1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/psiUtil/ktPsiUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/psiUtil/ktPsiUtil.kt @@ -347,6 +347,10 @@ fun KtSimpleNameExpression.isPackageDirectiveExpression(): Boolean { return parent is KtPackageDirective || parent?.parent is KtPackageDirective } +fun KtExpression.isInImportDirective(): Boolean { + return parents.takeWhile { it !is KtDeclaration && it !is KtBlockExpression }.any { it is KtImportDirective } +} + fun KtExpression.isLambdaOutsideParentheses(): Boolean { val parent = parent return when (parent) { diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ImportAllMembersIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ImportAllMembersIntention.kt index 4549dd47acd..d82a0668292 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/ImportAllMembersIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ImportAllMembersIntention.kt @@ -30,6 +30,7 @@ import org.jetbrains.kotlin.psi.KtNameReferenceExpression import org.jetbrains.kotlin.psi.KtPsiFactory import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElementSelector +import org.jetbrains.kotlin.psi.psiUtil.isInImportDirective import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.scopes.receivers.ClassQualifier @@ -44,7 +45,9 @@ class ImportAllMembersIntention : SelfTargetingIntention { qualifiedExpression -> + val qualifiedExpressions = element.containingKtFile.collectDescendantsOfType { qualifiedExpression -> val qualifierName = qualifiedExpression.receiverExpression.getQualifiedElementSelector() as? KtNameReferenceExpression qualifierName?.getReferencedNameAsName() == classFqName.shortName() && target(qualifiedExpression)?.importableFqName?.parent() == classFqName } diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ImportMemberIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ImportMemberIntention.kt index cd629225e9c..1b9459139f9 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/ImportMemberIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ImportMemberIntention.kt @@ -18,21 +18,18 @@ package org.jetbrains.kotlin.idea.intentions import com.intellij.openapi.editor.Editor import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.idea.core.ShortenReferences import org.jetbrains.kotlin.idea.imports.canBeReferencedViaImport import org.jetbrains.kotlin.idea.imports.importableFqName import org.jetbrains.kotlin.idea.references.mainReference import org.jetbrains.kotlin.idea.util.ImportDescriptorResult import org.jetbrains.kotlin.idea.util.ImportInsertHelper -import org.jetbrains.kotlin.idea.core.ShortenReferences import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtDotQualifiedExpression import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtNameReferenceExpression import org.jetbrains.kotlin.psi.KtUserType -import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType -import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElement -import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElementSelector -import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression +import org.jetbrains.kotlin.psi.psiUtil.* import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode @@ -44,6 +41,8 @@ class ImportMemberIntention : SelfTargetingOffsetIndependentIntention() != null - override fun getPossibleClassKinds(element: KtSimpleNameExpression, diagnostic: Diagnostic): List { fun isEnum(element: PsiElement): Boolean { return when (element) { @@ -120,7 +115,7 @@ object CreateClassFromReferenceExpressionActionFactory : CreateClassFromUsageFac val fullCallExpr = getFullCallExpression(element) ?: return null - if (isInsideOfImport(element) || isQualifierExpected(element)) { + if (element.isInImportDirective() || isQualifierExpected(element)) { val receiverSelector = (fullCallExpr as? KtQualifiedExpression)?.receiverExpression?.getQualifiedElementSelector() as? KtReferenceExpression val qualifierDescriptor = receiverSelector?.let { context[BindingContext.REFERENCE_TARGET, it] } diff --git a/idea/testData/intentions/importAllMembers/ImportAllMembersInImport.kt b/idea/testData/intentions/importAllMembers/ImportAllMembersInImport.kt new file mode 100644 index 00000000000..1eec9972c09 --- /dev/null +++ b/idea/testData/intentions/importAllMembers/ImportAllMembersInImport.kt @@ -0,0 +1,4 @@ +// IS_APPLICABLE: false +// WITH_RUNTIME + +import javax.swing.SwingConstants.CENTER diff --git a/idea/testData/intentions/importMember/ImportMemberInImport.kt b/idea/testData/intentions/importMember/ImportMemberInImport.kt new file mode 100644 index 00000000000..826fb8f7363 --- /dev/null +++ b/idea/testData/intentions/importMember/ImportMemberInImport.kt @@ -0,0 +1,4 @@ +// IS_APPLICABLE: false +// WITH_RUNTIME + +import javax.swing.SwingConstants.CENTER \ No newline at end of file diff --git a/idea/testData/intentions/importMember/ImportMemberInMiddleOfImport.kt b/idea/testData/intentions/importMember/ImportMemberInMiddleOfImport.kt new file mode 100644 index 00000000000..4e7b1fec860 --- /dev/null +++ b/idea/testData/intentions/importMember/ImportMemberInMiddleOfImport.kt @@ -0,0 +1,4 @@ +// IS_APPLICABLE: false +// WITH_RUNTIME + +import javax.swing.SwingConstants.CENTER \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java index 03a6ee3606f..c6b48e4aec1 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java @@ -7739,6 +7739,12 @@ public class IntentionTestGenerated extends AbstractIntentionTest { doTest(fileName); } + @TestMetadata("ImportAllMembersInImport.kt") + public void testImportAllMembersInImport() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/importAllMembers/ImportAllMembersInImport.kt"); + doTest(fileName); + } + @TestMetadata("NotFromCompanionObject.kt") public void testNotFromCompanionObject() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/importAllMembers/NotFromCompanionObject.kt"); @@ -7802,6 +7808,18 @@ public class IntentionTestGenerated extends AbstractIntentionTest { doTest(fileName); } + @TestMetadata("ImportMemberInImport.kt") + public void testImportMemberInImport() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/importMember/ImportMemberInImport.kt"); + doTest(fileName); + } + + @TestMetadata("ImportMemberInMiddleOfImport.kt") + public void testImportMemberInMiddleOfImport() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/importMember/ImportMemberInMiddleOfImport.kt"); + doTest(fileName); + } + @TestMetadata("NestedClass1.kt") public void testNestedClass1() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/importMember/NestedClass1.kt");