Import members from: suggest on type reference
#KT-29927 Fixed
This commit is contained in:
committed by
Dmitry Gridin
parent
3af6b36401
commit
6b5ba272a0
@@ -25,9 +25,7 @@ import org.jetbrains.kotlin.idea.imports.importableFqName
|
|||||||
import org.jetbrains.kotlin.idea.references.mainReference
|
import org.jetbrains.kotlin.idea.references.mainReference
|
||||||
import org.jetbrains.kotlin.idea.util.ImportDescriptorResult
|
import org.jetbrains.kotlin.idea.util.ImportDescriptorResult
|
||||||
import org.jetbrains.kotlin.idea.util.ImportInsertHelper
|
import org.jetbrains.kotlin.idea.util.ImportInsertHelper
|
||||||
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
|
import org.jetbrains.kotlin.psi.*
|
||||||
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.collectDescendantsOfType
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElementSelector
|
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElementSelector
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.isInImportDirective
|
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.lazy.BodyResolveMode
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassQualifier
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassQualifier
|
||||||
|
|
||||||
class ImportAllMembersIntention : SelfTargetingIntention<KtDotQualifiedExpression>(
|
class ImportAllMembersIntention : SelfTargetingIntention<KtElement>(KtElement::class.java, "Import members with '*'"){
|
||||||
KtDotQualifiedExpression::class.java,
|
override fun isApplicableTo(element: KtElement, caretOffset: Int): Boolean {
|
||||||
"Import members with '*'"
|
val receiverExpression = element.receiverExpression() ?: return false
|
||||||
){
|
if (!receiverExpression.range.containsOffset(caretOffset)) return false
|
||||||
override fun isApplicableTo(element: KtDotQualifiedExpression, caretOffset: Int): Boolean {
|
|
||||||
if (!element.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
|
val targetFqName = target.importableFqName ?: return false
|
||||||
|
|
||||||
if (element.isInImportDirective()) return false
|
if (receiverExpression.isInImportDirective()) return false
|
||||||
|
|
||||||
val file = element.containingKtFile
|
val file = element.containingKtFile
|
||||||
val project = file.project
|
val project = file.project
|
||||||
@@ -58,12 +54,12 @@ class ImportAllMembersIntention : SelfTargetingIntention<KtDotQualifiedExpressio
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun applyTo(element: KtDotQualifiedExpression, editor: Editor?) {
|
override fun applyTo(element: KtElement, editor: Editor?) {
|
||||||
element.importReceiverMembers()
|
element.importReceiverMembers()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun KtDotQualifiedExpression.importReceiverMembers() {
|
fun KtElement.importReceiverMembers() {
|
||||||
val target = target(this) ?: return
|
val target = target(this) ?: return
|
||||||
val classFqName = target.importableFqName!!.parent()
|
val classFqName = target.importableFqName!!.parent()
|
||||||
|
|
||||||
@@ -73,19 +69,36 @@ class ImportAllMembersIntention : SelfTargetingIntention<KtDotQualifiedExpressio
|
|||||||
val qualifierName = qualifiedExpression.receiverExpression.getQualifiedElementSelector() as? KtNameReferenceExpression
|
val qualifierName = qualifiedExpression.receiverExpression.getQualifiedElementSelector() as? KtNameReferenceExpression
|
||||||
qualifierName?.getReferencedNameAsName() == classFqName.shortName() && target(qualifiedExpression)?.importableFqName?.parent() == classFqName
|
qualifierName?.getReferencedNameAsName() == classFqName.shortName() && target(qualifiedExpression)?.importableFqName?.parent() == classFqName
|
||||||
}
|
}
|
||||||
|
val userTypes = containingKtFile.collectDescendantsOfType<KtUserType> { userType ->
|
||||||
|
val receiver = userType.receiverExpression()?.getQualifiedElementSelector() as? KtNameReferenceExpression
|
||||||
|
receiver?.getReferencedNameAsName() == classFqName.shortName() && target(userType)?.importableFqName?.parent() == classFqName
|
||||||
|
}
|
||||||
|
|
||||||
//TODO: not deep
|
//TODO: not deep
|
||||||
ShortenReferences.DEFAULT.process(qualifiedExpressions)
|
ShortenReferences.DEFAULT.process(qualifiedExpressions + userTypes)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun target(expression: KtDotQualifiedExpression): DeclarationDescriptor? {
|
private fun target(qualifiedElement: KtElement, receiverExpression: KtExpression): DeclarationDescriptor? {
|
||||||
val bindingContext = expression.analyze(BodyResolveMode.PARTIAL)
|
val bindingContext = qualifiedElement.analyze(BodyResolveMode.PARTIAL)
|
||||||
if (bindingContext[BindingContext.QUALIFIER, expression.receiverExpression] !is ClassQualifier) {
|
if (bindingContext[BindingContext.QUALIFIER, receiverExpression] !is ClassQualifier) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
val selector = expression.getQualifiedElementSelector() as? KtNameReferenceExpression ?: return null
|
val selector = qualifiedElement.getQualifiedElementSelector() as? KtNameReferenceExpression ?: return null
|
||||||
return selector.mainReference.resolveToDescriptors(bindingContext).firstOrNull()
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.test
|
||||||
|
|
||||||
|
sealed class States {
|
||||||
|
object Loading : States()
|
||||||
|
object Content : States()
|
||||||
|
object Error : States()
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.test
|
||||||
|
|
||||||
|
sealed class States {
|
||||||
|
object Loading : States()
|
||||||
|
object Content : States()
|
||||||
|
object Error : States()
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
// INTENTION_TEXT: "Import members from 'com.test.States'"
|
||||||
|
import com.test.States
|
||||||
|
|
||||||
|
fun foo(s: States) {
|
||||||
|
when (s) {
|
||||||
|
is <caret>States.Loading -> {
|
||||||
|
}
|
||||||
|
is States.Error -> {
|
||||||
|
}
|
||||||
|
is States.Content -> {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun bar(): States.Loading = States.Loading
|
||||||
@@ -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
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.test
|
||||||
|
|
||||||
|
sealed class States {
|
||||||
|
object Loading : States()
|
||||||
|
object Content : States()
|
||||||
|
object Error : States()
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.test
|
||||||
|
|
||||||
|
sealed class States {
|
||||||
|
object Loading : States()
|
||||||
|
object Content : States()
|
||||||
|
object Error : States()
|
||||||
|
}
|
||||||
@@ -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(): <caret>States.Loading = States.Loading
|
||||||
@@ -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
|
||||||
@@ -9534,6 +9534,16 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
|||||||
runTest("idea/testData/intentions/importAllMembers/StaticJavaMembers.kt");
|
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")
|
@TestMetadata("UnresolvedMember.kt")
|
||||||
public void testUnresolvedMember() throws Exception {
|
public void testUnresolvedMember() throws Exception {
|
||||||
runTest("idea/testData/intentions/importAllMembers/UnresolvedMember.kt");
|
runTest("idea/testData/intentions/importAllMembers/UnresolvedMember.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user