KT-10433 Copy-pasting reference to companion object member causes import dialog in specific case
#KT-10433 Fixed
This commit is contained in:
+17
-4
@@ -34,7 +34,6 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
import org.jetbrains.kotlin.idea.util.getFileResolutionScope
|
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveImportReference
|
import org.jetbrains.kotlin.idea.caches.resolve.resolveImportReference
|
||||||
import org.jetbrains.kotlin.idea.codeInsight.shorten.performDelayedShortening
|
import org.jetbrains.kotlin.idea.codeInsight.shorten.performDelayedShortening
|
||||||
@@ -45,12 +44,14 @@ import org.jetbrains.kotlin.idea.imports.importableFqName
|
|||||||
import org.jetbrains.kotlin.idea.references.*
|
import org.jetbrains.kotlin.idea.references.*
|
||||||
import org.jetbrains.kotlin.idea.util.ImportInsertHelper
|
import org.jetbrains.kotlin.idea.util.ImportInsertHelper
|
||||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||||
|
import org.jetbrains.kotlin.idea.util.getFileResolutionScope
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.elementsInRange
|
import org.jetbrains.kotlin.psi.psiUtil.elementsInRange
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType
|
import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||||
import org.jetbrains.kotlin.resolve.scopes.utils.findFunction
|
import org.jetbrains.kotlin.resolve.scopes.utils.findFunction
|
||||||
@@ -142,12 +143,12 @@ class KotlinCopyPasteReferenceProcessor() : CopyPastePostProcessor<KotlinReferen
|
|||||||
element.forEachDescendantOfType<KtElement>(canGoInside = { it.javaClass as Class<*> !in IGNORE_REFERENCES_INSIDE }) { element ->
|
element.forEachDescendantOfType<KtElement>(canGoInside = { it.javaClass as Class<*> !in IGNORE_REFERENCES_INSIDE }) { element ->
|
||||||
val reference = element.mainReference ?: return@forEachDescendantOfType
|
val reference = element.mainReference ?: return@forEachDescendantOfType
|
||||||
|
|
||||||
val descriptors = reference.resolveToDescriptors(element.analyze()) //TODO: we could use partial body resolve for all references together
|
val descriptors = resolveReference(reference)
|
||||||
//check whether this reference is unambiguous
|
//check whether this reference is unambiguous
|
||||||
if (reference !is KtMultiReference<*> && descriptors.size > 1) return@forEachDescendantOfType
|
if (reference !is KtMultiReference<*> && descriptors.size > 1) return@forEachDescendantOfType
|
||||||
|
|
||||||
for (descriptor in descriptors) {
|
for (descriptor in descriptors) {
|
||||||
val declarations = DescriptorToSourceUtilsIde.getAllDeclarations(file.getProject(), descriptor)
|
val declarations = DescriptorToSourceUtilsIde.getAllDeclarations(file.project, descriptor)
|
||||||
val declaration = declarations.singleOrNull()
|
val declaration = declarations.singleOrNull()
|
||||||
if (declaration != null && declaration.isInCopiedArea(file, startOffsets, endOffsets)) continue
|
if (declaration != null && declaration.isInCopiedArea(file, startOffsets, endOffsets)) continue
|
||||||
|
|
||||||
@@ -242,7 +243,7 @@ class KotlinCopyPasteReferenceProcessor() : CopyPastePostProcessor<KotlinReferen
|
|||||||
}
|
}
|
||||||
|
|
||||||
val referencedDescriptors = try {
|
val referencedDescriptors = try {
|
||||||
reference.resolveToDescriptors(reference.getElement().analyze()) //TODO: we could use partial body resolve for all references together
|
resolveReference(reference)
|
||||||
}
|
}
|
||||||
catch (e: Throwable) {
|
catch (e: Throwable) {
|
||||||
LOG.error("Failed to analyze reference ($reference) after copy paste", e)
|
LOG.error("Failed to analyze reference ($reference) after copy paste", e)
|
||||||
@@ -262,6 +263,18 @@ class KotlinCopyPasteReferenceProcessor() : CopyPastePostProcessor<KotlinReferen
|
|||||||
return ReferenceToRestoreData(reference, refData)
|
return ReferenceToRestoreData(reference, refData)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun resolveReference(reference: KtReference): Collection<DeclarationDescriptor> {
|
||||||
|
val element = reference.element
|
||||||
|
val bindingContext = element.analyze() //TODO: we could use partial body resolve for all references together
|
||||||
|
|
||||||
|
if (element is KtNameReferenceExpression && reference is KtSimpleNameReference) {
|
||||||
|
bindingContext[BindingContext.SHORT_REFERENCE_TO_COMPANION_OBJECT, element]
|
||||||
|
?.let { return listOf(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
return reference.resolveToDescriptors(bindingContext)
|
||||||
|
}
|
||||||
|
|
||||||
private fun restoreReferences(referencesToRestore: Collection<ReferenceToRestoreData>, file: KtFile) {
|
private fun restoreReferences(referencesToRestore: Collection<ReferenceToRestoreData>, file: KtFile) {
|
||||||
val importHelper = ImportInsertHelper.getInstance(file.project)
|
val importHelper = ImportInsertHelper.getInstance(file.project)
|
||||||
val smartPointerManager = SmartPointerManager.getInstance(file.project)
|
val smartPointerManager = SmartPointerManager.getInstance(file.project)
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
a.A
|
a.A
|
||||||
a.A.Companion
|
|
||||||
a.B
|
a.B
|
||||||
a.B.Companion
|
a.T
|
||||||
a.T
|
|
||||||
@@ -1,2 +1 @@
|
|||||||
a.a
|
a.a
|
||||||
a.a.Companion
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
d.A
|
d.A
|
||||||
d.ClassObject.Companion
|
d.ClassObject
|
||||||
d.E.ENTRY
|
d.E.ENTRY
|
||||||
d.O1
|
d.O1
|
||||||
d.O2
|
d.O2
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
d.A
|
d.A
|
||||||
d.ClassObject.Companion
|
d.ClassObject
|
||||||
d.E.ENTRY
|
d.E.ENTRY
|
||||||
d.O1
|
d.O1
|
||||||
d.O2
|
d.O2
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// ERROR: Unresolved reference: vfff
|
||||||
|
// ERROR: No value passed for parameter text
|
||||||
|
package p
|
||||||
|
|
||||||
|
fun g() {
|
||||||
|
val fff = "0"
|
||||||
|
c(X.vfff)
|
||||||
|
}
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
package p
|
||||||
|
|
||||||
|
class X {
|
||||||
|
companion object { val v = 1 }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun c(value:Int, text:String) {}
|
||||||
|
|
||||||
|
fun f() {
|
||||||
|
c(<selection>X.v</selection>, "")
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package p
|
||||||
|
|
||||||
|
fun g() {
|
||||||
|
val fff = "0"
|
||||||
|
c(<caret>fff)
|
||||||
|
}
|
||||||
|
|
||||||
+12
@@ -259,6 +259,12 @@ public class InsertImportOnPasteTestGenerated extends AbstractInsertImportOnPast
|
|||||||
doTestCopy(fileName);
|
doTestCopy(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("KT10433.kt")
|
||||||
|
public void testKT10433() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/copyPaste/imports/KT10433.kt");
|
||||||
|
doTestCopy(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("KeywordClassName.kt")
|
@TestMetadata("KeywordClassName.kt")
|
||||||
public void testKeywordClassName() throws Exception {
|
public void testKeywordClassName() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/copyPaste/imports/KeywordClassName.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/copyPaste/imports/KeywordClassName.kt");
|
||||||
@@ -616,6 +622,12 @@ public class InsertImportOnPasteTestGenerated extends AbstractInsertImportOnPast
|
|||||||
doTestCut(fileName);
|
doTestCut(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("KT10433.kt")
|
||||||
|
public void testKT10433() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/copyPaste/imports/KT10433.kt");
|
||||||
|
doTestCut(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("KeywordClassName.kt")
|
@TestMetadata("KeywordClassName.kt")
|
||||||
public void testKeywordClassName() throws Exception {
|
public void testKeywordClassName() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/copyPaste/imports/KeywordClassName.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/copyPaste/imports/KeywordClassName.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user