Delete/Move: Delete entire file when deleting top-level class or object and no other top-level declarations are present. Ask the user confirmation if deletion if caused by the Move refactoring

#KT-8033 Fixed
This commit is contained in:
Alexey Sedunov
2015-06-15 16:17:57 +03:00
parent e1e818858e
commit dda271d38d
4 changed files with 23 additions and 16 deletions
@@ -16,10 +16,13 @@
package org.jetbrains.kotlin.psi package org.jetbrains.kotlin.psi
import com.intellij.lang.ASTNode
import com.intellij.lang.ASTNode import com.intellij.lang.ASTNode
import com.intellij.navigation.ItemPresentation import com.intellij.navigation.ItemPresentation
import com.intellij.navigation.ItemPresentationProviders import com.intellij.navigation.ItemPresentationProviders
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.impl.CheckUtil
import com.intellij.psi.impl.source.codeStyle.CodeEditUtil
import com.intellij.psi.stubs.IStubElementType import com.intellij.psi.stubs.IStubElementType
import org.jetbrains.kotlin.JetNodeTypes import org.jetbrains.kotlin.JetNodeTypes
import org.jetbrains.kotlin.lexer.JetTokens import org.jetbrains.kotlin.lexer.JetTokens
@@ -62,4 +65,16 @@ abstract public class JetClassOrObject : JetTypeParameterListOwnerStub<KotlinCla
public fun getSecondaryConstructors(): List<JetSecondaryConstructor> = getBody()?.getSecondaryConstructors().orEmpty() public fun getSecondaryConstructors(): List<JetSecondaryConstructor> = getBody()?.getSecondaryConstructors().orEmpty()
public fun isAnnotation(): Boolean = hasModifier(JetTokens.ANNOTATION_KEYWORD) public fun isAnnotation(): Boolean = hasModifier(JetTokens.ANNOTATION_KEYWORD)
public override fun delete() {
CheckUtil.checkWritable(this);
val file = getContainingJetFile();
if (!isTopLevel() || file.getDeclarations().size() > 1) {
CodeEditUtil.removeChild(getParent().getNode(), getNode());
}
else {
file.delete();
}
}
} }
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.idea.core
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.PsiWhiteSpace import com.intellij.psi.PsiWhiteSpace
import com.intellij.psi.impl.source.codeStyle.CodeEditUtil
import com.intellij.psi.util.PsiTreeUtil import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil import org.jetbrains.kotlin.psi.psiUtil
@@ -149,3 +150,7 @@ private fun deleteElementWithDelimiters(element: PsiElement) {
parent.deleteChildRange(from, to) parent.deleteChildRange(from, to)
} }
public fun PsiElement.deleteSingle() {
CodeEditUtil.removeChild(getParent()?.getNode() ?: return, getNode() ?: return)
}
@@ -45,6 +45,7 @@ import org.jetbrains.kotlin.asJava.toLightElements
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
import org.jetbrains.kotlin.idea.codeInsight.JetFileReferencesResolver import org.jetbrains.kotlin.idea.codeInsight.JetFileReferencesResolver
import org.jetbrains.kotlin.idea.codeInsight.shorten.addToShorteningWaitSet import org.jetbrains.kotlin.idea.codeInsight.shorten.addToShorteningWaitSet
import org.jetbrains.kotlin.idea.core.deleteSingle
import org.jetbrains.kotlin.idea.core.refactoring.getUsageContext import org.jetbrains.kotlin.idea.core.refactoring.getUsageContext
import org.jetbrains.kotlin.idea.refactoring.JetRefactoringBundle import org.jetbrains.kotlin.idea.refactoring.JetRefactoringBundle
import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName
@@ -68,7 +69,7 @@ trait Mover: (originalElement: JetNamedDeclaration, targetFile: JetFile) -> JetN
object Default: Mover { object Default: Mover {
override fun invoke(originalElement: JetNamedDeclaration, targetFile: JetFile): JetNamedDeclaration { override fun invoke(originalElement: JetNamedDeclaration, targetFile: JetFile): JetNamedDeclaration {
val newElement = targetFile.add(originalElement) as JetNamedDeclaration val newElement = targetFile.add(originalElement) as JetNamedDeclaration
originalElement.delete() originalElement.deleteSingle()
return newElement return newElement
} }
} }
@@ -37,12 +37,12 @@ import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.idea.JetBundle import org.jetbrains.kotlin.idea.JetBundle
import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.core.deleteElementAndCleanParent
import org.jetbrains.kotlin.idea.refactoring.JetRefactoringUtil import org.jetbrains.kotlin.idea.refactoring.JetRefactoringUtil
import org.jetbrains.kotlin.idea.references.JetReference import org.jetbrains.kotlin.idea.references.JetReference
import org.jetbrains.kotlin.idea.search.usagesSearch.processDelegationCallConstructorUsages import org.jetbrains.kotlin.idea.search.usagesSearch.processDelegationCallConstructorUsages
import org.jetbrains.kotlin.lexer.JetTokens import org.jetbrains.kotlin.lexer.JetTokens
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.idea.core.deleteElementAndCleanParent
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import java.util.ArrayList import java.util.ArrayList
@@ -326,18 +326,4 @@ public class KotlinSafeDeleteProcessor : JavaSafeDeleteProcessor() {
else -> super.getElementsToSearch(element, module, allElementsToDelete) 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
}
} }