Move: Make minor improvements and refactorings

This commit is contained in:
Alexey Sedunov
2017-04-05 15:24:11 +03:00
parent 97789d4a32
commit 5c35061afa
16 changed files with 314 additions and 286 deletions
@@ -401,3 +401,8 @@ fun DeclarationDescriptor.isPublishedApi(): Boolean {
val descriptor = if (this is CallableMemberDescriptor) DescriptorUtils.getDirectMember(this) else this
return descriptor.annotations.hasAnnotation(KotlinBuiltIns.FQ_NAMES.publishedApi)
}
fun DeclarationDescriptor.isAncestorOf(descriptor: DeclarationDescriptor, strict: Boolean): Boolean
= DescriptorUtils.isAncestor(this, descriptor, strict)
fun DeclarationDescriptor.isCompanionObject(): Boolean = DescriptorUtils.isCompanionObject(this)
@@ -58,10 +58,11 @@ class MoveMemberOutOfCompanionObjectIntention : SelfTargetingRangeIntention<KtNa
}
if (element is KtClassOrObject) {
val moveDescriptor = MoveDeclarationsDescriptor(listOf(element),
val moveDescriptor = MoveDeclarationsDescriptor(project,
listOf(element),
KotlinMoveTargetForExistingElement(targetClass),
MoveDeclarationsDelegate.NestedClass())
MoveKotlinDeclarationsProcessor(project, moveDescriptor).run()
MoveKotlinDeclarationsProcessor(moveDescriptor).run()
deleteCompanionIfEmpty()
return
}
@@ -46,7 +46,6 @@ import org.jetbrains.kotlin.idea.refactoring.checkConflictsInteractively
import org.jetbrains.kotlin.idea.refactoring.move.OuterInstanceReferenceUsageInfo
import org.jetbrains.kotlin.idea.refactoring.move.collectOuterInstanceReferences
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.*
import org.jetbrains.kotlin.idea.refactoring.move.reportConflictIfAny
import org.jetbrains.kotlin.idea.refactoring.move.traverseOuterInstanceReferences
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
import org.jetbrains.kotlin.idea.runSynchronouslyWithProgress
@@ -262,11 +261,12 @@ class MoveMemberToCompanionObjectIntention : SelfTargetingRangeIntention<KtNamed
return Mover.Default(originalElement, targetContainer).apply { movedClass = this as KtClassOrObject }
}
}
val moveDescriptor = MoveDeclarationsDescriptor(listOf(element),
val moveDescriptor = MoveDeclarationsDescriptor(project,
listOf(element),
KotlinMoveTargetForCompanion(containingClass),
MoveDeclarationsDelegate.NestedClass(null, outerInstanceName),
moveCallback = MoveCallback { runTemplateForInstanceParam(movedClass!!, nameSuggestions, editor) })
MoveKotlinDeclarationsProcessor(project, moveDescriptor, mover).run()
MoveKotlinDeclarationsProcessor(moveDescriptor, mover).run()
return
}
@@ -29,7 +29,7 @@ import com.intellij.refactoring.util.RefactoringMessageDialog
import com.intellij.usageView.UsageInfo
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.processInternalReferencesToUpdateOnPackageNameChange
import org.jetbrains.kotlin.idea.refactoring.move.postProcessMoveUsages
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.*
@@ -82,7 +82,7 @@ internal fun preProcessInternalUsages(element: KtElement, usages: List<KtElement
for (targetPackage in targetPackages) {
if (targetPackage == mainFile.packageFqName) continue
val packageNameInfo = ContainerChangeInfo(ContainerInfo.Package(mainFile.packageFqName), ContainerInfo.Package(targetPackage))
element.lazilyProcessInternalReferencesToUpdateOnPackageNameChange(packageNameInfo) { expr, factory ->
element.processInternalReferencesToUpdateOnPackageNameChange(packageNameInfo) { expr, factory ->
val infos =
expr.internalUsageInfos
?: LinkedHashMap<FqName, (KtSimpleNameExpression) -> UsageInfo?>().apply { expr.internalUsageInfos = this }
@@ -40,8 +40,8 @@ class KotlinChangePackageRefactoring(val file: KtFile) {
val currentFqName = packageDirective.fqName
val declarationProcessor = MoveKotlinDeclarationsProcessor(
project,
MoveDeclarationsDescriptor(
project = project,
elementsToMove = file.declarations.filterIsInstance<KtNamedDeclaration>(),
moveTarget = object: KotlinDirectoryBasedMoveTarget {
override val targetContainerFqName = newFqName
@@ -93,7 +93,8 @@ class MoveDeclarationToSeparateFileIntention :
val moveTarget = KotlinMoveTargetForDeferredFile(packageName, directory, null) {
createKotlinFile(targetFileName, directory, packageName.asString())
}
val moveOptions = MoveDeclarationsDescriptor(
val descriptor = MoveDeclarationsDescriptor(
project = project,
elementsToMove = listOf(element),
moveTarget = moveTarget,
delegate = MoveDeclarationsDelegate.TopLevel,
@@ -107,7 +108,7 @@ class MoveDeclarationToSeparateFileIntention :
}
)
val move = { MoveKotlinDeclarationsProcessor(project, moveOptions).run() }
val move = { MoveKotlinDeclarationsProcessor(descriptor).run() }
val optimizeImports = { OptimizeImportsProcessor(project, file).run() }
move.runRefactoringWithPostprocessing(project, MoveKotlinDeclarationsProcessor.REFACTORING_ID, optimizeImports)
@@ -16,7 +16,6 @@
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
@@ -35,37 +34,30 @@ import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
sealed class MoveDeclarationsDelegate {
abstract fun getContainerChangeInfo(originalDeclaration: KtNamedDeclaration, moveTarget: KotlinMoveTarget): ContainerChangeInfo
abstract fun findInternalUsages(descriptor: MoveDeclarationsDescriptor): List<UsageInfo>
abstract fun collectConflicts(
open fun findInternalUsages(descriptor: MoveDeclarationsDescriptor): List<UsageInfo> = emptyList()
open fun collectConflicts(
descriptor: MoveDeclarationsDescriptor,
internalUsages: MutableSet<UsageInfo>,
conflicts: MultiMap<PsiElement, String>
)
abstract fun preprocessDeclaration(descriptor: MoveDeclarationsDescriptor, originalDeclaration: KtNamedDeclaration)
abstract fun preprocessUsages(project: Project, descriptor: MoveDeclarationsDescriptor, usages: List<UsageInfo>)
) {
}
open fun preprocessDeclaration(descriptor: MoveDeclarationsDescriptor, originalDeclaration: KtNamedDeclaration) {
}
open fun preprocessUsages(descriptor: MoveDeclarationsDescriptor, usages: List<UsageInfo>) {
}
object TopLevel : MoveDeclarationsDelegate() {
override fun getContainerChangeInfo(originalDeclaration: KtNamedDeclaration, moveTarget: KotlinMoveTarget): ContainerChangeInfo {
return ContainerChangeInfo(ContainerInfo.Package(originalDeclaration.containingKtFile.packageFqName),
ContainerInfo.Package(moveTarget.targetContainerFqName!!))
}
override fun findInternalUsages(descriptor: MoveDeclarationsDescriptor): List<UsageInfo> = emptyList()
override fun collectConflicts(
descriptor: MoveDeclarationsDescriptor,
internalUsages: MutableSet<UsageInfo>,
conflicts: MultiMap<PsiElement, String>
) {
}
override fun preprocessDeclaration(descriptor: MoveDeclarationsDescriptor, originalDeclaration: KtNamedDeclaration) {
}
override fun preprocessUsages(project: Project, descriptor: MoveDeclarationsDescriptor, usages: List<UsageInfo>) {
val sourcePackage = ContainerInfo.Package(originalDeclaration.containingKtFile.packageFqName)
val targetPackage = moveTarget.targetContainerFqName?.let { ContainerInfo.Package(it) } ?: ContainerInfo.UnknownPackage
return ContainerChangeInfo(sourcePackage, targetPackage)
}
}
@@ -76,10 +68,11 @@ sealed class MoveDeclarationsDelegate {
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!!)
val targetContainerFqName = moveTarget.targetContainerFqName
val newInfo = when {
targetContainerFqName == null -> ContainerInfo.UnknownPackage
movingToClass -> ContainerInfo.Class(targetContainerFqName)
else -> ContainerInfo.Package(targetContainerFqName)
}
return ContainerChangeInfo(originalInfo, newInfo)
}
@@ -137,9 +130,9 @@ sealed class MoveDeclarationsDelegate {
}
}
override fun preprocessUsages(project: Project, descriptor: MoveDeclarationsDescriptor, usages: List<UsageInfo>) {
override fun preprocessUsages(descriptor: MoveDeclarationsDescriptor, usages: List<UsageInfo>) {
if (outerInstanceParameterName == null) return
val psiFactory = KtPsiFactory(project)
val psiFactory = KtPsiFactory(descriptor.project)
val newOuterInstanceRef = psiFactory.createExpression(outerInstanceParameterName)
val classToMove = descriptor.elementsToMove.singleOrNull() as? KtClass
@@ -86,6 +86,7 @@ interface Mover : (KtNamedDeclaration, KtElement) -> KtNamedDeclaration {
internal var KtSimpleNameExpression.internalUsageInfo: UsageInfo? by CopyableUserDataProperty(Key.create("INTERNAL_USAGE_INFO"))
class MoveDeclarationsDescriptor(
val project: Project,
val elementsToMove: Collection<KtNamedDeclaration>,
val moveTarget: KotlinMoveTarget,
val delegate: MoveDeclarationsDelegate,
@@ -99,15 +100,35 @@ class MoveDeclarationsDescriptor(
class ConflictUsageInfo(element: PsiElement, val messages: Collection<String>) : UsageInfo(element)
private object ElementHashingStrategy : TObjectHashingStrategy<PsiElement> {
override fun equals(e1: PsiElement?, e2: PsiElement?): Boolean {
if (e1 === e2) return true
// Name should be enough to distinguish different light elements based on the same original declaration
if (e1 is KtLightElement<*, *> && e2 is KtLightElement<*, *>) {
return e1.kotlinOrigin == e2.kotlinOrigin && e1.name == e2.name
}
return e1 == e2
}
override fun computeHashCode(e: PsiElement?): Int {
return when (e) {
null -> 0
is KtLightElement<*, *> -> (e.kotlinOrigin?.hashCode() ?: 0) * 31 + (e.name?.hashCode() ?: 0)
else -> e.hashCode()
}
}
}
class MoveKotlinDeclarationsProcessor(
val project: Project,
val descriptor: MoveDeclarationsDescriptor,
val mover: Mover = Mover.Default) : BaseRefactoringProcessor(project) {
val mover: Mover = Mover.Default) : BaseRefactoringProcessor(descriptor.project) {
companion object {
private val REFACTORING_NAME = "Move declarations"
val REFACTORING_ID = "move.kotlin.declarations"
}
val project get() = descriptor.project
private var nonCodeUsages: Array<NonCodeUsageInfo>? = null
private val elementsToMove = descriptor.elementsToMove.filter { e -> e.parent != descriptor.moveTarget.getTargetPsiIfExists(e) }
private val kotlinToLightElementsBySourceFile = elementsToMove
@@ -132,16 +153,16 @@ class MoveKotlinDeclarationsProcessor(
val newContainerName = descriptor.moveTarget.targetContainerFqName?.asString() ?: ""
fun collectUsages(kotlinToLightElements: Map<KtNamedDeclaration, List<PsiNamedElement>>, result: MutableCollection<UsageInfo>) {
kotlinToLightElements.values.flatMap { it }.flatMapTo(result) { lightElement ->
kotlinToLightElements.values.flatten().flatMapTo(result) { lightElement ->
val newFqName = StringUtil.getQualifiedName(newContainerName, lightElement.name)
val foundReferences = HashSet<PsiReference>()
val projectScope = lightElement.project.projectScope()
val projectScope = project.projectScope()
val results = ReferencesSearch
.search(lightElement, projectScope, false)
.search(lightElement, projectScope)
.mapNotNullTo(ArrayList()) { ref ->
if (foundReferences.add(ref) && elementsToMove.all { !it.isAncestor(ref.element)}) {
createMoveUsageInfoIfPossible(ref, lightElement, true, null)
if (foundReferences.add(ref) && elementsToMove.none { it.isAncestor(ref.element)}) {
createMoveUsageInfoIfPossible(ref, lightElement, true, false)
}
else null
}
@@ -166,7 +187,6 @@ class MoveKotlinDeclarationsProcessor(
}
}
val usagesToProcessBeforeMove = LinkedHashSet<UsageInfo>()
val usages = ArrayList<UsageInfo>()
val conflictChecker = MoveConflictChecker(project, elementsToMove, descriptor.moveTarget, elementsToMove.first())
for ((sourceFile, kotlinToLightElements) in kotlinToLightElementsBySourceFile) {
@@ -196,8 +216,6 @@ class MoveKotlinDeclarationsProcessor(
usages += externalUsages
}
descriptor.delegate.collectConflicts(descriptor, usagesToProcessBeforeMove, conflicts)
return UsageViewUtil.removeDuplicatedUsages(usages.toTypedArray())
}
@@ -216,7 +234,7 @@ class MoveKotlinDeclarationsProcessor(
}
val usageList = usages.toList()
val (oldInternalUsages, externalUsages) = usageList.partition { (it as? InternableUsage)?.scope != null }
val (oldInternalUsages, externalUsages) = usageList.partition { it is KotlinMoveUsage && it.isInternal }
val newInternalUsages = ArrayList<UsageInfo>()
oldInternalUsages.forEach { (it.element as? KtSimpleNameExpression)?.internalUsageInfo = it }
@@ -224,28 +242,9 @@ class MoveKotlinDeclarationsProcessor(
val usagesToProcess = ArrayList(externalUsages)
try {
descriptor.delegate.preprocessUsages(project, descriptor, usageList)
descriptor.delegate.preprocessUsages(descriptor, usageList)
val oldToNewElementsMapping = THashMap<PsiElement, PsiElement>(
object: TObjectHashingStrategy<PsiElement> {
override fun equals(e1: PsiElement?, e2: PsiElement?): Boolean {
if (e1 === e2) return true
// Name should be enough to distinguish different light elements based on the same original declaration
if (e1 is KtLightElement<*, *> && e2 is KtLightElement<*, *>) {
return e1.kotlinOrigin == e2.kotlinOrigin && e1.name == e2.name
}
return e1 == e2
}
override fun computeHashCode(e: PsiElement?): Int {
return when (e) {
null -> 0
is KtLightElement<*, *> -> (e.kotlinOrigin?.hashCode() ?: 0) * 31 + (e.name?.hashCode() ?: 0)
else -> e.hashCode()
}
}
}
)
val oldToNewElementsMapping = THashMap<PsiElement, PsiElement>(ElementHashingStrategy)
val newDeclarations = ArrayList<KtNamedDeclaration>()
@@ -279,9 +278,9 @@ class MoveKotlinDeclarationsProcessor(
val usageInfo = it.internalUsageInfo
if (usageInfo?.element != null) return@mapNotNull usageInfo
val referencedElement = (usageInfo as? MoveRenameUsageInfo)?.referencedElement ?: return@mapNotNull null
val newReferencedElement = oldToNewElementsMapping[referencedElement] ?: referencedElement
val newReferencedElement = mapToNewOrThis(referencedElement, oldToNewElementsMapping)
if (!newReferencedElement.isValid) return@mapNotNull null
(usageInfo as? InternableUsage)?.refresh(it, newReferencedElement)
(usageInfo as? KotlinMoveUsage)?.refresh(it, newReferencedElement)
}
}
@@ -295,10 +294,7 @@ class MoveKotlinDeclarationsProcessor(
}
finally {
(newInternalUsages + oldInternalUsages).forEach {
val element = it.element as? KtSimpleNameExpression ?: return@forEach
if (element.isValid) {
element.internalUsageInfo = null
}
(it.element as? KtSimpleNameExpression)?.internalUsageInfo = null
}
}
}
@@ -253,9 +253,9 @@ public class MoveKotlinNestedClassesDialog extends RefactoringDialog {
KotlinMoveTarget target = new KotlinMoveTargetForExistingElement(targetClass);
MoveDeclarationsDelegate.NestedClass delegate = new MoveDeclarationsDelegate.NestedClass();
MoveDeclarationsDescriptor descriptor = new MoveDeclarationsDescriptor(
elementsToMove, target, delegate, false, false, false, false, moveCallback, openInEditorCheckBox.isSelected()
myProject, elementsToMove, target, delegate, false, false, false, false, moveCallback, openInEditorCheckBox.isSelected()
);
invokeRefactoring(new MoveKotlinDeclarationsProcessor(myProject, descriptor, Mover.Default.INSTANCE));
invokeRefactoring(new MoveKotlinDeclarationsProcessor(descriptor, Mover.Default.INSTANCE));
}
@Override
@@ -406,6 +406,7 @@ public class MoveKotlinNestedClassesToUpperLevelDialog extends MoveDialogBase {
String newClassName = getClassName();
MoveDeclarationsDelegate delegate = new MoveDeclarationsDelegate.NestedClass(newClassName, outerInstanceParameterName);
MoveDeclarationsDescriptor moveDescriptor = new MoveDeclarationsDescriptor(
project,
CollectionsKt.listOf(innerClass),
moveTarget,
delegate,
@@ -418,6 +419,6 @@ public class MoveKotlinNestedClassesToUpperLevelDialog extends MoveDialogBase {
);
saveOpenInEditorOption();
invokeRefactoring(new MoveKotlinDeclarationsProcessor(project, moveDescriptor, Mover.Default.INSTANCE));
invokeRefactoring(new MoveKotlinDeclarationsProcessor(moveDescriptor, Mover.Default.INSTANCE));
}
}
@@ -24,7 +24,6 @@ import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.JavaProjectRootsUtil;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.util.Pair;
@@ -764,6 +763,7 @@ public class MoveKotlinTopLevelDeclarationsDialog extends RefactoringDialog {
}
MoveDeclarationsDescriptor options = new MoveDeclarationsDescriptor(
myProject,
elementsToMove,
target,
MoveDeclarationsDelegate.TopLevel.INSTANCE,
@@ -774,7 +774,7 @@ public class MoveKotlinTopLevelDeclarationsDialog extends RefactoringDialog {
moveCallback,
false
);
invokeRefactoring(new MoveKotlinDeclarationsProcessor(myProject, options, Mover.Default.INSTANCE));
invokeRefactoring(new MoveKotlinDeclarationsProcessor(options, Mover.Default.INSTANCE));
}
catch (IncorrectOperationException e) {
CommonRefactoringUtil.showErrorMessage(RefactoringBundle.message("error.title"), e.getMessage(), null, myProject);
@@ -18,7 +18,10 @@ package org.jetbrains.kotlin.idea.refactoring.move.moveFilesOrDirectories
import com.intellij.openapi.module.ModuleUtilCore
import com.intellij.openapi.roots.JavaProjectRootsUtil
import com.intellij.psi.*
import com.intellij.psi.PsiCompiledElement
import com.intellij.psi.PsiDirectory
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.psi.impl.light.LightElement
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFileHandler
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesUtil
@@ -35,7 +38,6 @@ import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtNamedDeclaration
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import java.util.*
class MoveKotlinFileHandler : MoveFileHandler() {
internal class InternalUsagesWrapper(file: KtFile, val usages: List<UsageInfo>) : UsageInfo(file)
@@ -88,8 +90,8 @@ class MoveKotlinFileHandler : MoveFileHandler() {
}
val declarationMoveProcessor = MoveKotlinDeclarationsProcessor(
project,
MoveDeclarationsDescriptor(
project = project,
elementsToMove = psiFile.declarations.filterIsInstance<KtNamedDeclaration>(),
moveTarget = moveTarget,
delegate = MoveDeclarationsDelegate.TopLevel,
@@ -0,0 +1,148 @@
/*
* Copyright 2010-2017 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
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.DialogWrapper
import com.intellij.psi.PsiDirectory
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.refactoring.RefactoringBundle
import com.intellij.refactoring.copy.CopyFilesOrDirectoriesHandler
import com.intellij.refactoring.move.MoveCallback
import com.intellij.refactoring.move.MoveHandler
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesProcessor
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesUtil
import com.intellij.refactoring.util.CommonRefactoringUtil
import com.intellij.util.IncorrectOperationException
import org.jetbrains.kotlin.idea.refactoring.isInJavaSourceRoot
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.MoveFilesWithDeclarationsProcessor
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.ui.KotlinAwareMoveFilesOrDirectoriesDialog
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
import org.jetbrains.kotlin.idea.util.application.executeCommand
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile
fun invokeMoveFilesOrDirectoriesRefactoring(
moveDialog: KotlinAwareMoveFilesOrDirectoriesDialog?,
project: Project,
elements: Array<out PsiElement>,
initialTargetDirectory: PsiDirectory?,
moveCallback: MoveCallback?
) {
fun closeDialog() {
moveDialog?.close(DialogWrapper.CANCEL_EXIT_CODE)
}
project.executeCommand(MoveHandler.REFACTORING_NAME) {
val selectedDir = if (moveDialog != null) moveDialog.targetDirectory else initialTargetDirectory
val updatePackageDirective = (moveDialog as? KotlinAwareMoveFilesOrDirectoriesDialog)?.updatePackageDirective
try {
val choice = if (elements.size > 1 || elements[0] is PsiDirectory) intArrayOf(-1) else null
val elementsToMove = elements
.filterNot {
it is PsiFile
&& runWriteAction { CopyFilesOrDirectoriesHandler.checkFileExist(selectedDir, choice, it, it.name, "Move") }
}
.sortedWith( // process Kotlin files first so that light classes are updated before changing references in Java files
java.util.Comparator { o1, o2 ->
when {
o1 is KtElement && o2 !is KtElement -> -1
o1 !is KtElement && o2 is KtElement -> 1
else -> 0
}
}
)
elementsToMove.forEach {
MoveFilesOrDirectoriesUtil.checkMove(it, selectedDir!!)
if (it is KtFile && it.isInJavaSourceRoot()) {
it.updatePackageDirective = updatePackageDirective
}
}
val enableSearchReferences = elements.any { ProjectRootsUtil.isInProjectSource(it) }
if (elementsToMove.isNotEmpty()) {
@Suppress("UNCHECKED_CAST")
val processor = if (elementsToMove.all { it is KtFile } && selectedDir != null) {
MoveFilesWithDeclarationsProcessor(
project,
elementsToMove as List<KtFile>,
selectedDir,
null,
false,
false,
moveCallback,
Runnable(::closeDialog)
)
}
else {
MoveFilesOrDirectoriesProcessor(
project,
elementsToMove.toTypedArray(),
selectedDir,
enableSearchReferences,
false,
false,
moveCallback,
Runnable(::closeDialog)
)
}
processor.run()
}
else {
closeDialog()
}
}
catch (e: IncorrectOperationException) {
CommonRefactoringUtil.showErrorMessage(RefactoringBundle.message("error.title"), e.message, "refactoring.moveFile", project)
}
}
}
// Mostly copied from MoveFilesOrDirectoriesUtil.doMove()
fun moveFilesOrDirectories(
project: Project,
elements: Array<PsiElement>,
targetElement: PsiElement?,
moveCallback: MoveCallback? = null
) {
elements.forEach { if (it !is PsiFile && it !is PsiDirectory) throw IllegalArgumentException("unexpected element type: " + it) }
val targetDirectory = MoveFilesOrDirectoriesUtil.resolveToDirectory(project, targetElement)
if (targetElement != null && targetDirectory == null) return
val initialTargetDirectory = MoveFilesOrDirectoriesUtil.getInitialTargetDirectory(targetDirectory, elements)
fun doRun(moveDialog: KotlinAwareMoveFilesOrDirectoriesDialog?) {
invokeMoveFilesOrDirectoriesRefactoring(moveDialog, project, elements, initialTargetDirectory, moveCallback)
}
if (ApplicationManager.getApplication().isUnitTestMode) {
doRun(null)
return
}
with(KotlinAwareMoveFilesOrDirectoriesDialog(project, ::doRun)) {
setData(elements, initialTargetDirectory, "refactoring.moveFile")
show()
}
}
@@ -16,24 +16,13 @@
package org.jetbrains.kotlin.idea.refactoring.move
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.DialogWrapper
import com.intellij.openapi.util.Comparing
import com.intellij.openapi.util.Key
import com.intellij.psi.*
import com.intellij.psi.impl.source.resolve.reference.impl.PsiMultiReference
import com.intellij.refactoring.RefactoringBundle
import com.intellij.refactoring.copy.CopyFilesOrDirectoriesHandler
import com.intellij.refactoring.move.MoveCallback
import com.intellij.refactoring.move.MoveHandler
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesProcessor
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesUtil
import com.intellij.refactoring.move.moveMembers.MockMoveMembersOptions
import com.intellij.refactoring.move.moveMembers.MoveMemberHandler
import com.intellij.refactoring.move.moveMembers.MoveMembersProcessor
import com.intellij.refactoring.util.CommonRefactoringUtil
import com.intellij.refactoring.util.MoveRenameUsageInfo
import com.intellij.refactoring.util.NonCodeUsageInfo
import com.intellij.usageView.UsageInfo
@@ -46,19 +35,12 @@ 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.codeInsight.DescriptorToSourceUtilsIde
import org.jetbrains.kotlin.idea.codeInsight.KotlinFileReferencesResolver
import org.jetbrains.kotlin.idea.codeInsight.shorten.addDelayedImportRequest
import org.jetbrains.kotlin.idea.imports.importableFqName
import org.jetbrains.kotlin.idea.refactoring.fqName.isImported
import org.jetbrains.kotlin.idea.refactoring.isInJavaSourceRoot
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.MoveFilesWithDeclarationsProcessor
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.ui.KotlinAwareMoveFilesOrDirectoriesDialog
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference.ShorteningMode
import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
import org.jetbrains.kotlin.idea.util.application.executeCommand
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.*
@@ -66,6 +48,8 @@ import org.jetbrains.kotlin.resolve.BindingContext
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.isAncestorOf
import org.jetbrains.kotlin.resolve.descriptorUtil.isCompanionObject
import org.jetbrains.kotlin.resolve.descriptorUtil.parents
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver
@@ -98,13 +82,15 @@ data class ContainerChangeInfo(val oldContainer: ContainerInfo, val newContainer
fun KtElement.getInternalReferencesToUpdateOnPackageNameChange(containerChangeInfo: ContainerChangeInfo): List<UsageInfo> {
val usages = ArrayList<UsageInfo>()
lazilyProcessInternalReferencesToUpdateOnPackageNameChange(containerChangeInfo) { expr, factory -> usages.addIfNotNull(factory(expr)) }
processInternalReferencesToUpdateOnPackageNameChange(containerChangeInfo) { expr, factory -> usages.addIfNotNull(factory(expr)) }
return usages
}
fun KtElement.lazilyProcessInternalReferencesToUpdateOnPackageNameChange(
private typealias UsageInfoFactory = (KtSimpleNameExpression) -> UsageInfo?
fun KtElement.processInternalReferencesToUpdateOnPackageNameChange(
containerChangeInfo: ContainerChangeInfo,
body: (originalRefExpr: KtSimpleNameExpression, usageFactory: (KtSimpleNameExpression) -> UsageInfo?) -> Unit
body: (originalRefExpr: KtSimpleNameExpression, usageFactory: UsageInfoFactory) -> Unit
) {
val file = containingFile as? KtFile ?: return
@@ -121,11 +107,10 @@ fun KtElement.lazilyProcessInternalReferencesToUpdateOnPackageNameChange(
}
}
fun processReference(refExpr: KtSimpleNameExpression, bindingContext: BindingContext): ((KtSimpleNameExpression) -> UsageInfo?)? {
fun processReference(refExpr: KtSimpleNameExpression, bindingContext: BindingContext): (UsageInfoFactory)? {
val descriptor = bindingContext[BindingContext.REFERENCE_TARGET, refExpr]?.getImportableDescriptor() ?: return null
val containingDescriptor = descriptor.containingDeclaration ?: return null
var declaration = DescriptorToSourceUtilsIde.getAnyDeclaration(project, descriptor) ?: return null
val callableKind = (descriptor as? CallableMemberDescriptor)?.kind
if (callableKind != null && callableKind != CallableMemberDescriptor.Kind.DECLARATION) return null
@@ -135,7 +120,7 @@ fun KtElement.lazilyProcessInternalReferencesToUpdateOnPackageNameChange(
if (descriptor is ClassDescriptor && descriptor.isInner && refExpr.parent is KtCallExpression) return null
val isCallable = descriptor is CallableDescriptor
val isExtension = isCallable && declaration.isExtensionDeclaration()
val isExtension = isCallable && (descriptor as CallableDescriptor).extensionReceiverParameter != null
val isCallableReference = isCallableReference(refExpr.mainReference)
if (isCallable) {
@@ -143,7 +128,7 @@ fun KtElement.lazilyProcessInternalReferencesToUpdateOnPackageNameChange(
if (isExtension && containingDescriptor is ClassDescriptor) {
val dispatchReceiver = refExpr.getResolvedCall(bindingContext)?.dispatchReceiver
val implicitClass = (dispatchReceiver as? ImplicitClassReceiver)?.classDescriptor
if (DescriptorUtils.isCompanionObject(implicitClass)) {
if (implicitClass?.isCompanionObject ?: false) {
return ::ImplicitCompanionAsDispatchReceiverUsageInfo
}
if (dispatchReceiver != null || containingDescriptor.kind != ClassKind.OBJECT) return null
@@ -156,14 +141,14 @@ fun KtElement.lazilyProcessInternalReferencesToUpdateOnPackageNameChange(
}
}
if (declaration is KtObjectDeclaration
&& declaration.isCompanion()
var declaration = DescriptorToSourceUtilsIde.getAnyDeclaration(project, descriptor) ?: return null
if (descriptor.isCompanionObject()
&& bindingContext[BindingContext.SHORT_REFERENCE_TO_COMPANION_OBJECT, refExpr] != null) {
declaration = declaration.containingClassOrObject ?: declaration
declaration = (declaration as KtObjectDeclaration).containingClassOrObject ?: declaration
}
val fqName = DescriptorUtils.getFqName(descriptor)
if (!fqName.isSafe) return null
if (!DescriptorUtils.getFqName(descriptor).isSafe) return null
val (oldContainer, newContainer) = containerChangeInfo
@@ -179,16 +164,15 @@ fun KtElement.lazilyProcessInternalReferencesToUpdateOnPackageNameChange(
.firstOrNull()
if (isExtension || containerFqName != null || isImported(descriptor)) return {
createMoveUsageInfoIfPossible(it.mainReference, declaration, false, this@lazilyProcessInternalReferencesToUpdateOnPackageNameChange)
createMoveUsageInfoIfPossible(it.mainReference, declaration, false, true)
}
return null
}
val referenceToContext = KotlinFileReferencesResolver.resolve(file = file, elements = listOf(this))
for ((refExpr, bindingContext) in referenceToContext) {
if (refExpr !is KtSimpleNameExpression || refExpr.parent is KtThisExpression) continue
val bindingContext = analyzeFully()
forEachDescendantOfType<KtReferenceExpression> { refExpr ->
if (refExpr !is KtSimpleNameExpression || refExpr.parent is KtThisExpression) return@forEachDescendantOfType
processReference(refExpr, bindingContext)?.let { body(refExpr, it) }
}
@@ -196,8 +180,8 @@ fun KtElement.lazilyProcessInternalReferencesToUpdateOnPackageNameChange(
class ImplicitCompanionAsDispatchReceiverUsageInfo(callee: KtSimpleNameExpression) : UsageInfo(callee)
interface InternableUsage {
val scope: PsiElement?
interface KotlinMoveUsage {
val isInternal: Boolean
fun refresh(refExpr: KtSimpleNameExpression, referencedElement: PsiElement): UsageInfo?
}
@@ -208,10 +192,10 @@ class UnqualifiableMoveRenameUsageInfo(
referencedElement: PsiElement,
val originalFile: PsiFile,
val addImportToOriginalFile: Boolean,
override val scope: PsiElement?
): MoveRenameUsageInfo(element, reference, reference.rangeInElement.startOffset, reference.rangeInElement.endOffset, referencedElement, false), InternableUsage {
override val isInternal: Boolean
): MoveRenameUsageInfo(element, reference, reference.rangeInElement.startOffset, reference.rangeInElement.endOffset, referencedElement, false), KotlinMoveUsage {
override fun refresh(refExpr: KtSimpleNameExpression, referencedElement: PsiElement): UsageInfo? {
return UnqualifiableMoveRenameUsageInfo(refExpr, refExpr.mainReference, referencedElement, originalFile, addImportToOriginalFile, scope)
return UnqualifiableMoveRenameUsageInfo(refExpr, refExpr.mainReference, referencedElement, originalFile, addImportToOriginalFile, isInternal)
}
}
@@ -219,11 +203,11 @@ class QualifiableMoveRenameUsageInfo(
element: PsiElement,
reference: PsiReference,
referencedElement: PsiElement,
override val scope: PsiElement?
override val isInternal: Boolean
): MoveRenameUsageInfo(element, reference, reference.rangeInElement.startOffset, reference.rangeInElement.endOffset, referencedElement, false),
InternableUsage {
KotlinMoveUsage {
override fun refresh(refExpr: KtSimpleNameExpression, referencedElement: PsiElement): UsageInfo? {
return QualifiableMoveRenameUsageInfo(refExpr, refExpr.mainReference, referencedElement, scope)
return QualifiableMoveRenameUsageInfo(refExpr, refExpr.mainReference, referencedElement, isInternal)
}
}
@@ -231,17 +215,15 @@ fun createMoveUsageInfoIfPossible(
reference: PsiReference,
referencedElement: PsiElement,
addImportToOriginalFile: Boolean,
scope: PsiElement?
isInternal: Boolean
): UsageInfo? {
val element = reference.element
if (element.getStrictParentOfType<KtSuperExpression>() != null) return null
return when (getReferenceKind(reference, referencedElement)) {
ReferenceKind.QUALIFIABLE -> QualifiableMoveRenameUsageInfo(
element, reference, referencedElement, scope
element, reference, referencedElement, isInternal
)
ReferenceKind.UNQUALIFIABLE -> UnqualifiableMoveRenameUsageInfo(
element, reference, referencedElement, element.containingFile!!, addImportToOriginalFile, scope
element, reference, referencedElement, element.containingFile!!, addImportToOriginalFile, isInternal
)
else -> null
}
@@ -256,6 +238,8 @@ private enum class ReferenceKind {
private fun getReferenceKind(reference: PsiReference, referencedElement: PsiElement): ReferenceKind {
val element = reference.element as? KtSimpleNameExpression ?: return ReferenceKind.QUALIFIABLE
if (element.getStrictParentOfType<KtSuperExpression>() != null) return ReferenceKind.IRRELEVANT
if ((referencedElement.namedUnwrappedElement as? KtDeclaration)?.isExtensionDeclaration() ?: false
&& reference.element.getNonStrictParentOfType<KtImportDirective>() == null) return ReferenceKind.UNQUALIFIABLE
@@ -315,7 +299,7 @@ private fun updateJavaReference(reference: PsiReferenceExpression, oldElement: P
return false
}
private fun mapToNewOrThis(e: PsiElement, oldToNewElementsMapping: Map<PsiElement, PsiElement>) = oldToNewElementsMapping[e] ?: e
internal fun mapToNewOrThis(e: PsiElement, oldToNewElementsMapping: Map<PsiElement, PsiElement>) = oldToNewElementsMapping[e] ?: e
private fun postProcessMoveUsage(
usage: UsageInfo,
@@ -337,7 +321,7 @@ private fun postProcessMoveUsage(
is MoveRenameUsageInfo -> {
val oldElement = usage.referencedElement!!
val newElement = mapToNewOrThis(oldElement, oldToNewElementsMapping)
val reference = usage.reference ?: (usage.element as? KtSimpleNameExpression)?.mainReference
val reference = (usage.element as? KtSimpleNameExpression)?.mainReference ?: usage.reference
processReference(reference, newElement, shorteningMode, oldElement)
}
}
@@ -346,7 +330,6 @@ private fun postProcessMoveUsage(
private fun processReference(reference: PsiReference?, newElement: PsiElement, shorteningMode: ShorteningMode, oldElement: PsiElement) {
try {
when {
reference is PsiMultiReference -> reference.references.forEach { processReference(it, newElement, shorteningMode, oldElement) }
reference is KtSimpleNameReference -> reference.bindToElement(newElement, shorteningMode)
reference is PsiReferenceExpression && updateJavaReference(reference, oldElement, newElement) -> return
else -> reference?.bindToElement(newElement)
@@ -399,115 +382,18 @@ fun postProcessMoveUsages(
var KtFile.updatePackageDirective: Boolean? by UserDataProperty(Key.create("UPDATE_PACKAGE_DIRECTIVE"))
fun invokeMoveFilesOrDirectoriesRefactoring(
moveDialog: KotlinAwareMoveFilesOrDirectoriesDialog?,
project: Project,
elements: Array<out PsiElement>,
initialTargetDirectory: PsiDirectory?,
moveCallback: MoveCallback?
) {
fun closeDialog() {
moveDialog?.close(DialogWrapper.CANCEL_EXIT_CODE)
}
project.executeCommand(MoveHandler.REFACTORING_NAME) {
val selectedDir = if (moveDialog != null) moveDialog.targetDirectory else initialTargetDirectory
val updatePackageDirective = (moveDialog as? KotlinAwareMoveFilesOrDirectoriesDialog)?.updatePackageDirective
try {
val choice = if (elements.size > 1 || elements[0] is PsiDirectory) intArrayOf(-1) else null
val elementsToMove = elements
.filterNot {
it is PsiFile
&& runWriteAction { CopyFilesOrDirectoriesHandler.checkFileExist(selectedDir, choice, it, it.name, "Move") }
}
.sortedWith( // process Kotlin files first so that light classes are updated before changing references in Java files
Comparator { o1, o2 ->
when {
o1 is KtElement && o2 !is KtElement -> -1
o1 !is KtElement && o2 is KtElement -> 1
else -> 0
}
}
)
elementsToMove.forEach {
MoveFilesOrDirectoriesUtil.checkMove(it, selectedDir!!)
if (it is KtFile && it.isInJavaSourceRoot()) {
it.updatePackageDirective = updatePackageDirective
}
}
val enableSearchReferences = elements.any { ProjectRootsUtil.isInProjectSource(it) }
if (elementsToMove.isNotEmpty()) {
@Suppress("UNCHECKED_CAST")
val processor = if (elementsToMove.all { it is KtFile } && selectedDir != null) {
MoveFilesWithDeclarationsProcessor(
project,
elementsToMove as List<KtFile>,
selectedDir,
null,
false,
false,
moveCallback,
Runnable(::closeDialog)
)
}
else {
MoveFilesOrDirectoriesProcessor(
project,
elementsToMove.toTypedArray(),
selectedDir,
enableSearchReferences,
false,
false,
moveCallback,
Runnable(::closeDialog)
)
}
processor.run()
}
else {
closeDialog()
}
}
catch (e: IncorrectOperationException) {
CommonRefactoringUtil.showErrorMessage(RefactoringBundle.message("error.title"), e.message, "refactoring.moveFile", project)
}
}
}
// Mostly copied from MoveFilesOrDirectoriesUtil.doMove()
fun moveFilesOrDirectories(
project: Project,
elements: Array<PsiElement>,
targetElement: PsiElement?,
moveCallback: MoveCallback? = null
) {
elements.forEach { if (it !is PsiFile && it !is PsiDirectory) throw IllegalArgumentException("unexpected element type: " + it) }
val targetDirectory = MoveFilesOrDirectoriesUtil.resolveToDirectory(project, targetElement)
if (targetElement != null && targetDirectory == null) return
val initialTargetDirectory = MoveFilesOrDirectoriesUtil.getInitialTargetDirectory(targetDirectory, elements)
fun doRun(moveDialog: KotlinAwareMoveFilesOrDirectoriesDialog?) {
invokeMoveFilesOrDirectoriesRefactoring(moveDialog, project, elements, initialTargetDirectory, moveCallback)
}
if (ApplicationManager.getApplication().isUnitTestMode) {
doRun(null)
return
}
with(KotlinAwareMoveFilesOrDirectoriesDialog(project, ::doRun)) {
setData(elements, initialTargetDirectory, "refactoring.moveFile")
show()
}
}
sealed class OuterInstanceReferenceUsageInfo(element: PsiElement, val isIndirectOuter: Boolean) : UsageInfo(element) {
open fun reportConflictIfAny(conflicts: MultiMap<PsiElement, String>): Boolean {
val element = element ?: return false
if (isIndirectOuter) {
conflicts.putValue(element, "Indirect outer instances won't be extracted: ${element.text}")
return true
}
return false
}
class ExplicitThis(
expression: KtThisExpression,
isIndirectOuter: Boolean
@@ -523,6 +409,24 @@ sealed class OuterInstanceReferenceUsageInfo(element: PsiElement, val isIndirect
) : OuterInstanceReferenceUsageInfo(callElement, isIndirectOuter) {
val callElement: KtElement?
get() = element as? KtElement
override fun reportConflictIfAny(conflicts: MultiMap<PsiElement, String>): Boolean {
if (super.reportConflictIfAny(conflicts)) return true
val fullCall = callElement?.let { it.getQualifiedExpressionForSelector() ?: it } ?: return false
return when {
fullCall is KtQualifiedExpression -> {
conflicts.putValue(fullCall, "Qualified call won't be processed: ${fullCall.text}")
true
}
isDoubleReceiver -> {
conflicts.putValue(fullCall, "Member extension call won't be processed: ${fullCall.text}")
true
}
else -> false
}
}
}
}
@@ -542,7 +446,7 @@ fun traverseOuterInstanceReferences(member: KtNamedDeclaration, stopAtFirst: Boo
val descriptor = context[BindingContext.REFERENCE_TARGET, element.instanceReference]
val isIndirect = when {
descriptor == outerClassDescriptor -> false
DescriptorUtils.isAncestor(descriptor, outerClassDescriptor, true) -> true
descriptor?.isAncestorOf(outerClassDescriptor, true) ?: false -> true
else -> return null
}
OuterInstanceReferenceUsageInfo.ExplicitThis(element, isIndirect)
@@ -552,15 +456,15 @@ fun traverseOuterInstanceReferences(member: KtNamedDeclaration, stopAtFirst: Boo
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
val isDoubleReceiver = when (outerClassDescriptor) {
dispatchReceiver?.declarationDescriptor -> extensionReceiver != null
extensionReceiver?.declarationDescriptor -> dispatchReceiver != null
else -> {
isIndirect = true
when {
DescriptorUtils.isAncestor(dispatchReceiver?.declarationDescriptor, outerClassDescriptor, true) ->
dispatchReceiver?.declarationDescriptor?.isAncestorOf(outerClassDescriptor, true) ?: false ->
extensionReceiver != null
DescriptorUtils.isAncestor(extensionReceiver?.declarationDescriptor, outerClassDescriptor, true) ->
extensionReceiver?.declarationDescriptor?.isAncestorOf(outerClassDescriptor, true) ?: false ->
dispatchReceiver != null
else -> return null
}
@@ -587,30 +491,7 @@ fun traverseOuterInstanceReferences(member: KtNamedDeclaration, stopAtFirst: Boo
}
fun collectOuterInstanceReferences(member: KtNamedDeclaration): List<OuterInstanceReferenceUsageInfo> {
return SmartList<OuterInstanceReferenceUsageInfo>().apply { traverseOuterInstanceReferences(member, false) { add(it) } }
}
fun OuterInstanceReferenceUsageInfo.reportConflictIfAny(conflicts: MultiMap<PsiElement, String>): Boolean {
val element = element ?: return false
if (isIndirectOuter) {
conflicts.putValue(element, "Indirect outer instances won't be extracted: ${element.text}")
return true
}
if (this !is OuterInstanceReferenceUsageInfo.ImplicitReceiver) return false
val fullCall = callElement?.let { it.getQualifiedExpressionForSelector() ?: it } ?: return false
return when {
fullCall is KtQualifiedExpression -> {
conflicts.putValue(fullCall, "Qualified call won't be processed: ${fullCall.text}")
true
}
isDoubleReceiver -> {
conflicts.putValue(fullCall, "Call with two implicit receivers won't be processed: ${fullCall.text}")
true
}
else -> false
}
val result = SmartList<OuterInstanceReferenceUsageInfo>()
traverseOuterInstanceReferences(member, false) { result += it }
return result
}
@@ -1,3 +1,3 @@
Call with two implicit receivers won't be processed: bar()
Call with two implicit receivers won't be processed: foo()
Member extension call won't be processed: bar()
Member extension call won't be processed: foo()
Qualified call won't be processed: 1.foo()
@@ -295,7 +295,7 @@ enum class MoveAction {
val moveTarget = config.getNullableString("targetPackage")?.let { packageName ->
val targetSourceRootPath = config["targetSourceRoot"]?.asString
val packageWrapper = PackageWrapper(mainFile.getManager(), packageName)
val packageWrapper = PackageWrapper(mainFile.manager, packageName)
val moveDestination: MoveDestination = targetSourceRootPath?.let {
AutocreatingSingleSourceRootMoveDestination(packageWrapper, rootDir.findFileByRelativePath(it)!!)
} ?: MultipleRootsMoveDestination(packageWrapper)
@@ -313,8 +313,8 @@ enum class MoveAction {
KotlinMoveTargetForExistingElement(PsiManager.getInstance(project).findFile(rootDir.findFileByRelativePath(filePath)!!) as KtFile)
}
val options = MoveDeclarationsDescriptor(elementsToMove, moveTarget, MoveDeclarationsDelegate.TopLevel)
MoveKotlinDeclarationsProcessor(mainFile.getProject(), options).run()
val descriptor = MoveDeclarationsDescriptor(project, elementsToMove, moveTarget, MoveDeclarationsDelegate.TopLevel)
MoveKotlinDeclarationsProcessor(descriptor).run()
}
},
@@ -357,8 +357,8 @@ enum class MoveAction {
createKotlinFile(fileName, targetDir, targetPackageFqName.asString())
}
}
val descriptor = MoveDeclarationsDescriptor(listOf(elementToMove), moveTarget, delegate)
MoveKotlinDeclarationsProcessor(project, descriptor).run()
val descriptor = MoveDeclarationsDescriptor(project, listOf(elementToMove), moveTarget, delegate)
MoveKotlinDeclarationsProcessor(descriptor).run()
}
};