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 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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+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);
|
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");
|
||||||
|
|||||||
Reference in New Issue
Block a user