Move: Fix rebinding of references to singleton members and Java statics
#KT-6082 Fixed
This commit is contained in:
@@ -35,6 +35,8 @@ import org.jetbrains.jet.lang.resolve.calls.callUtil.getCalleeExpressionIfAny
|
||||
import java.util.LinkedHashSet
|
||||
import org.jetbrains.jet.lang.resolve.ImportPath
|
||||
import org.jetbrains.jet.lang.psi.psiUtil.getQualifiedElement
|
||||
import org.jetbrains.jet.lang.types.JetType
|
||||
import org.jetbrains.jet.lang.resolve.descriptorUtil.getImportableDescriptor
|
||||
|
||||
public object ShortenReferences {
|
||||
public fun process(element: JetElement) {
|
||||
@@ -291,11 +293,8 @@ public object ShortenReferences {
|
||||
= DescriptorRenderer.FQ_NAMES_IN_TYPES.render(this)
|
||||
|
||||
private fun JetReferenceExpression.getTargets(context: BindingContext): Collection<DeclarationDescriptor> {
|
||||
fun adjustDescriptor(it: DeclarationDescriptor): DeclarationDescriptor =
|
||||
(it as? ConstructorDescriptor)?.getContainingDeclaration() ?: it
|
||||
|
||||
return context[BindingContext.REFERENCE_TARGET, this]?.let { Collections.singletonList(adjustDescriptor(it)) }
|
||||
?: context[BindingContext.AMBIGUOUS_REFERENCE_TARGET, this]?.mapTo(HashSet<DeclarationDescriptor>()) { adjustDescriptor(it) }
|
||||
return context[BindingContext.REFERENCE_TARGET, this]?.let { Collections.singletonList(it.getImportableDescriptor()) }
|
||||
?: context[BindingContext.AMBIGUOUS_REFERENCE_TARGET, this]?.mapTo(HashSet<DeclarationDescriptor>()) { it.getImportableDescriptor() }
|
||||
?: Collections.emptyList()
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ package org.jetbrains.jet.plugin.refactoring.move
|
||||
import org.jetbrains.jet.plugin.codeInsight.JetFileReferencesResolver
|
||||
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext
|
||||
import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils
|
||||
import org.jetbrains.jet.lang.descriptors.PackageFragmentDescriptor
|
||||
import org.jetbrains.jet.plugin.references.JetSimpleNameReference
|
||||
@@ -28,7 +27,6 @@ import org.jetbrains.jet.lang.psi.JetFile
|
||||
import org.jetbrains.jet.lang.psi.JetElement
|
||||
import org.jetbrains.jet.plugin.JetFileType
|
||||
import org.jetbrains.jet.lang.psi.JetNamedDeclaration
|
||||
import org.jetbrains.jet.plugin.imports.canBeReferencedViaImport
|
||||
import org.jetbrains.jet.plugin.codeInsight.DescriptorToDeclarationUtil
|
||||
import org.jetbrains.jet.lang.psi.psiUtil.isAncestor
|
||||
import java.util.Collections
|
||||
@@ -56,6 +54,12 @@ import com.intellij.openapi.util.Comparing
|
||||
import java.util.Comparator
|
||||
import com.intellij.util.IncorrectOperationException
|
||||
import com.intellij.psi.PsiFile
|
||||
import org.jetbrains.jet.lang.resolve.descriptorUtil.getImportableDescriptor
|
||||
import org.jetbrains.jet.lang.psi.psiUtil.getReceiverExpression
|
||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor
|
||||
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor.Kind
|
||||
import org.jetbrains.jet.lang.psi.psiUtil.getQualifiedElementSelector
|
||||
|
||||
public class PackageNameInfo(val oldPackageName: FqName, val newPackageName: FqName)
|
||||
|
||||
@@ -76,37 +80,59 @@ public fun JetElement.getInternalReferencesToUpdateOnPackageNameChange(packageNa
|
||||
}
|
||||
}
|
||||
|
||||
val referenceToContext = JetFileReferencesResolver.resolve(file = file, elements = listOf(this), resolveQualifiers = false)
|
||||
fun processReference(refExpr: JetSimpleNameExpression, bindingContext: BindingContext): UsageInfo? {
|
||||
val descriptor = bindingContext[BindingContext.REFERENCE_TARGET, refExpr]?.getImportableDescriptor() ?: return null
|
||||
|
||||
val usages = ArrayList<UsageInfo>()
|
||||
for ((refExpr, bindingContext) in referenceToContext) {
|
||||
if (refExpr !is JetSimpleNameExpression || refExpr.getParent() is JetThisExpression) continue
|
||||
val declaration = DescriptorToDeclarationUtil.getDeclaration(file, descriptor) ?: return null
|
||||
if (isAncestor(declaration, false)) return null
|
||||
|
||||
val descriptor = bindingContext[BindingContext.REFERENCE_TARGET, refExpr]?.let { descriptor ->
|
||||
if (descriptor is ConstructorDescriptor) descriptor.getContainingDeclaration() else descriptor
|
||||
val isCallable = descriptor is CallableDescriptor
|
||||
val isExtension = isCallable && (descriptor as CallableDescriptor).getExtensionReceiverParameter() != null
|
||||
|
||||
if (isCallable && !isExtension) {
|
||||
val containingDescriptor = descriptor.getContainingDeclaration()
|
||||
val receiver = refExpr.getReceiverExpression()
|
||||
if (receiver != null) {
|
||||
val receiverRef = receiver.getQualifiedElementSelector() as? JetSimpleNameExpression ?: return null
|
||||
if (bindingContext[BindingContext.QUALIFIER, receiverRef] == null) return null
|
||||
if (descriptor is CallableMemberDescriptor && descriptor.getKind() == Kind.SYNTHESIZED) {
|
||||
return processReference(receiverRef, bindingContext)
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (containingDescriptor !is PackageFragmentDescriptor) return null
|
||||
}
|
||||
}
|
||||
if (descriptor == null || !descriptor.canBeReferencedViaImport()) continue
|
||||
|
||||
val declaration = DescriptorToDeclarationUtil.getDeclaration(file, descriptor)
|
||||
if (declaration == null || isAncestor(declaration, false)) continue
|
||||
|
||||
val fqName = DescriptorUtils.getFqName(descriptor)
|
||||
if (!fqName.isSafe()) continue
|
||||
if (!fqName.isSafe()) return null
|
||||
|
||||
val packageName = DescriptorUtils.getParentOfType(descriptor, javaClass<PackageFragmentDescriptor>(), false)?.let {
|
||||
DescriptorUtils.getFqName(it).toSafe()
|
||||
}
|
||||
|
||||
when {
|
||||
declaration.isExtensionDeclaration(),
|
||||
return when {
|
||||
isExtension,
|
||||
packageName == packageNameInfo.oldPackageName,
|
||||
packageName == packageNameInfo.newPackageName,
|
||||
isImported(descriptor) -> {
|
||||
(refExpr.getReference() as? JetSimpleNameReference)?.let { usages.add(createMoveUsageInfo(it, declaration, false)) }
|
||||
(refExpr.getReference() as? JetSimpleNameReference)?.let { createMoveUsageInfo(it, declaration, false) }
|
||||
}
|
||||
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
val referenceToContext = JetFileReferencesResolver.resolve(file = file, elements = listOf(this))
|
||||
|
||||
val usages = ArrayList<UsageInfo>()
|
||||
for ((refExpr, bindingContext) in referenceToContext) {
|
||||
if (refExpr !is JetSimpleNameExpression || refExpr.getParent() is JetThisExpression) continue
|
||||
if (bindingContext[BindingContext.QUALIFIER, refExpr] != null) continue
|
||||
|
||||
processReference(refExpr, bindingContext)?.let { usages.add(it) }
|
||||
}
|
||||
|
||||
return usages
|
||||
}
|
||||
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package library;
|
||||
|
||||
public class JavaClass {
|
||||
public static int foo() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public static class Inner {
|
||||
public static int foo() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package library
|
||||
|
||||
class KtClass {
|
||||
class Inner {
|
||||
class object {
|
||||
fun foo(): Int = 1
|
||||
}
|
||||
}
|
||||
|
||||
class object {
|
||||
fun foo(): Int = 1
|
||||
}
|
||||
}
|
||||
|
||||
object KtObject {
|
||||
class Inner {
|
||||
class object {
|
||||
fun foo(): Int = 1
|
||||
}
|
||||
}
|
||||
|
||||
fun foo(): Int = 1
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package source
|
||||
|
||||
import library.*
|
||||
|
||||
class Bar {
|
||||
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package target
|
||||
|
||||
import library.JavaClass
|
||||
import library.KtObject
|
||||
import library.KtClass
|
||||
|
||||
class Foo {
|
||||
val jv1 = JavaClass.foo()
|
||||
val jv2 = JavaClass().foo()
|
||||
val jv3 = JavaClass.Inner.foo()
|
||||
val jv4 = JavaClass.Inner().foo()
|
||||
val kt1 = KtClass.foo()
|
||||
val kt2 = KtObject.foo()
|
||||
val kt3 = KtClass.Inner.foo()
|
||||
val kt4 = KtObject.Inner.foo()
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package library;
|
||||
|
||||
public class JavaClass {
|
||||
public static int foo() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public static class Inner {
|
||||
public static int foo() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package library
|
||||
|
||||
class KtClass {
|
||||
class Inner {
|
||||
class object {
|
||||
fun foo(): Int = 1
|
||||
}
|
||||
}
|
||||
|
||||
class object {
|
||||
fun foo(): Int = 1
|
||||
}
|
||||
}
|
||||
|
||||
object KtObject {
|
||||
class Inner {
|
||||
class object {
|
||||
fun foo(): Int = 1
|
||||
}
|
||||
}
|
||||
|
||||
fun foo(): Int = 1
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package source
|
||||
|
||||
import library.*
|
||||
|
||||
class <caret>Foo {
|
||||
val jv1 = JavaClass.foo()
|
||||
val jv2 = JavaClass().foo()
|
||||
val jv3 = JavaClass.Inner.foo()
|
||||
val jv4 = JavaClass.Inner().foo()
|
||||
val kt1 = KtClass.foo()
|
||||
val kt2 = KtObject.foo()
|
||||
val kt3 = KtClass.Inner.foo()
|
||||
val kt4 = KtObject.Inner.foo()
|
||||
}
|
||||
|
||||
class Bar {
|
||||
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"mainFile": "source/Foo.kt",
|
||||
"type": "MOVE_KOTLIN_TOP_LEVEL_DECLARATIONS",
|
||||
"targetPackage": "target"
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
package library;
|
||||
|
||||
public enum JavaEnum {
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package library
|
||||
|
||||
enum class KtEnum
|
||||
|
||||
data class KtData(val n: Int)
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package source
|
||||
|
||||
import library.*
|
||||
|
||||
class Bar {
|
||||
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package target
|
||||
|
||||
import library.JavaEnum
|
||||
import library.KtEnum
|
||||
import library.KtData
|
||||
|
||||
class Foo {
|
||||
val javaEnum = JavaEnum.values()
|
||||
val ktEnum = KtEnum.values()
|
||||
val ktData = KtData(1).copy()
|
||||
val n = KtData(1).component1()
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
package library;
|
||||
|
||||
public enum JavaEnum {
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package library
|
||||
|
||||
enum class KtEnum
|
||||
|
||||
data class KtData(val n: Int)
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package source
|
||||
|
||||
import library.*
|
||||
|
||||
class <caret>Foo {
|
||||
val javaEnum = JavaEnum.values()
|
||||
val ktEnum = KtEnum.values()
|
||||
val ktData = KtData(1).copy()
|
||||
val n = KtData(1).component1()
|
||||
}
|
||||
|
||||
class Bar {
|
||||
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"mainFile": "source/Foo.kt",
|
||||
"type": "MOVE_KOTLIN_TOP_LEVEL_DECLARATIONS",
|
||||
"targetPackage": "target"
|
||||
}
|
||||
@@ -264,6 +264,18 @@ public class JetMoveTestGenerated extends AbstractJetMoveTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/singletonsAndStatics.test")
|
||||
public void testKotlin_moveTopLevelDeclarations_misc_singletonsAndStatics_SingletonsAndStatics() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/singletonsAndStatics.test");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kotlin/moveTopLevelDeclarations/misc/syntheticMembers/syntheticMembers.test")
|
||||
public void testKotlin_moveTopLevelDeclarations_misc_syntheticMembers_SyntheticMembers() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/syntheticMembers/syntheticMembers.test");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kotlin/moveTopLevelDeclarations/moveClassToFile/moveClassToFile.test")
|
||||
public void testKotlin_moveTopLevelDeclarations_moveClassToFile_MoveClassToFile() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/moveClassToFile/moveClassToFile.test");
|
||||
|
||||
Reference in New Issue
Block a user