diff --git a/annotations/com/intellij/refactoring/move/moveClassesOrPackages/annotations.xml b/annotations/com/intellij/refactoring/move/moveClassesOrPackages/annotations.xml
new file mode 100644
index 00000000000..e14982837b4
--- /dev/null
+++ b/annotations/com/intellij/refactoring/move/moveClassesOrPackages/annotations.xml
@@ -0,0 +1,6 @@
+
+ -
+
+
+
\ No newline at end of file
diff --git a/idea/src/org/jetbrains/jet/plugin/codeInsight/JetFileReferencesResolver.kt b/idea/src/org/jetbrains/jet/plugin/codeInsight/JetFileReferencesResolver.kt
index 78ccb2902bb..6a6669111a5 100644
--- a/idea/src/org/jetbrains/jet/plugin/codeInsight/JetFileReferencesResolver.kt
+++ b/idea/src/org/jetbrains/jet/plugin/codeInsight/JetFileReferencesResolver.kt
@@ -29,25 +29,28 @@ import org.jetbrains.jet.lang.psi.JetCallExpression
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression
import java.util.Collections
import org.jetbrains.jet.plugin.caches.resolve.getLazyResolveSession
+import org.jetbrains.jet.lang.psi.JetQualifiedExpression
+import org.jetbrains.jet.lang.descriptors.ClassDescriptor
+import org.jetbrains.jet.lang.descriptors.PackageViewDescriptor
object JetFileReferencesResolver {
fun resolve(
element: JetElement,
- visitReceivers: Boolean = true,
- visitShortNames: Boolean = true
+ resolveQualifiers: Boolean = true,
+ resolveShortNames: Boolean = true
): Map {
return (element.getContainingFile() as? JetFile)?.let { file ->
- resolve(file, listOf(element), visitReceivers, visitShortNames)
+ resolve(file, listOf(element), resolveQualifiers, resolveShortNames)
} ?: Collections.emptyMap()
}
fun resolve(
file: JetFile,
elements: Iterable? = null,
- visitReceivers: Boolean = true,
- visitShortNames: Boolean = true
+ resolveQualifiers: Boolean = true,
+ resolveShortNames: Boolean = true
): Map {
- val visitor = ResolveAllReferencesVisitor(file, visitReceivers, visitShortNames)
+ val visitor = ResolveAllReferencesVisitor(file, resolveQualifiers, resolveShortNames)
if (elements != null) {
elements.forEach { it.accept(visitor) }
}
@@ -57,18 +60,18 @@ object JetFileReferencesResolver {
return visitor.result
}
- private class ResolveAllReferencesVisitor(file: JetFile, val visitReceivers: Boolean, val visitShortNames: Boolean) : JetTreeVisitorVoid() {
+ private class ResolveAllReferencesVisitor(file: JetFile, val resolveQualifiers: Boolean, val resolveShortNames: Boolean) : JetTreeVisitorVoid() {
private val resolveSession = file.getLazyResolveSession()
private val resolveMap = HashMap()
public val result: Map = resolveMap
override fun visitUserType(userType: JetUserType) {
- if (visitReceivers) {
+ if (resolveQualifiers) {
userType.acceptChildren(this)
}
- if (visitShortNames || userType.getQualifier() != null) {
+ if (resolveShortNames || userType.getQualifier() != null) {
val referenceExpression = userType.getReferenceExpression()
if (referenceExpression != null) {
resolveMap[referenceExpression] = resolveSession.resolveToElement(referenceExpression)
@@ -76,21 +79,24 @@ object JetFileReferencesResolver {
}
}
- override fun visitDotQualifiedExpression(expression: JetDotQualifiedExpression) {
- if (visitReceivers) {
- expression.acceptChildren(this)
- }
+ private fun JetExpression.isReceiver(): Boolean {
+ val parent = getParent()
+ if (parent !is JetQualifiedExpression) return false
+ if (parent.getReceiverExpression() == this) return true
- val referenceExpression = expression.getSelectorExpression()?.referenceExpression()
- if (referenceExpression != null) {
- resolveMap[referenceExpression] = resolveSession.resolveToElement(referenceExpression)
- }
+ val parentParent = parent.getParent()
+ return parentParent is JetQualifiedExpression && parentParent.getReceiverExpression() == parent
}
override fun visitSimpleNameExpression(expression: JetSimpleNameExpression) {
- if (visitShortNames) {
- resolveMap[expression] = resolveSession.resolveToElement(expression)
+ val context = resolveSession.resolveToElement(expression)
+ val descriptor = context[BindingContext.REFERENCE_TARGET, expression]
+ if ((descriptor is ClassDescriptor || descriptor is PackageViewDescriptor) && expression.isReceiver()) {
+ if (!resolveQualifiers) return
}
+ if (!resolveShortNames) return
+
+ resolveMap[expression] = context
}
}
}
diff --git a/idea/src/org/jetbrains/jet/plugin/codeInsight/ShortenReferences.kt b/idea/src/org/jetbrains/jet/plugin/codeInsight/ShortenReferences.kt
index 29dc3cbf432..2652ef40dae 100644
--- a/idea/src/org/jetbrains/jet/plugin/codeInsight/ShortenReferences.kt
+++ b/idea/src/org/jetbrains/jet/plugin/codeInsight/ShortenReferences.kt
@@ -101,7 +101,7 @@ public object ShortenReferences {
ImportInsertHelper.optimizeImportsIfNeeded(file)
// first resolve all qualified references - optimization
- val referenceToContext = JetFileReferencesResolver.resolve(file, fileElements, visitShortNames = false)
+ val referenceToContext = JetFileReferencesResolver.resolve(file, fileElements, resolveShortNames = false)
val shortenTypesVisitor = ShortenTypesVisitor(file, elementFilter, referenceToContext)
processElements(fileElements, shortenTypesVisitor)
diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/move/moveFilesOrDirectories/MoveKotlinFileHandler.kt b/idea/src/org/jetbrains/jet/plugin/refactoring/move/moveFilesOrDirectories/MoveKotlinFileHandler.kt
index 3f0da644222..31593e32b71 100644
--- a/idea/src/org/jetbrains/jet/plugin/refactoring/move/moveFilesOrDirectories/MoveKotlinFileHandler.kt
+++ b/idea/src/org/jetbrains/jet/plugin/refactoring/move/moveFilesOrDirectories/MoveKotlinFileHandler.kt
@@ -25,7 +25,6 @@ import com.intellij.openapi.roots.JavaProjectRootsUtil
import com.intellij.psi.PsiCompiledElement
import org.jetbrains.jet.lang.psi.JetFile
import java.util.ArrayList
-import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.searches.ReferencesSearch
import com.intellij.refactoring.util.MoveRenameUsageInfo
import org.jetbrains.jet.lang.psi.JetNamedDeclaration
@@ -39,7 +38,6 @@ import org.jetbrains.jet.lang.psi.psiUtil.getPackage
import org.jetbrains.jet.plugin.references.JetReference
import org.jetbrains.jet.asJava.toLightElements
import org.jetbrains.jet.lang.psi.JetDeclaration
-import org.jetbrains.jet.lang.psi.JetPsiUtil
import com.intellij.openapi.util.TextRange
import com.intellij.openapi.diagnostic.Logger
import org.jetbrains.jet.lang.psi.JetClassOrObject
@@ -48,12 +46,12 @@ import org.jetbrains.jet.lang.resolve.DescriptorUtils
import com.intellij.refactoring.util.TextOccurrencesUtil
import java.util.Collections
import org.jetbrains.jet.plugin.refactoring.move.PackageNameInfo
-import org.jetbrains.jet.plugin.refactoring.move.updateInternalReferencesOnPackageNameChange
import org.jetbrains.jet.plugin.search.projectScope
import org.jetbrains.jet.plugin.search.fileScope
-import org.jetbrains.jet.plugin.search.not
-import org.jetbrains.jet.plugin.search.and
import org.jetbrains.jet.plugin.search.minus
+import org.jetbrains.jet.plugin.refactoring.move.getInternalReferencesToUpdateOnPackageNameChange
+import org.jetbrains.jet.plugin.refactoring.move.postProcessMoveUsages
+import org.jetbrains.jet.plugin.codeInsight.addToShorteningWaitSet
public class MoveKotlinFileHandler : MoveFileHandler() {
class object {
@@ -181,7 +179,8 @@ public class MoveKotlinFileHandler : MoveFileHandler() {
val packageNameInfo = file.getAndRemoveCopyableUserData(PACKAGE_NAME_INFO_KEY)
if (packageNameInfo == null) return
- file.updateInternalReferencesOnPackageNameChange(packageNameInfo, updateImportedReferences = false)
+ val usages = file.getInternalReferencesToUpdateOnPackageNameChange(packageNameInfo)
+ postProcessMoveUsages(usages)
val packageRef = file.getPackageDirective()?.getLastReferenceExpression()?.getReference() as? JetSimpleNameReference
packageRef?.bindToFqName(packageNameInfo.newPackageName)
diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/move/moveTopLevelDeclarations/MoveKotlinTopLevelDeclarationsProcessor.kt b/idea/src/org/jetbrains/jet/plugin/refactoring/move/moveTopLevelDeclarations/MoveKotlinTopLevelDeclarationsProcessor.kt
index 0e7bbce687b..0276a5330d0 100644
--- a/idea/src/org/jetbrains/jet/plugin/refactoring/move/moveTopLevelDeclarations/MoveKotlinTopLevelDeclarationsProcessor.kt
+++ b/idea/src/org/jetbrains/jet/plugin/refactoring/move/moveTopLevelDeclarations/MoveKotlinTopLevelDeclarationsProcessor.kt
@@ -27,7 +27,6 @@ import com.intellij.usageView.UsageViewUtil
import com.intellij.openapi.diagnostic.Logger
import com.intellij.psi.PsiElement
import com.intellij.refactoring.util.NonCodeUsageInfo
-import com.intellij.refactoring.move.moveClassesOrPackages.CommonMoveUtil
import com.intellij.util.IncorrectOperationException
import com.intellij.refactoring.util.RefactoringUIUtil
import org.jetbrains.jet.utils.keysToMap
@@ -39,7 +38,6 @@ import org.jetbrains.jet.lang.psi.psiUtil.getPackage
import org.jetbrains.jet.lang.psi.JetFile
import org.jetbrains.jet.plugin.refactoring.move.PackageNameInfo
import org.jetbrains.jet.plugin.refactoring.createKotlinFile
-import org.jetbrains.jet.plugin.refactoring.move.updateInternalReferencesOnPackageNameChange
import org.jetbrains.jet.plugin.codeInsight.addToShorteningWaitSet
import org.jetbrains.jet.plugin.refactoring.move.getFileNameAfterMove
import org.jetbrains.jet.lang.psi.JetNamedDeclaration
@@ -67,13 +65,13 @@ import com.intellij.psi.PsiModifier
import com.intellij.util.VisibilityUtil
import com.intellij.openapi.util.Ref
import org.jetbrains.jet.plugin.refactoring.getKotlinFqName
-import org.jetbrains.jet.plugin.references.JetSimpleNameReference.ShorteningMode
import org.jetbrains.jet.plugin.search.projectScope
-import org.jetbrains.jet.lang.psi.psiUtil.isExtensionDeclaration
-import org.jetbrains.jet.plugin.references.JetReference
-import org.jetbrains.jet.plugin.quickfix.ImportInsertHelper
-import org.jetbrains.jet.lang.psi.psiUtil.getParentByType
-import org.jetbrains.jet.lang.psi.JetImportDirective
+import org.jetbrains.jet.plugin.refactoring.move.getInternalReferencesToUpdateOnPackageNameChange
+import org.jetbrains.jet.plugin.refactoring.move.createMoveUsageInfo
+import org.jetbrains.jet.plugin.refactoring.move.postProcessMoveUsages
+import org.jetbrains.jet.plugin.references.JetSimpleNameReference.ShorteningMode
+import org.jetbrains.jet.lang.psi.psiUtil.isAncestor
+import org.jetbrains.jet.plugin.refactoring.move.MoveRenameUsageInfoForExtension
public class MoveKotlinTopLevelDeclarationsOptions(
val elementsToMove: Collection,
@@ -83,14 +81,6 @@ public class MoveKotlinTopLevelDeclarationsOptions(
val moveCallback: MoveCallback? = null
)
-class MoveRenameUsageInfoForExtension(
- element: PsiElement,
- reference: PsiReference,
- startOffset: Int,
- endOffset: Int,
- referencedElement: PsiElement
-): MoveRenameUsageInfo(element, reference, startOffset, endOffset, referencedElement, false)
-
public class MoveKotlinTopLevelDeclarationsProcessor(project: Project, val options: MoveKotlinTopLevelDeclarationsOptions) : BaseRefactoringProcessor(project) {
class object {
private val LOG: Logger = Logger.getInstance(javaClass())
@@ -111,21 +101,6 @@ public class MoveKotlinTopLevelDeclarationsProcessor(project: Project, val optio
}
override fun findUsages(): Array {
- fun createUsageInfo(
- element: PsiElement,
- reference: PsiReference,
- startOffset: Int,
- endOffset: Int,
- referencedElement: PsiElement
- ): UsageInfo {
- if (reference is JetReference
- && referencedElement.namedUnwrappedElement!!.isExtensionDeclaration()
- && element.getParentByType(javaClass()) == null) {
- return MoveRenameUsageInfoForExtension(element, reference, startOffset, endOffset, referencedElement)
- }
- return MoveRenameUsageInfo(element, reference, startOffset, endOffset, referencedElement, false)
- }
-
val newPackageName = options.moveTarget.packageWrapper?.getQualifiedName() ?: ""
fun collectUsages(): List {
@@ -137,9 +112,8 @@ public class MoveKotlinTopLevelDeclarationsProcessor(project: Project, val optio
val results = ReferencesSearch
.search(lightElement, projectScope, false)
.mapTo(ArrayList()) { ref ->
- if (foundReferences.add(ref)) {
- val range = ref.getRangeInElement()!!
- createUsageInfo(ref.getElement(), ref, range.getStartOffset(), range.getEndOffset(), lightElement)
+ if (foundReferences.add(ref) && elementsToMove.all { !it.isAncestor(ref.getElement())}) {
+ createMoveUsageInfo(ref, lightElement, true)
}
else null
}
@@ -201,7 +175,7 @@ public class MoveKotlinTopLevelDeclarationsProcessor(project: Project, val optio
fun collectConflictsInDeclarations() {
val declarationToReferenceTargets = HashMap>()
for (declaration in elementsToMove) {
- val referenceToContext = JetFileReferencesResolver.resolve(element = declaration, visitReceivers = false)
+ val referenceToContext = JetFileReferencesResolver.resolve(element = declaration, resolveQualifiers = false)
for ((refExpr, bindingContext) in referenceToContext) {
val refTarget = bindingContext[BindingContext.REFERENCE_TARGET, refExpr]?.let { descriptor ->
DescriptorToDeclarationUtil.getDeclaration(declaration.getProject(), descriptor)
@@ -246,7 +220,11 @@ public class MoveKotlinTopLevelDeclarationsProcessor(project: Project, val optio
}
override fun performRefactoring(usages: Array?) {
- fun moveDeclaration(declaration: JetNamedDeclaration, moveTarget: KotlinMoveTarget): JetNamedDeclaration? {
+ fun moveDeclaration(
+ declaration: JetNamedDeclaration,
+ moveTarget: KotlinMoveTarget,
+ usagesToProcessAfterMove: MutableList
+ ): JetNamedDeclaration? {
val file = declaration.getContainingFile() as? JetFile
assert (file != null, "${declaration.javaClass}: ${declaration.getText()}")
@@ -265,14 +243,12 @@ public class MoveKotlinTopLevelDeclarationsProcessor(project: Project, val optio
assert(targetFile is JetFile, "Couldn't create Koltin file for: ${declaration.javaClass}: ${declaration.getText()}")
- val newPackageFqName = (targetFile as JetFile).getPackageFqName()
-
- val packageNameInfo = PackageNameInfo(file!!.getPackageFqName(), newPackageFqName)
- declaration.updateInternalReferencesOnPackageNameChange(
- packageNameInfo,
- updateImportedReferences = true,
- shorteningMode = ShorteningMode.NO_SHORTENING
- )
+ val packageNameInfo = PackageNameInfo(file!!.getPackageFqName(), (targetFile as JetFile).getPackageFqName())
+ val (usagesToProcessLater, usagesToProcessNow) = declaration
+ .getInternalReferencesToUpdateOnPackageNameChange(packageNameInfo)
+ .partition { it is MoveRenameUsageInfoForExtension }
+ postProcessMoveUsages(usagesToProcessNow, shorteningMode = ShorteningMode.NO_SHORTENING)
+ usagesToProcessAfterMove.addAll(usagesToProcessLater)
val newElement = targetFile.add(declaration) as JetNamedDeclaration
declaration.delete()
@@ -283,9 +259,13 @@ public class MoveKotlinTopLevelDeclarationsProcessor(project: Project, val optio
}
try {
+ val usageList = usages.toArrayList()
+
val oldToNewElementsMapping = HashMap()
for ((oldDeclaration, oldLightElements) in kotlinToLightElements) {
- val newDeclaration = moveDeclaration(oldDeclaration, options.moveTarget)
+ val oldFile = oldDeclaration.getContainingJetFile()
+
+ val newDeclaration = moveDeclaration(oldDeclaration, options.moveTarget, usageList)
if (newDeclaration == null) {
for (oldElement in oldLightElements) {
oldToNewElementsMapping[oldElement] = oldElement
@@ -293,26 +273,15 @@ public class MoveKotlinTopLevelDeclarationsProcessor(project: Project, val optio
continue
}
+ oldToNewElementsMapping[oldFile] = newDeclaration.getContainingJetFile()
+
getTransaction()!!.getElementListener(oldDeclaration).elementMoved(newDeclaration)
for ((oldElement, newElement) in oldLightElements.stream() zip newDeclaration.toLightElements().stream()) {
oldToNewElementsMapping[oldElement] = newElement
}
}
- if (usages == null) return
-
- nonCodeUsages = CommonMoveUtil.retargetUsages(
- usages.filter { it !is MoveRenameUsageInfoForExtension }.copyToArray(),
- oldToNewElementsMapping
- )
- for (usage in usages.filterIsInstance(javaClass())) {
- val newElement = oldToNewElementsMapping[usage.getReferencedElement()]
-
- ImportInsertHelper.addImportDirectiveIfNeeded(
- newElement!!.getKotlinFqName()!!,
- usage.getElement()!!.getContainingFile() as JetFile
- )
- }
+ nonCodeUsages = postProcessMoveUsages(usageList, oldToNewElementsMapping).copyToArray()
}
catch (e: IncorrectOperationException) {
nonCodeUsages = null
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 4dda11df8c9..da71ad067b3 100644
--- a/idea/src/org/jetbrains/jet/plugin/refactoring/move/moveUtils.kt
+++ b/idea/src/org/jetbrains/jet/plugin/refactoring/move/moveUtils.kt
@@ -26,7 +26,6 @@ import org.jetbrains.jet.plugin.references.JetSimpleNameReference
import org.jetbrains.jet.lang.resolve.name.FqName
import org.jetbrains.jet.lang.psi.JetFile
import org.jetbrains.jet.lang.psi.JetElement
-import org.jetbrains.jet.plugin.references.JetSimpleNameReference.ShorteningMode
import org.jetbrains.jet.plugin.JetFileType
import org.jetbrains.jet.lang.psi.JetNamedDeclaration
import org.jetbrains.jet.plugin.imports.canBeReferencedViaImport
@@ -34,30 +33,54 @@ import org.jetbrains.jet.plugin.codeInsight.DescriptorToDeclarationUtil
import org.jetbrains.jet.lang.psi.psiUtil.isAncestor
import java.util.Collections
import org.jetbrains.jet.lang.resolve.name.isImported
+import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor
+import org.jetbrains.jet.lang.descriptors.ClassDescriptor
+import org.jetbrains.jet.lang.descriptors.PackageViewDescriptor
+import com.intellij.usageView.UsageInfo
+import org.jetbrains.jet.lang.psi.psiUtil.isExtensionDeclaration
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiReference
+import com.intellij.refactoring.util.MoveRenameUsageInfo
+import org.jetbrains.jet.plugin.references.JetReference
+import org.jetbrains.jet.asJava.namedUnwrappedElement
+import org.jetbrains.jet.lang.psi.psiUtil.getParentByType
+import org.jetbrains.jet.lang.psi.JetImportDirective
+import java.util.ArrayList
+import com.intellij.refactoring.util.NonCodeUsageInfo
+import org.jetbrains.jet.plugin.quickfix.ImportInsertHelper
+import org.jetbrains.jet.plugin.refactoring.getKotlinFqName
+import org.jetbrains.jet.lang.psi.JetThisExpression
+import org.jetbrains.jet.plugin.references.JetSimpleNameReference.ShorteningMode
+import com.intellij.openapi.vfs.VirtualFile
+import com.intellij.openapi.util.Comparing
+import java.util.Comparator
+import com.intellij.util.IncorrectOperationException
+import com.intellij.psi.PsiFile
public class PackageNameInfo(val oldPackageName: FqName, val newPackageName: FqName)
-public fun JetElement.updateInternalReferencesOnPackageNameChange(
- packageNameInfo: PackageNameInfo,
- updateImportedReferences: Boolean,
- shorteningMode: ShorteningMode = ShorteningMode.DELAYED_SHORTENING
-) {
+public fun JetElement.getInternalReferencesToUpdateOnPackageNameChange(packageNameInfo: PackageNameInfo): List {
val file = getContainingFile() as? JetFile
- if (file == null) return
+ if (file == null) return Collections.emptyList()
- val importPaths =
- if (updateImportedReferences) {
- file.getImportDirectives().map { it.getImportPath() }.filterNotNull()
- }
- else Collections.emptyList()
+ val importPaths = file.getImportDirectives().map { it.getImportPath() }.filterNotNull()
- fun isImportedName(fqName: FqName): Boolean =
- updateImportedReferences && importPaths.any { fqName.isImported(it, false) }
+ [tailRecursive] fun isImported(descriptor: DeclarationDescriptor): Boolean {
+ val fqName = DescriptorUtils.getFqName(descriptor).let { if (it.isSafe()) it.toSafe() else return@isImported false }
+ if (importPaths.any { fqName.isImported(it, false) }) return true
- val referenceToContext = JetFileReferencesResolver.resolve(file = file, elements = listOf(this), visitReceivers = false)
+ val containingDescriptor = descriptor.getContainingDeclaration()
+ return when (containingDescriptor) {
+ is ClassDescriptor, is PackageViewDescriptor -> isImported(containingDescriptor)
+ else -> false
+ }
+ }
+ val referenceToContext = JetFileReferencesResolver.resolve(file = file, elements = listOf(this), resolveQualifiers = false)
+
+ val usages = ArrayList()
for ((refExpr, bindingContext) in referenceToContext) {
- if (refExpr !is JetSimpleNameExpression) continue
+ if (refExpr !is JetSimpleNameExpression || refExpr.getParent() is JetThisExpression) continue
val descriptor = bindingContext[BindingContext.REFERENCE_TARGET, refExpr]?.let { descriptor ->
if (descriptor is ConstructorDescriptor) descriptor.getContainingDeclaration() else descriptor
@@ -70,23 +93,122 @@ public fun JetElement.updateInternalReferencesOnPackageNameChange(
val fqName = DescriptorUtils.getFqName(descriptor)
if (!fqName.isSafe()) continue
- val fqNameSafe = fqName.toSafe()
- val packageName = DescriptorUtils.getParentOfType(
- descriptor, javaClass(), false
- )?.let { DescriptorUtils.getFqName(it).toSafe() }
+ val packageName = DescriptorUtils.getParentOfType(descriptor, javaClass(), false)?.let {
+ DescriptorUtils.getFqName(it).toSafe()
+ }
when {
+ declaration.isExtensionDeclaration(),
packageName == packageNameInfo.oldPackageName,
packageName == packageNameInfo.newPackageName,
- isImportedName(fqNameSafe) -> {
- (refExpr.getReference() as? JetSimpleNameReference)?.bindToFqName(fqNameSafe, shorteningMode)
+ isImported(descriptor) -> {
+ (refExpr.getReference() as? JetSimpleNameReference)?.let { usages.add(createMoveUsageInfo(it, declaration, false)) }
}
}
}
+
+ return usages
+}
+
+class MoveRenameUsageInfoForExtension(
+ element: PsiElement,
+ reference: PsiReference,
+ startOffset: Int,
+ endOffset: Int,
+ referencedElement: PsiElement,
+ val originalFile: PsiFile,
+ val addImportToOriginalFile: Boolean
+): MoveRenameUsageInfo(element, reference, startOffset, endOffset, referencedElement, false)
+
+fun createMoveUsageInfo(
+ reference: PsiReference,
+ referencedElement: PsiElement,
+ addImportToOriginalFile: Boolean
+): UsageInfo {
+ val range = reference.getRangeInElement()!!
+ val element = reference.getElement()
+ val startOffset = range.getStartOffset()
+ val endOffset = range.getEndOffset()
+
+ if (reference is JetReference
+ && referencedElement.namedUnwrappedElement!!.isExtensionDeclaration()
+ && element.getParentByType(javaClass()) == null) {
+ return MoveRenameUsageInfoForExtension(
+ element, reference, startOffset, endOffset, referencedElement, element.getContainingFile()!!, addImportToOriginalFile
+ )
+ }
+ return MoveRenameUsageInfo(element, reference, startOffset, endOffset, referencedElement, false)
}
public fun JetNamedDeclaration.getFileNameAfterMove(): String? {
return (getContainingFile() as? JetFile)?.let { file ->
if (file.getDeclarations().size > 1) "${getName()}.${JetFileType.INSTANCE.getDefaultExtension()}" else file.getName()
}
+}
+
+/**
+ * Perform usage postprocessing and return non-code usages
+ */
+fun postProcessMoveUsages(usages: List,
+ oldToNewElementsMapping: Map = Collections.emptyMap(),
+ shorteningMode: ShorteningMode = ShorteningMode.DELAYED_SHORTENING
+): List {
+ fun counterpart(e: PsiElement) = oldToNewElementsMapping[e] ?: e
+
+ val sortedUsages = usages.sortBy(
+ object : Comparator {
+ override fun compare(o1: UsageInfo, o2: UsageInfo): Int {
+ val file1 = o1.getVirtualFile()
+ val file2 = o2.getVirtualFile()
+ if (Comparing.equal(file1, file2)) {
+ val rangeInElement1 = o1.getRangeInElement()
+ val rangeInElement2 = o2.getRangeInElement()
+ if (rangeInElement1 != null && rangeInElement2 != null) {
+ return rangeInElement2.getStartOffset() - rangeInElement1.getStartOffset()
+ }
+ return 0
+ }
+ if (file1 == null) return -1
+ if (file2 == null) return 1
+ return Comparing.compare(file1.getPath(), file2.getPath())
+ }
+ }
+ )
+
+ val nonCodeUsages = ArrayList()
+
+ for (usage in sortedUsages) {
+ when (usage) {
+ is NonCodeUsageInfo -> {
+ nonCodeUsages.add(usage as NonCodeUsageInfo)
+ }
+
+ is MoveRenameUsageInfoForExtension -> {
+ val element = counterpart(usage.getReferencedElement()!!)
+ val file = with(usage) { if (addImportToOriginalFile) originalFile else counterpart(originalFile) } as JetFile
+ ImportInsertHelper.addImportDirectiveIfNeeded(element.getKotlinFqName()!!, file)
+ }
+
+ is MoveRenameUsageInfo -> {
+ val moveRenameUsage = usage as MoveRenameUsageInfo
+ val oldElement = moveRenameUsage.getReferencedElement()!!
+ val newElement = counterpart(oldElement)
+ moveRenameUsage.getReference()?.let {
+ try {
+ if (it is JetSimpleNameReference) {
+ it.bindToElement(newElement, shorteningMode)
+ }
+ else {
+ it.bindToElement(newElement)
+ }
+ }
+ catch (e: IncorrectOperationException) {
+ // Suppress exception if bindToElement is not implemented
+ }
+ }
+ }
+ }
+ }
+
+ return nonCodeUsages
}
\ No newline at end of file
diff --git a/idea/src/org/jetbrains/jet/plugin/references/JetSimpleNameReference.kt b/idea/src/org/jetbrains/jet/plugin/references/JetSimpleNameReference.kt
index 20d2a5a5a48..2745dac6e53 100644
--- a/idea/src/org/jetbrains/jet/plugin/references/JetSimpleNameReference.kt
+++ b/idea/src/org/jetbrains/jet/plugin/references/JetSimpleNameReference.kt
@@ -105,9 +105,11 @@ public class JetSimpleNameReference(
}
// By default reference binding is delayed
- override fun bindToElement(element: PsiElement): PsiElement {
- return element.getKotlinFqName()?.let { fqName -> bindToFqName(fqName) } ?: expression
- }
+ override fun bindToElement(element: PsiElement): PsiElement =
+ bindToElement(element, ShorteningMode.DELAYED_SHORTENING)
+
+ fun bindToElement(element: PsiElement, shorteningMode: ShorteningMode): PsiElement =
+ element.getKotlinFqName()?.let { fqName -> bindToFqName(fqName, shorteningMode) } ?: expression
public fun bindToFqName(fqName: FqName, shorteningMode: ShorteningMode = ShorteningMode.DELAYED_SHORTENING): PsiElement {
if (fqName.isRoot()) return expression
diff --git a/idea/testData/refactoring/move/kotlin/moveFile/internalReferences/after/library/misc.kt b/idea/testData/refactoring/move/kotlin/moveFile/internalReferences/after/library/misc.kt
new file mode 100644
index 00000000000..31450ddae4a
--- /dev/null
+++ b/idea/testData/refactoring/move/kotlin/moveFile/internalReferences/after/library/misc.kt
@@ -0,0 +1,7 @@
+package library
+
+open public class B {
+ fun foo(): B = this
+}
+
+fun B.bar(): B = this
\ No newline at end of file
diff --git a/idea/testData/refactoring/move/kotlin/moveFile/internalReferences/after/source/some.kt b/idea/testData/refactoring/move/kotlin/moveFile/internalReferences/after/source/some.kt
new file mode 100644
index 00000000000..86569cdb0fa
--- /dev/null
+++ b/idea/testData/refactoring/move/kotlin/moveFile/internalReferences/after/source/some.kt
@@ -0,0 +1,5 @@
+package source
+
+import target.A
+
+fun test1() = target.test(A())
\ No newline at end of file
diff --git a/idea/testData/refactoring/move/kotlin/moveFile/internalReferences/after/target/A.kt b/idea/testData/refactoring/move/kotlin/moveFile/internalReferences/after/target/A.kt
new file mode 100644
index 00000000000..4cb9c1b227b
--- /dev/null
+++ b/idea/testData/refactoring/move/kotlin/moveFile/internalReferences/after/target/A.kt
@@ -0,0 +1,21 @@
+package target
+
+import library.B
+import library.bar
+
+public class A: B() {
+ fun test() {
+ bar()
+ foo()
+ this.bar()
+ this.foo()
+ }
+}
+
+public fun test(a: A) {
+ a.bar()
+ a.foo()
+ B().foo().bar()
+ B().foo().bar()
+ B().bar().foo()
+}
\ No newline at end of file
diff --git a/idea/testData/refactoring/move/kotlin/moveFile/internalReferences/after/target/some.kt b/idea/testData/refactoring/move/kotlin/moveFile/internalReferences/after/target/some.kt
new file mode 100644
index 00000000000..9faf72a450b
--- /dev/null
+++ b/idea/testData/refactoring/move/kotlin/moveFile/internalReferences/after/target/some.kt
@@ -0,0 +1,3 @@
+package target
+
+fun test2() = test(A())
\ No newline at end of file
diff --git a/idea/testData/refactoring/move/kotlin/moveFile/internalReferences/before/library/misc.kt b/idea/testData/refactoring/move/kotlin/moveFile/internalReferences/before/library/misc.kt
new file mode 100644
index 00000000000..31450ddae4a
--- /dev/null
+++ b/idea/testData/refactoring/move/kotlin/moveFile/internalReferences/before/library/misc.kt
@@ -0,0 +1,7 @@
+package library
+
+open public class B {
+ fun foo(): B = this
+}
+
+fun B.bar(): B = this
\ No newline at end of file
diff --git a/idea/testData/refactoring/move/kotlin/moveFile/internalReferences/before/source/A.kt b/idea/testData/refactoring/move/kotlin/moveFile/internalReferences/before/source/A.kt
new file mode 100644
index 00000000000..f077d04543c
--- /dev/null
+++ b/idea/testData/refactoring/move/kotlin/moveFile/internalReferences/before/source/A.kt
@@ -0,0 +1,21 @@
+package source
+
+import library.B
+import library.bar
+
+public class A: B() {
+ fun test() {
+ bar()
+ foo()
+ this.bar()
+ this.foo()
+ }
+}
+
+public fun test(a: A) {
+ a.bar()
+ a.foo()
+ B().foo().bar()
+ library.B().foo().bar()
+ B().bar().foo()
+}
\ No newline at end of file
diff --git a/idea/testData/refactoring/move/kotlin/moveFile/internalReferences/before/source/some.kt b/idea/testData/refactoring/move/kotlin/moveFile/internalReferences/before/source/some.kt
new file mode 100644
index 00000000000..b2d8e884024
--- /dev/null
+++ b/idea/testData/refactoring/move/kotlin/moveFile/internalReferences/before/source/some.kt
@@ -0,0 +1,3 @@
+package source
+
+fun test1() = test(A())
\ No newline at end of file
diff --git a/idea/testData/refactoring/move/kotlin/moveFile/internalReferences/before/target/some.kt b/idea/testData/refactoring/move/kotlin/moveFile/internalReferences/before/target/some.kt
new file mode 100644
index 00000000000..e1eebd508c2
--- /dev/null
+++ b/idea/testData/refactoring/move/kotlin/moveFile/internalReferences/before/target/some.kt
@@ -0,0 +1,3 @@
+package target
+
+fun test2() = source.test(source.A())
\ No newline at end of file
diff --git a/idea/testData/refactoring/move/kotlin/moveFile/internalReferences/internalReferences.test b/idea/testData/refactoring/move/kotlin/moveFile/internalReferences/internalReferences.test
new file mode 100644
index 00000000000..959a5db15c4
--- /dev/null
+++ b/idea/testData/refactoring/move/kotlin/moveFile/internalReferences/internalReferences.test
@@ -0,0 +1,5 @@
+{
+ "mainFile": "source/A.kt",
+ "type": "MOVE_FILES",
+ "targetPackage": "target"
+}
\ No newline at end of file
diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/internalReferences/after/library/some.kt b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/internalReferences/after/library/some.kt
new file mode 100644
index 00000000000..31450ddae4a
--- /dev/null
+++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/internalReferences/after/library/some.kt
@@ -0,0 +1,7 @@
+package library
+
+open public class B {
+ fun foo(): B = this
+}
+
+fun B.bar(): B = this
\ No newline at end of file
diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/internalReferences/after/source/some.kt b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/internalReferences/after/source/some.kt
new file mode 100644
index 00000000000..0ca538772f8
--- /dev/null
+++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/internalReferences/after/source/some.kt
@@ -0,0 +1,5 @@
+package source
+
+import target.A
+
+fun test1() = A()
\ No newline at end of file
diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/internalReferences/after/target/A.kt b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/internalReferences/after/target/A.kt
new file mode 100644
index 00000000000..8a61c2a9e87
--- /dev/null
+++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/internalReferences/after/target/A.kt
@@ -0,0 +1,16 @@
+package target
+
+import library.bar
+import library.B
+
+public class A: B() {
+ fun test() {
+ bar()
+ foo()
+ this.bar()
+ this.foo()
+ B().foo().bar()
+ B().foo().bar()
+ B().bar().foo()
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/internalReferences/after/target/some.kt b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/internalReferences/after/target/some.kt
new file mode 100644
index 00000000000..6269bc9f9cf
--- /dev/null
+++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/internalReferences/after/target/some.kt
@@ -0,0 +1,3 @@
+package target
+
+fun test2() = A()
\ No newline at end of file
diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/internalReferences/before/library/some.kt b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/internalReferences/before/library/some.kt
new file mode 100644
index 00000000000..31450ddae4a
--- /dev/null
+++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/internalReferences/before/library/some.kt
@@ -0,0 +1,7 @@
+package library
+
+open public class B {
+ fun foo(): B = this
+}
+
+fun B.bar(): B = this
\ No newline at end of file
diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/internalReferences/before/source/A.kt b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/internalReferences/before/source/A.kt
new file mode 100644
index 00000000000..19115fece2f
--- /dev/null
+++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/internalReferences/before/source/A.kt
@@ -0,0 +1,16 @@
+package source
+
+import library.B
+import library.bar
+
+public class A: B() {
+ fun test() {
+ bar()
+ foo()
+ this.bar()
+ this.foo()
+ B().foo().bar()
+ library.B().foo().bar()
+ B().bar().foo()
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/internalReferences/before/source/some.kt b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/internalReferences/before/source/some.kt
new file mode 100644
index 00000000000..6d16d8d51cf
--- /dev/null
+++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/internalReferences/before/source/some.kt
@@ -0,0 +1,3 @@
+package source
+
+fun test1() = A()
\ No newline at end of file
diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/internalReferences/before/target/some.kt b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/internalReferences/before/target/some.kt
new file mode 100644
index 00000000000..e72b95320bb
--- /dev/null
+++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/internalReferences/before/target/some.kt
@@ -0,0 +1,3 @@
+package target
+
+fun test2() = source.A()
\ No newline at end of file
diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/internalReferences/internalReferences.test b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/internalReferences/internalReferences.test
new file mode 100644
index 00000000000..69190fd7e7f
--- /dev/null
+++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/internalReferences/internalReferences.test
@@ -0,0 +1,5 @@
+{
+ "mainFile": "source/A.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 a35730169cd..dd5a067eab9 100644
--- a/idea/tests/org/jetbrains/jet/plugin/refactoring/move/JetMoveTestGenerated.java
+++ b/idea/tests/org/jetbrains/jet/plugin/refactoring/move/JetMoveTestGenerated.java
@@ -212,6 +212,12 @@ public class JetMoveTestGenerated extends AbstractJetMoveTest {
doTest(fileName);
}
+ @TestMetadata("kotlin/moveFile/internalReferences/internalReferences.test")
+ public void testKotlin_moveFile_internalReferences_InternalReferences() throws Exception {
+ String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/move/kotlin/moveFile/internalReferences/internalReferences.test");
+ doTest(fileName);
+ }
+
@TestMetadata("kotlin/moveFile/moveFileToFile/moveFileToFile.test")
public void testKotlin_moveFile_moveFileToFile_MoveFileToFile() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/move/kotlin/moveFile/moveFileToFile/moveFileToFile.test");
@@ -236,6 +242,12 @@ public class JetMoveTestGenerated extends AbstractJetMoveTest {
doTest(fileName);
}
+ @TestMetadata("kotlin/moveTopLevelDeclarations/misc/internalReferences/internalReferences.test")
+ public void testKotlin_moveTopLevelDeclarations_misc_internalReferences_InternalReferences() throws Exception {
+ String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/internalReferences/internalReferences.test");
+ doTest(fileName);
+ }
+
@TestMetadata("kotlin/moveTopLevelDeclarations/misc/moveClassWithImportsRetained/moveClassWithImportsRetained.test")
public void testKotlin_moveTopLevelDeclarations_misc_moveClassWithImportsRetained_MoveClassWithImportsRetained() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/moveClassWithImportsRetained/moveClassWithImportsRetained.test");