Safe Delete: Delete interface reference from super-type list when applying Safe Delete to Java interface

#KT-11282 Fixed
This commit is contained in:
Alexey Sedunov
2016-04-20 12:47:13 +03:00
parent 613a274c90
commit 6a1387b9b9
18 changed files with 120 additions and 1 deletions
+1
View File
@@ -35,6 +35,7 @@ Issues fixed:
- [KT-11617](https://youtrack.jetbrains.com/issue/KT-11617) Fixed title of Introduce Parameter declaration chooser
- [KT-11817](https://youtrack.jetbrains.com/issue/KT-11817) Fixed rename of Kotlin enum constants through Java references
- [KT-11816](https://youtrack.jetbrains.com/issue/KT-11816) Fixed usages search for Safe Delete on simple enum entries
- [KT-11282](https://youtrack.jetbrains.com/issue/KT-11282) Delete interface reference from super-type list when applying Safe Delete to Java interface
#### Debugger
@@ -17,7 +17,13 @@
package org.jetbrains.kotlin.psi;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiComment;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.lexer.KtTokens;
import org.jetbrains.kotlin.psi.stubs.KotlinPlaceHolderStub;
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes;
@@ -38,6 +44,20 @@ public class KtSuperTypeList extends KtElementImplStub<KotlinPlaceHolderStub<KtS
return visitor.visitSuperTypeList(this, data);
}
public void removeEntry(@NotNull KtSuperTypeListEntry entry) {
EditCommaSeparatedListHelper.INSTANCE.removeItem(entry);
if (getEntries().isEmpty()) {
delete();
}
}
@Override
public void delete() throws IncorrectOperationException {
PsiElement left = PsiTreeUtil.skipSiblingsBackward(this, PsiWhiteSpace.class, PsiComment.class);
if (left == null || left.getNode().getElementType() != KtTokens.COLON) left = this;
getParent().deleteChildRange(left, this);
}
public List<KtSuperTypeListEntry> getEntries() {
return Arrays.asList(getStubOrPsiChildren(KtStubElementTypes.SUPER_TYPE_LIST_ENTRIES, KtSuperTypeListEntry.ARRAY_FACTORY));
}
@@ -531,6 +531,7 @@ fun main(args: Array<String>) {
testClass<AbstractSafeDeleteTest>() {
model("refactoring/safeDelete/deleteClass/kotlinClass", testMethod = "doClassTest")
model("refactoring/safeDelete/deleteClass/kotlinClassWithJava", testMethod = "doClassTestWithJava")
model("refactoring/safeDelete/deleteClass/javaClassWithKotlin", extension = "java", testMethod = "doJavaClassTest")
model("refactoring/safeDelete/deleteObject/kotlinObject", testMethod = "doObjectTest")
model("refactoring/safeDelete/deleteFunction/kotlinFunction", testMethod = "doFunctionTest")
model("refactoring/safeDelete/deleteFunction/kotlinFunctionWithJava", testMethod = "doFunctionTestWithJava")
@@ -45,6 +45,7 @@ import org.jetbrains.kotlin.idea.search.usagesSearch.processDelegationCallConstr
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypeAndBranch
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.utils.SmartSet
import org.jetbrains.kotlin.utils.ifEmpty
@@ -99,6 +100,8 @@ class KotlinSafeDeleteProcessor : JavaSafeDeleteProcessor() {
else -> {
usageElement.getNonStrictParentOfType<KtImportDirective>()?.let { importDirective ->
SafeDeleteImportDirectiveUsageInfo(importDirective, element.unwrapped as KtDeclaration)
} ?: usageElement.getParentOfTypeAndBranch<KtSuperTypeEntry> { typeReference }?.let {
if (element is PsiClass && element.isInterface) SafeDeleteSuperTypeUsageInfo(it, element) else usageInfo
} ?: if (forceReferencedElementUnwrapping) {
SafeDeleteReferenceJavaDeleteUsageInfo(usageElement, element.unwrapped, usageInfo.isSafeDelete)
} else usageInfo
@@ -214,6 +217,9 @@ class KotlinSafeDeleteProcessor : JavaSafeDeleteProcessor() {
is PsiMethod ->
findUsagesByJavaProcessor(element, false)
is PsiClass ->
findUsagesByJavaProcessor(element, false)
is KtProperty -> {
if (!LightClassUtil.canGenerateLightClass(element)) {
findKotlinDeclarationUsages(element)
@@ -0,0 +1,19 @@
package org.jetbrains.kotlin.idea.refactoring.safeDelete
import com.intellij.psi.PsiElement
import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteReferenceUsageInfo
import org.jetbrains.kotlin.psi.KtSuperTypeEntry
import org.jetbrains.kotlin.psi.KtSuperTypeList
class SafeDeleteSuperTypeUsageInfo(
entry: KtSuperTypeEntry,
referencedElement: PsiElement
) : SafeDeleteReferenceUsageInfo(entry, referencedElement, true) {
private val entry: KtSuperTypeEntry?
get() = element as? KtSuperTypeEntry
override fun deleteElement() {
val entry = entry ?: return
(entry.parent as? KtSuperTypeList)?.removeEntry(entry)
}
}
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.idea.refactoring.safeDelete
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiMethod
import com.intellij.psi.search.searches.OverridingMethodsSearch
@@ -36,6 +37,7 @@ fun PsiElement.canDeleteElement(): Boolean {
|| this is KtSecondaryConstructor
|| this is KtNamedFunction
|| this is PsiMethod
|| this is PsiClass
|| this is KtProperty
|| this is KtTypeParameter
}
@@ -0,0 +1,11 @@
public interface <caret>I {
}
public interface II {
}
public class J implements I, II {
}
@@ -0,0 +1,7 @@
public interface II {
}
public class J implements II {
}
@@ -0,0 +1,3 @@
class K : I, II {
}
@@ -0,0 +1,7 @@
public interface <caret>I {
}
public class J implements I {
}
@@ -0,0 +1,5 @@
package test
class B{
}
@@ -1 +0,0 @@
interface test.A has 1 usage that is not safe to delete.
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.idea.refactoring.safeDelete;
import com.intellij.codeInsight.TargetElementUtilBase;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.util.PsiTreeUtil;
@@ -58,6 +59,10 @@ public abstract class AbstractSafeDeleteTest extends KotlinLightCodeInsightFixtu
doTest(path, KtClass.class, true);
}
public void doJavaClassTest(@NotNull String path) throws Exception {
doTest(path, PsiClass.class, true);
}
public void doObjectTest(@NotNull String path) throws Exception {
doTest(path, KtObjectDeclaration.class, false);
}
@@ -137,6 +137,27 @@ public class SafeDeleteTestGenerated extends AbstractSafeDeleteTest {
}
}
@TestMetadata("idea/testData/refactoring/safeDelete/deleteClass/javaClassWithKotlin")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class JavaClassWithKotlin extends AbstractSafeDeleteTest {
public void testAllFilesPresentInJavaClassWithKotlin() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/refactoring/safeDelete/deleteClass/javaClassWithKotlin"), Pattern.compile("^(.+)\\.java$"), true);
}
@TestMetadata("javaInterfaceInSuperTypeList.java")
public void testJavaInterfaceInSuperTypeList() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/safeDelete/deleteClass/javaClassWithKotlin/javaInterfaceInSuperTypeList.java");
doJavaClassTest(fileName);
}
@TestMetadata("javaInterfaceInSuperTypeListLast.java")
public void testJavaInterfaceInSuperTypeListLast() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/safeDelete/deleteClass/javaClassWithKotlin/javaInterfaceInSuperTypeListLast.java");
doJavaClassTest(fileName);
}
}
@TestMetadata("idea/testData/refactoring/safeDelete/deleteObject/kotlinObject")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)