Safe Delete: Delete interface reference from super-type list when applying Safe Delete to Java interface
#KT-11282 Fixed
This commit is contained in:
@@ -35,6 +35,7 @@ Issues fixed:
|
|||||||
- [KT-11617](https://youtrack.jetbrains.com/issue/KT-11617) Fixed title of Introduce Parameter declaration chooser
|
- [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-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-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
|
#### Debugger
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,13 @@
|
|||||||
package org.jetbrains.kotlin.psi;
|
package org.jetbrains.kotlin.psi;
|
||||||
|
|
||||||
import com.intellij.lang.ASTNode;
|
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.annotations.NotNull;
|
||||||
|
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||||
import org.jetbrains.kotlin.psi.stubs.KotlinPlaceHolderStub;
|
import org.jetbrains.kotlin.psi.stubs.KotlinPlaceHolderStub;
|
||||||
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes;
|
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes;
|
||||||
|
|
||||||
@@ -38,6 +44,20 @@ public class KtSuperTypeList extends KtElementImplStub<KotlinPlaceHolderStub<KtS
|
|||||||
return visitor.visitSuperTypeList(this, data);
|
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() {
|
public List<KtSuperTypeListEntry> getEntries() {
|
||||||
return Arrays.asList(getStubOrPsiChildren(KtStubElementTypes.SUPER_TYPE_LIST_ENTRIES, KtSuperTypeListEntry.ARRAY_FACTORY));
|
return Arrays.asList(getStubOrPsiChildren(KtStubElementTypes.SUPER_TYPE_LIST_ENTRIES, KtSuperTypeListEntry.ARRAY_FACTORY));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -531,6 +531,7 @@ fun main(args: Array<String>) {
|
|||||||
testClass<AbstractSafeDeleteTest>() {
|
testClass<AbstractSafeDeleteTest>() {
|
||||||
model("refactoring/safeDelete/deleteClass/kotlinClass", testMethod = "doClassTest")
|
model("refactoring/safeDelete/deleteClass/kotlinClass", testMethod = "doClassTest")
|
||||||
model("refactoring/safeDelete/deleteClass/kotlinClassWithJava", testMethod = "doClassTestWithJava")
|
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/deleteObject/kotlinObject", testMethod = "doObjectTest")
|
||||||
model("refactoring/safeDelete/deleteFunction/kotlinFunction", testMethod = "doFunctionTest")
|
model("refactoring/safeDelete/deleteFunction/kotlinFunction", testMethod = "doFunctionTest")
|
||||||
model("refactoring/safeDelete/deleteFunction/kotlinFunctionWithJava", testMethod = "doFunctionTestWithJava")
|
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.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypeAndBranch
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.utils.SmartSet
|
import org.jetbrains.kotlin.utils.SmartSet
|
||||||
import org.jetbrains.kotlin.utils.ifEmpty
|
import org.jetbrains.kotlin.utils.ifEmpty
|
||||||
@@ -99,6 +100,8 @@ class KotlinSafeDeleteProcessor : JavaSafeDeleteProcessor() {
|
|||||||
else -> {
|
else -> {
|
||||||
usageElement.getNonStrictParentOfType<KtImportDirective>()?.let { importDirective ->
|
usageElement.getNonStrictParentOfType<KtImportDirective>()?.let { importDirective ->
|
||||||
SafeDeleteImportDirectiveUsageInfo(importDirective, element.unwrapped as KtDeclaration)
|
SafeDeleteImportDirectiveUsageInfo(importDirective, element.unwrapped as KtDeclaration)
|
||||||
|
} ?: usageElement.getParentOfTypeAndBranch<KtSuperTypeEntry> { typeReference }?.let {
|
||||||
|
if (element is PsiClass && element.isInterface) SafeDeleteSuperTypeUsageInfo(it, element) else usageInfo
|
||||||
} ?: if (forceReferencedElementUnwrapping) {
|
} ?: if (forceReferencedElementUnwrapping) {
|
||||||
SafeDeleteReferenceJavaDeleteUsageInfo(usageElement, element.unwrapped, usageInfo.isSafeDelete)
|
SafeDeleteReferenceJavaDeleteUsageInfo(usageElement, element.unwrapped, usageInfo.isSafeDelete)
|
||||||
} else usageInfo
|
} else usageInfo
|
||||||
@@ -214,6 +217,9 @@ class KotlinSafeDeleteProcessor : JavaSafeDeleteProcessor() {
|
|||||||
is PsiMethod ->
|
is PsiMethod ->
|
||||||
findUsagesByJavaProcessor(element, false)
|
findUsagesByJavaProcessor(element, false)
|
||||||
|
|
||||||
|
is PsiClass ->
|
||||||
|
findUsagesByJavaProcessor(element, false)
|
||||||
|
|
||||||
is KtProperty -> {
|
is KtProperty -> {
|
||||||
if (!LightClassUtil.canGenerateLightClass(element)) {
|
if (!LightClassUtil.canGenerateLightClass(element)) {
|
||||||
findKotlinDeclarationUsages(element)
|
findKotlinDeclarationUsages(element)
|
||||||
|
|||||||
+19
@@ -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
|
package org.jetbrains.kotlin.idea.refactoring.safeDelete
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiClass
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiMethod
|
import com.intellij.psi.PsiMethod
|
||||||
import com.intellij.psi.search.searches.OverridingMethodsSearch
|
import com.intellij.psi.search.searches.OverridingMethodsSearch
|
||||||
@@ -36,6 +37,7 @@ fun PsiElement.canDeleteElement(): Boolean {
|
|||||||
|| this is KtSecondaryConstructor
|
|| this is KtSecondaryConstructor
|
||||||
|| this is KtNamedFunction
|
|| this is KtNamedFunction
|
||||||
|| this is PsiMethod
|
|| this is PsiMethod
|
||||||
|
|| this is PsiClass
|
||||||
|| this is KtProperty
|
|| this is KtProperty
|
||||||
|| this is KtTypeParameter
|
|| this is KtTypeParameter
|
||||||
}
|
}
|
||||||
|
|||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
public interface <caret>I {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface II {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class J implements I, II {
|
||||||
|
|
||||||
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
public interface II {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class J implements II {
|
||||||
|
|
||||||
|
}
|
||||||
idea/testData/refactoring/safeDelete/deleteClass/javaClassWithKotlin/javaInterfaceInSuperTypeList.kt
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
class K : I, II {
|
||||||
|
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
class K : II {
|
||||||
|
|
||||||
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
public interface <caret>I {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class J implements I {
|
||||||
|
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
public class J {
|
||||||
|
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
class K : I {
|
||||||
|
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
class K {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
class B{
|
||||||
|
|
||||||
|
}
|
||||||
-1
@@ -1 +0,0 @@
|
|||||||
interface test.A has 1 usage that is not safe to delete.
|
|
||||||
+5
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.idea.refactoring.safeDelete;
|
|||||||
import com.intellij.codeInsight.TargetElementUtilBase;
|
import com.intellij.codeInsight.TargetElementUtilBase;
|
||||||
import com.intellij.openapi.editor.Editor;
|
import com.intellij.openapi.editor.Editor;
|
||||||
import com.intellij.openapi.util.text.StringUtil;
|
import com.intellij.openapi.util.text.StringUtil;
|
||||||
|
import com.intellij.psi.PsiClass;
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import com.intellij.psi.PsiMethod;
|
import com.intellij.psi.PsiMethod;
|
||||||
import com.intellij.psi.util.PsiTreeUtil;
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
@@ -58,6 +59,10 @@ public abstract class AbstractSafeDeleteTest extends KotlinLightCodeInsightFixtu
|
|||||||
doTest(path, KtClass.class, true);
|
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 {
|
public void doObjectTest(@NotNull String path) throws Exception {
|
||||||
doTest(path, KtObjectDeclaration.class, false);
|
doTest(path, KtObjectDeclaration.class, false);
|
||||||
}
|
}
|
||||||
|
|||||||
+21
@@ -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")
|
@TestMetadata("idea/testData/refactoring/safeDelete/deleteObject/kotlinObject")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Reference in New Issue
Block a user