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 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
}
@@ -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);
}
@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");