Move: Nested classes support
#KT-9027 In Progress
This commit is contained in:
@@ -330,7 +330,7 @@
|
|||||||
order="before moveJavaFileOrDir"/>
|
order="before moveJavaFileOrDir"/>
|
||||||
<refactoring.moveHandler
|
<refactoring.moveHandler
|
||||||
id="kotlin.moveTopLevelDeclarations"
|
id="kotlin.moveTopLevelDeclarations"
|
||||||
implementation="org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations.MoveKotlinTopLevelDeclarationsHandler"
|
implementation="org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.MoveKotlinDeclarationsHandler"
|
||||||
order="before kotlin.moveFilesOrDirectories"/>
|
order="before kotlin.moveFilesOrDirectories"/>
|
||||||
<moveFileHandler implementation="org.jetbrains.kotlin.idea.refactoring.move.moveFilesOrDirectories.MoveKotlinFileHandler" />
|
<moveFileHandler implementation="org.jetbrains.kotlin.idea.refactoring.move.moveFilesOrDirectories.MoveKotlinFileHandler" />
|
||||||
<refactoring.moveDirectoryWithClassesHelper
|
<refactoring.moveDirectoryWithClassesHelper
|
||||||
@@ -1059,7 +1059,7 @@
|
|||||||
</intentionAction>
|
</intentionAction>
|
||||||
|
|
||||||
<intentionAction>
|
<intentionAction>
|
||||||
<className>org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations.MoveDeclarationToSeparateFileIntention</className>
|
<className>org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.MoveDeclarationToSeparateFileIntention</className>
|
||||||
<category>Kotlin</category>
|
<category>Kotlin</category>
|
||||||
</intentionAction>
|
</intentionAction>
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,8 @@ import org.jetbrains.kotlin.idea.core.replaced
|
|||||||
import org.jetbrains.kotlin.idea.refactoring.addTypeArgumentsIfNeeded
|
import org.jetbrains.kotlin.idea.refactoring.addTypeArgumentsIfNeeded
|
||||||
import org.jetbrains.kotlin.idea.refactoring.checkConflictsInteractively
|
import org.jetbrains.kotlin.idea.refactoring.checkConflictsInteractively
|
||||||
import org.jetbrains.kotlin.idea.refactoring.getQualifiedTypeArgumentList
|
import org.jetbrains.kotlin.idea.refactoring.getQualifiedTypeArgumentList
|
||||||
import org.jetbrains.kotlin.idea.refactoring.move.PackageNameInfo
|
import org.jetbrains.kotlin.idea.refactoring.move.ContainerChangeInfo
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.move.ContainerInfo
|
||||||
import org.jetbrains.kotlin.idea.refactoring.move.lazilyProcessInternalReferencesToUpdateOnPackageNameChange
|
import org.jetbrains.kotlin.idea.refactoring.move.lazilyProcessInternalReferencesToUpdateOnPackageNameChange
|
||||||
import org.jetbrains.kotlin.idea.refactoring.move.postProcessMoveUsages
|
import org.jetbrains.kotlin.idea.refactoring.move.postProcessMoveUsages
|
||||||
import org.jetbrains.kotlin.idea.references.mainReference
|
import org.jetbrains.kotlin.idea.references.mainReference
|
||||||
@@ -167,7 +168,7 @@ class KotlinInlineValHandler : InlineActionHandler() {
|
|||||||
val targetPackages = referenceExpressions.mapNotNullTo(LinkedHashSet()) { (it.containingFile as? KtFile)?.packageFqName }
|
val targetPackages = referenceExpressions.mapNotNullTo(LinkedHashSet()) { (it.containingFile as? KtFile)?.packageFqName }
|
||||||
for (targetPackage in targetPackages) {
|
for (targetPackage in targetPackages) {
|
||||||
if (targetPackage == file.packageFqName) continue
|
if (targetPackage == file.packageFqName) continue
|
||||||
val packageNameInfo = PackageNameInfo(file.packageFqName, targetPackage.toUnsafe())
|
val packageNameInfo = ContainerChangeInfo(ContainerInfo.Package(file.packageFqName), ContainerInfo.Package(targetPackage))
|
||||||
initializer.lazilyProcessInternalReferencesToUpdateOnPackageNameChange(packageNameInfo) { expr, factory ->
|
initializer.lazilyProcessInternalReferencesToUpdateOnPackageNameChange(packageNameInfo) { expr, factory ->
|
||||||
val infos = expr.internalUsageInfos
|
val infos = expr.internalUsageInfos
|
||||||
?: LinkedHashMap<FqName, (KtSimpleNameExpression) -> UsageInfo?>()
|
?: LinkedHashMap<FqName, (KtSimpleNameExpression) -> UsageInfo?>()
|
||||||
|
|||||||
+15
-15
@@ -16,47 +16,47 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.refactoring.move
|
package org.jetbrains.kotlin.idea.refactoring.move
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiClass
|
||||||
|
import com.intellij.psi.PsiWhiteSpace
|
||||||
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
import com.intellij.refactoring.move.moveInner.MoveInnerClassUsagesHandler
|
import com.intellij.refactoring.move.moveInner.MoveInnerClassUsagesHandler
|
||||||
import com.intellij.usageView.UsageInfo
|
import com.intellij.usageView.UsageInfo
|
||||||
import com.intellij.psi.PsiClass
|
import org.jetbrains.kotlin.idea.references.mainReference
|
||||||
import org.jetbrains.kotlin.psi.KtQualifiedExpression
|
import org.jetbrains.kotlin.idea.references.matchesTarget
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElementSelector
|
|
||||||
import org.jetbrains.kotlin.psi.KtCallExpression
|
import org.jetbrains.kotlin.psi.KtCallExpression
|
||||||
import org.jetbrains.kotlin.psi.KtPsiFactory
|
import org.jetbrains.kotlin.psi.KtPsiFactory
|
||||||
import java.util.ArrayList
|
import org.jetbrains.kotlin.psi.KtQualifiedExpression
|
||||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||||
import com.intellij.psi.util.PsiTreeUtil
|
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElementSelector
|
||||||
import com.intellij.psi.PsiWhiteSpace
|
import java.util.*
|
||||||
import org.jetbrains.kotlin.idea.references.mainReference
|
|
||||||
|
|
||||||
class MoveJavaInnerClassKotlinUsagesHandler: MoveInnerClassUsagesHandler {
|
class MoveJavaInnerClassKotlinUsagesHandler: MoveInnerClassUsagesHandler {
|
||||||
override fun correctInnerClassUsage(usage: UsageInfo, outerClass: PsiClass) {
|
override fun correctInnerClassUsage(usage: UsageInfo, outerClass: PsiClass) {
|
||||||
val innerCall = usage.element?.parent as? KtCallExpression ?: return
|
val innerCall = usage.element?.parent as? KtCallExpression ?: return
|
||||||
|
|
||||||
val receiver = (innerCall.parent as? KtQualifiedExpression)?.receiverExpression
|
val receiver = (innerCall.parent as? KtQualifiedExpression)?.receiverExpression ?: return
|
||||||
val outerClassRef = when (receiver) {
|
val outerClassRefExpr = when (receiver) {
|
||||||
is KtCallExpression -> receiver.calleeExpression
|
is KtCallExpression -> receiver.calleeExpression
|
||||||
is KtQualifiedExpression -> receiver.getQualifiedElementSelector()
|
is KtQualifiedExpression -> receiver.getQualifiedElementSelector()
|
||||||
else -> null
|
else -> null
|
||||||
} as? KtSimpleNameExpression
|
} as? KtSimpleNameExpression
|
||||||
if (outerClassRef?.mainReference?.resolve() != outerClass) return
|
val outerClassRef = outerClassRefExpr?.mainReference ?: return
|
||||||
|
if (!outerClassRef.matchesTarget(outerClass)) return
|
||||||
val outerCall = outerClassRef!!.parent as? KtCallExpression ?: return
|
|
||||||
|
|
||||||
val psiFactory = KtPsiFactory(usage.project)
|
val psiFactory = KtPsiFactory(usage.project)
|
||||||
|
|
||||||
val argumentList = innerCall.valueArgumentList
|
val argumentList = innerCall.valueArgumentList
|
||||||
if (argumentList != null) {
|
if (argumentList != null) {
|
||||||
val newArguments = ArrayList<String>()
|
val newArguments = ArrayList<String>()
|
||||||
newArguments.add(outerCall.text!!)
|
newArguments.add(receiver.text!!)
|
||||||
argumentList.arguments.mapTo(newArguments) { it.text!! }
|
argumentList.arguments.mapTo(newArguments) { it.text!! }
|
||||||
argumentList.replace(psiFactory.createCallArguments(newArguments.joinToString(prefix = "(", postfix = ")")))
|
argumentList.replace(psiFactory.createCallArguments(newArguments.joinToString(prefix = "(", postfix = ")")))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
innerCall.lambdaArguments.firstOrNull()?.let { lambdaArg ->
|
innerCall.lambdaArguments.firstOrNull()?.let { lambdaArg ->
|
||||||
val anchor = PsiTreeUtil.skipSiblingsBackward(lambdaArg, PsiWhiteSpace::class.java)
|
val anchor = PsiTreeUtil.skipSiblingsBackward(lambdaArg, PsiWhiteSpace::class.java)
|
||||||
innerCall.addAfter(psiFactory.createCallArguments("(${outerCall.text})"), anchor)
|
innerCall.addAfter(psiFactory.createCallArguments("(${receiver.text})"), anchor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+10
-11
@@ -18,14 +18,11 @@ package org.jetbrains.kotlin.idea.refactoring.move.changePackage
|
|||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiFile
|
import com.intellij.psi.PsiFile
|
||||||
import com.intellij.refactoring.PackageWrapper
|
|
||||||
import org.jetbrains.kotlin.idea.codeInsight.shorten.runWithElementsToShortenIsEmptyIgnored
|
import org.jetbrains.kotlin.idea.codeInsight.shorten.runWithElementsToShortenIsEmptyIgnored
|
||||||
import org.jetbrains.kotlin.idea.refactoring.move.PackageNameInfo
|
import org.jetbrains.kotlin.idea.refactoring.move.ContainerChangeInfo
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.move.ContainerInfo
|
||||||
import org.jetbrains.kotlin.idea.refactoring.move.getInternalReferencesToUpdateOnPackageNameChange
|
import org.jetbrains.kotlin.idea.refactoring.move.getInternalReferencesToUpdateOnPackageNameChange
|
||||||
import org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations.KotlinMoveTarget
|
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.*
|
||||||
import org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations.MoveKotlinTopLevelDeclarationsOptions
|
|
||||||
import org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations.MoveKotlinTopLevelDeclarationsProcessor
|
|
||||||
import org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations.Mover
|
|
||||||
import org.jetbrains.kotlin.idea.refactoring.move.postProcessMoveUsages
|
import org.jetbrains.kotlin.idea.refactoring.move.postProcessMoveUsages
|
||||||
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
|
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
@@ -39,26 +36,28 @@ class KotlinChangePackageRefactoring(val file: KtFile) {
|
|||||||
val packageDirective = file.packageDirective ?: return
|
val packageDirective = file.packageDirective ?: return
|
||||||
val currentFqName = packageDirective.fqName
|
val currentFqName = packageDirective.fqName
|
||||||
|
|
||||||
val declarationProcessor = MoveKotlinTopLevelDeclarationsProcessor(
|
val declarationProcessor = MoveKotlinDeclarationsProcessor(
|
||||||
project,
|
project,
|
||||||
MoveKotlinTopLevelDeclarationsOptions(
|
MoveDeclarationsDescriptor(
|
||||||
elementsToMove = file.declarations.filterIsInstance<KtNamedDeclaration>(),
|
elementsToMove = file.declarations.filterIsInstance<KtNamedDeclaration>(),
|
||||||
moveTarget = object: KotlinMoveTarget {
|
moveTarget = object: KotlinMoveTarget {
|
||||||
override val packageWrapper = PackageWrapper(file.manager, newFqName.asString())
|
override val targetContainerFqName = newFqName
|
||||||
|
|
||||||
override fun getOrCreateTargetPsi(originalPsi: PsiElement) = originalPsi.containingFile
|
override fun getOrCreateTargetPsi(originalPsi: PsiElement) = originalPsi.containingFile as? KtFile
|
||||||
|
|
||||||
override fun getTargetPsiIfExists(originalPsi: PsiElement) = null
|
override fun getTargetPsiIfExists(originalPsi: PsiElement) = null
|
||||||
|
|
||||||
override fun verify(file: PsiFile) = null
|
override fun verify(file: PsiFile) = null
|
||||||
},
|
},
|
||||||
|
delegate = MoveDeclarationsDelegate.TopLevel,
|
||||||
updateInternalReferences = false
|
updateInternalReferences = false
|
||||||
),
|
),
|
||||||
Mover.Idle // we don't need to move any declarations physically
|
Mover.Idle // we don't need to move any declarations physically
|
||||||
)
|
)
|
||||||
|
|
||||||
val declarationUsages = declarationProcessor.findUsages().toList()
|
val declarationUsages = declarationProcessor.findUsages().toList()
|
||||||
val internalUsages = file.getInternalReferencesToUpdateOnPackageNameChange(PackageNameInfo(currentFqName, newFqName.toUnsafe()))
|
val changeInfo = ContainerChangeInfo(ContainerInfo.Package(currentFqName), ContainerInfo.Package(newFqName))
|
||||||
|
val internalUsages = file.getInternalReferencesToUpdateOnPackageNameChange(changeInfo)
|
||||||
|
|
||||||
project.executeWriteCommand("Change file's package to '${newFqName.asString()}'") {
|
project.executeWriteCommand("Change file's package to '${newFqName.asString()}'") {
|
||||||
packageDirective.fqName = newFqName
|
packageDirective.fqName = newFqName
|
||||||
|
|||||||
+15
-21
@@ -14,56 +14,50 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations
|
package org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiFile
|
import com.intellij.psi.PsiFile
|
||||||
import com.intellij.psi.PsiManager
|
|
||||||
import com.intellij.refactoring.PackageWrapper
|
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.utils.getOrPutNullable
|
import org.jetbrains.kotlin.utils.getOrPutNullable
|
||||||
import java.util.HashMap
|
import java.util.*
|
||||||
|
|
||||||
interface KotlinMoveTarget {
|
interface KotlinMoveTarget {
|
||||||
val packageWrapper: PackageWrapper?
|
val targetContainerFqName: FqName?
|
||||||
fun getOrCreateTargetPsi(originalPsi: PsiElement): PsiFile?
|
fun getOrCreateTargetPsi(originalPsi: PsiElement): KtElement?
|
||||||
fun getTargetPsiIfExists(originalPsi: PsiElement): PsiFile?
|
fun getTargetPsiIfExists(originalPsi: PsiElement): KtElement?
|
||||||
|
|
||||||
// Check possible errors and return corresponding message, or null if no errors are detected
|
// Check possible errors and return corresponding message, or null if no errors are detected
|
||||||
fun verify(file: PsiFile): String?
|
fun verify(file: PsiFile): String?
|
||||||
}
|
}
|
||||||
|
|
||||||
object EmptyKotlinMoveTarget: KotlinMoveTarget {
|
object EmptyKotlinMoveTarget: KotlinMoveTarget {
|
||||||
override val packageWrapper: PackageWrapper? get() = null
|
override val targetContainerFqName = null
|
||||||
override fun getOrCreateTargetPsi(originalPsi: PsiElement) = null
|
override fun getOrCreateTargetPsi(originalPsi: PsiElement) = null
|
||||||
override fun getTargetPsiIfExists(originalPsi: PsiElement) = null
|
override fun getTargetPsiIfExists(originalPsi: PsiElement) = null
|
||||||
override fun verify(file: PsiFile) = null
|
override fun verify(file: PsiFile) = null
|
||||||
}
|
}
|
||||||
|
|
||||||
class KotlinMoveTargetForExistingFile(val targetFile: KtFile): KotlinMoveTarget {
|
class KotlinMoveTargetForExistingElement(val targetElement: KtElement): KotlinMoveTarget {
|
||||||
override val packageWrapper: PackageWrapper? = targetFile.packageFqName.asString().let { packageName ->
|
override val targetContainerFqName = targetElement.getContainingKtFile().packageFqName
|
||||||
PackageWrapper(PsiManager.getInstance(targetFile.project), packageName)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getOrCreateTargetPsi(originalPsi: PsiElement) = targetFile
|
override fun getOrCreateTargetPsi(originalPsi: PsiElement) = targetElement
|
||||||
|
|
||||||
override fun getTargetPsiIfExists(originalPsi: PsiElement) = targetFile
|
override fun getTargetPsiIfExists(originalPsi: PsiElement) = targetElement
|
||||||
|
|
||||||
// No additional verification is needed
|
// No additional verification is needed
|
||||||
override fun verify(file: PsiFile): String? = null
|
override fun verify(file: PsiFile): String? = null
|
||||||
}
|
}
|
||||||
|
|
||||||
class KotlinMoveTargetForDeferredFile(
|
class KotlinMoveTargetForDeferredFile(
|
||||||
project: Project,
|
override val targetContainerFqName: FqName,
|
||||||
private val packageFqName: FqName,
|
private val createFile: (KtFile) -> KtFile?
|
||||||
private val createFile: (KtFile) -> KtFile?): KotlinMoveTarget {
|
): KotlinMoveTarget {
|
||||||
private val createdFiles = HashMap<KtFile, KtFile?>()
|
private val createdFiles = HashMap<KtFile, KtFile?>()
|
||||||
|
|
||||||
override val packageWrapper: PackageWrapper = PackageWrapper(PsiManager.getInstance(project), packageFqName.asString())
|
override fun getOrCreateTargetPsi(originalPsi: PsiElement): KtElement? {
|
||||||
|
|
||||||
override fun getOrCreateTargetPsi(originalPsi: PsiElement): PsiFile? {
|
|
||||||
val originalFile = originalPsi.containingFile as? KtFile ?: return null
|
val originalFile = originalPsi.containingFile as? KtFile ?: return null
|
||||||
return createdFiles.getOrPutNullable(originalFile) { createFile(originalFile) }
|
return createdFiles.getOrPutNullable(originalFile) { createFile(originalFile) }
|
||||||
}
|
}
|
||||||
+6
-5
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations
|
package org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations
|
||||||
|
|
||||||
import com.intellij.codeInsight.intention.LowPriorityAction
|
import com.intellij.codeInsight.intention.LowPriorityAction
|
||||||
import com.intellij.codeInsight.navigation.NavigationUtil
|
import com.intellij.codeInsight.navigation.NavigationUtil
|
||||||
@@ -27,7 +27,7 @@ import com.intellij.refactoring.util.CommonRefactoringUtil
|
|||||||
import org.jetbrains.kotlin.idea.intentions.SelfTargetingRangeIntention
|
import org.jetbrains.kotlin.idea.intentions.SelfTargetingRangeIntention
|
||||||
import org.jetbrains.kotlin.idea.quickfix.moveCaret
|
import org.jetbrains.kotlin.idea.quickfix.moveCaret
|
||||||
import org.jetbrains.kotlin.idea.refactoring.createKotlinFile
|
import org.jetbrains.kotlin.idea.refactoring.createKotlinFile
|
||||||
import org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations.ui.MoveKotlinTopLevelDeclarationsDialog
|
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.ui.MoveKotlinTopLevelDeclarationsDialog
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.psi.KtClass
|
import org.jetbrains.kotlin.psi.KtClass
|
||||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
@@ -86,12 +86,13 @@ class MoveDeclarationToSeparateFileIntention :
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val moveTarget = KotlinMoveTargetForDeferredFile(project, packageName) {
|
val moveTarget = KotlinMoveTargetForDeferredFile(packageName) {
|
||||||
createKotlinFile(targetFileName, directory, packageName.asString())
|
createKotlinFile(targetFileName, directory, packageName.asString())
|
||||||
}
|
}
|
||||||
val moveOptions = MoveKotlinTopLevelDeclarationsOptions(
|
val moveOptions = MoveDeclarationsDescriptor(
|
||||||
elementsToMove = listOf(element),
|
elementsToMove = listOf(element),
|
||||||
moveTarget = moveTarget,
|
moveTarget = moveTarget,
|
||||||
|
delegate = MoveDeclarationsDelegate.TopLevel,
|
||||||
searchInCommentsAndStrings = false,
|
searchInCommentsAndStrings = false,
|
||||||
searchInNonCode = false,
|
searchInNonCode = false,
|
||||||
updateInternalReferences = true,
|
updateInternalReferences = true,
|
||||||
@@ -102,6 +103,6 @@ class MoveDeclarationToSeparateFileIntention :
|
|||||||
FileEditorManager.getInstance(project).selectedTextEditor?.moveCaret(newDeclaration.startOffset + originalOffset)
|
FileEditorManager.getInstance(project).selectedTextEditor?.moveCaret(newDeclaration.startOffset + originalOffset)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
MoveKotlinTopLevelDeclarationsProcessor(project, moveOptions).run()
|
MoveKotlinDeclarationsProcessor(project, moveOptions).run()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+180
@@ -0,0 +1,180 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2016 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations
|
||||||
|
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.refactoring.move.moveInner.MoveInnerClassUsagesHandler
|
||||||
|
import com.intellij.refactoring.util.MoveRenameUsageInfo
|
||||||
|
import com.intellij.usageView.UsageInfo
|
||||||
|
import com.intellij.util.containers.MultiMap
|
||||||
|
import org.jetbrains.kotlin.asJava.toLightClass
|
||||||
|
import org.jetbrains.kotlin.asJava.unwrapped
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.move.*
|
||||||
|
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||||
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelector
|
||||||
|
|
||||||
|
sealed class MoveDeclarationsDelegate {
|
||||||
|
abstract fun getOriginalContainerFqName(descriptor: MoveDeclarationsDescriptor, originalFile: KtFile): FqName
|
||||||
|
abstract fun getContainerChangeInfo(originalDeclaration: KtNamedDeclaration, moveTarget: KotlinMoveTarget): ContainerChangeInfo
|
||||||
|
abstract fun findUsages(descriptor: MoveDeclarationsDescriptor): List<UsageInfo>
|
||||||
|
abstract fun collectConflicts(usages: MutableList<UsageInfo>, conflicts: MultiMap<PsiElement, String>)
|
||||||
|
abstract fun preprocessDeclaration(descriptor: MoveDeclarationsDescriptor, originalDeclaration: KtNamedDeclaration)
|
||||||
|
abstract fun preprocessUsages(project: Project, usages: List<UsageInfo>)
|
||||||
|
|
||||||
|
object TopLevel : MoveDeclarationsDelegate() {
|
||||||
|
override fun getOriginalContainerFqName(descriptor: MoveDeclarationsDescriptor, originalFile: KtFile) = originalFile.packageFqName
|
||||||
|
|
||||||
|
override fun getContainerChangeInfo(originalDeclaration: KtNamedDeclaration, moveTarget: KotlinMoveTarget): ContainerChangeInfo {
|
||||||
|
return ContainerChangeInfo(ContainerInfo.Package(originalDeclaration.getContainingKtFile().packageFqName),
|
||||||
|
ContainerInfo.Package(moveTarget.targetContainerFqName!!))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun findUsages(descriptor: MoveDeclarationsDescriptor): List<UsageInfo> = emptyList()
|
||||||
|
|
||||||
|
override fun collectConflicts(usages: MutableList<UsageInfo>, conflicts: MultiMap<PsiElement, String>) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun preprocessDeclaration(descriptor: MoveDeclarationsDescriptor, originalDeclaration: KtNamedDeclaration) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun preprocessUsages(project: Project, usages: List<UsageInfo>) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NestedClass(
|
||||||
|
val newClassName: String? = null,
|
||||||
|
val outerInstanceParameterName: String? = null
|
||||||
|
) : MoveDeclarationsDelegate() {
|
||||||
|
override fun getOriginalContainerFqName(descriptor: MoveDeclarationsDescriptor, originalFile: KtFile): FqName {
|
||||||
|
return descriptor.elementsToMove.first().containingClassOrObject!!.fqName!!
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getContainerChangeInfo(originalDeclaration: KtNamedDeclaration, moveTarget: KotlinMoveTarget): ContainerChangeInfo {
|
||||||
|
val originalInfo = ContainerInfo.Class(originalDeclaration.containingClassOrObject!!.fqName!!)
|
||||||
|
val movingToClass = (moveTarget as? KotlinMoveTargetForExistingElement)?.targetElement is KtClassOrObject
|
||||||
|
val newInfo = if (movingToClass) {
|
||||||
|
ContainerInfo.Class(moveTarget.targetContainerFqName!!)
|
||||||
|
} else {
|
||||||
|
ContainerInfo.Package(moveTarget.targetContainerFqName!!)
|
||||||
|
}
|
||||||
|
return ContainerChangeInfo(originalInfo, newInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun findUsages(descriptor: MoveDeclarationsDescriptor): List<UsageInfo> {
|
||||||
|
val classToMove = descriptor.elementsToMove.singleOrNull() as? KtClass ?: return emptyList()
|
||||||
|
return collectOuterInstanceReferences(classToMove)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun collectConflicts(usages: MutableList<UsageInfo>, conflicts: MultiMap<PsiElement, String>) {
|
||||||
|
val usageIterator = usages.iterator()
|
||||||
|
while (usageIterator.hasNext()) {
|
||||||
|
val usage = usageIterator.next();
|
||||||
|
val element = usage.element ?: continue
|
||||||
|
|
||||||
|
if (usage is ImplicitCompanionAsDispatchReceiverUsageInfo) {
|
||||||
|
conflicts.putValue(element, "Implicit companion object will be inaccessible: ${element.text}")
|
||||||
|
usageIterator.remove()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usage !is OuterInstanceReferenceUsageInfo) continue
|
||||||
|
|
||||||
|
if (usage.isIndirectOuter) {
|
||||||
|
conflicts.putValue(element, "Indirect outer instances won't be extracted: ${element.text}")
|
||||||
|
usageIterator.remove()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usage !is OuterInstanceReferenceUsageInfo.ImplicitReceiver) continue
|
||||||
|
|
||||||
|
val fullCall = usage.callElement?.let { it.getQualifiedExpressionForSelector() ?: it } ?: continue
|
||||||
|
when {
|
||||||
|
fullCall is KtQualifiedExpression -> {
|
||||||
|
conflicts.putValue(
|
||||||
|
fullCall,
|
||||||
|
"Qualified call won't be processed: ${fullCall.text}"
|
||||||
|
)
|
||||||
|
usageIterator.remove()
|
||||||
|
}
|
||||||
|
|
||||||
|
usage.isDoubleReceiver -> {
|
||||||
|
conflicts.putValue(
|
||||||
|
fullCall,
|
||||||
|
"Call with two implicit receivers won't be processed: ${fullCall.text}"
|
||||||
|
)
|
||||||
|
usageIterator.remove()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun preprocessDeclaration(descriptor: MoveDeclarationsDescriptor, originalDeclaration: KtNamedDeclaration) {
|
||||||
|
with(originalDeclaration) {
|
||||||
|
newClassName?.let { setName(it) }
|
||||||
|
|
||||||
|
if (this is KtClass) {
|
||||||
|
if ((descriptor.moveTarget as? KotlinMoveTargetForExistingElement)?.targetElement !is KtClassOrObject) {
|
||||||
|
if (hasModifier(KtTokens.INNER_KEYWORD)) removeModifier(KtTokens.INNER_KEYWORD)
|
||||||
|
if (hasModifier(KtTokens.PROTECTED_KEYWORD)) removeModifier(KtTokens.PROTECTED_KEYWORD)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outerInstanceParameterName != null) {
|
||||||
|
val type = (containingClassOrObject!!.resolveToDescriptor() as ClassDescriptor).defaultType
|
||||||
|
val parameter = KtPsiFactory(project)
|
||||||
|
.createParameter("private val $outerInstanceParameterName: ${IdeDescriptorRenderers.SOURCE_CODE.renderType(type)}")
|
||||||
|
createPrimaryConstructorParameterListIfAbsent().addParameter(parameter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun preprocessUsages(project: Project, usages: List<UsageInfo>) {
|
||||||
|
if (outerInstanceParameterName == null) return
|
||||||
|
val psiFactory = KtPsiFactory(project)
|
||||||
|
val newOuterInstanceRef = psiFactory.createExpression(outerInstanceParameterName)
|
||||||
|
|
||||||
|
for (usage in usages) {
|
||||||
|
val referencedNestedClass = (usage as? MoveRenameUsageInfo)?.referencedElement?.unwrapped as? KtClassOrObject
|
||||||
|
val outerClass = referencedNestedClass?.containingClassOrObject
|
||||||
|
val lightOuterClass = outerClass?.toLightClass()
|
||||||
|
if (lightOuterClass != null) {
|
||||||
|
MoveInnerClassUsagesHandler.EP_NAME
|
||||||
|
.forLanguage(usage.element!!.language)
|
||||||
|
?.correctInnerClassUsage(usage, lightOuterClass)
|
||||||
|
}
|
||||||
|
|
||||||
|
when (usage) {
|
||||||
|
is OuterInstanceReferenceUsageInfo.ExplicitThis -> {
|
||||||
|
usage.expression?.replace(newOuterInstanceRef)
|
||||||
|
}
|
||||||
|
is OuterInstanceReferenceUsageInfo.ImplicitReceiver -> {
|
||||||
|
usage.callElement?.let { it.replace(psiFactory.createExpressionByPattern("$0.$1", outerInstanceParameterName, it)) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-3
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations
|
package org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations
|
||||||
|
|
||||||
import com.intellij.openapi.actionSystem.DataContext
|
import com.intellij.openapi.actionSystem.DataContext
|
||||||
import com.intellij.openapi.actionSystem.LangDataKeys
|
import com.intellij.openapi.actionSystem.LangDataKeys
|
||||||
@@ -32,11 +32,11 @@ import com.intellij.refactoring.move.moveClassesOrPackages.MoveClassesOrPackages
|
|||||||
import com.intellij.refactoring.util.CommonRefactoringUtil
|
import com.intellij.refactoring.util.CommonRefactoringUtil
|
||||||
import org.jetbrains.kotlin.idea.core.getPackage
|
import org.jetbrains.kotlin.idea.core.getPackage
|
||||||
import org.jetbrains.kotlin.idea.refactoring.canRefactor
|
import org.jetbrains.kotlin.idea.refactoring.canRefactor
|
||||||
import org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations.ui.MoveKotlinTopLevelDeclarationsDialog
|
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.ui.MoveKotlinTopLevelDeclarationsDialog
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class MoveKotlinTopLevelDeclarationsHandler : MoveHandlerDelegate() {
|
class MoveKotlinDeclarationsHandler : MoveHandlerDelegate() {
|
||||||
private fun getSourceDirectories(elements: Array<out PsiElement>) = elements.mapTo(LinkedHashSet()) { it.containingFile?.parent }
|
private fun getSourceDirectories(elements: Array<out PsiElement>) = elements.mapTo(LinkedHashSet()) { it.containingFile?.parent }
|
||||||
|
|
||||||
private fun doMoveWithCheck(
|
private fun doMoveWithCheck(
|
||||||
+71
-51
@@ -14,8 +14,9 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations
|
package org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations
|
||||||
|
|
||||||
|
import com.intellij.ide.util.EditorHelper
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.util.Ref
|
import com.intellij.openapi.util.Ref
|
||||||
import com.intellij.openapi.util.text.StringUtil
|
import com.intellij.openapi.util.text.StringUtil
|
||||||
@@ -25,16 +26,17 @@ import com.intellij.refactoring.BaseRefactoringProcessor
|
|||||||
import com.intellij.refactoring.move.MoveCallback
|
import com.intellij.refactoring.move.MoveCallback
|
||||||
import com.intellij.refactoring.move.MoveMultipleElementsViewDescriptor
|
import com.intellij.refactoring.move.MoveMultipleElementsViewDescriptor
|
||||||
import com.intellij.refactoring.move.moveClassesOrPackages.MoveClassHandler
|
import com.intellij.refactoring.move.moveClassesOrPackages.MoveClassHandler
|
||||||
import com.intellij.refactoring.move.moveClassesOrPackages.MoveClassesOrPackagesUtil
|
|
||||||
import com.intellij.refactoring.rename.RenameUtil
|
import com.intellij.refactoring.rename.RenameUtil
|
||||||
import com.intellij.refactoring.util.MoveRenameUsageInfo
|
import com.intellij.refactoring.util.MoveRenameUsageInfo
|
||||||
import com.intellij.refactoring.util.NonCodeUsageInfo
|
import com.intellij.refactoring.util.NonCodeUsageInfo
|
||||||
import com.intellij.refactoring.util.RefactoringUIUtil
|
import com.intellij.refactoring.util.RefactoringUIUtil
|
||||||
import com.intellij.refactoring.util.TextOccurrencesUtil
|
import com.intellij.refactoring.util.TextOccurrencesUtil
|
||||||
import com.intellij.usageView.UsageInfo
|
import com.intellij.usageView.UsageInfo
|
||||||
|
import com.intellij.usageView.UsageViewBundle
|
||||||
import com.intellij.usageView.UsageViewDescriptor
|
import com.intellij.usageView.UsageViewDescriptor
|
||||||
import com.intellij.usageView.UsageViewUtil
|
import com.intellij.usageView.UsageViewUtil
|
||||||
import com.intellij.util.IncorrectOperationException
|
import com.intellij.util.IncorrectOperationException
|
||||||
|
import com.intellij.util.SmartList
|
||||||
import com.intellij.util.VisibilityUtil
|
import com.intellij.util.VisibilityUtil
|
||||||
import com.intellij.util.containers.MultiMap
|
import com.intellij.util.containers.MultiMap
|
||||||
import gnu.trove.THashMap
|
import gnu.trove.THashMap
|
||||||
@@ -54,9 +56,8 @@ import org.jetbrains.kotlin.idea.refactoring.move.*
|
|||||||
import org.jetbrains.kotlin.idea.refactoring.move.moveFilesOrDirectories.MoveKotlinClassHandler
|
import org.jetbrains.kotlin.idea.refactoring.move.moveFilesOrDirectories.MoveKotlinClassHandler
|
||||||
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference.ShorteningMode
|
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference.ShorteningMode
|
||||||
import org.jetbrains.kotlin.idea.search.projectScope
|
import org.jetbrains.kotlin.idea.search.projectScope
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.KtModifierListOwner
|
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
|
||||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.isInsideOf
|
import org.jetbrains.kotlin.psi.psiUtil.isInsideOf
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.isPrivate
|
import org.jetbrains.kotlin.psi.psiUtil.isPrivate
|
||||||
@@ -64,58 +65,64 @@ import org.jetbrains.kotlin.resolve.BindingContext
|
|||||||
import org.jetbrains.kotlin.utils.keysToMap
|
import org.jetbrains.kotlin.utils.keysToMap
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
interface Mover: (KtNamedDeclaration, KtFile) -> KtNamedDeclaration {
|
interface Mover: (KtNamedDeclaration, KtElement) -> KtNamedDeclaration {
|
||||||
object Default: Mover {
|
object Default : Mover {
|
||||||
override fun invoke(originalElement: KtNamedDeclaration, targetFile: KtFile): KtNamedDeclaration {
|
override fun invoke(originalElement: KtNamedDeclaration, targetContainer: KtElement): KtNamedDeclaration {
|
||||||
val newElement = targetFile.add(originalElement) as KtNamedDeclaration
|
return when (targetContainer) {
|
||||||
originalElement.deleteSingle()
|
is KtFile -> targetContainer.add(originalElement) as KtNamedDeclaration
|
||||||
return newElement
|
is KtClassOrObject -> targetContainer.addDeclaration(originalElement) as KtNamedDeclaration
|
||||||
|
else -> error("Unexpected element: ${targetContainer.getElementTextWithContext()}")
|
||||||
|
}.apply { originalElement.deleteSingle() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object Idle: Mover {
|
object Idle : Mover {
|
||||||
override fun invoke(originalElement: KtNamedDeclaration, targetFile: KtFile) = originalElement
|
override fun invoke(originalElement: KtNamedDeclaration, targetContainer: KtElement) = originalElement
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MoveKotlinTopLevelDeclarationsOptions(
|
class MoveDeclarationsDescriptor(
|
||||||
val elementsToMove: Collection<KtNamedDeclaration>,
|
val elementsToMove: Collection<KtNamedDeclaration>,
|
||||||
val moveTarget: KotlinMoveTarget,
|
val moveTarget: KotlinMoveTarget,
|
||||||
|
val delegate: MoveDeclarationsDelegate,
|
||||||
val searchInCommentsAndStrings: Boolean = true,
|
val searchInCommentsAndStrings: Boolean = true,
|
||||||
val searchInNonCode: Boolean = true,
|
val searchInNonCode: Boolean = true,
|
||||||
val updateInternalReferences: Boolean = true,
|
val updateInternalReferences: Boolean = true,
|
||||||
val deleteSourceFiles: Boolean = false,
|
val deleteSourceFiles: Boolean = false,
|
||||||
val moveCallback: MoveCallback? = null
|
val moveCallback: MoveCallback? = null,
|
||||||
|
val openInEditor: Boolean = false
|
||||||
)
|
)
|
||||||
|
|
||||||
class MoveKotlinTopLevelDeclarationsProcessor(
|
class MoveKotlinDeclarationsProcessor(
|
||||||
val project: Project,
|
val project: Project,
|
||||||
val options: MoveKotlinTopLevelDeclarationsOptions,
|
val descriptor: MoveDeclarationsDescriptor,
|
||||||
val mover: Mover = Mover.Default) : BaseRefactoringProcessor(project) {
|
val mover: Mover = Mover.Default) : BaseRefactoringProcessor(project) {
|
||||||
companion object {
|
companion object {
|
||||||
private val REFACTORING_NAME: String = KotlinRefactoringBundle.message("refactoring.move.top.level.declarations")
|
private val REFACTORING_NAME: String = KotlinRefactoringBundle.message("refactoring.move.top.level.declarations")
|
||||||
}
|
}
|
||||||
|
|
||||||
private var nonCodeUsages: Array<NonCodeUsageInfo>? = null
|
private var nonCodeUsages: Array<NonCodeUsageInfo>? = null
|
||||||
private val elementsToMove = options.elementsToMove.filter { e -> e.containingFile != options.moveTarget.getTargetPsiIfExists(e) }
|
private val elementsToMove = descriptor.elementsToMove.filter { e -> e.parent != descriptor.moveTarget.getTargetPsiIfExists(e) }
|
||||||
private val kotlinToLightElementsBySourceFile = elementsToMove
|
private val kotlinToLightElementsBySourceFile = elementsToMove
|
||||||
.groupBy { it.getContainingKtFile() }
|
.groupBy { it.getContainingKtFile() }
|
||||||
.mapValues { it.value.keysToMap { it.toLightElements() } }
|
.mapValues { it.value.keysToMap { it.toLightElements() } }
|
||||||
private val conflicts = MultiMap<PsiElement, String>()
|
private val conflicts = MultiMap<PsiElement, String>()
|
||||||
|
|
||||||
override fun createUsageViewDescriptor(usages: Array<out UsageInfo>): UsageViewDescriptor {
|
override fun createUsageViewDescriptor(usages: Array<out UsageInfo>): UsageViewDescriptor {
|
||||||
return MoveMultipleElementsViewDescriptor(
|
val targetContainerFqName = descriptor.moveTarget.targetContainerFqName?.let {
|
||||||
elementsToMove.toTypedArray(),
|
if (it.isRoot) UsageViewBundle.message("default.package.presentable.name") else it.asString()
|
||||||
MoveClassesOrPackagesUtil.getPackageName(options.moveTarget.packageWrapper)
|
}
|
||||||
)
|
return MoveMultipleElementsViewDescriptor(elementsToMove.toTypedArray(), targetContainerFqName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val usagesToProcessBeforeMove = SmartList<UsageInfo>()
|
||||||
|
|
||||||
public override fun findUsages(): Array<UsageInfo> {
|
public override fun findUsages(): Array<UsageInfo> {
|
||||||
val newPackageName = options.moveTarget.packageWrapper?.qualifiedName ?: ""
|
val newContainerName = descriptor.moveTarget.targetContainerFqName?.asString() ?: ""
|
||||||
|
|
||||||
fun collectUsages(kotlinToLightElements: Map<KtNamedDeclaration, List<PsiNamedElement>>, result: MutableList<UsageInfo>) {
|
fun collectUsages(kotlinToLightElements: Map<KtNamedDeclaration, List<PsiNamedElement>>, result: MutableList<UsageInfo>) {
|
||||||
kotlinToLightElements.values.flatMap { it }.flatMapTo(result) { lightElement ->
|
kotlinToLightElements.values.flatMap { it }.flatMapTo(result) { lightElement ->
|
||||||
val newFqName = StringUtil.getQualifiedName(newPackageName, lightElement.name)
|
val newFqName = StringUtil.getQualifiedName(newContainerName, lightElement.name)
|
||||||
|
|
||||||
val foundReferences = HashSet<PsiReference>()
|
val foundReferences = HashSet<PsiReference>()
|
||||||
val projectScope = lightElement.project.projectScope()
|
val projectScope = lightElement.project.projectScope()
|
||||||
@@ -133,8 +140,8 @@ class MoveKotlinTopLevelDeclarationsProcessor(
|
|||||||
TextOccurrencesUtil.findNonCodeUsages(
|
TextOccurrencesUtil.findNonCodeUsages(
|
||||||
lightElement,
|
lightElement,
|
||||||
name,
|
name,
|
||||||
options.searchInCommentsAndStrings,
|
descriptor.searchInCommentsAndStrings,
|
||||||
options.searchInNonCode,
|
descriptor.searchInNonCode,
|
||||||
newFqName,
|
newFqName,
|
||||||
results
|
results
|
||||||
)
|
)
|
||||||
@@ -169,8 +176,9 @@ class MoveKotlinTopLevelDeclarationsProcessor(
|
|||||||
val container = element.getUsageContext()
|
val container = element.getUsageContext()
|
||||||
if (!declarationToContainers.getOrPut(declaration) { HashSet<PsiElement>() }.add(container)) continue
|
if (!declarationToContainers.getOrPut(declaration) { HashSet<PsiElement>() }.add(container)) continue
|
||||||
|
|
||||||
|
// todo: ok for now, will be replaced by proper visibility analysis
|
||||||
val currentPackage = element.containingFile?.containingDirectory?.getPackage()
|
val currentPackage = element.containingFile?.containingDirectory?.getPackage()
|
||||||
if (currentPackage?.qualifiedName == newPackageName) continue
|
if (currentPackage?.qualifiedName == newContainerName) continue
|
||||||
|
|
||||||
conflicts.putValue(
|
conflicts.putValue(
|
||||||
declaration,
|
declaration,
|
||||||
@@ -184,7 +192,7 @@ class MoveKotlinTopLevelDeclarationsProcessor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun collectConflictsInDeclarations() {
|
fun collectConflictsInDeclarations() {
|
||||||
if (newPackageName == UNKNOWN_PACKAGE_FQ_NAME.asString()) return
|
if (newContainerName == UNKNOWN_PACKAGE_FQ_NAME.asString()) return
|
||||||
|
|
||||||
val declarationToReferenceTargets = HashMap<KtNamedDeclaration, MutableSet<PsiElement>>()
|
val declarationToReferenceTargets = HashMap<KtNamedDeclaration, MutableSet<PsiElement>>()
|
||||||
for (declaration in elementsToMove) {
|
for (declaration in elementsToMove) {
|
||||||
@@ -207,8 +215,9 @@ class MoveKotlinTopLevelDeclarationsProcessor(
|
|||||||
|
|
||||||
if (!declarationToReferenceTargets.getOrPut(declaration) { HashSet<PsiElement>() }.add(refTarget)) continue
|
if (!declarationToReferenceTargets.getOrPut(declaration) { HashSet<PsiElement>() }.add(refTarget)) continue
|
||||||
|
|
||||||
|
// todo: ok for now, will be replaced by proper visibility analysis
|
||||||
val currentPackage = declaration.containingFile?.containingDirectory?.getPackage()
|
val currentPackage = declaration.containingFile?.containingDirectory?.getPackage()
|
||||||
if (currentPackage?.qualifiedName == newPackageName) continue
|
if (currentPackage?.qualifiedName == newContainerName) continue
|
||||||
|
|
||||||
conflicts.putValue(
|
conflicts.putValue(
|
||||||
declaration,
|
declaration,
|
||||||
@@ -224,14 +233,29 @@ class MoveKotlinTopLevelDeclarationsProcessor(
|
|||||||
|
|
||||||
val usages = ArrayList<UsageInfo>()
|
val usages = ArrayList<UsageInfo>()
|
||||||
for ((sourceFile, kotlinToLightElements) in kotlinToLightElementsBySourceFile) {
|
for ((sourceFile, kotlinToLightElements) in kotlinToLightElementsBySourceFile) {
|
||||||
// No need to find and process usages if package is not changed
|
kotlinToLightElements.keys.forEach {
|
||||||
if (sourceFile.packageFqName.asString() == newPackageName) return UsageInfo.EMPTY_ARRAY
|
if (descriptor.updateInternalReferences) {
|
||||||
|
val packageNameInfo = descriptor.delegate.getContainerChangeInfo(it, descriptor.moveTarget)
|
||||||
|
val (usagesToProcessLater, usagesToProcessEarly) = it
|
||||||
|
.getInternalReferencesToUpdateOnPackageNameChange(packageNameInfo)
|
||||||
|
.partition { it is MoveRenameUsageInfoForExtension }
|
||||||
|
usages.addAll(usagesToProcessLater)
|
||||||
|
usagesToProcessBeforeMove.addAll(usagesToProcessEarly)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No need to find and process usages if package is not changed
|
||||||
|
val originalContainerName = descriptor.delegate.getOriginalContainerFqName(descriptor, sourceFile).asString()
|
||||||
|
if (originalContainerName == newContainerName) return UsageInfo.EMPTY_ARRAY
|
||||||
|
|
||||||
|
usages += descriptor.delegate.findUsages(descriptor)
|
||||||
collectUsages(kotlinToLightElements, usages)
|
collectUsages(kotlinToLightElements, usages)
|
||||||
collectConflictsInUsages(usages)
|
collectConflictsInUsages(usages)
|
||||||
collectConflictsInDeclarations()
|
collectConflictsInDeclarations()
|
||||||
|
descriptor.delegate.collectConflicts(usages, conflicts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
descriptor.delegate.collectConflicts(usagesToProcessBeforeMove, conflicts)
|
||||||
|
|
||||||
return UsageViewUtil.removeDuplicatedUsages(usages.toTypedArray())
|
return UsageViewUtil.removeDuplicatedUsages(usages.toTypedArray())
|
||||||
}
|
}
|
||||||
@@ -241,27 +265,15 @@ class MoveKotlinTopLevelDeclarationsProcessor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun performRefactoring(usages: Array<out UsageInfo>) {
|
override fun performRefactoring(usages: Array<out UsageInfo>) {
|
||||||
fun moveDeclaration(
|
fun moveDeclaration(declaration: KtNamedDeclaration, moveTarget: KotlinMoveTarget): KtNamedDeclaration? {
|
||||||
declaration: KtNamedDeclaration,
|
|
||||||
moveTarget: KotlinMoveTarget,
|
|
||||||
usagesToProcessAfterMove: MutableList<UsageInfo>
|
|
||||||
): KtNamedDeclaration? {
|
|
||||||
val file = declaration.containingFile as? KtFile
|
val file = declaration.containingFile as? KtFile
|
||||||
assert(file != null) { "${declaration.javaClass}: ${declaration.text}" }
|
assert(file != null) { "${declaration.javaClass}: ${declaration.text}" }
|
||||||
|
|
||||||
val targetFile = moveTarget.getOrCreateTargetPsi(declaration) as? KtFile
|
val targetContainer = moveTarget.getOrCreateTargetPsi(declaration)
|
||||||
?: throw AssertionError("Couldn't create Kotlin file for: ${declaration.javaClass}: ${declaration.text}")
|
?: throw AssertionError("Couldn't create Kotlin file for: ${declaration.javaClass}: ${declaration.text}")
|
||||||
|
|
||||||
if (options.updateInternalReferences) {
|
descriptor.delegate.preprocessDeclaration(descriptor, declaration)
|
||||||
val packageNameInfo = PackageNameInfo(file!!.packageFqName, targetFile.packageFqName.toUnsafe())
|
val newElement = mover(declaration, targetContainer)
|
||||||
val (usagesToProcessLater, usagesToProcessNow) = declaration
|
|
||||||
.getInternalReferencesToUpdateOnPackageNameChange(packageNameInfo)
|
|
||||||
.partition { it is MoveRenameUsageInfoForExtension }
|
|
||||||
postProcessMoveUsages(usagesToProcessNow, shorteningMode = ShorteningMode.NO_SHORTENING)
|
|
||||||
usagesToProcessAfterMove.addAll(usagesToProcessLater)
|
|
||||||
}
|
|
||||||
|
|
||||||
val newElement = mover(declaration, targetFile)
|
|
||||||
|
|
||||||
newElement.addToShorteningWaitSet()
|
newElement.addToShorteningWaitSet()
|
||||||
|
|
||||||
@@ -271,6 +283,10 @@ class MoveKotlinTopLevelDeclarationsProcessor(
|
|||||||
try {
|
try {
|
||||||
val usageList = usages.toArrayList()
|
val usageList = usages.toArrayList()
|
||||||
|
|
||||||
|
descriptor.delegate.preprocessUsages(project, usageList)
|
||||||
|
|
||||||
|
postProcessMoveUsages(usagesToProcessBeforeMove, shorteningMode = ShorteningMode.NO_SHORTENING)
|
||||||
|
|
||||||
val oldToNewElementsMapping = THashMap<PsiElement, PsiElement>(
|
val oldToNewElementsMapping = THashMap<PsiElement, PsiElement>(
|
||||||
object: TObjectHashingStrategy<PsiElement> {
|
object: TObjectHashingStrategy<PsiElement> {
|
||||||
override fun equals(e1: PsiElement?, e2: PsiElement?): Boolean {
|
override fun equals(e1: PsiElement?, e2: PsiElement?): Boolean {
|
||||||
@@ -293,7 +309,7 @@ class MoveKotlinTopLevelDeclarationsProcessor(
|
|||||||
)
|
)
|
||||||
for ((sourceFile, kotlinToLightElements) in kotlinToLightElementsBySourceFile) {
|
for ((sourceFile, kotlinToLightElements) in kotlinToLightElementsBySourceFile) {
|
||||||
for ((oldDeclaration, oldLightElements) in kotlinToLightElements) {
|
for ((oldDeclaration, oldLightElements) in kotlinToLightElements) {
|
||||||
val newDeclaration = moveDeclaration(oldDeclaration, options.moveTarget, usageList)
|
val newDeclaration = moveDeclaration(oldDeclaration, descriptor.moveTarget)
|
||||||
if (newDeclaration == null) {
|
if (newDeclaration == null) {
|
||||||
for (oldElement in oldLightElements) {
|
for (oldElement in oldLightElements) {
|
||||||
oldToNewElementsMapping[oldElement] = oldElement
|
oldToNewElementsMapping[oldElement] = oldElement
|
||||||
@@ -307,9 +323,13 @@ class MoveKotlinTopLevelDeclarationsProcessor(
|
|||||||
for ((oldElement, newElement) in oldLightElements.asSequence().zip(newDeclaration.toLightElements().asSequence())) {
|
for ((oldElement, newElement) in oldLightElements.asSequence().zip(newDeclaration.toLightElements().asSequence())) {
|
||||||
oldToNewElementsMapping[oldElement] = newElement
|
oldToNewElementsMapping[oldElement] = newElement
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (descriptor.openInEditor) {
|
||||||
|
EditorHelper.openInEditor(newDeclaration)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.deleteSourceFiles) {
|
if (descriptor.deleteSourceFiles) {
|
||||||
sourceFile.delete()
|
sourceFile.delete()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -324,7 +344,7 @@ class MoveKotlinTopLevelDeclarationsProcessor(
|
|||||||
|
|
||||||
override fun performPsiSpoilingRefactoring() {
|
override fun performPsiSpoilingRefactoring() {
|
||||||
nonCodeUsages?.let { nonCodeUsages -> RenameUtil.renameNonCodeUsages(myProject, nonCodeUsages) }
|
nonCodeUsages?.let { nonCodeUsages -> RenameUtil.renameNonCodeUsages(myProject, nonCodeUsages) }
|
||||||
options.moveCallback?.refactoringCompleted()
|
descriptor.moveCallback?.refactoringCompleted()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun execute(usages: List<UsageInfo>) {
|
fun execute(usages: List<UsageInfo>) {
|
||||||
+1
-1
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations.ui
|
package org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.ui
|
||||||
|
|
||||||
import com.intellij.ide.util.DirectoryUtil
|
import com.intellij.ide.util.DirectoryUtil
|
||||||
import com.intellij.ide.util.PropertiesComponent
|
import com.intellij.ide.util.PropertiesComponent
|
||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations.ui.MoveKotlinTopLevelDeclarationsDialog">
|
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.ui.MoveKotlinTopLevelDeclarationsDialog">
|
||||||
<grid id="1a398" binding="mainPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
|
<grid id="1a398" binding="mainPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
|
||||||
<constraints>
|
<constraints>
|
||||||
<xy x="10" y="10" width="472" height="414"/>
|
<xy x="10" y="10" width="472" height="414"/>
|
||||||
+14
-8
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations.ui;
|
package org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.ui;
|
||||||
|
|
||||||
import com.intellij.openapi.editor.Document;
|
import com.intellij.openapi.editor.Document;
|
||||||
import com.intellij.openapi.editor.event.DocumentAdapter;
|
import com.intellij.openapi.editor.event.DocumentAdapter;
|
||||||
@@ -69,7 +69,7 @@ import org.jetbrains.kotlin.idea.refactoring.memberInfo.KotlinMemberInfo;
|
|||||||
import org.jetbrains.kotlin.idea.refactoring.memberInfo.KotlinMemberSelectionPanel;
|
import org.jetbrains.kotlin.idea.refactoring.memberInfo.KotlinMemberSelectionPanel;
|
||||||
import org.jetbrains.kotlin.idea.refactoring.memberInfo.KotlinMemberSelectionTable;
|
import org.jetbrains.kotlin.idea.refactoring.memberInfo.KotlinMemberSelectionTable;
|
||||||
import org.jetbrains.kotlin.idea.refactoring.move.MoveUtilsKt;
|
import org.jetbrains.kotlin.idea.refactoring.move.MoveUtilsKt;
|
||||||
import org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations.*;
|
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.*;
|
||||||
import org.jetbrains.kotlin.idea.util.application.ApplicationUtilsKt;
|
import org.jetbrains.kotlin.idea.util.application.ApplicationUtilsKt;
|
||||||
import org.jetbrains.kotlin.name.FqName;
|
import org.jetbrains.kotlin.name.FqName;
|
||||||
import org.jetbrains.kotlin.psi.KtFile;
|
import org.jetbrains.kotlin.psi.KtFile;
|
||||||
@@ -533,7 +533,6 @@ public class MoveKotlinTopLevelDeclarationsDialog extends RefactoringDialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return new KotlinMoveTargetForDeferredFile(
|
return new KotlinMoveTargetForDeferredFile(
|
||||||
myProject,
|
|
||||||
new FqName(getTargetPackage()),
|
new FqName(getTargetPackage()),
|
||||||
new Function1<KtFile, KtFile>() {
|
new Function1<KtFile, KtFile>() {
|
||||||
@Override
|
@Override
|
||||||
@@ -556,7 +555,7 @@ public class MoveKotlinTopLevelDeclarationsDialog extends RefactoringDialog {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new KotlinMoveTargetForExistingFile(jetFile);
|
return new KotlinMoveTargetForExistingElement(jetFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
File targetDir = targetFile.getParentFile();
|
File targetDir = targetFile.getParentFile();
|
||||||
@@ -570,7 +569,6 @@ public class MoveKotlinTopLevelDeclarationsDialog extends RefactoringDialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return new KotlinMoveTargetForDeferredFile(
|
return new KotlinMoveTargetForDeferredFile(
|
||||||
myProject,
|
|
||||||
new FqName(psiPackage.getQualifiedName()),
|
new FqName(psiPackage.getQualifiedName()),
|
||||||
new Function1<KtFile, KtFile>() {
|
new Function1<KtFile, KtFile>() {
|
||||||
@Override
|
@Override
|
||||||
@@ -757,10 +755,18 @@ public class MoveKotlinTopLevelDeclarationsDialog extends RefactoringDialog {
|
|||||||
deleteSourceFile = ret == Messages.YES;
|
deleteSourceFile = ret == Messages.YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
MoveKotlinTopLevelDeclarationsOptions options = new MoveKotlinTopLevelDeclarationsOptions(
|
MoveDeclarationsDescriptor options = new MoveDeclarationsDescriptor(
|
||||||
elementsToMove, target, isSearchInComments(), isSearchInNonJavaFiles(), true, deleteSourceFile, moveCallback
|
elementsToMove,
|
||||||
|
target,
|
||||||
|
MoveDeclarationsDelegate.TopLevel.INSTANCE,
|
||||||
|
isSearchInComments(),
|
||||||
|
isSearchInNonJavaFiles(),
|
||||||
|
true,
|
||||||
|
deleteSourceFile,
|
||||||
|
moveCallback,
|
||||||
|
false
|
||||||
);
|
);
|
||||||
invokeRefactoring(new MoveKotlinTopLevelDeclarationsProcessor(myProject, options, Mover.Default.INSTANCE));
|
invokeRefactoring(new MoveKotlinDeclarationsProcessor(myProject, options, Mover.Default.INSTANCE));
|
||||||
}
|
}
|
||||||
catch (IncorrectOperationException e) {
|
catch (IncorrectOperationException e) {
|
||||||
CommonRefactoringUtil.showErrorMessage(RefactoringBundle.message("error.title"), e.getMessage(), null, myProject);
|
CommonRefactoringUtil.showErrorMessage(RefactoringBundle.message("error.title"), e.getMessage(), null, myProject);
|
||||||
+3
-3
@@ -27,7 +27,7 @@ import com.intellij.usageView.UsageInfo
|
|||||||
import com.intellij.util.Function
|
import com.intellij.util.Function
|
||||||
import org.jetbrains.kotlin.idea.core.getPackage
|
import org.jetbrains.kotlin.idea.core.getPackage
|
||||||
import org.jetbrains.kotlin.idea.refactoring.invokeOnceOnCommandFinish
|
import org.jetbrains.kotlin.idea.refactoring.invokeOnceOnCommandFinish
|
||||||
import org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations.MoveKotlinTopLevelDeclarationsProcessor
|
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.MoveKotlinDeclarationsProcessor
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
@@ -37,13 +37,13 @@ class KotlinMoveDirectoryWithClassesHelper : MoveDirectoryWithClassesHelper() {
|
|||||||
private class FileUsagesWrapper(
|
private class FileUsagesWrapper(
|
||||||
val psiFile: PsiFile,
|
val psiFile: PsiFile,
|
||||||
val usages: List<UsageInfo>,
|
val usages: List<UsageInfo>,
|
||||||
val moveDeclarationsProcessor: MoveKotlinTopLevelDeclarationsProcessor?
|
val moveDeclarationsProcessor: MoveKotlinDeclarationsProcessor?
|
||||||
) : UsageInfo(psiFile)
|
) : UsageInfo(psiFile)
|
||||||
|
|
||||||
private class MoveContext(
|
private class MoveContext(
|
||||||
val newParent: PsiDirectory,
|
val newParent: PsiDirectory,
|
||||||
val internalUsages: MoveKotlinFileHandler.InternalUsagesWrapper,
|
val internalUsages: MoveKotlinFileHandler.InternalUsagesWrapper,
|
||||||
val moveDeclarationsProcessor: MoveKotlinTopLevelDeclarationsProcessor?
|
val moveDeclarationsProcessor: MoveKotlinDeclarationsProcessor?
|
||||||
)
|
)
|
||||||
|
|
||||||
private val fileHandler = MoveKotlinFileHandler()
|
private val fileHandler = MoveKotlinFileHandler()
|
||||||
|
|||||||
+17
-17
@@ -28,7 +28,7 @@ import org.jetbrains.kotlin.idea.core.getPackage
|
|||||||
import org.jetbrains.kotlin.idea.core.packageMatchesDirectory
|
import org.jetbrains.kotlin.idea.core.packageMatchesDirectory
|
||||||
import org.jetbrains.kotlin.idea.refactoring.hasIdentifiersOnly
|
import org.jetbrains.kotlin.idea.refactoring.hasIdentifiersOnly
|
||||||
import org.jetbrains.kotlin.idea.refactoring.move.*
|
import org.jetbrains.kotlin.idea.refactoring.move.*
|
||||||
import org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations.*
|
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.*
|
||||||
import org.jetbrains.kotlin.name.FqNameUnsafe
|
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||||
@@ -42,48 +42,50 @@ class MoveKotlinFileHandler : MoveFileHandler() {
|
|||||||
// so that it can be kept in the transition map
|
// so that it can be kept in the transition map
|
||||||
private class MoveContext(
|
private class MoveContext(
|
||||||
psiManager: PsiManager,
|
psiManager: PsiManager,
|
||||||
val declarationMoveProcessor: MoveKotlinTopLevelDeclarationsProcessor
|
val declarationMoveProcessor: MoveKotlinDeclarationsProcessor
|
||||||
): LightElement(psiManager, KotlinLanguage.INSTANCE) {
|
): LightElement(psiManager, KotlinLanguage.INSTANCE) {
|
||||||
override fun toString() = ""
|
override fun toString() = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KtFile.getPackageNameInfo(newParent: PsiDirectory?, clearUserData: Boolean): PackageNameInfo? {
|
private fun KtFile.getPackageNameInfo(newParent: PsiDirectory?, clearUserData: Boolean): ContainerChangeInfo? {
|
||||||
val shouldUpdatePackageDirective = updatePackageDirective ?: packageMatchesDirectory()
|
val shouldUpdatePackageDirective = updatePackageDirective ?: packageMatchesDirectory()
|
||||||
updatePackageDirective = if (clearUserData) null else shouldUpdatePackageDirective
|
updatePackageDirective = if (clearUserData) null else shouldUpdatePackageDirective
|
||||||
|
|
||||||
if (!shouldUpdatePackageDirective) return null
|
if (!shouldUpdatePackageDirective) return null
|
||||||
|
|
||||||
val oldPackageName = packageFqName
|
val oldPackageName = packageFqName
|
||||||
val newPackage = newParent?.getPackage() ?: return PackageNameInfo(oldPackageName, UNKNOWN_PACKAGE_FQ_NAME)
|
val newPackage = newParent?.getPackage() ?: return ContainerChangeInfo(ContainerInfo.Package(oldPackageName),
|
||||||
|
ContainerInfo.UnknownPackage)
|
||||||
|
|
||||||
val newPackageName = FqNameUnsafe(newPackage.qualifiedName)
|
val newPackageName = FqNameUnsafe(newPackage.qualifiedName)
|
||||||
if (oldPackageName.asString() == newPackageName.asString()) return null
|
if (oldPackageName.asString() == newPackageName.asString()) return null
|
||||||
if (newPackageName != UNKNOWN_PACKAGE_FQ_NAME && !newPackageName.hasIdentifiersOnly()) return null
|
if (!newPackageName.hasIdentifiersOnly()) return null
|
||||||
|
|
||||||
return PackageNameInfo(oldPackageName, newPackageName)
|
return ContainerChangeInfo(ContainerInfo.Package(oldPackageName), ContainerInfo.Package(newPackageName.toSafe()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun initMoveProcessor(psiFile: PsiFile, newParent: PsiDirectory?): MoveKotlinTopLevelDeclarationsProcessor? {
|
fun initMoveProcessor(psiFile: PsiFile, newParent: PsiDirectory?): MoveKotlinDeclarationsProcessor? {
|
||||||
if (psiFile !is KtFile) return null
|
if (psiFile !is KtFile) return null
|
||||||
val packageNameInfo = psiFile.getPackageNameInfo(newParent, false) ?: return null
|
val packageNameInfo = psiFile.getPackageNameInfo(newParent, false) ?: return null
|
||||||
|
|
||||||
val project = psiFile.project
|
val project = psiFile.project
|
||||||
|
|
||||||
val newPackageName = packageNameInfo.newPackageName
|
val newPackage = packageNameInfo.newContainer
|
||||||
val moveTarget = when (newPackageName) {
|
val moveTarget = when (newPackage) {
|
||||||
UNKNOWN_PACKAGE_FQ_NAME -> EmptyKotlinMoveTarget
|
ContainerInfo.UnknownPackage -> EmptyKotlinMoveTarget
|
||||||
|
|
||||||
else -> KotlinMoveTargetForDeferredFile(project, newPackageName.toSafe()) {
|
else -> KotlinMoveTargetForDeferredFile(newPackage.fqName!!) {
|
||||||
MoveFilesOrDirectoriesUtil.doMoveFile(psiFile, newParent)
|
MoveFilesOrDirectoriesUtil.doMoveFile(psiFile, newParent)
|
||||||
newParent?.findFile(psiFile.name) as? KtFile
|
newParent?.findFile(psiFile.name) as? KtFile
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val declarationMoveProcessor = MoveKotlinTopLevelDeclarationsProcessor(
|
val declarationMoveProcessor = MoveKotlinDeclarationsProcessor(
|
||||||
project,
|
project,
|
||||||
MoveKotlinTopLevelDeclarationsOptions(
|
MoveDeclarationsDescriptor(
|
||||||
elementsToMove = psiFile.declarations.filterIsInstance<KtNamedDeclaration>(),
|
elementsToMove = psiFile.declarations.filterIsInstance<KtNamedDeclaration>(),
|
||||||
moveTarget = moveTarget,
|
moveTarget = moveTarget,
|
||||||
|
delegate = MoveDeclarationsDelegate.TopLevel,
|
||||||
updateInternalReferences = false
|
updateInternalReferences = false
|
||||||
),
|
),
|
||||||
Mover.Idle
|
Mover.Idle
|
||||||
@@ -126,9 +128,7 @@ class MoveKotlinFileHandler : MoveFileHandler() {
|
|||||||
if (file !is KtFile) return
|
if (file !is KtFile) return
|
||||||
val newDirectory = file.parent ?: return
|
val newDirectory = file.parent ?: return
|
||||||
val packageNameInfo = file.getPackageNameInfo(newDirectory, true) ?: return
|
val packageNameInfo = file.getPackageNameInfo(newDirectory, true) ?: return
|
||||||
val newPackageName = packageNameInfo.newPackageName
|
file.packageDirective?.fqName = packageNameInfo.newContainer.fqName!!
|
||||||
assert(newPackageName.isSafe) { newPackageName }
|
|
||||||
file.packageDirective?.fqName = newPackageName.toSafe()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun retargetUsages(usageInfos: List<UsageInfo>?, oldToNewMap: Map<PsiElement, PsiElement>) {
|
override fun retargetUsages(usageInfos: List<UsageInfo>?, oldToNewMap: Map<PsiElement, PsiElement>) {
|
||||||
@@ -136,7 +136,7 @@ class MoveKotlinFileHandler : MoveFileHandler() {
|
|||||||
retargetUsages(usageInfos, moveContext.declarationMoveProcessor)
|
retargetUsages(usageInfos, moveContext.declarationMoveProcessor)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun retargetUsages(usageInfos: List<UsageInfo>?, moveDeclarationsProcessor: MoveKotlinTopLevelDeclarationsProcessor) {
|
fun retargetUsages(usageInfos: List<UsageInfo>?, moveDeclarationsProcessor: MoveKotlinDeclarationsProcessor) {
|
||||||
postProcessMoveUsages(usageInfos?.firstIsInstanceOrNull<InternalUsagesWrapper>()?.usages ?: emptyList())
|
postProcessMoveUsages(usageInfos?.firstIsInstanceOrNull<InternalUsagesWrapper>()?.usages ?: emptyList())
|
||||||
moveDeclarationsProcessor.project.runWithElementsToShortenIsEmptyIgnored {
|
moveDeclarationsProcessor.project.runWithElementsToShortenIsEmptyIgnored {
|
||||||
usageInfos?.let { moveDeclarationsProcessor.execute(it) }
|
usageInfos?.let { moveDeclarationsProcessor.execute(it) }
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import com.intellij.openapi.ui.DialogWrapper
|
|||||||
import com.intellij.openapi.util.Comparing
|
import com.intellij.openapi.util.Comparing
|
||||||
import com.intellij.openapi.util.Key
|
import com.intellij.openapi.util.Key
|
||||||
import com.intellij.psi.*
|
import com.intellij.psi.*
|
||||||
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
import com.intellij.refactoring.RefactoringBundle
|
import com.intellij.refactoring.RefactoringBundle
|
||||||
import com.intellij.refactoring.RefactoringSettings
|
import com.intellij.refactoring.RefactoringSettings
|
||||||
import com.intellij.refactoring.copy.CopyFilesOrDirectoriesHandler
|
import com.intellij.refactoring.copy.CopyFilesOrDirectoriesHandler
|
||||||
@@ -36,17 +37,20 @@ import com.intellij.refactoring.util.MoveRenameUsageInfo
|
|||||||
import com.intellij.refactoring.util.NonCodeUsageInfo
|
import com.intellij.refactoring.util.NonCodeUsageInfo
|
||||||
import com.intellij.usageView.UsageInfo
|
import com.intellij.usageView.UsageInfo
|
||||||
import com.intellij.util.IncorrectOperationException
|
import com.intellij.util.IncorrectOperationException
|
||||||
|
import com.intellij.util.SmartList
|
||||||
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
|
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
|
||||||
import org.jetbrains.kotlin.asJava.unwrapped
|
import org.jetbrains.kotlin.asJava.unwrapped
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.analyzeFully
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||||
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
||||||
import org.jetbrains.kotlin.idea.codeInsight.KotlinFileReferencesResolver
|
import org.jetbrains.kotlin.idea.codeInsight.KotlinFileReferencesResolver
|
||||||
import org.jetbrains.kotlin.idea.imports.importableFqName
|
import org.jetbrains.kotlin.idea.imports.importableFqName
|
||||||
import org.jetbrains.kotlin.idea.refactoring.fqName.isImported
|
import org.jetbrains.kotlin.idea.refactoring.fqName.isImported
|
||||||
import org.jetbrains.kotlin.idea.refactoring.isInJavaSourceRoot
|
import org.jetbrains.kotlin.idea.refactoring.isInJavaSourceRoot
|
||||||
import org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations.ui.KotlinAwareMoveFilesOrDirectoriesDialog
|
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.ui.KotlinAwareMoveFilesOrDirectoriesDialog
|
||||||
import org.jetbrains.kotlin.idea.references.KtReference
|
import org.jetbrains.kotlin.idea.references.KtReference
|
||||||
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
|
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
|
||||||
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference.ShorteningMode
|
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference.ShorteningMode
|
||||||
@@ -60,22 +64,48 @@ import org.jetbrains.kotlin.psi.*
|
|||||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getImportableDescriptor
|
import org.jetbrains.kotlin.resolve.descriptorUtil.getImportableDescriptor
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.parents
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
val UNKNOWN_PACKAGE_FQ_NAME = FqNameUnsafe("org.jetbrains.kotlin.idea.refactoring.move.<unknown-package>")
|
val UNKNOWN_PACKAGE_FQ_NAME = FqNameUnsafe("org.jetbrains.kotlin.idea.refactoring.move.<unknown-package>")
|
||||||
|
|
||||||
class PackageNameInfo(val oldPackageName: FqName, val newPackageName: FqNameUnsafe)
|
sealed class ContainerInfo() {
|
||||||
|
abstract val fqName: FqName?
|
||||||
|
abstract fun matches(descriptor: DeclarationDescriptor): Boolean
|
||||||
|
|
||||||
fun KtElement.getInternalReferencesToUpdateOnPackageNameChange(packageNameInfo: PackageNameInfo): List<UsageInfo> {
|
object UnknownPackage : ContainerInfo() {
|
||||||
|
override val fqName = null
|
||||||
|
override fun matches(descriptor: DeclarationDescriptor) = descriptor is PackageViewDescriptor
|
||||||
|
}
|
||||||
|
|
||||||
|
class Package(override val fqName: FqName): ContainerInfo() {
|
||||||
|
override fun matches(descriptor: DeclarationDescriptor): Boolean {
|
||||||
|
return descriptor is PackageFragmentDescriptor && descriptor.fqName == fqName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Class(override val fqName: FqName) : ContainerInfo() {
|
||||||
|
override fun matches(descriptor: DeclarationDescriptor): Boolean {
|
||||||
|
return descriptor is ClassDescriptor && descriptor.importableFqName == fqName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class ContainerChangeInfo(val oldContainer: ContainerInfo, val newContainer: ContainerInfo)
|
||||||
|
|
||||||
|
fun KtElement.getInternalReferencesToUpdateOnPackageNameChange(containerChangeInfo: ContainerChangeInfo): List<UsageInfo> {
|
||||||
val usages = ArrayList<UsageInfo>()
|
val usages = ArrayList<UsageInfo>()
|
||||||
lazilyProcessInternalReferencesToUpdateOnPackageNameChange(packageNameInfo) { expr, factory -> usages.addIfNotNull(factory(expr)) }
|
lazilyProcessInternalReferencesToUpdateOnPackageNameChange(containerChangeInfo) { expr, factory -> usages.addIfNotNull(factory(expr)) }
|
||||||
return usages
|
return usages
|
||||||
}
|
}
|
||||||
|
|
||||||
fun KtElement.lazilyProcessInternalReferencesToUpdateOnPackageNameChange(
|
fun KtElement.lazilyProcessInternalReferencesToUpdateOnPackageNameChange(
|
||||||
packageNameInfo: PackageNameInfo,
|
containerChangeInfo: ContainerChangeInfo,
|
||||||
body: (originalRefExpr: KtSimpleNameExpression, usageFactory: (KtSimpleNameExpression) -> UsageInfo?) -> Unit
|
body: (originalRefExpr: KtSimpleNameExpression, usageFactory: (KtSimpleNameExpression) -> UsageInfo?) -> Unit
|
||||||
) {
|
) {
|
||||||
val file = containingFile as? KtFile ?: return
|
val file = containingFile as? KtFile ?: return
|
||||||
@@ -99,46 +129,61 @@ fun KtElement.lazilyProcessInternalReferencesToUpdateOnPackageNameChange(
|
|||||||
val declaration = DescriptorToSourceUtilsIde.getAnyDeclaration(project, descriptor) ?: return null
|
val declaration = DescriptorToSourceUtilsIde.getAnyDeclaration(project, descriptor) ?: return null
|
||||||
|
|
||||||
// Special case for enum entry superclass references (they have empty text and don't need to be processed by the refactoring)
|
// Special case for enum entry superclass references (they have empty text and don't need to be processed by the refactoring)
|
||||||
if (refExpr.textRange.isEmpty) {
|
if (refExpr.textRange.isEmpty) return null
|
||||||
return null
|
|
||||||
}
|
if (descriptor is ClassDescriptor && descriptor.isInner && refExpr.parent is KtCallExpression) return null
|
||||||
|
|
||||||
val isCallable = descriptor is CallableDescriptor
|
val isCallable = descriptor is CallableDescriptor
|
||||||
val isExtension = isCallable && declaration.isExtensionDeclaration()
|
val isExtension = isCallable && declaration.isExtensionDeclaration()
|
||||||
|
|
||||||
if (isCallable && !isExtension) {
|
if (isCallable) {
|
||||||
val containingDescriptor = descriptor.containingDeclaration
|
val containingDescriptor = descriptor.containingDeclaration
|
||||||
if (refExpr.getReceiverExpression() != null) {
|
if (isExtension && containingDescriptor is ClassDescriptor) {
|
||||||
return fun(refExpr: KtSimpleNameExpression): UsageInfo? {
|
val implicitClass = (refExpr.getResolvedCall(bindingContext)?.dispatchReceiver as? ImplicitClassReceiver)?.classDescriptor
|
||||||
val receiver = refExpr.getReceiverExpression() ?: return null
|
if (DescriptorUtils.isCompanionObject(implicitClass)) {
|
||||||
val receiverRef = receiver.getQualifiedElementSelector() as? KtSimpleNameExpression ?: return null
|
return { ImplicitCompanionAsDispatchReceiverUsageInfo(it) }
|
||||||
if (bindingContext[BindingContext.QUALIFIER, receiverRef] == null) return null
|
|
||||||
return processReference(receiverRef, bindingContext)?.invoke(receiverRef)
|
|
||||||
}
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
if (!isExtension) {
|
||||||
|
if (refExpr.getReceiverExpression() != null) {
|
||||||
|
return fun(refExpr: KtSimpleNameExpression): UsageInfo? {
|
||||||
|
val receiver = refExpr.getReceiverExpression() ?: return null
|
||||||
|
val receiverRef = receiver.getQualifiedElementSelector() as? KtSimpleNameExpression ?: return null
|
||||||
|
if (bindingContext[BindingContext.QUALIFIER, receiverRef] == null) return null
|
||||||
|
return processReference(receiverRef, bindingContext)?.invoke(receiverRef)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!(containingDescriptor is PackageFragmentDescriptor
|
||||||
|
|| containingDescriptor is ClassDescriptor && containingDescriptor.kind == ClassKind.OBJECT)) return null
|
||||||
}
|
}
|
||||||
if (containingDescriptor !is PackageFragmentDescriptor) return null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val fqName = DescriptorUtils.getFqName(descriptor)
|
val fqName = DescriptorUtils.getFqName(descriptor)
|
||||||
if (!fqName.isSafe) return null
|
if (!fqName.isSafe) return null
|
||||||
|
|
||||||
val packageName = DescriptorUtils.getParentOfType(descriptor, PackageFragmentDescriptor::class.java, false)?.let {
|
val (oldContainer, newContainer) = containerChangeInfo
|
||||||
DescriptorUtils.getFqName(it).toSafe()
|
|
||||||
}
|
|
||||||
|
|
||||||
val oldPackageName = packageNameInfo.oldPackageName
|
val containerFqName = descriptor
|
||||||
val newPackageName = packageNameInfo.newPackageName
|
.parents
|
||||||
|
.mapNotNull {
|
||||||
|
when {
|
||||||
|
oldContainer.matches(it) -> oldContainer.fqName
|
||||||
|
newContainer.matches(it) -> newContainer.fqName
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.firstOrNull()
|
||||||
|
|
||||||
fun doCreateUsageInfo(refExpr: KtSimpleNameExpression): UsageInfo? {
|
fun doCreateUsageInfo(refExpr: KtSimpleNameExpression): UsageInfo? {
|
||||||
if (isAncestor(declaration, false)) {
|
if (isAncestor(declaration, false)) {
|
||||||
if (descriptor.importableFqName == null) return null
|
if (descriptor.importableFqName == null) return null
|
||||||
if (descriptor is ClassDescriptor && descriptor.isInner && refExpr.parent is KtCallExpression) return null
|
|
||||||
if (isUnqualifiedExtensionReference(refExpr.mainReference, declaration)) return null
|
if (isUnqualifiedExtensionReference(refExpr.mainReference, declaration)) return null
|
||||||
if (packageName == null || !newPackageName.isSafe) return null
|
if (containerFqName == null || newContainer is ContainerInfo.UnknownPackage) return null
|
||||||
return fqName.asString().let {
|
return fqName.asString().let {
|
||||||
val prefix = packageName.asString()
|
val prefix = containerFqName.asString()
|
||||||
val prefixOffset = it.indexOf(prefix)
|
val prefixOffset = it.indexOf(prefix)
|
||||||
val newFqName = FqName(it.replaceRange(prefixOffset..prefixOffset + prefix.length - 1, newPackageName.asString()))
|
val newFqName = FqName(it.replaceRange(prefixOffset..prefixOffset + prefix.length - 1, newContainer.fqName!!.asString()))
|
||||||
MoveRenameSelfUsageInfo(refExpr.mainReference, declaration, newFqName)
|
MoveRenameSelfUsageInfo(refExpr.mainReference, declaration, newFqName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -146,11 +191,8 @@ fun KtElement.lazilyProcessInternalReferencesToUpdateOnPackageNameChange(
|
|||||||
return createMoveUsageInfoIfPossible(refExpr.mainReference, declaration, false)
|
return createMoveUsageInfoIfPossible(refExpr.mainReference, declaration, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isExtension &&
|
if (isExtension || containerFqName != null || isImported(descriptor)) return ::doCreateUsageInfo
|
||||||
packageName != oldPackageName &&
|
return null
|
||||||
packageName?.asString() != newPackageName.asString() &&
|
|
||||||
!isImported(descriptor)) return null
|
|
||||||
return ::doCreateUsageInfo
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val referenceToContext = KotlinFileReferencesResolver.resolve(file = file, elements = listOf(this))
|
val referenceToContext = KotlinFileReferencesResolver.resolve(file = file, elements = listOf(this))
|
||||||
@@ -163,6 +205,8 @@ fun KtElement.lazilyProcessInternalReferencesToUpdateOnPackageNameChange(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ImplicitCompanionAsDispatchReceiverUsageInfo(callee: KtSimpleNameExpression) : UsageInfo(callee)
|
||||||
|
|
||||||
class MoveRenameUsageInfoForExtension(
|
class MoveRenameUsageInfoForExtension(
|
||||||
element: PsiElement,
|
element: PsiElement,
|
||||||
reference: PsiReference,
|
reference: PsiReference,
|
||||||
@@ -276,7 +320,7 @@ fun postProcessMoveUsages(usages: List<UsageInfo>,
|
|||||||
|
|
||||||
val nonCodeUsages = ArrayList<NonCodeUsageInfo>()
|
val nonCodeUsages = ArrayList<NonCodeUsageInfo>()
|
||||||
|
|
||||||
for (usage in sortedUsages) {
|
usageLoop@ for (usage in sortedUsages) {
|
||||||
when (usage) {
|
when (usage) {
|
||||||
is NonCodeUsageInfo -> {
|
is NonCodeUsageInfo -> {
|
||||||
nonCodeUsages.add(usage)
|
nonCodeUsages.add(usage)
|
||||||
@@ -295,21 +339,17 @@ fun postProcessMoveUsages(usages: List<UsageInfo>,
|
|||||||
is MoveRenameUsageInfo -> {
|
is MoveRenameUsageInfo -> {
|
||||||
val oldElement = usage.referencedElement!!
|
val oldElement = usage.referencedElement!!
|
||||||
val newElement = counterpart(oldElement)
|
val newElement = counterpart(oldElement)
|
||||||
usage.reference?.let {
|
val reference = usage.reference ?: (usage.element as? KtSimpleNameExpression)?.mainReference
|
||||||
try {
|
try {
|
||||||
if (it is KtSimpleNameReference) {
|
when {
|
||||||
it.bindToElement(newElement, shorteningMode)
|
reference is KtSimpleNameReference -> reference.bindToElement(newElement, shorteningMode)
|
||||||
}
|
reference is PsiReferenceExpression && updateJavaReference(reference, oldElement, newElement) -> continue@usageLoop
|
||||||
else if (it is PsiReferenceExpression && updateJavaReference(it, oldElement, newElement)) {
|
else -> reference?.bindToElement(newElement)
|
||||||
}
|
|
||||||
else {
|
|
||||||
it.bindToElement(newElement)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (e: IncorrectOperationException) {
|
|
||||||
// Suppress exception if bindToElement is not implemented
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (e: IncorrectOperationException) {
|
||||||
|
// Suppress exception if bindToElement is not implemented
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -388,3 +428,86 @@ fun moveFilesOrDirectories(
|
|||||||
show()
|
show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sealed class OuterInstanceReferenceUsageInfo(element: PsiElement, val isIndirectOuter: Boolean) : UsageInfo(element) {
|
||||||
|
class ExplicitThis(
|
||||||
|
expression: KtThisExpression,
|
||||||
|
isIndirectOuter: Boolean
|
||||||
|
) : OuterInstanceReferenceUsageInfo(expression, isIndirectOuter) {
|
||||||
|
val expression: KtThisExpression?
|
||||||
|
get() = element as? KtThisExpression
|
||||||
|
}
|
||||||
|
|
||||||
|
class ImplicitReceiver(
|
||||||
|
callElement: KtElement,
|
||||||
|
isIndirectOuter: Boolean,
|
||||||
|
val isDoubleReceiver: Boolean
|
||||||
|
) : OuterInstanceReferenceUsageInfo(callElement, isIndirectOuter) {
|
||||||
|
val callElement: KtElement?
|
||||||
|
get() = element as? KtElement
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmOverloads
|
||||||
|
fun traverseOuterInstanceReferences(innerClass: KtClass, stopAtFirst: Boolean, body: (OuterInstanceReferenceUsageInfo) -> Unit = {}): Boolean {
|
||||||
|
if (!innerClass.isInner()) return false
|
||||||
|
|
||||||
|
val context = innerClass.analyzeFully()
|
||||||
|
val innerClassDescriptor = innerClass.resolveToDescriptorIfAny() as? ClassDescriptor ?: return false
|
||||||
|
val outerClassDescriptor = innerClassDescriptor.containingDeclaration as? ClassDescriptor ?: return false
|
||||||
|
var found = false
|
||||||
|
innerClass.accept(
|
||||||
|
object : PsiRecursiveElementWalkingVisitor() {
|
||||||
|
private fun getOuterInstanceReference(element: PsiElement): OuterInstanceReferenceUsageInfo? {
|
||||||
|
return when (element) {
|
||||||
|
is KtThisExpression -> {
|
||||||
|
val descriptor = context[BindingContext.REFERENCE_TARGET, element.instanceReference]
|
||||||
|
val isIndirect = when {
|
||||||
|
descriptor == outerClassDescriptor -> false
|
||||||
|
DescriptorUtils.isAncestor(descriptor, outerClassDescriptor, true) -> true
|
||||||
|
else -> return null
|
||||||
|
}
|
||||||
|
OuterInstanceReferenceUsageInfo.ExplicitThis(element, isIndirect)
|
||||||
|
}
|
||||||
|
is KtSimpleNameExpression -> {
|
||||||
|
val resolvedCall = element.getResolvedCall(context) ?: return null
|
||||||
|
val dispatchReceiver = resolvedCall.dispatchReceiver as? ImplicitReceiver
|
||||||
|
val extensionReceiver = resolvedCall.extensionReceiver as? ImplicitReceiver
|
||||||
|
var isIndirect = false
|
||||||
|
val isDoubleReceiver = when {
|
||||||
|
dispatchReceiver?.declarationDescriptor == outerClassDescriptor -> extensionReceiver != null
|
||||||
|
extensionReceiver?.declarationDescriptor == outerClassDescriptor -> dispatchReceiver != null
|
||||||
|
else -> {
|
||||||
|
isIndirect = true
|
||||||
|
when {
|
||||||
|
DescriptorUtils.isAncestor(dispatchReceiver?.declarationDescriptor, outerClassDescriptor, true) ->
|
||||||
|
extensionReceiver != null
|
||||||
|
DescriptorUtils.isAncestor(extensionReceiver?.declarationDescriptor, outerClassDescriptor, true) ->
|
||||||
|
dispatchReceiver != null
|
||||||
|
else -> return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OuterInstanceReferenceUsageInfo.ImplicitReceiver(resolvedCall.call.callElement, isIndirect, isDoubleReceiver)
|
||||||
|
}
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitElement(element: PsiElement) {
|
||||||
|
getOuterInstanceReference(element)?.let {
|
||||||
|
body(it)
|
||||||
|
found = true
|
||||||
|
if (stopAtFirst) stopWalking()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
super.visitElement(element)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return found
|
||||||
|
}
|
||||||
|
|
||||||
|
fun collectOuterInstanceReferences(innerClass: KtClass): List<OuterInstanceReferenceUsageInfo> {
|
||||||
|
return SmartList<OuterInstanceReferenceUsageInfo>().apply { traverseOuterInstanceReferences(innerClass, false) { add(it) } }
|
||||||
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"mainFile": "source/test.kt",
|
"mainFile": "source/test.kt",
|
||||||
"intentionClass": "org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations.MoveDeclarationToSeparateFileIntention"
|
"intentionClass": "org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.MoveDeclarationToSeparateFileIntention"
|
||||||
}
|
}
|
||||||
idea/testData/multiFileIntentions/moveDeclarationToSeparateFile/moveClassToFile/moveClassToFile.test
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"mainFile": "source/test.kt",
|
"mainFile": "source/test.kt",
|
||||||
"intentionClass": "org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations.MoveDeclarationToSeparateFileIntention"
|
"intentionClass": "org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.MoveDeclarationToSeparateFileIntention"
|
||||||
}
|
}
|
||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"mainFile": "source/test.kt",
|
"mainFile": "source/test.kt",
|
||||||
"intentionClass": "org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations.MoveDeclarationToSeparateFileIntention",
|
"intentionClass": "org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.MoveDeclarationToSeparateFileIntention",
|
||||||
"isApplicable": "false"
|
"isApplicable": "false"
|
||||||
}
|
}
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
class A {
|
||||||
|
inner class OuterOuterY
|
||||||
|
|
||||||
|
inner class B {
|
||||||
|
inner class C {
|
||||||
|
fun test() {
|
||||||
|
OuterOuterY()
|
||||||
|
this@A.OuterOuterY()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
class A {
|
||||||
|
inner class OuterOuterY
|
||||||
|
|
||||||
|
inner class B {
|
||||||
|
inner class <caret>C {
|
||||||
|
fun test() {
|
||||||
|
OuterOuterY()
|
||||||
|
this@A.OuterOuterY()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
Indirect outer instances won't be extracted: OuterOuterY()
|
||||||
|
Indirect outer instances won't be extracted: this@A
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"mainFile": "test.kt",
|
||||||
|
"type": "MOVE_KOTLIN_NESTED_CLASS",
|
||||||
|
"outerInstanceParameter": "a",
|
||||||
|
"withRuntime": "true"
|
||||||
|
}
|
||||||
Vendored
+26
@@ -0,0 +1,26 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
class C(private val b: A.B) {
|
||||||
|
fun test() {
|
||||||
|
A.X()
|
||||||
|
|
||||||
|
A.Companion.Y()
|
||||||
|
A.foo(A.bar)
|
||||||
|
//1.extFoo(1.extBar) // conflict
|
||||||
|
|
||||||
|
b.OuterY()
|
||||||
|
b.outerFoo(b.outerBar)
|
||||||
|
|
||||||
|
b.OuterY()
|
||||||
|
b.outerFoo(b.outerBar)
|
||||||
|
|
||||||
|
A.O.Y()
|
||||||
|
A.O.foo(A.O.bar)
|
||||||
|
|
||||||
|
with (A.O) {
|
||||||
|
A.Companion.Y()
|
||||||
|
foo(bar)
|
||||||
|
1.extFoo(1.extBar)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+42
@@ -0,0 +1,42 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
inline fun <T, R> with(receiver: T, block: T.() -> R): R = receiver.block()
|
||||||
|
|
||||||
|
class A {
|
||||||
|
class X {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
class Y
|
||||||
|
|
||||||
|
fun foo(n: Int) {}
|
||||||
|
|
||||||
|
val bar = 1
|
||||||
|
|
||||||
|
fun Int.extFoo(n: Int) {}
|
||||||
|
|
||||||
|
val Int.extBar: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
object O {
|
||||||
|
class Y
|
||||||
|
|
||||||
|
fun foo(n: Int) {}
|
||||||
|
|
||||||
|
val bar = 1
|
||||||
|
|
||||||
|
fun Int.extFoo(n: Int) {}
|
||||||
|
|
||||||
|
val Int.extBar: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class B {
|
||||||
|
inner class OuterY
|
||||||
|
|
||||||
|
fun outerFoo(n: Int) {}
|
||||||
|
|
||||||
|
val outerBar = 1
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
package test2;
|
||||||
|
|
||||||
|
import test.A;
|
||||||
|
import test.C;
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
C foo() {
|
||||||
|
return new C(new A().new B());
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
package test2;
|
||||||
|
|
||||||
|
import test.A;
|
||||||
|
import test.C;
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
C foo() {
|
||||||
|
return new C(new A().new B());
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
package test2;
|
||||||
|
|
||||||
|
import test.A;
|
||||||
|
import test.C;
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
C foo() {
|
||||||
|
return new C(new A().new B());
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+8
@@ -0,0 +1,8 @@
|
|||||||
|
package test2
|
||||||
|
|
||||||
|
import test.A
|
||||||
|
import test.C
|
||||||
|
|
||||||
|
fun foo(): C {
|
||||||
|
return C(A().B())
|
||||||
|
}
|
||||||
Vendored
+8
@@ -0,0 +1,8 @@
|
|||||||
|
package test2
|
||||||
|
|
||||||
|
import test.A
|
||||||
|
import test.C
|
||||||
|
|
||||||
|
fun foo2(): C {
|
||||||
|
return C(A().B())
|
||||||
|
}
|
||||||
Vendored
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package test2
|
||||||
|
|
||||||
|
import test.A
|
||||||
|
import test.A.B
|
||||||
|
import test.C
|
||||||
|
|
||||||
|
fun foo2(): C {
|
||||||
|
return C(A().B())
|
||||||
|
}
|
||||||
Vendored
+66
@@ -0,0 +1,66 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
inline fun <T, R> with(receiver: T, block: T.() -> R): R = receiver.block()
|
||||||
|
|
||||||
|
class A {
|
||||||
|
class X {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
class Y
|
||||||
|
|
||||||
|
fun foo(n: Int) {}
|
||||||
|
|
||||||
|
val bar = 1
|
||||||
|
|
||||||
|
fun Int.extFoo(n: Int) {}
|
||||||
|
|
||||||
|
val Int.extBar: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
object O {
|
||||||
|
class Y
|
||||||
|
|
||||||
|
fun foo(n: Int) {}
|
||||||
|
|
||||||
|
val bar = 1
|
||||||
|
|
||||||
|
fun Int.extFoo(n: Int) {}
|
||||||
|
|
||||||
|
val Int.extBar: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class B {
|
||||||
|
inner class OuterY
|
||||||
|
|
||||||
|
fun outerFoo(n: Int) {}
|
||||||
|
|
||||||
|
val outerBar = 1
|
||||||
|
|
||||||
|
inner class <caret>C {
|
||||||
|
fun test() {
|
||||||
|
X()
|
||||||
|
|
||||||
|
Y()
|
||||||
|
foo(bar)
|
||||||
|
//1.extFoo(1.extBar) // conflict
|
||||||
|
|
||||||
|
OuterY()
|
||||||
|
outerFoo(outerBar)
|
||||||
|
|
||||||
|
this@B.OuterY()
|
||||||
|
this@B.outerFoo(this@B.outerBar)
|
||||||
|
|
||||||
|
O.Y()
|
||||||
|
O.foo(O.bar)
|
||||||
|
|
||||||
|
with (O) {
|
||||||
|
Y()
|
||||||
|
foo(bar)
|
||||||
|
1.extFoo(1.extBar)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package test2;
|
||||||
|
|
||||||
|
import test.A;
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
A.B.C foo() {
|
||||||
|
return new A().new B().new C();
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
package test2;
|
||||||
|
|
||||||
|
import test.A;
|
||||||
|
import test.A.B.C;
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
C foo() {
|
||||||
|
return new A().new B().new C();
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
package test2;
|
||||||
|
|
||||||
|
import test.A;
|
||||||
|
import test.A.B;
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
B.C foo() {
|
||||||
|
return new A().new B().new C();
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+7
@@ -0,0 +1,7 @@
|
|||||||
|
package test2
|
||||||
|
|
||||||
|
import test.A
|
||||||
|
|
||||||
|
fun foo(): A.B.C {
|
||||||
|
return A().B().C()
|
||||||
|
}
|
||||||
Vendored
+8
@@ -0,0 +1,8 @@
|
|||||||
|
package test2
|
||||||
|
|
||||||
|
import test.A
|
||||||
|
import test.A.B.C
|
||||||
|
|
||||||
|
fun foo2(): C {
|
||||||
|
return A().B().C()
|
||||||
|
}
|
||||||
Vendored
+8
@@ -0,0 +1,8 @@
|
|||||||
|
package test2
|
||||||
|
|
||||||
|
import test.A
|
||||||
|
import test.A.B
|
||||||
|
|
||||||
|
fun foo2(): B.C {
|
||||||
|
return A().B().C()
|
||||||
|
}
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"mainFile": "test.kt",
|
||||||
|
"type": "MOVE_KOTLIN_NESTED_CLASS",
|
||||||
|
"outerInstanceParameter": "b",
|
||||||
|
"withRuntime": "true"
|
||||||
|
}
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
class C {
|
||||||
|
fun test() {
|
||||||
|
A.X()
|
||||||
|
|
||||||
|
A.Companion.Y()
|
||||||
|
A.foo(A.bar)
|
||||||
|
//1.extFoo(1.extBar) // conflict
|
||||||
|
|
||||||
|
A.O.Y()
|
||||||
|
A.O.foo(A.O.bar)
|
||||||
|
|
||||||
|
with (A.O) {
|
||||||
|
A.Companion.Y()
|
||||||
|
foo(bar)
|
||||||
|
1.extFoo(1.extBar)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+36
@@ -0,0 +1,36 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
inline fun <T, R> with(receiver: T, block: T.() -> R): R = receiver.block()
|
||||||
|
|
||||||
|
class A {
|
||||||
|
class X {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
class Y
|
||||||
|
|
||||||
|
fun foo(n: Int) {}
|
||||||
|
|
||||||
|
val bar = 1
|
||||||
|
|
||||||
|
fun Int.extFoo(n: Int) {}
|
||||||
|
|
||||||
|
val Int.extBar: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
object O {
|
||||||
|
class Y
|
||||||
|
|
||||||
|
fun foo(n: Int) {}
|
||||||
|
|
||||||
|
val bar = 1
|
||||||
|
|
||||||
|
fun Int.extFoo(n: Int) {}
|
||||||
|
|
||||||
|
val Int.extBar: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
class B {
|
||||||
|
}
|
||||||
|
}
|
||||||
idea/testData/refactoring/move/kotlin/moveNestedClass/deepNonInnerToTopLevel/after/test2/usages.java
Vendored
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package test2;
|
||||||
|
|
||||||
|
import test.C;
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
C foo() {
|
||||||
|
return new C();
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package test2;
|
||||||
|
|
||||||
|
import test.C;
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
C foo() {
|
||||||
|
return new C();
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package test2;
|
||||||
|
|
||||||
|
import test.C;
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
C foo() {
|
||||||
|
return new C();
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+8
@@ -0,0 +1,8 @@
|
|||||||
|
package test2
|
||||||
|
|
||||||
|
import test.A
|
||||||
|
import test.C
|
||||||
|
|
||||||
|
fun foo(): C {
|
||||||
|
return C()
|
||||||
|
}
|
||||||
Vendored
+7
@@ -0,0 +1,7 @@
|
|||||||
|
package test2
|
||||||
|
|
||||||
|
import test.C
|
||||||
|
|
||||||
|
fun foo(): C {
|
||||||
|
return C()
|
||||||
|
}
|
||||||
Vendored
+8
@@ -0,0 +1,8 @@
|
|||||||
|
package test2
|
||||||
|
|
||||||
|
import test.A.B
|
||||||
|
import test.C
|
||||||
|
|
||||||
|
fun foo(): C {
|
||||||
|
return C()
|
||||||
|
}
|
||||||
Vendored
+54
@@ -0,0 +1,54 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
inline fun <T, R> with(receiver: T, block: T.() -> R): R = receiver.block()
|
||||||
|
|
||||||
|
class A {
|
||||||
|
class X {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
class Y
|
||||||
|
|
||||||
|
fun foo(n: Int) {}
|
||||||
|
|
||||||
|
val bar = 1
|
||||||
|
|
||||||
|
fun Int.extFoo(n: Int) {}
|
||||||
|
|
||||||
|
val Int.extBar: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
object O {
|
||||||
|
class Y
|
||||||
|
|
||||||
|
fun foo(n: Int) {}
|
||||||
|
|
||||||
|
val bar = 1
|
||||||
|
|
||||||
|
fun Int.extFoo(n: Int) {}
|
||||||
|
|
||||||
|
val Int.extBar: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
class B {
|
||||||
|
class <caret>C {
|
||||||
|
fun test() {
|
||||||
|
X()
|
||||||
|
|
||||||
|
Y()
|
||||||
|
foo(bar)
|
||||||
|
//1.extFoo(1.extBar) // conflict
|
||||||
|
|
||||||
|
O.Y()
|
||||||
|
O.foo(O.bar)
|
||||||
|
|
||||||
|
with (O) {
|
||||||
|
Y()
|
||||||
|
foo(bar)
|
||||||
|
1.extFoo(1.extBar)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package test2;
|
||||||
|
|
||||||
|
import test.A;
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
A.B.C foo() {
|
||||||
|
return new A.B.C();
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package test2;
|
||||||
|
|
||||||
|
import test.A.B.C;
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
C foo() {
|
||||||
|
return new C();
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package test2;
|
||||||
|
|
||||||
|
import test.A.B;
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
B.C foo() {
|
||||||
|
return new B.C();
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+7
@@ -0,0 +1,7 @@
|
|||||||
|
package test2
|
||||||
|
|
||||||
|
import test.A
|
||||||
|
|
||||||
|
fun foo(): A.B.C {
|
||||||
|
return A.B.C()
|
||||||
|
}
|
||||||
Vendored
+7
@@ -0,0 +1,7 @@
|
|||||||
|
package test2
|
||||||
|
|
||||||
|
import test.A.B.C
|
||||||
|
|
||||||
|
fun foo(): C {
|
||||||
|
return C()
|
||||||
|
}
|
||||||
Vendored
+7
@@ -0,0 +1,7 @@
|
|||||||
|
package test2
|
||||||
|
|
||||||
|
import test.A.B
|
||||||
|
|
||||||
|
fun foo(): B.C {
|
||||||
|
return B.C()
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"mainFile": "test.kt",
|
||||||
|
"type": "MOVE_KOTLIN_NESTED_CLASS",
|
||||||
|
"withRuntime": "true"
|
||||||
|
}
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
class B {
|
||||||
|
fun test() {
|
||||||
|
A.X()
|
||||||
|
|
||||||
|
A.Companion.Y()
|
||||||
|
A.foo(A.bar)
|
||||||
|
//1.extFoo(1.extBar) // conflict
|
||||||
|
|
||||||
|
A.O.Y()
|
||||||
|
A.O.foo(A.O.bar)
|
||||||
|
|
||||||
|
with (A.O) {
|
||||||
|
A.Companion.Y()
|
||||||
|
foo(bar)
|
||||||
|
1.extFoo(1.extBar)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+34
@@ -0,0 +1,34 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
inline fun <T, R> with(receiver: T, block: T.() -> R): R = receiver.block()
|
||||||
|
|
||||||
|
class A {
|
||||||
|
class X {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
class Y
|
||||||
|
|
||||||
|
fun foo(n: Int) {}
|
||||||
|
|
||||||
|
val bar = 1
|
||||||
|
|
||||||
|
fun Int.extFoo(n: Int) {}
|
||||||
|
|
||||||
|
val Int.extBar: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
object O {
|
||||||
|
class Y
|
||||||
|
|
||||||
|
fun foo(n: Int) {}
|
||||||
|
|
||||||
|
val bar = 1
|
||||||
|
|
||||||
|
fun Int.extFoo(n: Int) {}
|
||||||
|
|
||||||
|
val Int.extBar: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Vendored
+10
@@ -0,0 +1,10 @@
|
|||||||
|
package test2;
|
||||||
|
|
||||||
|
import test.A;
|
||||||
|
import test.B;
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
B foo() {
|
||||||
|
return new A().new B();
|
||||||
|
}
|
||||||
|
}
|
||||||
idea/testData/refactoring/move/kotlin/moveNestedClass/innerToTopLevelNoThis/after/test2/usages2.java
Vendored
+10
@@ -0,0 +1,10 @@
|
|||||||
|
package test2;
|
||||||
|
|
||||||
|
import test.A;
|
||||||
|
import test.B;
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
B foo() {
|
||||||
|
return new A().new B();
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+8
@@ -0,0 +1,8 @@
|
|||||||
|
package test2
|
||||||
|
|
||||||
|
import test.A
|
||||||
|
import test.B
|
||||||
|
|
||||||
|
fun foo(): B {
|
||||||
|
return B()
|
||||||
|
}
|
||||||
Vendored
+8
@@ -0,0 +1,8 @@
|
|||||||
|
package test2
|
||||||
|
|
||||||
|
import test.A
|
||||||
|
import test.B
|
||||||
|
|
||||||
|
fun foo2(): B {
|
||||||
|
return B()
|
||||||
|
}
|
||||||
+52
@@ -0,0 +1,52 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
inline fun <T, R> with(receiver: T, block: T.() -> R): R = receiver.block()
|
||||||
|
|
||||||
|
class A {
|
||||||
|
class X {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
class Y
|
||||||
|
|
||||||
|
fun foo(n: Int) {}
|
||||||
|
|
||||||
|
val bar = 1
|
||||||
|
|
||||||
|
fun Int.extFoo(n: Int) {}
|
||||||
|
|
||||||
|
val Int.extBar: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
object O {
|
||||||
|
class Y
|
||||||
|
|
||||||
|
fun foo(n: Int) {}
|
||||||
|
|
||||||
|
val bar = 1
|
||||||
|
|
||||||
|
fun Int.extFoo(n: Int) {}
|
||||||
|
|
||||||
|
val Int.extBar: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class <caret>B {
|
||||||
|
fun test() {
|
||||||
|
X()
|
||||||
|
|
||||||
|
Y()
|
||||||
|
foo(bar)
|
||||||
|
//1.extFoo(1.extBar) // conflict
|
||||||
|
|
||||||
|
O.Y()
|
||||||
|
O.foo(O.bar)
|
||||||
|
|
||||||
|
with (O) {
|
||||||
|
Y()
|
||||||
|
foo(bar)
|
||||||
|
1.extFoo(1.extBar)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
idea/testData/refactoring/move/kotlin/moveNestedClass/innerToTopLevelNoThis/before/test2/usages.java
Vendored
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package test2;
|
||||||
|
|
||||||
|
import test.A;
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
A.B foo() {
|
||||||
|
return new A().new B();
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
package test2;
|
||||||
|
|
||||||
|
import test.A;
|
||||||
|
import test.A.B;
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
B foo() {
|
||||||
|
return new A().new B();
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+7
@@ -0,0 +1,7 @@
|
|||||||
|
package test2
|
||||||
|
|
||||||
|
import test.A
|
||||||
|
|
||||||
|
fun foo(): A.B {
|
||||||
|
return A().B()
|
||||||
|
}
|
||||||
Vendored
+8
@@ -0,0 +1,8 @@
|
|||||||
|
package test2
|
||||||
|
|
||||||
|
import test.A
|
||||||
|
import test.A.B
|
||||||
|
|
||||||
|
fun foo2(): B {
|
||||||
|
return A().B()
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"mainFile": "test.kt",
|
||||||
|
"type": "MOVE_KOTLIN_NESTED_CLASS",
|
||||||
|
"withRuntime": "true"
|
||||||
|
}
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
class B(private val a: A) {
|
||||||
|
fun test() {
|
||||||
|
A.X()
|
||||||
|
|
||||||
|
A.Companion.Y()
|
||||||
|
A.foo(A.bar)
|
||||||
|
//1.extFoo(1.extBar) // conflict
|
||||||
|
|
||||||
|
a.OuterY()
|
||||||
|
a.outerFoo(a.outerBar)
|
||||||
|
|
||||||
|
a.OuterY()
|
||||||
|
a.outerFoo(a.outerBar)
|
||||||
|
|
||||||
|
A.O.Y()
|
||||||
|
A.O.foo(A.O.bar)
|
||||||
|
|
||||||
|
with (A.O) {
|
||||||
|
A.Companion.Y()
|
||||||
|
foo(bar)
|
||||||
|
1.extFoo(1.extBar)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+40
@@ -0,0 +1,40 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
inline fun <T, R> with(receiver: T, block: T.() -> R): R = receiver.block()
|
||||||
|
|
||||||
|
class A {
|
||||||
|
class X {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class OuterY
|
||||||
|
|
||||||
|
fun outerFoo(n: Int) {}
|
||||||
|
|
||||||
|
val outerBar = 1
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
class Y
|
||||||
|
|
||||||
|
fun foo(n: Int) {}
|
||||||
|
|
||||||
|
val bar = 1
|
||||||
|
|
||||||
|
fun Int.extFoo(n: Int) {}
|
||||||
|
|
||||||
|
val Int.extBar: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
object O {
|
||||||
|
class Y
|
||||||
|
|
||||||
|
fun foo(n: Int) {}
|
||||||
|
|
||||||
|
val bar = 1
|
||||||
|
|
||||||
|
fun Int.extFoo(n: Int) {}
|
||||||
|
|
||||||
|
val Int.extBar: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
package test2;
|
||||||
|
|
||||||
|
import test.A;
|
||||||
|
import test.B;
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
B foo() {
|
||||||
|
return new B(new A());
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
package test2;
|
||||||
|
|
||||||
|
import test.A;
|
||||||
|
import test.B;
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
B foo() {
|
||||||
|
return new B(new A());
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+8
@@ -0,0 +1,8 @@
|
|||||||
|
package test2
|
||||||
|
|
||||||
|
import test.A
|
||||||
|
import test.B
|
||||||
|
|
||||||
|
fun foo(): B {
|
||||||
|
return B(A())
|
||||||
|
}
|
||||||
Vendored
+8
@@ -0,0 +1,8 @@
|
|||||||
|
package test2
|
||||||
|
|
||||||
|
import test.A
|
||||||
|
import test.B
|
||||||
|
|
||||||
|
fun foo2(): B {
|
||||||
|
return B(A())
|
||||||
|
}
|
||||||
Vendored
+64
@@ -0,0 +1,64 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
inline fun <T, R> with(receiver: T, block: T.() -> R): R = receiver.block()
|
||||||
|
|
||||||
|
class A {
|
||||||
|
class X {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class OuterY
|
||||||
|
|
||||||
|
fun outerFoo(n: Int) {}
|
||||||
|
|
||||||
|
val outerBar = 1
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
class Y
|
||||||
|
|
||||||
|
fun foo(n: Int) {}
|
||||||
|
|
||||||
|
val bar = 1
|
||||||
|
|
||||||
|
fun Int.extFoo(n: Int) {}
|
||||||
|
|
||||||
|
val Int.extBar: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
object O {
|
||||||
|
class Y
|
||||||
|
|
||||||
|
fun foo(n: Int) {}
|
||||||
|
|
||||||
|
val bar = 1
|
||||||
|
|
||||||
|
fun Int.extFoo(n: Int) {}
|
||||||
|
|
||||||
|
val Int.extBar: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class <caret>B {
|
||||||
|
fun test() {
|
||||||
|
X()
|
||||||
|
|
||||||
|
Y()
|
||||||
|
foo(bar)
|
||||||
|
//1.extFoo(1.extBar) // conflict
|
||||||
|
|
||||||
|
OuterY()
|
||||||
|
outerFoo(outerBar)
|
||||||
|
|
||||||
|
this@A.OuterY()
|
||||||
|
this@A.outerFoo(this@A.outerBar)
|
||||||
|
|
||||||
|
O.Y()
|
||||||
|
O.foo(O.bar)
|
||||||
|
|
||||||
|
with (O) {
|
||||||
|
Y()
|
||||||
|
foo(bar)
|
||||||
|
1.extFoo(1.extBar)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package test2;
|
||||||
|
|
||||||
|
import test.A;
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
A.B foo() {
|
||||||
|
return new A().new B();
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
package test2;
|
||||||
|
|
||||||
|
import test.A;
|
||||||
|
import test.A.B;
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
B foo() {
|
||||||
|
return new A().new B();
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+7
@@ -0,0 +1,7 @@
|
|||||||
|
package test2
|
||||||
|
|
||||||
|
import test.A
|
||||||
|
|
||||||
|
fun foo(): A.B {
|
||||||
|
return A().B()
|
||||||
|
}
|
||||||
Vendored
+8
@@ -0,0 +1,8 @@
|
|||||||
|
package test2
|
||||||
|
|
||||||
|
import test.A
|
||||||
|
import test.A.B
|
||||||
|
|
||||||
|
fun foo2(): B {
|
||||||
|
return A().B()
|
||||||
|
}
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"mainFile": "test.kt",
|
||||||
|
"type": "MOVE_KOTLIN_NESTED_CLASS",
|
||||||
|
"outerInstanceParameter": "a",
|
||||||
|
"withRuntime": "true"
|
||||||
|
}
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
inline fun <T, R> with(receiver: T, block: T.() -> R): R = receiver.block()
|
||||||
|
|
||||||
|
class A() {
|
||||||
|
fun X.bar() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class X {
|
||||||
|
fun Int.foo() {}
|
||||||
|
|
||||||
|
inner class Y {
|
||||||
|
fun test() {
|
||||||
|
1.foo()
|
||||||
|
with(1) { foo() }
|
||||||
|
with(A()) { bar() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
inline fun <T, R> with(receiver: T, block: T.() -> R): R = receiver.block()
|
||||||
|
|
||||||
|
class A() {
|
||||||
|
fun X.bar() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class X {
|
||||||
|
fun Int.foo() {}
|
||||||
|
|
||||||
|
inner class <caret>Y {
|
||||||
|
fun test() {
|
||||||
|
1.foo()
|
||||||
|
with(1) { foo() }
|
||||||
|
with(A()) { bar() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
Call with two implicit receivers won't be processed: bar()
|
||||||
|
Call with two implicit receivers won't be processed: foo()
|
||||||
|
Qualified call won't be processed: 1.foo()
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"mainFile": "test.kt",
|
||||||
|
"type": "MOVE_KOTLIN_NESTED_CLASS",
|
||||||
|
"outerInstanceParameter": "a",
|
||||||
|
"withRuntime": "true"
|
||||||
|
}
|
||||||
+55
@@ -0,0 +1,55 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
inline fun <T, R> with(receiver: T, block: T.() -> R): R = receiver.block()
|
||||||
|
|
||||||
|
class A {
|
||||||
|
class B {
|
||||||
|
class X {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
class Y
|
||||||
|
|
||||||
|
fun foo(n: Int) {}
|
||||||
|
|
||||||
|
val bar = 1
|
||||||
|
|
||||||
|
fun Int.extFoo(n: Int) {}
|
||||||
|
|
||||||
|
val Int.extBar: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
object O {
|
||||||
|
class Y
|
||||||
|
|
||||||
|
fun foo(n: Int) {}
|
||||||
|
|
||||||
|
val bar = 1
|
||||||
|
|
||||||
|
fun Int.extFoo(n: Int) {}
|
||||||
|
|
||||||
|
val Int.extBar: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class C {
|
||||||
|
fun test() {
|
||||||
|
B.X()
|
||||||
|
|
||||||
|
B.Companion.Y()
|
||||||
|
B.foo(B.bar)
|
||||||
|
//1.extFoo(1.extBar) // conflict
|
||||||
|
|
||||||
|
B.O.Y()
|
||||||
|
B.O.foo(B.O.bar)
|
||||||
|
|
||||||
|
with (B.O) {
|
||||||
|
B.Companion.Y()
|
||||||
|
foo(bar)
|
||||||
|
1.extFoo(1.extBar)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package test2;
|
||||||
|
|
||||||
|
import test.A;
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
A.C foo() {
|
||||||
|
return new A.C();
|
||||||
|
}
|
||||||
|
}
|
||||||
idea/testData/refactoring/move/kotlin/moveNestedClass/nonInnerToOuterClass1/after/test2/usages2.java
Vendored
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package test2;
|
||||||
|
|
||||||
|
import test.A.C;
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
C foo() {
|
||||||
|
return new C();
|
||||||
|
}
|
||||||
|
}
|
||||||
idea/testData/refactoring/move/kotlin/moveNestedClass/nonInnerToOuterClass1/after/test2/usages3.java
Vendored
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package test2;
|
||||||
|
|
||||||
|
import test.A;
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
A.C foo() {
|
||||||
|
return new A.C();
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+7
@@ -0,0 +1,7 @@
|
|||||||
|
package test2
|
||||||
|
|
||||||
|
import test.A
|
||||||
|
|
||||||
|
fun foo(): A.C {
|
||||||
|
return A.C()
|
||||||
|
}
|
||||||
Vendored
+7
@@ -0,0 +1,7 @@
|
|||||||
|
package test2
|
||||||
|
|
||||||
|
import test.A.C
|
||||||
|
|
||||||
|
fun foo(): C {
|
||||||
|
return C()
|
||||||
|
}
|
||||||
Vendored
+8
@@ -0,0 +1,8 @@
|
|||||||
|
package test2
|
||||||
|
|
||||||
|
import test.A
|
||||||
|
import test.A.B
|
||||||
|
|
||||||
|
fun foo(): A.C {
|
||||||
|
return A.C()
|
||||||
|
}
|
||||||
+54
@@ -0,0 +1,54 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
inline fun <T, R> with(receiver: T, block: T.() -> R): R = receiver.block()
|
||||||
|
|
||||||
|
class A {
|
||||||
|
class B {
|
||||||
|
class X {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
class Y
|
||||||
|
|
||||||
|
fun foo(n: Int) {}
|
||||||
|
|
||||||
|
val bar = 1
|
||||||
|
|
||||||
|
fun Int.extFoo(n: Int) {}
|
||||||
|
|
||||||
|
val Int.extBar: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
object O {
|
||||||
|
class Y
|
||||||
|
|
||||||
|
fun foo(n: Int) {}
|
||||||
|
|
||||||
|
val bar = 1
|
||||||
|
|
||||||
|
fun Int.extFoo(n: Int) {}
|
||||||
|
|
||||||
|
val Int.extBar: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
class <caret>C {
|
||||||
|
fun test() {
|
||||||
|
X()
|
||||||
|
|
||||||
|
Y()
|
||||||
|
foo(bar)
|
||||||
|
//1.extFoo(1.extBar) // conflict
|
||||||
|
|
||||||
|
O.Y()
|
||||||
|
O.foo(O.bar)
|
||||||
|
|
||||||
|
with (O) {
|
||||||
|
Y()
|
||||||
|
foo(bar)
|
||||||
|
1.extFoo(1.extBar)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
idea/testData/refactoring/move/kotlin/moveNestedClass/nonInnerToOuterClass1/before/test2/usages.java
Vendored
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package test2;
|
||||||
|
|
||||||
|
import test.A;
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
A.B.C foo() {
|
||||||
|
return new A.B.C();
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package test2;
|
||||||
|
|
||||||
|
import test.A.B.C;
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
C foo() {
|
||||||
|
return new C();
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package test2;
|
||||||
|
|
||||||
|
import test.A.B;
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
B.C foo() {
|
||||||
|
return new B.C();
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+7
@@ -0,0 +1,7 @@
|
|||||||
|
package test2
|
||||||
|
|
||||||
|
import test.A
|
||||||
|
|
||||||
|
fun foo(): A.B.C {
|
||||||
|
return A.B.C()
|
||||||
|
}
|
||||||
Vendored
+7
@@ -0,0 +1,7 @@
|
|||||||
|
package test2
|
||||||
|
|
||||||
|
import test.A.B.C
|
||||||
|
|
||||||
|
fun foo(): C {
|
||||||
|
return C()
|
||||||
|
}
|
||||||
Vendored
+7
@@ -0,0 +1,7 @@
|
|||||||
|
package test2
|
||||||
|
|
||||||
|
import test.A.B
|
||||||
|
|
||||||
|
fun foo(): B.C {
|
||||||
|
return B.C()
|
||||||
|
}
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"mainFile": "test.kt",
|
||||||
|
"type": "MOVE_KOTLIN_NESTED_CLASS",
|
||||||
|
"targetClass": "test.A",
|
||||||
|
"withRuntime": "true"
|
||||||
|
}
|
||||||
+55
@@ -0,0 +1,55 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
inline fun <T, R> with(receiver: T, block: T.() -> R): R = receiver.block()
|
||||||
|
|
||||||
|
class A {
|
||||||
|
class X {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
class Y
|
||||||
|
|
||||||
|
fun foo(n: Int) {}
|
||||||
|
|
||||||
|
val bar = 1
|
||||||
|
|
||||||
|
fun Int.extFoo(n: Int) {}
|
||||||
|
|
||||||
|
val Int.extBar: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
object O {
|
||||||
|
class Y
|
||||||
|
|
||||||
|
fun foo(n: Int) {}
|
||||||
|
|
||||||
|
val bar = 1
|
||||||
|
|
||||||
|
fun Int.extFoo(n: Int) {}
|
||||||
|
|
||||||
|
val Int.extBar: Int get() = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
class B {
|
||||||
|
}
|
||||||
|
|
||||||
|
class C {
|
||||||
|
fun test() {
|
||||||
|
X()
|
||||||
|
|
||||||
|
Y()
|
||||||
|
foo(bar)
|
||||||
|
//1.extFoo(1.extBar) // conflict
|
||||||
|
|
||||||
|
O.Y()
|
||||||
|
O.foo(O.bar)
|
||||||
|
|
||||||
|
with (O) {
|
||||||
|
Y()
|
||||||
|
foo(bar)
|
||||||
|
1.extFoo(1.extBar)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package test2;
|
||||||
|
|
||||||
|
import test.A;
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
A.C foo() {
|
||||||
|
return new A.C();
|
||||||
|
}
|
||||||
|
}
|
||||||
idea/testData/refactoring/move/kotlin/moveNestedClass/nonInnerToOuterClass2/after/test2/usages2.java
Vendored
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package test2;
|
||||||
|
|
||||||
|
import test.A.C;
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
C foo() {
|
||||||
|
return new C();
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user