diff --git a/idea/idea-analysis/src/org/jetbrains/jet/plugin/codeInsight/ShortenReferences.kt b/idea/idea-analysis/src/org/jetbrains/jet/plugin/codeInsight/ShortenReferences.kt index 3709bbbfff7..70cbe4ba55f 100644 --- a/idea/idea-analysis/src/org/jetbrains/jet/plugin/codeInsight/ShortenReferences.kt +++ b/idea/idea-analysis/src/org/jetbrains/jet/plugin/codeInsight/ShortenReferences.kt @@ -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 { - 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()) { adjustDescriptor(it) } + return context[BindingContext.REFERENCE_TARGET, this]?.let { Collections.singletonList(it.getImportableDescriptor()) } + ?: context[BindingContext.AMBIGUOUS_REFERENCE_TARGET, this]?.mapTo(HashSet()) { it.getImportableDescriptor() } ?: Collections.emptyList() } diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/move/moveUtils.kt b/idea/src/org/jetbrains/jet/plugin/refactoring/move/moveUtils.kt index 8d98f7b2f96..6fa7c1837da 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/move/moveUtils.kt +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/move/moveUtils.kt @@ -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() - 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(), 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() + 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 } diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/after/library/JavaClass.java b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/after/library/JavaClass.java new file mode 100644 index 00000000000..e83ac504c8d --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/after/library/JavaClass.java @@ -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; + } + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/after/library/KtClass.kt b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/after/library/KtClass.kt new file mode 100644 index 00000000000..6977ba6ebe2 --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/after/library/KtClass.kt @@ -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 +} \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/after/source/Foo.kt b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/after/source/Foo.kt new file mode 100644 index 00000000000..daeab71966c --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/after/source/Foo.kt @@ -0,0 +1,7 @@ +package source + +import library.* + +class Bar { + +} \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/after/target/Foo.kt b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/after/target/Foo.kt new file mode 100644 index 00000000000..57b35f3525e --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/after/target/Foo.kt @@ -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() +} \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/before/library/JavaClass.java b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/before/library/JavaClass.java new file mode 100644 index 00000000000..e83ac504c8d --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/before/library/JavaClass.java @@ -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; + } + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/before/library/KtClass.kt b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/before/library/KtClass.kt new file mode 100644 index 00000000000..6977ba6ebe2 --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/before/library/KtClass.kt @@ -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 +} \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/before/source/Foo.kt b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/before/source/Foo.kt new file mode 100644 index 00000000000..53b18972c6b --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/before/source/Foo.kt @@ -0,0 +1,18 @@ +package source + +import library.* + +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() +} + +class Bar { + +} \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/singletonsAndStatics.test b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/singletonsAndStatics.test new file mode 100644 index 00000000000..1a649bb5efc --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/singletonsAndStatics.test @@ -0,0 +1,5 @@ +{ + "mainFile": "source/Foo.kt", + "type": "MOVE_KOTLIN_TOP_LEVEL_DECLARATIONS", + "targetPackage": "target" +} diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/syntheticMembers/after/library/JavaEnum.java b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/syntheticMembers/after/library/JavaEnum.java new file mode 100644 index 00000000000..eb623562dc8 --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/syntheticMembers/after/library/JavaEnum.java @@ -0,0 +1,4 @@ +package library; + +public enum JavaEnum { +} \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/syntheticMembers/after/library/KtEnum.kt b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/syntheticMembers/after/library/KtEnum.kt new file mode 100644 index 00000000000..044ea744735 --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/syntheticMembers/after/library/KtEnum.kt @@ -0,0 +1,5 @@ +package library + +enum class KtEnum + +data class KtData(val n: Int) \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/syntheticMembers/after/source/Foo.kt b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/syntheticMembers/after/source/Foo.kt new file mode 100644 index 00000000000..daeab71966c --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/syntheticMembers/after/source/Foo.kt @@ -0,0 +1,7 @@ +package source + +import library.* + +class Bar { + +} \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/syntheticMembers/after/target/Foo.kt b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/syntheticMembers/after/target/Foo.kt new file mode 100644 index 00000000000..dacfb67f328 --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/syntheticMembers/after/target/Foo.kt @@ -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() +} \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/syntheticMembers/before/library/JavaEnum.java b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/syntheticMembers/before/library/JavaEnum.java new file mode 100644 index 00000000000..eb623562dc8 --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/syntheticMembers/before/library/JavaEnum.java @@ -0,0 +1,4 @@ +package library; + +public enum JavaEnum { +} \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/syntheticMembers/before/library/KtEnum.kt b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/syntheticMembers/before/library/KtEnum.kt new file mode 100644 index 00000000000..044ea744735 --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/syntheticMembers/before/library/KtEnum.kt @@ -0,0 +1,5 @@ +package library + +enum class KtEnum + +data class KtData(val n: Int) \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/syntheticMembers/before/source/Foo.kt b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/syntheticMembers/before/source/Foo.kt new file mode 100644 index 00000000000..d906ca2f193 --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/syntheticMembers/before/source/Foo.kt @@ -0,0 +1,14 @@ +package source + +import library.* + +class Foo { + val javaEnum = JavaEnum.values() + val ktEnum = KtEnum.values() + val ktData = KtData(1).copy() + val n = KtData(1).component1() +} + +class Bar { + +} \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/syntheticMembers/syntheticMembers.test b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/syntheticMembers/syntheticMembers.test new file mode 100644 index 00000000000..1a649bb5efc --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/syntheticMembers/syntheticMembers.test @@ -0,0 +1,5 @@ +{ + "mainFile": "source/Foo.kt", + "type": "MOVE_KOTLIN_TOP_LEVEL_DECLARATIONS", + "targetPackage": "target" +} diff --git a/idea/tests/org/jetbrains/jet/plugin/refactoring/move/JetMoveTestGenerated.java b/idea/tests/org/jetbrains/jet/plugin/refactoring/move/JetMoveTestGenerated.java index 0f6de7d6dd4..93d9f87c118 100644 --- a/idea/tests/org/jetbrains/jet/plugin/refactoring/move/JetMoveTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/plugin/refactoring/move/JetMoveTestGenerated.java @@ -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");