Add expect/actual move refactoring support
Fixed #KT-27389
This commit is contained in:
@@ -816,7 +816,7 @@ label.text.target.file.name=Target file name:
|
|||||||
label.text.to.file=To &file:
|
label.text.to.file=To &file:
|
||||||
label.text.to.package=To p&ackage:
|
label.text.to.package=To p&ackage:
|
||||||
label.text.type=&Type:\u0020
|
label.text.type=&Type:\u0020
|
||||||
label.text.update.package.directive=&Update package directive
|
label.text.move.expect.actual.counterparts=&Move expect/actual counterparts
|
||||||
label.text.visibility=&Visibility:\u0020
|
label.text.visibility=&Visibility:\u0020
|
||||||
member.info.abstract.0=abstract {0}
|
member.info.abstract.0=abstract {0}
|
||||||
member.info.companion.0=companion {0}
|
member.info.companion.0=companion {0}
|
||||||
@@ -876,6 +876,7 @@ text.cannot.inline.0.1.usages=Cannot inline {0}/{1} usages
|
|||||||
text.cannot.move.for.current.project=Can't move for current project
|
text.cannot.move.for.current.project=Can't move for current project
|
||||||
text.cannot.move.inner.class.0.into.itself=Cannot move nested class {0} to itself
|
text.cannot.move.inner.class.0.into.itself=Cannot move nested class {0} to itself
|
||||||
text.cannot.move.to.original.file=Can't move to the original file
|
text.cannot.move.to.original.file=Can't move to the original file
|
||||||
|
text.cannot.move.expect.actual.declaration.to.file=Could't move expect/actual declaration to file
|
||||||
text.change.file.package.to.0=Change file''s package to ''{0}''
|
text.change.file.package.to.0=Change file''s package to ''{0}''
|
||||||
text.choose.containing.file=Choose Containing File
|
text.choose.containing.file=Choose Containing File
|
||||||
text.class.0.already.contains.member.1={0} already contains {1}
|
text.class.0.already.contains.member.1={0} already contains {1}
|
||||||
|
|||||||
+2
@@ -156,6 +156,7 @@ internal class MoveKotlinDeclarationsHandlerTestActions(private val caseDataKeep
|
|||||||
searchInComments: Boolean,
|
searchInComments: Boolean,
|
||||||
searchForTextOccurrences: Boolean,
|
searchForTextOccurrences: Boolean,
|
||||||
deleteEmptySourceFiles: Boolean,
|
deleteEmptySourceFiles: Boolean,
|
||||||
|
moveMppDeclarations: Boolean,
|
||||||
moveCallback: MoveCallback?
|
moveCallback: MoveCallback?
|
||||||
) {
|
) {
|
||||||
val selectedElementsToMove = mutableSetOf<KtNamedDeclaration>()
|
val selectedElementsToMove = mutableSetOf<KtNamedDeclaration>()
|
||||||
@@ -181,6 +182,7 @@ internal class MoveKotlinDeclarationsHandlerTestActions(private val caseDataKeep
|
|||||||
isDeleteEmptyFiles = randomBoolean(),
|
isDeleteEmptyFiles = randomBoolean(),
|
||||||
isUpdatePackageDirective = randomBoolean(),
|
isUpdatePackageDirective = randomBoolean(),
|
||||||
isFullFileMove = randomBoolean(),
|
isFullFileMove = randomBoolean(),
|
||||||
|
applyMPPDeclarations = true,
|
||||||
moveCallback = null
|
moveCallback = null
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -61,6 +61,9 @@ class KotlinRefactoringSettings : PersistentStateComponent<KotlinRefactoringSett
|
|||||||
@JvmField
|
@JvmField
|
||||||
var MOVE_DELETE_EMPTY_SOURCE_FILES = true
|
var MOVE_DELETE_EMPTY_SOURCE_FILES = true
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
var MOVE_MPP_DECLARATIONS = true
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
var EXTRACT_INTERFACE_JAVADOC: Int = 0
|
var EXTRACT_INTERFACE_JAVADOC: Int = 0
|
||||||
|
|
||||||
|
|||||||
+1
@@ -160,6 +160,7 @@ class ExtractDeclarationFromCurrentFileIntention :
|
|||||||
/* searchInComments = */ true,
|
/* searchInComments = */ true,
|
||||||
/* searchForTextOccurrences = */ true,
|
/* searchForTextOccurrences = */ true,
|
||||||
/* deleteEmptySourceFiles = */ true,
|
/* deleteEmptySourceFiles = */ true,
|
||||||
|
/* moveMppDeclarations = */ false,
|
||||||
callBack
|
callBack
|
||||||
).showWithTransaction()
|
).showWithTransaction()
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-13
@@ -71,6 +71,7 @@ private val defaultHandlerActions = object : MoveKotlinDeclarationsHandlerAction
|
|||||||
searchInComments: Boolean,
|
searchInComments: Boolean,
|
||||||
searchForTextOccurrences: Boolean,
|
searchForTextOccurrences: Boolean,
|
||||||
deleteEmptySourceFiles: Boolean,
|
deleteEmptySourceFiles: Boolean,
|
||||||
|
moveMppDeclarations: Boolean,
|
||||||
moveCallback: MoveCallback?
|
moveCallback: MoveCallback?
|
||||||
) = MoveKotlinTopLevelDeclarationsDialog(
|
) = MoveKotlinTopLevelDeclarationsDialog(
|
||||||
project,
|
project,
|
||||||
@@ -82,6 +83,7 @@ private val defaultHandlerActions = object : MoveKotlinDeclarationsHandlerAction
|
|||||||
searchInComments,
|
searchInComments,
|
||||||
searchForTextOccurrences,
|
searchForTextOccurrences,
|
||||||
deleteEmptySourceFiles,
|
deleteEmptySourceFiles,
|
||||||
|
moveMppDeclarations,
|
||||||
moveCallback
|
moveCallback
|
||||||
).show()
|
).show()
|
||||||
|
|
||||||
@@ -127,19 +129,6 @@ class MoveKotlinDeclarationsHandler internal constructor(private val handlerActi
|
|||||||
): Boolean {
|
): Boolean {
|
||||||
if (!CommonRefactoringUtil.checkReadOnlyStatusRecursively(project, elements.toList(), true)) return false
|
if (!CommonRefactoringUtil.checkReadOnlyStatusRecursively(project, elements.toList(), true)) return false
|
||||||
|
|
||||||
if (!ApplicationManager.getApplication().isUnitTestMode &&
|
|
||||||
elements.any { it is KtDeclaration && (it.isExpectDeclaration() || it.isEffectivelyActual()) }
|
|
||||||
) {
|
|
||||||
val proceedWithIncompleteRefactoring = Messages.showYesNoDialog(
|
|
||||||
project,
|
|
||||||
"This refactoring will move selected declaration without it's expect/actual counterparts that may lead to compilation errors.\n" +
|
|
||||||
"Do you wish to proceed?",
|
|
||||||
"MPP declarations does not supported by this refactoring.",
|
|
||||||
Messages.getWarningIcon()
|
|
||||||
)
|
|
||||||
if (proceedWithIncompleteRefactoring != Messages.YES) return true
|
|
||||||
}
|
|
||||||
|
|
||||||
val container = getUniqueContainer(elements)
|
val container = getUniqueContainer(elements)
|
||||||
if (container == null) {
|
if (container == null) {
|
||||||
handlerActions.showErrorHint(
|
handlerActions.showErrorHint(
|
||||||
@@ -207,6 +196,7 @@ class MoveKotlinDeclarationsHandler internal constructor(private val handlerActi
|
|||||||
val searchInComments = KotlinRefactoringSettings.instance.MOVE_SEARCH_IN_COMMENTS
|
val searchInComments = KotlinRefactoringSettings.instance.MOVE_SEARCH_IN_COMMENTS
|
||||||
val searchInText = KotlinRefactoringSettings.instance.MOVE_SEARCH_FOR_TEXT
|
val searchInText = KotlinRefactoringSettings.instance.MOVE_SEARCH_FOR_TEXT
|
||||||
val deleteEmptySourceFiles = KotlinRefactoringSettings.instance.MOVE_DELETE_EMPTY_SOURCE_FILES
|
val deleteEmptySourceFiles = KotlinRefactoringSettings.instance.MOVE_DELETE_EMPTY_SOURCE_FILES
|
||||||
|
val moveMppDeclarations = KotlinRefactoringSettings.instance.MOVE_MPP_DECLARATIONS
|
||||||
val targetFile = targetContainer as? KtFile
|
val targetFile = targetContainer as? KtFile
|
||||||
val moveToPackage = targetContainer !is KtFile
|
val moveToPackage = targetContainer !is KtFile
|
||||||
|
|
||||||
@@ -220,6 +210,7 @@ class MoveKotlinDeclarationsHandler internal constructor(private val handlerActi
|
|||||||
searchInComments,
|
searchInComments,
|
||||||
searchInText,
|
searchInText,
|
||||||
deleteEmptySourceFiles,
|
deleteEmptySourceFiles,
|
||||||
|
moveMppDeclarations,
|
||||||
callback
|
callback
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -34,6 +34,7 @@ internal interface MoveKotlinDeclarationsHandlerActions {
|
|||||||
searchInComments: Boolean,
|
searchInComments: Boolean,
|
||||||
searchForTextOccurrences: Boolean,
|
searchForTextOccurrences: Boolean,
|
||||||
deleteEmptySourceFiles: Boolean,
|
deleteEmptySourceFiles: Boolean,
|
||||||
|
moveMppDeclarations: Boolean,
|
||||||
moveCallback: MoveCallback?
|
moveCallback: MoveCallback?
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
+10
-1
@@ -116,7 +116,7 @@
|
|||||||
<text resource-bundle="messages/KotlinBundle" key="label.text.update.package.directive"/>
|
<text resource-bundle="messages/KotlinBundle" key="label.text.update.package.directive"/>
|
||||||
</properties>
|
</properties>
|
||||||
</component>
|
</component>
|
||||||
<grid id="69aba" layout-manager="GridLayoutManager" row-count="3" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
<grid id="69aba" layout-manager="GridLayoutManager" row-count="4" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||||
<margin top="0" left="0" bottom="0" right="0"/>
|
<margin top="0" left="0" bottom="0" right="0"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<grid row="5" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
<grid row="5" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||||
@@ -160,6 +160,15 @@
|
|||||||
<text resource-bundle="messages/KotlinBundle" key="checkbox.text.delete.empty.source.files"/>
|
<text resource-bundle="messages/KotlinBundle" key="checkbox.text.delete.empty.source.files"/>
|
||||||
</properties>
|
</properties>
|
||||||
</component>
|
</component>
|
||||||
|
<component id="cc60d" class="javax.swing.JCheckBox" binding="cbApplyMPPDeclarationsMove">
|
||||||
|
<constraints>
|
||||||
|
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<selected value="true"/>
|
||||||
|
<text resource-bundle="messages/KotlinBundle" key="label.text.move.expect.actual.counterparts"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
</children>
|
</children>
|
||||||
</grid>
|
</grid>
|
||||||
</children>
|
</children>
|
||||||
|
|||||||
+36
-2
@@ -41,6 +41,8 @@ import org.jetbrains.kotlin.idea.refactoring.memberInfo.KotlinMemberSelectionTab
|
|||||||
import org.jetbrains.kotlin.idea.refactoring.move.MoveUtilsKt;
|
import org.jetbrains.kotlin.idea.refactoring.move.MoveUtilsKt;
|
||||||
import org.jetbrains.kotlin.idea.refactoring.ui.KotlinDestinationFolderComboBox;
|
import org.jetbrains.kotlin.idea.refactoring.ui.KotlinDestinationFolderComboBox;
|
||||||
import org.jetbrains.kotlin.idea.refactoring.ui.KotlinFileChooserDialog;
|
import org.jetbrains.kotlin.idea.refactoring.ui.KotlinFileChooserDialog;
|
||||||
|
import org.jetbrains.kotlin.idea.util.ExpectActualUtilKt;
|
||||||
|
import org.jetbrains.kotlin.psi.KtElement;
|
||||||
import org.jetbrains.kotlin.psi.KtFile;
|
import org.jetbrains.kotlin.psi.KtFile;
|
||||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration;
|
import org.jetbrains.kotlin.psi.KtNamedDeclaration;
|
||||||
import org.jetbrains.kotlin.psi.KtPureElement;
|
import org.jetbrains.kotlin.psi.KtPureElement;
|
||||||
@@ -75,6 +77,7 @@ public class MoveKotlinTopLevelDeclarationsDialog extends RefactoringDialog {
|
|||||||
private JCheckBox cbUpdatePackageDirective;
|
private JCheckBox cbUpdatePackageDirective;
|
||||||
private JCheckBox cbDeleteEmptySourceFiles;
|
private JCheckBox cbDeleteEmptySourceFiles;
|
||||||
private JCheckBox cbSearchReferences;
|
private JCheckBox cbSearchReferences;
|
||||||
|
private JCheckBox cbApplyMPPDeclarationsMove;
|
||||||
private KotlinMemberSelectionTable memberTable;
|
private KotlinMemberSelectionTable memberTable;
|
||||||
|
|
||||||
private class MemberSelectionerInfoChangeListener implements MemberInfoChangeListener<KtNamedDeclaration, KotlinMemberInfo> {
|
private class MemberSelectionerInfoChangeListener implements MemberInfoChangeListener<KtNamedDeclaration, KotlinMemberInfo> {
|
||||||
@@ -100,6 +103,7 @@ public class MoveKotlinTopLevelDeclarationsDialog extends RefactoringDialog {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void memberInfoChanged(@NotNull MemberInfoChange<KtNamedDeclaration, KotlinMemberInfo> event) {
|
public void memberInfoChanged(@NotNull MemberInfoChange<KtNamedDeclaration, KotlinMemberInfo> event) {
|
||||||
|
updateControls();
|
||||||
updatePackageDirectiveCheckBox();
|
updatePackageDirectiveCheckBox();
|
||||||
updateFileNameInPackageField();
|
updateFileNameInPackageField();
|
||||||
// Update file name field only if it user hasn't changed it to some non-default value
|
// Update file name field only if it user hasn't changed it to some non-default value
|
||||||
@@ -119,6 +123,7 @@ public class MoveKotlinTopLevelDeclarationsDialog extends RefactoringDialog {
|
|||||||
boolean searchInComments,
|
boolean searchInComments,
|
||||||
boolean searchForTextOccurrences,
|
boolean searchForTextOccurrences,
|
||||||
boolean deleteEmptySourceFiles,
|
boolean deleteEmptySourceFiles,
|
||||||
|
boolean moveMppDeclarations,
|
||||||
@Nullable MoveCallback moveCallback
|
@Nullable MoveCallback moveCallback
|
||||||
) {
|
) {
|
||||||
super(project, true);
|
super(project, true);
|
||||||
@@ -132,7 +137,7 @@ public class MoveKotlinTopLevelDeclarationsDialog extends RefactoringDialog {
|
|||||||
|
|
||||||
setTitle(MoveHandler.REFACTORING_NAME);
|
setTitle(MoveHandler.REFACTORING_NAME);
|
||||||
|
|
||||||
initSearchOptions(searchInComments, searchForTextOccurrences, deleteEmptySourceFiles);
|
initSearchOptions(searchInComments, searchForTextOccurrences, deleteEmptySourceFiles, moveMppDeclarations);
|
||||||
|
|
||||||
initPackageChooser(targetPackageName, targetDirectory, sourceFiles);
|
initPackageChooser(targetPackageName, targetDirectory, sourceFiles);
|
||||||
|
|
||||||
@@ -190,6 +195,7 @@ public class MoveKotlinTopLevelDeclarationsDialog extends RefactoringDialog {
|
|||||||
selectionPanel.getTable().setMemberInfoModel(memberInfoModel);
|
selectionPanel.getTable().setMemberInfoModel(memberInfoModel);
|
||||||
selectionPanel.getTable().addMemberInfoChangeListener(memberInfoModel);
|
selectionPanel.getTable().addMemberInfoChangeListener(memberInfoModel);
|
||||||
selectionPanel.getTable().addMemberInfoChangeListener(new MemberSelectionerInfoChangeListener(memberInfos));
|
selectionPanel.getTable().addMemberInfoChangeListener(new MemberSelectionerInfoChangeListener(memberInfos));
|
||||||
|
cbApplyMPPDeclarationsMove.addChangeListener(e -> updateControls());
|
||||||
memberInfoPanel.add(selectionPanel, BorderLayout.CENTER);
|
memberInfoPanel.add(selectionPanel, BorderLayout.CENTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,10 +235,11 @@ public class MoveKotlinTopLevelDeclarationsDialog extends RefactoringDialog {
|
|||||||
cbUpdatePackageDirective.setSelected(arePackagesAndDirectoryMatched(sourceFiles));
|
cbUpdatePackageDirective.setSelected(arePackagesAndDirectoryMatched(sourceFiles));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initSearchOptions(boolean searchInComments, boolean searchForTextOccurences, boolean deleteEmptySourceFiles) {
|
private void initSearchOptions(boolean searchInComments, boolean searchForTextOccurences, boolean deleteEmptySourceFiles, boolean moveMppDeclarations) {
|
||||||
cbSearchInComments.setSelected(searchInComments);
|
cbSearchInComments.setSelected(searchInComments);
|
||||||
cbSearchTextOccurrences.setSelected(searchForTextOccurences);
|
cbSearchTextOccurrences.setSelected(searchForTextOccurences);
|
||||||
cbDeleteEmptySourceFiles.setSelected(deleteEmptySourceFiles);
|
cbDeleteEmptySourceFiles.setSelected(deleteEmptySourceFiles);
|
||||||
|
cbApplyMPPDeclarationsMove.setSelected(moveMppDeclarations);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initMoveToButtons(boolean moveToPackage) {
|
private void initMoveToButtons(boolean moveToPackage) {
|
||||||
@@ -327,7 +334,30 @@ public class MoveKotlinTopLevelDeclarationsDialog extends RefactoringDialog {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isMppDeclarationSelected() {
|
||||||
|
for(KtNamedDeclaration element : getSelectedElementsToMove()) {
|
||||||
|
if (ExpectActualUtilKt.isEffectivelyActual(element, true) ||
|
||||||
|
ExpectActualUtilKt.isExpectDeclaration(element)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private void updateControls() {
|
private void updateControls() {
|
||||||
|
|
||||||
|
boolean mppDeclarationSelected = isMppDeclarationSelected();
|
||||||
|
cbApplyMPPDeclarationsMove.setEnabled(mppDeclarationSelected);
|
||||||
|
|
||||||
|
boolean needToMoveMPPDeclarations = mppDeclarationSelected && cbApplyMPPDeclarationsMove.isSelected();
|
||||||
|
|
||||||
|
if (needToMoveMPPDeclarations) {
|
||||||
|
if (!rbMoveToPackage.isSelected()) {
|
||||||
|
rbMoveToPackage.setSelected(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UIUtil.setEnabled(rbMoveToFile, !needToMoveMPPDeclarations, true);
|
||||||
|
|
||||||
boolean moveToPackage = rbMoveToPackage.isSelected();
|
boolean moveToPackage = rbMoveToPackage.isSelected();
|
||||||
classPackageChooser.setEnabled(moveToPackage);
|
classPackageChooser.setEnabled(moveToPackage);
|
||||||
updateFileNameInPackageField();
|
updateFileNameInPackageField();
|
||||||
@@ -363,6 +393,7 @@ public class MoveKotlinTopLevelDeclarationsDialog extends RefactoringDialog {
|
|||||||
refactoringSettings.MOVE_SEARCH_FOR_TEXT = cbSearchTextOccurrences.isSelected();
|
refactoringSettings.MOVE_SEARCH_FOR_TEXT = cbSearchTextOccurrences.isSelected();
|
||||||
refactoringSettings.MOVE_DELETE_EMPTY_SOURCE_FILES = cbDeleteEmptySourceFiles.isSelected();
|
refactoringSettings.MOVE_DELETE_EMPTY_SOURCE_FILES = cbDeleteEmptySourceFiles.isSelected();
|
||||||
refactoringSettings.MOVE_PREVIEW_USAGES = isPreviewUsages();
|
refactoringSettings.MOVE_PREVIEW_USAGES = isPreviewUsages();
|
||||||
|
refactoringSettings.MOVE_MPP_DECLARATIONS = cbApplyMPPDeclarationsMove.isSelected();
|
||||||
|
|
||||||
RecentsManager.getInstance(myProject).registerRecentEntry(RECENTS_KEY, getTargetPackage());
|
RecentsManager.getInstance(myProject).registerRecentEntry(RECENTS_KEY, getTargetPackage());
|
||||||
}
|
}
|
||||||
@@ -401,6 +432,8 @@ public class MoveKotlinTopLevelDeclarationsDialog extends RefactoringDialog {
|
|||||||
DirectoryChooser.ItemWrapper selectedItem = (DirectoryChooser.ItemWrapper) destinationFolderCB.getComboBox().getSelectedItem();
|
DirectoryChooser.ItemWrapper selectedItem = (DirectoryChooser.ItemWrapper) destinationFolderCB.getComboBox().getSelectedItem();
|
||||||
PsiDirectory selectedPsiDirectory = selectedItem != null ? selectedItem.getDirectory() : initialTargetDirectory;
|
PsiDirectory selectedPsiDirectory = selectedItem != null ? selectedItem.getDirectory() : initialTargetDirectory;
|
||||||
|
|
||||||
|
boolean mppDeclarationSelected = cbApplyMPPDeclarationsMove.isSelected() && isMppDeclarationSelected();
|
||||||
|
|
||||||
return new MoveKotlinTopLevelDeclarationsModel(
|
return new MoveKotlinTopLevelDeclarationsModel(
|
||||||
myProject,
|
myProject,
|
||||||
getSelectedElementsToMoveChecked(),
|
getSelectedElementsToMoveChecked(),
|
||||||
@@ -415,6 +448,7 @@ public class MoveKotlinTopLevelDeclarationsDialog extends RefactoringDialog {
|
|||||||
cbDeleteEmptySourceFiles.isSelected(),
|
cbDeleteEmptySourceFiles.isSelected(),
|
||||||
cbUpdatePackageDirective.isSelected(),
|
cbUpdatePackageDirective.isSelected(),
|
||||||
isFullFileMove(),
|
isFullFileMove(),
|
||||||
|
mppDeclarationSelected,
|
||||||
moveCallback
|
moveCallback
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+21
-2
@@ -27,6 +27,9 @@ import org.jetbrains.kotlin.idea.refactoring.getOrCreateKotlinFile
|
|||||||
import org.jetbrains.kotlin.idea.refactoring.move.getOrCreateDirectory
|
import org.jetbrains.kotlin.idea.refactoring.move.getOrCreateDirectory
|
||||||
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.*
|
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.*
|
||||||
import org.jetbrains.kotlin.idea.refactoring.move.updatePackageDirective
|
import org.jetbrains.kotlin.idea.refactoring.move.updatePackageDirective
|
||||||
|
import org.jetbrains.kotlin.idea.util.collectAllExpectAndActualDeclaration
|
||||||
|
import org.jetbrains.kotlin.idea.util.isEffectivelyActual
|
||||||
|
import org.jetbrains.kotlin.idea.util.isExpectDeclaration
|
||||||
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 org.jetbrains.kotlin.psi.KtNamedDeclaration
|
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||||
@@ -48,6 +51,7 @@ internal class MoveKotlinTopLevelDeclarationsModel(
|
|||||||
val isDeleteEmptyFiles: Boolean,
|
val isDeleteEmptyFiles: Boolean,
|
||||||
val isUpdatePackageDirective: Boolean,
|
val isUpdatePackageDirective: Boolean,
|
||||||
val isFullFileMove: Boolean,
|
val isFullFileMove: Boolean,
|
||||||
|
val applyMPPDeclarations: Boolean,
|
||||||
val moveCallback: MoveCallback?
|
val moveCallback: MoveCallback?
|
||||||
) : Model<BaseRefactoringProcessor> {
|
) : Model<BaseRefactoringProcessor> {
|
||||||
|
|
||||||
@@ -59,6 +63,8 @@ internal class MoveKotlinTopLevelDeclarationsModel(
|
|||||||
|
|
||||||
private val sourceFiles: Set<KtFile> = elementsToMove.mapTo(mutableSetOf()) { it.containingKtFile }
|
private val sourceFiles: Set<KtFile> = elementsToMove.mapTo(mutableSetOf()) { it.containingKtFile }
|
||||||
|
|
||||||
|
private val elementsToMoveHasMPP = applyMPPDeclarations && elementsToMove.any { it.isEffectivelyActual() || it.isExpectDeclaration() }
|
||||||
|
|
||||||
private val singleSourceFileMode = sourceFiles.size == 1
|
private val singleSourceFileMode = sourceFiles.size == 1
|
||||||
|
|
||||||
private fun selectPackageBasedDestination(): MoveDestination {
|
private fun selectPackageBasedDestination(): MoveDestination {
|
||||||
@@ -187,7 +193,11 @@ internal class MoveKotlinTopLevelDeclarationsModel(
|
|||||||
if (isMoveToPackage) selectMoveTargetToPackage() else selectMoveTargetToFile()
|
if (isMoveToPackage) selectMoveTargetToPackage() else selectMoveTargetToFile()
|
||||||
|
|
||||||
private fun verifyBeforeRun() {
|
private fun verifyBeforeRun() {
|
||||||
|
if (!isMoveToPackage && elementsToMoveHasMPP)
|
||||||
|
throw ConfigurationException(KotlinBundle.message("text.cannot.move.expect.actual.declaration.to.file"))
|
||||||
|
|
||||||
if (elementsToMove.isEmpty()) throw ConfigurationException(KotlinBundle.message("text.at.least.one.file.must.be.selected"))
|
if (elementsToMove.isEmpty()) throw ConfigurationException(KotlinBundle.message("text.at.least.one.file.must.be.selected"))
|
||||||
|
|
||||||
if (sourceFiles.isEmpty()) throw ConfigurationException("None elements were selected")
|
if (sourceFiles.isEmpty()) throw ConfigurationException("None elements were selected")
|
||||||
if (singleSourceFileMode && fileNameInPackage.isBlank()) throw ConfigurationException(KotlinBundle.message("text.file.name.cannot.be.empty"))
|
if (singleSourceFileMode && fileNameInPackage.isBlank()) throw ConfigurationException(KotlinBundle.message("text.file.name.cannot.be.empty"))
|
||||||
|
|
||||||
@@ -220,6 +230,8 @@ internal class MoveKotlinTopLevelDeclarationsModel(
|
|||||||
|
|
||||||
private fun tryMoveFile(throwOnConflicts: Boolean): BaseRefactoringProcessor? {
|
private fun tryMoveFile(throwOnConflicts: Boolean): BaseRefactoringProcessor? {
|
||||||
|
|
||||||
|
if (elementsToMoveHasMPP) return null
|
||||||
|
|
||||||
val targetFileName = if (sourceFiles.size > 1) null else fileNameInPackage
|
val targetFileName = if (sourceFiles.size > 1) null else fileNameInPackage
|
||||||
if (targetFileName != null) checkTargetFileName(targetFileName)
|
if (targetFileName != null) checkTargetFileName(targetFileName)
|
||||||
|
|
||||||
@@ -260,14 +272,21 @@ internal class MoveKotlinTopLevelDeclarationsModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun moveDeclaration(throwOnConflicts: Boolean): BaseRefactoringProcessor {
|
private fun moveDeclaration(throwOnConflicts: Boolean): BaseRefactoringProcessor {
|
||||||
|
|
||||||
|
val elementsWithMPPIfNeeded =
|
||||||
|
if (elementsToMoveHasMPP) elementsToMove
|
||||||
|
.flatMap { it.collectAllExpectAndActualDeclaration() }
|
||||||
|
.filterIsInstance<KtNamedDeclaration>()
|
||||||
|
else elementsToMove
|
||||||
|
|
||||||
val target = selectMoveTarget()
|
val target = selectMoveTarget()
|
||||||
for (element in elementsToMove) {
|
for (element in elementsWithMPPIfNeeded) {
|
||||||
target.verify(element.containingFile)?.let { throw ConfigurationException(it) }
|
target.verify(element.containingFile)?.let { throw ConfigurationException(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
val options = MoveDeclarationsDescriptor(
|
val options = MoveDeclarationsDescriptor(
|
||||||
project,
|
project,
|
||||||
MoveSource(elementsToMove),
|
MoveSource(elementsWithMPPIfNeeded),
|
||||||
target,
|
target,
|
||||||
MoveDeclarationsDelegate.TopLevel,
|
MoveDeclarationsDelegate.TopLevel,
|
||||||
isSearchInComments,
|
isSearchInComments,
|
||||||
|
|||||||
Reference in New Issue
Block a user