Move: Implement "Move nested class to upper level" UI

#KT-9027 In Progress
This commit is contained in:
Alexey Sedunov
2016-01-19 17:44:03 +03:00
parent d662b02e95
commit e943508d87
3 changed files with 561 additions and 16 deletions
@@ -32,53 +32,92 @@ import com.intellij.refactoring.move.moveClassesOrPackages.MoveClassesOrPackages
import com.intellij.refactoring.util.CommonRefactoringUtil
import org.jetbrains.kotlin.idea.core.getPackage
import org.jetbrains.kotlin.idea.refactoring.canRefactor
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.ui.MoveKotlinNestedClassesToUpperLevelDialog
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.ui.MoveKotlinTopLevelDeclarationsDialog
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
import java.util.*
class MoveKotlinDeclarationsHandler : MoveHandlerDelegate() {
private fun getSourceDirectories(elements: Array<out PsiElement>) = elements.mapTo(LinkedHashSet()) { it.containingFile?.parent }
private fun getUniqueContainer(elements: Array<out PsiElement>): PsiElement? {
val getContainer: (PsiElement) -> PsiElement? =
if (elements.any { it.parent !is KtFile }) { e ->
(e as? KtNamedDeclaration)?.containingClassOrObject
}
else { e ->
e.containingFile?.parent
}
return elements.mapNotNullTo(LinkedHashSet(), getContainer).singleOrNull()
}
private fun KtNamedDeclaration.canMove() = if (this is KtClassOrObject) !isLocal() else parent is KtFile
private fun doMoveWithCheck(
project: Project, elements: Array<out PsiElement>, targetContainer: PsiElement?, callback: MoveCallback?, editor: Editor?
): Boolean {
if (!CommonRefactoringUtil.checkReadOnlyStatusRecursively(project, elements.toList(), true)) return false
if (getSourceDirectories(elements).singleOrNull() == null) {
val container = getUniqueContainer(elements)
if (container == null) {
CommonRefactoringUtil.showErrorHint(
project, editor, "All declarations must belong to the same directory", MOVE_DECLARATIONS, null
project, editor, "All declarations must belong to the same directory or class", MOVE_DECLARATIONS, null
)
return false
}
val elementsToSearch = elements.mapTo(LinkedHashSet()) { it as KtNamedDeclaration }
if (elementsToSearch.any { it.parent !is KtFile }) {
val message = RefactoringBundle.getCannotRefactorMessage("Move declaration is only supported for top-level declarations")
// todo: allow moving companion object
if (elementsToSearch.any { it is KtObjectDeclaration && it.isCompanion() }) {
val message = RefactoringBundle.getCannotRefactorMessage("Move declaration is not supported for companion objects")
CommonRefactoringUtil.showErrorHint(project, editor, message, MOVE_DECLARATIONS, null)
return true
}
val targetPackageName = MoveClassesOrPackagesImpl.getInitialTargetPackageName(targetContainer, elements)
val targetDirectory = MoveClassesOrPackagesImpl.getInitialTargetDirectory(targetContainer, elements)
val searchInComments = JavaRefactoringSettings.getInstance()!!.MOVE_SEARCH_IN_COMMENTS
val searchInText = JavaRefactoringSettings.getInstance()!!.MOVE_SEARCH_FOR_TEXT
val targetFile = targetContainer as? KtFile
val moveToPackage = targetContainer !is KtFile
if (elementsToSearch.any { !it.canMove() }) {
val message = RefactoringBundle.getCannotRefactorMessage("Move declaration is only supported for top-level declarations and nested classes")
CommonRefactoringUtil.showErrorHint(project, editor, message, MOVE_DECLARATIONS, null)
return true
}
MoveKotlinTopLevelDeclarationsDialog(
project, elementsToSearch, targetPackageName, targetDirectory, targetFile, moveToPackage, searchInComments, searchInText, callback
).show()
when (container) {
is PsiDirectory, is PsiPackage, is KtFile -> {
val targetPackageName = MoveClassesOrPackagesImpl.getInitialTargetPackageName(targetContainer, elements)
val targetDirectory = MoveClassesOrPackagesImpl.getInitialTargetDirectory(targetContainer, elements)
val searchInComments = JavaRefactoringSettings.getInstance()!!.MOVE_SEARCH_IN_COMMENTS
val searchInText = JavaRefactoringSettings.getInstance()!!.MOVE_SEARCH_FOR_TEXT
val targetFile = targetContainer as? KtFile
val moveToPackage = targetContainer !is KtFile
MoveKotlinTopLevelDeclarationsDialog(
project, elementsToSearch, targetPackageName, targetDirectory, targetFile, moveToPackage, searchInComments, searchInText, callback
).show()
}
is KtClassOrObject -> {
if (elementsToSearch.size > 1) return false
val outerClass = container.parent as KtClassOrObject
val newContainer = targetContainer
?: outerClass.containingClassOrObject
?: outerClass.containingFile.let { it.containingDirectory ?: it }
MoveKotlinNestedClassesToUpperLevelDialog(project, elementsToSearch.first() as KtClassOrObject, newContainer).show()
}
else -> throw AssertionError("Unexpected container: ${container.getElementTextWithContext()}")
}
return true
}
private fun canMove(elements: Array<out PsiElement>, targetContainer: PsiElement?, editorMode: Boolean): Boolean {
if (!super.canMove(elements, targetContainer)) return false
if (getSourceDirectories(elements).singleOrNull() == null) return false
if (getUniqueContainer(elements) == null) return false
return elements.all { e ->
if (e is KtClass || (e is KtObjectDeclaration && !e.isObjectLiteral()) || e is KtNamedFunction || e is KtProperty) {
(editorMode || e.parent is KtFile) && e.canRefactor()
(editorMode || (e as KtNamedDeclaration).canMove()) && e.canRefactor()
}
else false
}
@@ -0,0 +1,102 @@
<?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.moveDeclarations.ui.MoveKotlinNestedClassesToUpperLevelDialog">
<grid id="27dc6" binding="panel" layout-manager="GridLayoutManager" row-count="10" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="500" height="400"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="39dca" class="javax.swing.JLabel" binding="classNameLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="messages/RefactoringBundle" key="class.name.prompt"/>
</properties>
</component>
<hspacer id="dbb8e">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
</hspacer>
<vspacer id="34c3">
<constraints>
<grid row="9" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<component id="8093b" class="com.intellij.ui.EditorTextField" binding="classNameField">
<constraints>
<grid row="1" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<component id="13f65" class="com.intellij.ui.NonFocusableCheckBox" binding="passOuterClassCheckBox">
<constraints>
<grid row="4" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="messages/RefactoringBundle" key="pass.outer.class.instance.as.parameter"/>
</properties>
</component>
<component id="ec0ba" class="javax.swing.JLabel" binding="parameterNameLabel">
<constraints>
<grid row="5" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="1" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="messages/RefactoringBundle" key="parameter.name.prompt"/>
</properties>
</component>
<component id="73425" class="com.intellij.refactoring.ui.NameSuggestionsField" binding="parameterField" custom-create="true">
<constraints>
<grid row="6" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="1" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<grid id="60537" layout-manager="FlowLayout" hgap="5" vgap="5" flow-align="0">
<constraints>
<grid row="7" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="46c54" class="com.intellij.ui.NonFocusableCheckBox" binding="searchInCommentsCheckBox">
<constraints/>
<properties>
<text resource-bundle="messages/RefactoringBundle" key="search.in.comments.and.strings"/>
</properties>
</component>
<component id="e1ccb" class="com.intellij.ui.NonFocusableCheckBox" binding="searchForTextOccurrencesCheckBox">
<constraints/>
<properties>
<text resource-bundle="messages/RefactoringBundle" key="search.for.text.occurrences"/>
</properties>
</component>
</children>
</grid>
<component id="ca9da" class="javax.swing.JLabel" binding="packageNameLabel">
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Packa&amp;ge name:"/>
</properties>
</component>
<component id="18010" class="com.intellij.refactoring.ui.PackageNameReferenceEditorCombo" binding="packageNameField" custom-create="true">
<constraints>
<grid row="3" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<grid id="f9ba1" binding="openInEditorPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
<constraints>
<grid row="8" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children/>
</grid>
</children>
</grid>
</form>
@@ -0,0 +1,404 @@
/*
* 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.ui;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.JavaProjectRootsUtil;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.NullableComputable;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.refactoring.HelpID;
import com.intellij.refactoring.PackageWrapper;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.move.MoveDialogBase;
import com.intellij.refactoring.move.moveClassesOrPackages.MoveClassesOrPackagesUtil;
import com.intellij.refactoring.move.moveInner.MoveInnerImpl;
import com.intellij.refactoring.ui.NameSuggestionsField;
import com.intellij.refactoring.ui.PackageNameReferenceEditorCombo;
import com.intellij.refactoring.util.CommonRefactoringUtil;
import com.intellij.refactoring.util.RefactoringMessageUtil;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.ui.EditorTextField;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import kotlin.collections.CollectionsKt;
import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor;
import org.jetbrains.kotlin.idea.KotlinFileType;
import org.jetbrains.kotlin.idea.caches.resolve.ResolutionUtils;
import org.jetbrains.kotlin.idea.core.CollectingNameValidator;
import org.jetbrains.kotlin.idea.core.KotlinNameSuggester;
import org.jetbrains.kotlin.idea.core.NewDeclarationNameValidator;
import org.jetbrains.kotlin.idea.refactoring.JetRefactoringUtilKt;
import org.jetbrains.kotlin.idea.refactoring.move.MoveUtilsKt;
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.*;
import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.types.KotlinType;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.List;
public class MoveKotlinNestedClassesToUpperLevelDialog extends MoveDialogBase {
@NonNls private static final String RECENTS_KEY = MoveKotlinNestedClassesToUpperLevelDialog.class.getName() + ".RECENTS_KEY";
private final Project project;
private final KtClassOrObject innerClass;
private final ClassDescriptor innerClassDescriptor;
private final PsiElement targetContainer;
private EditorTextField classNameField;
private NameSuggestionsField parameterField;
private JCheckBox passOuterClassCheckBox;
private JPanel panel;
private JCheckBox searchInCommentsCheckBox;
private JCheckBox searchForTextOccurrencesCheckBox;
private PackageNameReferenceEditorCombo packageNameField;
private JLabel packageNameLabel;
private JLabel classNameLabel;
private JLabel parameterNameLabel;
private JPanel openInEditorPanel;
public MoveKotlinNestedClassesToUpperLevelDialog(
@NotNull Project project,
@NotNull KtClassOrObject innerClass,
@NotNull PsiElement targetContainer
) {
super(project, true);
this.project = project;
this.innerClass = innerClass;
this.targetContainer = targetContainer;
this.innerClassDescriptor = (ClassDescriptor) ResolutionUtils.resolveToDescriptor(innerClass);
setTitle("Move Nested Classes to Upper Level");
init();
packageNameLabel.setLabelFor(packageNameField.getChildComponent());
classNameLabel.setLabelFor(classNameField);
parameterNameLabel.setLabelFor(parameterField);
openInEditorPanel.add(initOpenInEditorCb(), BorderLayout.EAST);
}
private void createUIComponents() {
parameterField = new NameSuggestionsField(project);
packageNameField = new PackageNameReferenceEditorCombo("", project, RECENTS_KEY,
RefactoringBundle.message("choose.destination.package"));
}
@Override
protected String getMovePropertySuffix() {
return "Nested Classes to Upper Level";
}
@Override
protected String getHelpId() {
return HelpID.MOVE_INNER_UPPER;
}
@Override
protected String getCbTitle() {
return "Open moved member in editor";
}
public boolean isSearchInComments() {
return searchInCommentsCheckBox.isSelected();
}
public boolean isSearchInNonJavaFiles() {
return searchForTextOccurrencesCheckBox.isSelected();
}
public String getClassName() {
return classNameField.getText().trim();
}
@Nullable
public String getParameterName() {
return parameterField != null ? parameterField.getEnteredName() : null;
}
private boolean isThisNeeded() {
return innerClass instanceof KtClass && MoveUtilsKt.traverseOuterInstanceReferences((KtClass) innerClass, true);
}
@Nullable
private FqName getTargetPackageFqName() {
if (targetContainer instanceof PsiDirectory) return innerClass.getContainingKtFile().getPackageFqName();
if (targetContainer instanceof KtFile) return ((KtFile) targetContainer).getPackageFqName();
return null;
}
@NotNull
private KotlinType getOuterInstanceType() {
return ((ClassDescriptor) innerClassDescriptor.getContainingDeclaration()).getDefaultType();
}
@Override
protected void init() {
classNameField.setText(innerClass.getName());
classNameField.selectAll();
if (innerClass instanceof KtClass && ((KtClass) innerClass).isInner()) {
passOuterClassCheckBox.setSelected(true);
passOuterClassCheckBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
parameterField.setEnabled(passOuterClassCheckBox.isSelected());
}
});
}
else {
passOuterClassCheckBox.setSelected(false);
passOuterClassCheckBox.setEnabled(false);
parameterField.setEnabled(false);
}
if (passOuterClassCheckBox.isEnabled()) {
boolean thisNeeded = isThisNeeded();
passOuterClassCheckBox.setSelected(thisNeeded);
parameterField.setEnabled(thisNeeded);
}
passOuterClassCheckBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
boolean selected = passOuterClassCheckBox.isSelected();
parameterField.getComponent().setEnabled(selected);
}
});
if (!(targetContainer instanceof PsiDirectory)) {
packageNameField.setVisible(false);
packageNameLabel.setVisible(false);
}
if (innerClass instanceof KtClass && ((KtClass) innerClass).isInner()) {
KtClassBody innerClassBody = innerClass.getBody();
Function1<String, Boolean> validator =
innerClassBody != null
? new NewDeclarationNameValidator(innerClassBody, (PsiElement) null,
NewDeclarationNameValidator.Target.VARIABLES)
: new CollectingNameValidator();
List<String> suggestions = KotlinNameSuggester.INSTANCE.suggestNamesByType(getOuterInstanceType(), validator, "outer");
parameterField.setSuggestions(ArrayUtil.toStringArray(suggestions));
}
else {
parameterField.getComponent().setEnabled(false);
}
FqName packageFqName = getTargetPackageFqName();
if (packageFqName != null) {
packageNameField.prependItem(packageFqName.asString());
}
super.init();
}
@Override
public JComponent getPreferredFocusedComponent() {
return classNameField;
}
@Override
protected String getDimensionServiceKey() {
return "#com.intellij.refactoring.move.moveInner.MoveInnerDialog";
}
@Override
protected JComponent createNorthPanel() {
return panel;
}
@Override
protected JComponent createCenterPanel() {
return null;
}
@Nullable
private PsiElement getTargetContainer() {
if (targetContainer instanceof PsiDirectory) {
PsiDirectory psiDirectory = (PsiDirectory) targetContainer;
FqName oldPackageFqName = getTargetPackageFqName();
String targetName = packageNameField.getText();
if (!Comparing.equal(oldPackageFqName != null ? oldPackageFqName.asString() : null, targetName)) {
ProjectRootManager projectRootManager = ProjectRootManager.getInstance(project);
List<VirtualFile> contentSourceRoots = JavaProjectRootsUtil.getSuitableDestinationSourceRoots(project);
final PackageWrapper newPackage = new PackageWrapper(PsiManager.getInstance(project), targetName);
final VirtualFile targetSourceRoot;
if (contentSourceRoots.size() > 1) {
PsiDirectory initialDir = null;
PsiPackage oldPackage = oldPackageFqName != null
? JavaPsiFacade.getInstance(project).findPackage(oldPackageFqName.asString())
: null;
if (oldPackage != null) {
PsiDirectory[] directories = oldPackage.getDirectories();
VirtualFile root = projectRootManager.getFileIndex().getContentRootForFile(psiDirectory.getVirtualFile());
for (PsiDirectory dir : directories) {
if (Comparing.equal(projectRootManager.getFileIndex().getContentRootForFile(dir.getVirtualFile()), root)) {
initialDir = dir;
}
}
}
VirtualFile sourceRoot = MoveClassesOrPackagesUtil.chooseSourceRoot(newPackage, contentSourceRoots, initialDir);
if (sourceRoot == null) return null;
targetSourceRoot = sourceRoot;
}
else {
targetSourceRoot = contentSourceRoots.get(0);
}
PsiDirectory dir = RefactoringUtil.findPackageDirectoryInSourceRoot(newPackage, targetSourceRoot);
if (dir == null) {
dir = ApplicationManager.getApplication().runWriteAction(new NullableComputable<PsiDirectory>() {
@Override
public PsiDirectory compute() {
try {
return RefactoringUtil.createPackageDirectoryInSourceRoot(newPackage, targetSourceRoot);
}
catch (IncorrectOperationException e) {
return null;
}
}
});
}
return dir;
}
return targetContainer;
}
if (targetContainer instanceof KtFile || targetContainer instanceof KtClassOrObject) return targetContainer;
return null;
}
@Nullable
private String getErrorMessageIfAny() {
String className = getClassName();
String parameterName = getParameterName();
if (className != null && className.isEmpty()) return RefactoringBundle.message("no.class.name.specified");
if (!KotlinNameSuggester.INSTANCE.isIdentifier(className)) return RefactoringMessageUtil.getIncorrectIdentifierMessage(className);
if (passOuterClassCheckBox.isSelected()) {
if (parameterName != null && parameterName.isEmpty()) return RefactoringBundle.message("no.parameter.name.specified");
if (!KotlinNameSuggester.INSTANCE.isIdentifier(parameterName)) return RefactoringMessageUtil.getIncorrectIdentifierMessage(parameterName);
}
PsiElement targetContainer = getTargetContainer();
if (targetContainer instanceof KtClassOrObject) {
KtClassOrObject targetClass = (KtClassOrObject) targetContainer;
for (KtDeclaration member : targetClass.getDeclarations()) {
if (member instanceof KtClassOrObject && className != null && className.equals(member.getName())) {
return RefactoringBundle.message("inner.class.exists", className, targetClass.getName());
}
}
}
if (targetContainer instanceof PsiDirectory || targetContainer instanceof KtFile) {
FqName targetPackageFqName = getTargetPackageFqName();
if (targetPackageFqName == null) return "No package corresponds to this directory";
//noinspection ConstantConditions
ClassifierDescriptor existingClass = DescriptorUtils
.getContainingModule(innerClassDescriptor)
.getPackage(targetPackageFqName)
.getMemberScope()
.getContributedClassifier(Name.identifier(className), NoLookupLocation.FROM_IDE);
if (existingClass != null) return "Class " + className + " already exists in package " + targetPackageFqName;
PsiDirectory targetDir = targetContainer instanceof PsiDirectory
? (PsiDirectory) targetContainer
: targetContainer.getContainingFile().getContainingDirectory();
return RefactoringMessageUtil.checkCanCreateFile(targetDir, className + ".kt");
}
return null;
}
@Override
protected void doAction() {
String errorMessage = getErrorMessageIfAny();
if (errorMessage != null) {
CommonRefactoringUtil.showErrorMessage(MoveInnerImpl.REFACTORING_NAME, errorMessage, HelpID.MOVE_INNER_UPPER, project);
return;
}
PsiElement target = getTargetContainer();
if (target == null) return;
KotlinMoveTarget moveTarget;
if (target instanceof PsiDirectory) {
final PsiDirectory targetDir = (PsiDirectory) target;
final FqName targetPackageFqName = getTargetPackageFqName();
if (targetPackageFqName == null) return;
final String targetFileName = KotlinNameSuggester.INSTANCE.suggestNameByName(
innerClass.getName() + "." + KotlinFileType.EXTENSION,
new Function1<String, Boolean>() {
@Override
public Boolean invoke(String s) {
return targetDir.findFile(s) == null;
}
}
);
moveTarget = new KotlinMoveTargetForDeferredFile(
targetPackageFqName,
new Function1<KtFile, KtFile>() {
@Override
public KtFile invoke(@NotNull KtFile originalFile) {
return JetRefactoringUtilKt.createKotlinFile(targetFileName, targetDir, targetPackageFqName.asString());
}
}
);
}
else {
//noinspection ConstantConditions
moveTarget = new KotlinMoveTargetForExistingElement((KtElement) target);
}
String outerInstanceParameterName = passOuterClassCheckBox.isSelected() ? getParameterName() : null;
String newClassName = getClassName();
MoveDeclarationsDelegate delegate = new MoveDeclarationsDelegate.NestedClass(newClassName, outerInstanceParameterName);
MoveDeclarationsDescriptor moveDescriptor = new MoveDeclarationsDescriptor(
CollectionsKt.listOf(innerClass),
moveTarget,
delegate,
isSearchInComments(),
isSearchInNonJavaFiles(),
true,
false,
null,
isOpenInEditor()
);
saveOpenInEditorOption();
invokeRefactoring(new MoveKotlinDeclarationsProcessor(project, moveDescriptor, Mover.Default.INSTANCE));
}
}