KT-10433 Copy-pasting reference to companion object member causes import dialog in specific case

#KT-10433 Fixed
This commit is contained in:
Valentin Kipyatkov
2016-06-20 16:41:44 +03:00
parent 9463880c4e
commit 1941572717
10 changed files with 60 additions and 11 deletions
@@ -34,7 +34,6 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
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.resolveImportReference
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.util.ImportInsertHelper
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.name.FqName
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.elementsInRange
import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
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 ->
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
if (reference !is KtMultiReference<*> && descriptors.size > 1) return@forEachDescendantOfType
for (descriptor in descriptors) {
val declarations = DescriptorToSourceUtilsIde.getAllDeclarations(file.getProject(), descriptor)
val declarations = DescriptorToSourceUtilsIde.getAllDeclarations(file.project, descriptor)
val declaration = declarations.singleOrNull()
if (declaration != null && declaration.isInCopiedArea(file, startOffsets, endOffsets)) continue
@@ -242,7 +243,7 @@ class KotlinCopyPasteReferenceProcessor() : CopyPastePostProcessor<KotlinReferen
}
val referencedDescriptors = try {
reference.resolveToDescriptors(reference.getElement().analyze()) //TODO: we could use partial body resolve for all references together
resolveReference(reference)
}
catch (e: Throwable) {
LOG.error("Failed to analyze reference ($reference) after copy paste", e)
@@ -262,6 +263,18 @@ class KotlinCopyPasteReferenceProcessor() : CopyPastePostProcessor<KotlinReferen
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) {
val importHelper = ImportInsertHelper.getInstance(file.project)
val smartPointerManager = SmartPointerManager.getInstance(file.project)
+1 -3
View File
@@ -1,5 +1,3 @@
a.A
a.A.Companion
a.B
a.B.Companion
a.T
a.T
@@ -1,2 +1 @@
a.a
a.a.Companion
a.a
@@ -1,5 +1,5 @@
d.A
d.ClassObject.Companion
d.ClassObject
d.E.ENTRY
d.O1
d.O2
@@ -1,5 +1,5 @@
d.A
d.ClassObject.Companion
d.ClassObject
d.E.ENTRY
d.O1
d.O2
+8
View File
@@ -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
View File
@@ -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>, "")
}
+7
View File
@@ -0,0 +1,7 @@
package p
fun g() {
val fff = "0"
c(<caret>fff)
}
@@ -259,6 +259,12 @@ public class InsertImportOnPasteTestGenerated extends AbstractInsertImportOnPast
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")
public void testKeywordClassName() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/copyPaste/imports/KeywordClassName.kt");
@@ -616,6 +622,12 @@ public class InsertImportOnPasteTestGenerated extends AbstractInsertImportOnPast
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")
public void testKeywordClassName() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/copyPaste/imports/KeywordClassName.kt");