Move: Suggest deleting file when all declarations are moved
This commit is contained in:
@@ -173,11 +173,6 @@ public class JetClass extends JetTypeParameterListOwnerStub<KotlinClassStub> imp
|
||||
return hasModifier(JetTokens.INNER_KEYWORD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() throws IncorrectOperationException {
|
||||
JetPsiUtil.deleteClass(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(PsiElement another) {
|
||||
if (super.isEquivalentTo(another)) {
|
||||
|
||||
@@ -182,11 +182,6 @@ public class JetObjectDeclaration extends JetNamedDeclarationStub<KotlinObjectSt
|
||||
return findChildByType(JetTokens.OBJECT_KEYWORD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() throws IncorrectOperationException {
|
||||
JetPsiUtil.deleteClass(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemPresentation getPresentation() {
|
||||
return ItemPresentationProviders.getItemPresentation(this);
|
||||
|
||||
@@ -297,18 +297,6 @@ public class JetPsiUtil {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void deleteClass(@NotNull JetClassOrObject clazz) {
|
||||
CheckUtil.checkWritable(clazz);
|
||||
JetFile file = clazz.getContainingJetFile();
|
||||
if (!clazz.isTopLevel() || file.getDeclarations().size() > 1) {
|
||||
PsiElement parent = clazz.getParent();
|
||||
CodeEditUtil.removeChild(parent.getNode(), clazz.getNode());
|
||||
}
|
||||
else {
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Name getAliasName(@NotNull JetImportDirective importDirective) {
|
||||
String aliasName = importDirective.getAliasName();
|
||||
|
||||
+5
@@ -86,6 +86,7 @@ public class MoveKotlinTopLevelDeclarationsOptions(
|
||||
val searchInCommentsAndStrings: Boolean = true,
|
||||
val searchInNonCode: Boolean = true,
|
||||
val updateInternalReferences: Boolean = true,
|
||||
val deleteSourceFile: Boolean = false,
|
||||
val moveCallback: MoveCallback? = null
|
||||
)
|
||||
|
||||
@@ -282,6 +283,10 @@ public class MoveKotlinTopLevelDeclarationsProcessor(
|
||||
}
|
||||
}
|
||||
|
||||
if (options.deleteSourceFile) {
|
||||
options.sourceFile.delete()
|
||||
}
|
||||
|
||||
nonCodeUsages = postProcessMoveUsages(usageList, oldToNewElementsMapping).toTypedArray()
|
||||
}
|
||||
catch (e: IncorrectOperationException) {
|
||||
|
||||
+65
-52
@@ -505,67 +505,80 @@ public class MoveKotlinTopLevelDeclarationsDialog extends RefactoringDialog {
|
||||
}
|
||||
|
||||
try {
|
||||
if (isMoveToPackage() && elementsToMove.equals(sourceFile.getDeclarations())) {
|
||||
final MoveDestination moveDestination = selectPackageBasedMoveDestination();
|
||||
//noinspection ConstantConditions
|
||||
PsiDirectory targetDir = moveDestination.getTargetIfExists(sourceFile);
|
||||
final String targetFileName = tfFileNameInPackage.getText();
|
||||
if (targetDir == null || targetDir.findFile(targetFileName) == null) {
|
||||
boolean deleteSourceFile = false;
|
||||
|
||||
if (elementsToMove.size() == sourceFile.getDeclarations().size()) {
|
||||
if (isMoveToPackage()) {
|
||||
final MoveDestination moveDestination = selectPackageBasedMoveDestination();
|
||||
//noinspection ConstantConditions
|
||||
final String temporaryName = UniqueNameGenerator.generateUniqueName(
|
||||
"temp",
|
||||
"",
|
||||
".kt",
|
||||
KotlinPackage.map(
|
||||
sourceFile.getContainingDirectory().getFiles(),
|
||||
new Function1<PsiFile, String>() {
|
||||
@Override
|
||||
public String invoke(PsiFile file) {
|
||||
return file.getName();
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
PsiDirectory targetDirectory = ApplicationPackage.runWriteAction(
|
||||
new Function0<PsiDirectory>() {
|
||||
@Override
|
||||
public PsiDirectory invoke() {
|
||||
sourceFile.setName(temporaryName);
|
||||
return moveDestination.getTargetDirectory(sourceFile);
|
||||
}
|
||||
}
|
||||
);
|
||||
invokeRefactoring(
|
||||
new MoveFilesOrDirectoriesProcessor(
|
||||
myProject,
|
||||
new PsiElement[] {sourceFile},
|
||||
targetDirectory,
|
||||
RefactoringSettings.getInstance().MOVE_SEARCH_FOR_REFERENCES_FOR_FILE,
|
||||
isSearchInComments(),
|
||||
isSearchInNonJavaFiles(),
|
||||
new MoveCallback() {
|
||||
@Override
|
||||
public void refactoringCompleted() {
|
||||
try {
|
||||
sourceFile.setName(targetFileName);
|
||||
PsiDirectory targetDir = moveDestination.getTargetIfExists(sourceFile);
|
||||
final String targetFileName = tfFileNameInPackage.getText();
|
||||
if (targetDir == null || targetDir.findFile(targetFileName) == null) {
|
||||
//noinspection ConstantConditions
|
||||
final String temporaryName = UniqueNameGenerator.generateUniqueName(
|
||||
"temp",
|
||||
"",
|
||||
".kt",
|
||||
KotlinPackage.map(
|
||||
sourceFile.getContainingDirectory().getFiles(),
|
||||
new Function1<PsiFile, String>() {
|
||||
@Override
|
||||
public String invoke(PsiFile file) {
|
||||
return file.getName();
|
||||
}
|
||||
finally {
|
||||
if (moveCallback != null) {
|
||||
moveCallback.refactoringCompleted();
|
||||
}
|
||||
)
|
||||
);
|
||||
PsiDirectory targetDirectory = ApplicationPackage.runWriteAction(
|
||||
new Function0<PsiDirectory>() {
|
||||
@Override
|
||||
public PsiDirectory invoke() {
|
||||
sourceFile.setName(temporaryName);
|
||||
return moveDestination.getTargetDirectory(sourceFile);
|
||||
}
|
||||
}
|
||||
);
|
||||
invokeRefactoring(
|
||||
new MoveFilesOrDirectoriesProcessor(
|
||||
myProject,
|
||||
new PsiElement[] {sourceFile},
|
||||
targetDirectory,
|
||||
RefactoringSettings.getInstance().MOVE_SEARCH_FOR_REFERENCES_FOR_FILE,
|
||||
isSearchInComments(),
|
||||
isSearchInNonJavaFiles(),
|
||||
new MoveCallback() {
|
||||
@Override
|
||||
public void refactoringCompleted() {
|
||||
try {
|
||||
sourceFile.setName(targetFileName);
|
||||
}
|
||||
finally {
|
||||
if (moveCallback != null) {
|
||||
moveCallback.refactoringCompleted();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
EmptyRunnable.INSTANCE
|
||||
)
|
||||
},
|
||||
EmptyRunnable.INSTANCE
|
||||
)
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int ret = Messages.showYesNoCancelDialog(
|
||||
myProject,
|
||||
"You are going to move all declarations out of '" + sourceFile.getVirtualFile().getPath() + "'. Do you want to delete this file?",
|
||||
RefactoringBundle.message("move.title"),
|
||||
Messages.getQuestionIcon()
|
||||
);
|
||||
|
||||
return;
|
||||
if (ret == Messages.CANCEL) return;
|
||||
deleteSourceFile = ret == Messages.YES;
|
||||
}
|
||||
}
|
||||
|
||||
MoveKotlinTopLevelDeclarationsOptions options = new MoveKotlinTopLevelDeclarationsOptions(
|
||||
sourceFile, elementsToMove, target, isSearchInComments(), isSearchInNonJavaFiles(), true, moveCallback
|
||||
sourceFile, elementsToMove, target, isSearchInComments(), isSearchInNonJavaFiles(), true, deleteSourceFile, moveCallback
|
||||
);
|
||||
invokeRefactoring(new MoveKotlinTopLevelDeclarationsProcessor(myProject, options, Mover.Default.INSTANCE$));
|
||||
}
|
||||
|
||||
@@ -156,8 +156,10 @@ fun createMoveUsageInfoIfPossible(
|
||||
}
|
||||
|
||||
public fun guessNewFileName(sourceFile: JetFile, declarationsToMove: Collection<JetNamedDeclaration>): String? {
|
||||
assert(sourceFile.getDeclarations().containsAll(declarationsToMove))
|
||||
|
||||
if (declarationsToMove.isEmpty()) return null
|
||||
if (sourceFile.getDeclarations() == declarationsToMove) return sourceFile.getName()
|
||||
if (sourceFile.getDeclarations().size() == declarationsToMove.size()) return sourceFile.getName()
|
||||
|
||||
val representative = declarationsToMove.firstOrNull { it is JetClassOrObject } ?: declarationsToMove.first()
|
||||
return "${representative.getName()}.${JetFileType.EXTENSION}"
|
||||
|
||||
+26
-13
@@ -24,30 +24,29 @@ import com.intellij.openapi.util.Conditions
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiMethod
|
||||
import com.intellij.psi.PsiParameter
|
||||
import com.intellij.psi.PsiReference
|
||||
import com.intellij.psi.impl.search.ConstructorReferencesSearchHelper
|
||||
import com.intellij.psi.search.SearchRequestCollector
|
||||
import com.intellij.psi.search.SearchSession
|
||||
import com.intellij.psi.search.searches.ReferencesSearch
|
||||
import com.intellij.refactoring.safeDelete.JavaSafeDeleteProcessor
|
||||
import com.intellij.refactoring.safeDelete.NonCodeUsageSearchInfo
|
||||
import com.intellij.refactoring.safeDelete.usageInfo.*
|
||||
import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteOverrideAnnotation
|
||||
import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteOverridingMethodUsageInfo
|
||||
import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteReferenceJavaDeleteUsageInfo
|
||||
import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteReferenceSimpleDeleteUsageInfo
|
||||
import com.intellij.usageView.UsageInfo
|
||||
import com.intellij.util.Processor
|
||||
import org.jetbrains.kotlin.asJava.*
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.lexer.JetTokens
|
||||
import org.jetbrains.kotlin.idea.JetBundle
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.refactoring.JetRefactoringUtil
|
||||
import org.jetbrains.kotlin.idea.references.JetReference
|
||||
import java.util.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.deleteElementAndCleanParent
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.processDelegationCallConstructorUsages
|
||||
import org.jetbrains.kotlin.lexer.JetTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.deleteElementAndCleanParent
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import java.util.ArrayList
|
||||
import java.util.Collections
|
||||
|
||||
public class KotlinSafeDeleteProcessor : JavaSafeDeleteProcessor() {
|
||||
override fun handlesElement(element: PsiElement): Boolean = element.canDeleteElement()
|
||||
@@ -327,4 +326,18 @@ public class KotlinSafeDeleteProcessor : JavaSafeDeleteProcessor() {
|
||||
else -> super.getElementsToSearch(element, module, allElementsToDelete)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getAdditionalElementsToDelete(
|
||||
element: PsiElement,
|
||||
allElementsToDelete: MutableCollection<PsiElement>,
|
||||
askUser: Boolean
|
||||
): Collection<PsiElement> {
|
||||
val filesToDelete = allElementsToDelete
|
||||
.filter { it is JetNamedDeclaration && it.getContainingJetFile() == it.getParent() }
|
||||
.groupBy { (it as JetNamedDeclaration).getContainingJetFile() }
|
||||
.filter { it.getKey().getDeclarations().size() == it.getValue().size() }
|
||||
.keySet()
|
||||
return super.getAdditionalElementsToDelete(element, allElementsToDelete, askUser)?.let { it + filesToDelete }
|
||||
?: filesToDelete
|
||||
}
|
||||
}
|
||||
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package source
|
||||
|
||||
import library.B
|
||||
import library.bar
|
||||
|
||||
Reference in New Issue
Block a user