diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ImportAllMembersIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ImportAllMembersIntention.kt index 92d1c7f05e3..919288212b0 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/ImportAllMembersIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ImportAllMembersIntention.kt @@ -25,9 +25,7 @@ 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.psi.KtDotQualifiedExpression -import org.jetbrains.kotlin.psi.KtNameReferenceExpression -import org.jetbrains.kotlin.psi.KtPsiFactory +import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElementSelector import org.jetbrains.kotlin.psi.psiUtil.isInImportDirective @@ -35,17 +33,15 @@ import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.scopes.receivers.ClassQualifier -class ImportAllMembersIntention : SelfTargetingIntention( - KtDotQualifiedExpression::class.java, - "Import members with '*'" -){ - override fun isApplicableTo(element: KtDotQualifiedExpression, caretOffset: Int): Boolean { - if (!element.receiverExpression.range.containsOffset(caretOffset)) return false +class ImportAllMembersIntention : SelfTargetingIntention(KtElement::class.java, "Import members with '*'"){ + override fun isApplicableTo(element: KtElement, caretOffset: Int): Boolean { + val receiverExpression = element.receiverExpression() ?: return false + if (!receiverExpression.range.containsOffset(caretOffset)) return false - val target = target(element) ?: return false + val target = target(element, receiverExpression) ?: return false val targetFqName = target.importableFqName ?: return false - if (element.isInImportDirective()) return false + if (receiverExpression.isInImportDirective()) return false val file = element.containingKtFile val project = file.project @@ -58,12 +54,12 @@ class ImportAllMembersIntention : SelfTargetingIntention { userType -> + val receiver = userType.receiverExpression()?.getQualifiedElementSelector() as? KtNameReferenceExpression + receiver?.getReferencedNameAsName() == classFqName.shortName() && target(userType)?.importableFqName?.parent() == classFqName + } //TODO: not deep - ShortenReferences.DEFAULT.process(qualifiedExpressions) + ShortenReferences.DEFAULT.process(qualifiedExpressions + userTypes) } - private fun target(expression: KtDotQualifiedExpression): DeclarationDescriptor? { - val bindingContext = expression.analyze(BodyResolveMode.PARTIAL) - if (bindingContext[BindingContext.QUALIFIER, expression.receiverExpression] !is ClassQualifier) { + private fun target(qualifiedElement: KtElement, receiverExpression: KtExpression): DeclarationDescriptor? { + val bindingContext = qualifiedElement.analyze(BodyResolveMode.PARTIAL) + if (bindingContext[BindingContext.QUALIFIER, receiverExpression] !is ClassQualifier) { return null } - val selector = expression.getQualifiedElementSelector() as? KtNameReferenceExpression ?: return null + val selector = qualifiedElement.getQualifiedElementSelector() as? KtNameReferenceExpression ?: return null return selector.mainReference.resolveToDescriptors(bindingContext).firstOrNull() } + + private fun target(qualifiedElement: KtElement): DeclarationDescriptor? { + val receiverExpression = qualifiedElement.receiverExpression() ?: return null + return target(qualifiedElement, receiverExpression) + } + + private fun KtElement.receiverExpression(): KtExpression? { + return when (this) { + is KtDotQualifiedExpression -> receiverExpression + is KtUserType -> qualifier?.referenceExpression + else -> null + } + } } } \ No newline at end of file diff --git a/idea/testData/intentions/importAllMembers/TypeReference.1.kt b/idea/testData/intentions/importAllMembers/TypeReference.1.kt new file mode 100644 index 00000000000..4542df6752b --- /dev/null +++ b/idea/testData/intentions/importAllMembers/TypeReference.1.kt @@ -0,0 +1,7 @@ +package com.test + +sealed class States { + object Loading : States() + object Content : States() + object Error : States() +} \ No newline at end of file diff --git a/idea/testData/intentions/importAllMembers/TypeReference.1.kt.after b/idea/testData/intentions/importAllMembers/TypeReference.1.kt.after new file mode 100644 index 00000000000..4542df6752b --- /dev/null +++ b/idea/testData/intentions/importAllMembers/TypeReference.1.kt.after @@ -0,0 +1,7 @@ +package com.test + +sealed class States { + object Loading : States() + object Content : States() + object Error : States() +} \ No newline at end of file diff --git a/idea/testData/intentions/importAllMembers/TypeReference.kt b/idea/testData/intentions/importAllMembers/TypeReference.kt new file mode 100644 index 00000000000..96be62a56be --- /dev/null +++ b/idea/testData/intentions/importAllMembers/TypeReference.kt @@ -0,0 +1,15 @@ +// INTENTION_TEXT: "Import members from 'com.test.States'" +import com.test.States + +fun foo(s: States) { + when (s) { + is States.Loading -> { + } + is States.Error -> { + } + is States.Content -> { + } + } +} + +fun bar(): States.Loading = States.Loading \ No newline at end of file diff --git a/idea/testData/intentions/importAllMembers/TypeReference.kt.after b/idea/testData/intentions/importAllMembers/TypeReference.kt.after new file mode 100644 index 00000000000..1b3b41ff69e --- /dev/null +++ b/idea/testData/intentions/importAllMembers/TypeReference.kt.after @@ -0,0 +1,16 @@ +// INTENTION_TEXT: "Import members from 'com.test.States'" +import com.test.States +import com.test.States.* + +fun foo(s: States) { + when (s) { + is Loading -> { + } + is Error -> { + } + is Content -> { + } + } +} + +fun bar(): Loading = Loading \ No newline at end of file diff --git a/idea/testData/intentions/importAllMembers/TypeReference2.1.kt b/idea/testData/intentions/importAllMembers/TypeReference2.1.kt new file mode 100644 index 00000000000..4542df6752b --- /dev/null +++ b/idea/testData/intentions/importAllMembers/TypeReference2.1.kt @@ -0,0 +1,7 @@ +package com.test + +sealed class States { + object Loading : States() + object Content : States() + object Error : States() +} \ No newline at end of file diff --git a/idea/testData/intentions/importAllMembers/TypeReference2.1.kt.after b/idea/testData/intentions/importAllMembers/TypeReference2.1.kt.after new file mode 100644 index 00000000000..4542df6752b --- /dev/null +++ b/idea/testData/intentions/importAllMembers/TypeReference2.1.kt.after @@ -0,0 +1,7 @@ +package com.test + +sealed class States { + object Loading : States() + object Content : States() + object Error : States() +} \ No newline at end of file diff --git a/idea/testData/intentions/importAllMembers/TypeReference2.kt b/idea/testData/intentions/importAllMembers/TypeReference2.kt new file mode 100644 index 00000000000..30fca04a49e --- /dev/null +++ b/idea/testData/intentions/importAllMembers/TypeReference2.kt @@ -0,0 +1,15 @@ +// INTENTION_TEXT: "Import members from 'com.test.States'" +import com.test.States + +fun foo(s: States) { + when (s) { + is States.Loading -> { + } + is States.Error -> { + } + is States.Content -> { + } + } +} + +fun bar(): States.Loading = States.Loading \ No newline at end of file diff --git a/idea/testData/intentions/importAllMembers/TypeReference2.kt.after b/idea/testData/intentions/importAllMembers/TypeReference2.kt.after new file mode 100644 index 00000000000..1b3b41ff69e --- /dev/null +++ b/idea/testData/intentions/importAllMembers/TypeReference2.kt.after @@ -0,0 +1,16 @@ +// INTENTION_TEXT: "Import members from 'com.test.States'" +import com.test.States +import com.test.States.* + +fun foo(s: States) { + when (s) { + is Loading -> { + } + is Error -> { + } + is Content -> { + } + } +} + +fun bar(): Loading = Loading \ 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 0f2133169a3..43d4bd38592 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java @@ -9534,6 +9534,16 @@ public class IntentionTestGenerated extends AbstractIntentionTest { runTest("idea/testData/intentions/importAllMembers/StaticJavaMembers.kt"); } + @TestMetadata("TypeReference.kt") + public void testTypeReference() throws Exception { + runTest("idea/testData/intentions/importAllMembers/TypeReference.kt"); + } + + @TestMetadata("TypeReference2.kt") + public void testTypeReference2() throws Exception { + runTest("idea/testData/intentions/importAllMembers/TypeReference2.kt"); + } + @TestMetadata("UnresolvedMember.kt") public void testUnresolvedMember() throws Exception { runTest("idea/testData/intentions/importAllMembers/UnresolvedMember.kt");