Move: Fix rebinding of references to singleton members and Java statics

#KT-6082 Fixed
This commit is contained in:
Alexey Sedunov
2014-10-21 15:30:00 +04:00
parent bc7ae4186b
commit 925177f3d8
19 changed files with 232 additions and 21 deletions
@@ -35,6 +35,8 @@ import org.jetbrains.jet.lang.resolve.calls.callUtil.getCalleeExpressionIfAny
import java.util.LinkedHashSet import java.util.LinkedHashSet
import org.jetbrains.jet.lang.resolve.ImportPath import org.jetbrains.jet.lang.resolve.ImportPath
import org.jetbrains.jet.lang.psi.psiUtil.getQualifiedElement 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 object ShortenReferences {
public fun process(element: JetElement) { public fun process(element: JetElement) {
@@ -291,11 +293,8 @@ public object ShortenReferences {
= DescriptorRenderer.FQ_NAMES_IN_TYPES.render(this) = DescriptorRenderer.FQ_NAMES_IN_TYPES.render(this)
private fun JetReferenceExpression.getTargets(context: BindingContext): Collection<DeclarationDescriptor> { private fun JetReferenceExpression.getTargets(context: BindingContext): Collection<DeclarationDescriptor> {
fun adjustDescriptor(it: DeclarationDescriptor): DeclarationDescriptor = return context[BindingContext.REFERENCE_TARGET, this]?.let { Collections.singletonList(it.getImportableDescriptor()) }
(it as? ConstructorDescriptor)?.getContainingDeclaration() ?: it ?: context[BindingContext.AMBIGUOUS_REFERENCE_TARGET, this]?.mapTo(HashSet<DeclarationDescriptor>()) { it.getImportableDescriptor() }
return context[BindingContext.REFERENCE_TARGET, this]?.let { Collections.singletonList(adjustDescriptor(it)) }
?: context[BindingContext.AMBIGUOUS_REFERENCE_TARGET, this]?.mapTo(HashSet<DeclarationDescriptor>()) { adjustDescriptor(it) }
?: Collections.emptyList() ?: Collections.emptyList()
} }
@@ -19,7 +19,6 @@ package org.jetbrains.jet.plugin.refactoring.move
import org.jetbrains.jet.plugin.codeInsight.JetFileReferencesResolver import org.jetbrains.jet.plugin.codeInsight.JetFileReferencesResolver
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression import org.jetbrains.jet.lang.psi.JetSimpleNameExpression
import org.jetbrains.jet.lang.resolve.BindingContext 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.resolve.DescriptorUtils
import org.jetbrains.jet.lang.descriptors.PackageFragmentDescriptor import org.jetbrains.jet.lang.descriptors.PackageFragmentDescriptor
import org.jetbrains.jet.plugin.references.JetSimpleNameReference 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.lang.psi.JetElement
import org.jetbrains.jet.plugin.JetFileType import org.jetbrains.jet.plugin.JetFileType
import org.jetbrains.jet.lang.psi.JetNamedDeclaration 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.plugin.codeInsight.DescriptorToDeclarationUtil
import org.jetbrains.jet.lang.psi.psiUtil.isAncestor import org.jetbrains.jet.lang.psi.psiUtil.isAncestor
import java.util.Collections import java.util.Collections
@@ -56,6 +54,12 @@ import com.intellij.openapi.util.Comparing
import java.util.Comparator import java.util.Comparator
import com.intellij.util.IncorrectOperationException import com.intellij.util.IncorrectOperationException
import com.intellij.psi.PsiFile 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) 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>() val declaration = DescriptorToDeclarationUtil.getDeclaration(file, descriptor) ?: return null
for ((refExpr, bindingContext) in referenceToContext) { if (isAncestor(declaration, false)) return null
if (refExpr !is JetSimpleNameExpression || refExpr.getParent() is JetThisExpression) continue
val descriptor = bindingContext[BindingContext.REFERENCE_TARGET, refExpr]?.let { descriptor -> val isCallable = descriptor is CallableDescriptor
if (descriptor is ConstructorDescriptor) descriptor.getContainingDeclaration() else descriptor 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) val fqName = DescriptorUtils.getFqName(descriptor)
if (!fqName.isSafe()) continue if (!fqName.isSafe()) return null
val packageName = DescriptorUtils.getParentOfType(descriptor, javaClass<PackageFragmentDescriptor>(), false)?.let { val packageName = DescriptorUtils.getParentOfType(descriptor, javaClass<PackageFragmentDescriptor>(), false)?.let {
DescriptorUtils.getFqName(it).toSafe() DescriptorUtils.getFqName(it).toSafe()
} }
when { return when {
declaration.isExtensionDeclaration(), isExtension,
packageName == packageNameInfo.oldPackageName, packageName == packageNameInfo.oldPackageName,
packageName == packageNameInfo.newPackageName, packageName == packageNameInfo.newPackageName,
isImported(descriptor) -> { 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 return usages
} }
@@ -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;
}
}
}
@@ -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
}
@@ -0,0 +1,7 @@
package source
import library.*
class Bar {
}
@@ -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()
}
@@ -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;
}
}
}
@@ -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
}
@@ -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 {
}
@@ -0,0 +1,5 @@
{
"mainFile": "source/Foo.kt",
"type": "MOVE_KOTLIN_TOP_LEVEL_DECLARATIONS",
"targetPackage": "target"
}
@@ -0,0 +1,4 @@
package library;
public enum JavaEnum {
}
@@ -0,0 +1,5 @@
package library
enum class KtEnum
data class KtData(val n: Int)
@@ -0,0 +1,7 @@
package source
import library.*
class Bar {
}
@@ -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()
}
@@ -0,0 +1,4 @@
package library;
public enum JavaEnum {
}
@@ -0,0 +1,5 @@
package library
enum class KtEnum
data class KtData(val n: Int)
@@ -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 {
}
@@ -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); 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") @TestMetadata("kotlin/moveTopLevelDeclarations/moveClassToFile/moveClassToFile.test")
public void testKotlin_moveTopLevelDeclarations_moveClassToFile_MoveClassToFile() throws Exception { public void testKotlin_moveTopLevelDeclarations_moveClassToFile_MoveClassToFile() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/moveClassToFile/moveClassToFile.test"); String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/moveClassToFile/moveClassToFile.test");