KT-11481 "Add import" intention is not available for 'is' branches in when
#KT-11481 Fixed
This commit is contained in:
@@ -26,10 +26,13 @@ import org.jetbrains.kotlin.idea.util.ImportInsertHelper
|
|||||||
import org.jetbrains.kotlin.idea.util.ShortenReferences
|
import org.jetbrains.kotlin.idea.util.ShortenReferences
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
|
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
|
||||||
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
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.collectDescendantsOfType
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElement
|
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElement
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElementSelector
|
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElementSelector
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getReceiverExpression
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
|
|
||||||
@@ -38,9 +41,10 @@ class ImportMemberIntention : SelfTargetingOffsetIndependentIntention<KtNameRefe
|
|||||||
"Add import for member"
|
"Add import for member"
|
||||||
){
|
){
|
||||||
override fun isApplicableTo(element: KtNameReferenceExpression): Boolean {
|
override fun isApplicableTo(element: KtNameReferenceExpression): Boolean {
|
||||||
val qualifiedExpression = qualifiedExpression(element) ?: return false
|
val qualifiedElement = element.getQualifiedElement()
|
||||||
|
if (qualifiedElement == element) return false
|
||||||
|
|
||||||
val fqName = targetFqName(qualifiedExpression) ?: return false
|
val fqName = targetFqName(qualifiedElement) ?: return false
|
||||||
|
|
||||||
text = "Add import for '${fqName.asString()}'"
|
text = "Add import for '${fqName.asString()}'"
|
||||||
return true
|
return true
|
||||||
@@ -59,19 +63,20 @@ class ImportMemberIntention : SelfTargetingOffsetIndependentIntention<KtNameRefe
|
|||||||
val selector = qualifiedExpression.getQualifiedElementSelector() as? KtNameReferenceExpression
|
val selector = qualifiedExpression.getQualifiedElementSelector() as? KtNameReferenceExpression
|
||||||
selector?.getReferencedNameAsName() == fqName.shortName() && targetFqName(qualifiedExpression) == fqName
|
selector?.getReferencedNameAsName() == fqName.shortName() && targetFqName(qualifiedExpression) == fqName
|
||||||
}
|
}
|
||||||
|
val userTypes = file.collectDescendantsOfType<KtUserType> { userType ->
|
||||||
|
val selector = userType.getQualifiedElementSelector() as? KtNameReferenceExpression
|
||||||
|
selector?.getReferencedNameAsName() == fqName.shortName() && targetFqName(userType) == fqName
|
||||||
|
}
|
||||||
|
|
||||||
//TODO: not deep
|
//TODO: not deep
|
||||||
ShortenReferences.DEFAULT.process(qualifiedExpressions)
|
ShortenReferences.DEFAULT.process(qualifiedExpressions + userTypes)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun qualifiedExpression(element: KtNameReferenceExpression): KtDotQualifiedExpression? {
|
private fun targetFqName(qualifiedElement: KtElement): FqName? {
|
||||||
return element.getQualifiedElement() as? KtDotQualifiedExpression
|
val nameExpression = qualifiedElement.getQualifiedElementSelector() as? KtNameReferenceExpression ?: return null
|
||||||
}
|
val receiver = nameExpression.getReceiverExpression() ?: return null
|
||||||
|
val bindingContext = qualifiedElement.analyze(BodyResolveMode.PARTIAL)
|
||||||
private fun targetFqName(qualifiedExpression: KtDotQualifiedExpression): FqName? {
|
if (bindingContext[BindingContext.QUALIFIER, receiver] == null) return null
|
||||||
val nameExpression = qualifiedExpression.getQualifiedElementSelector() as? KtNameReferenceExpression ?: return null
|
|
||||||
val bindingContext = qualifiedExpression.analyze(BodyResolveMode.PARTIAL)
|
|
||||||
if (bindingContext[BindingContext.QUALIFIER, qualifiedExpression.receiverExpression] == null) return null
|
|
||||||
|
|
||||||
val targets = nameExpression.mainReference.resolveToDescriptors(bindingContext)
|
val targets = nameExpression.mainReference.resolveToDescriptors(bindingContext)
|
||||||
if (targets.isEmpty()) return null
|
if (targets.isEmpty()) return null
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
// INTENTION_TEXT: "Add import for 'ppp.Foo.Bar'"
|
||||||
|
// WITH_RUNTIME
|
||||||
|
package ppp
|
||||||
|
|
||||||
|
sealed class Foo {
|
||||||
|
class Bar(val x: Int) : Foo()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
val foo = Foo.<caret>Bar(5)
|
||||||
|
|
||||||
|
when (foo) {
|
||||||
|
is Foo.Bar -> println(foo.x)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// INTENTION_TEXT: "Add import for 'ppp.Foo.Bar'"
|
||||||
|
// WITH_RUNTIME
|
||||||
|
package ppp
|
||||||
|
|
||||||
|
import ppp.Foo.Bar
|
||||||
|
|
||||||
|
sealed class Foo {
|
||||||
|
class Bar(val x: Int) : Foo()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
val foo = <caret>Bar(5)
|
||||||
|
|
||||||
|
when (foo) {
|
||||||
|
is Bar -> println(foo.x)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
// INTENTION_TEXT: "Add import for 'ppp.Foo.Bar'"
|
||||||
|
// WITH_RUNTIME
|
||||||
|
package ppp
|
||||||
|
|
||||||
|
sealed class Foo {
|
||||||
|
class Bar(val x: Int) : Foo()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
val foo = Foo.Bar(5)
|
||||||
|
|
||||||
|
when (foo) {
|
||||||
|
is Foo.<caret>Bar -> println(foo.x)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// INTENTION_TEXT: "Add import for 'ppp.Foo.Bar'"
|
||||||
|
// WITH_RUNTIME
|
||||||
|
package ppp
|
||||||
|
|
||||||
|
import ppp.Foo.Bar
|
||||||
|
|
||||||
|
sealed class Foo {
|
||||||
|
class Bar(val x: Int) : Foo()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
val foo = Bar(5)
|
||||||
|
|
||||||
|
when (foo) {
|
||||||
|
is <caret>Bar -> println(foo.x)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5706,6 +5706,18 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("NestedClass1.kt")
|
||||||
|
public void testNestedClass1() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/importMember/NestedClass1.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("NestedClass2.kt")
|
||||||
|
public void testNestedClass2() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/importMember/NestedClass2.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("NoTarget.kt")
|
@TestMetadata("NoTarget.kt")
|
||||||
public void testNoTarget() throws Exception {
|
public void testNoTarget() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/importMember/NoTarget.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/importMember/NoTarget.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user