Safe Delete: Skip usages inside of overriding to-be-deleted declarations
#KT-7253 Fixed
This commit is contained in:
+18
-9
@@ -46,6 +46,7 @@ import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.utils.SmartSet
|
||||
import org.jetbrains.kotlin.utils.ifEmpty
|
||||
import java.util.*
|
||||
|
||||
@@ -55,11 +56,12 @@ class KotlinSafeDeleteProcessor : JavaSafeDeleteProcessor() {
|
||||
override fun findUsages(
|
||||
element: PsiElement, allElementsToDelete: Array<out PsiElement>, usages: MutableList<UsageInfo>
|
||||
): NonCodeUsageSearchInfo {
|
||||
val deleteList = allElementsToDelete.toList()
|
||||
val deleteSet = SmartSet.create<PsiElement>()
|
||||
deleteSet.addAll(allElementsToDelete)
|
||||
|
||||
fun getIgnoranceCondition() = Condition<PsiElement> {
|
||||
if (it is KtFile) return@Condition false
|
||||
deleteList.any { element -> JavaSafeDeleteProcessor.isInside(it, element.unwrapped) }
|
||||
deleteSet.any { element -> JavaSafeDeleteProcessor.isInside(it, element.unwrapped) }
|
||||
}
|
||||
|
||||
fun getSearchInfo(element: PsiElement): NonCodeUsageSearchInfo {
|
||||
@@ -70,6 +72,10 @@ class KotlinSafeDeleteProcessor : JavaSafeDeleteProcessor() {
|
||||
val javaUsages = ArrayList<UsageInfo>()
|
||||
val searchInfo = super.findUsages(element, allElementsToDelete, javaUsages)
|
||||
|
||||
javaUsages.filterIsInstance<SafeDeleteOverridingMethodUsageInfo>().mapNotNullTo(deleteSet) { it.element }
|
||||
|
||||
val ignoranceCondition = getIgnoranceCondition()
|
||||
|
||||
javaUsages.mapNotNullTo(usages) { usageInfo ->
|
||||
when (usageInfo) {
|
||||
is SafeDeleteOverridingMethodUsageInfo ->
|
||||
@@ -87,13 +93,16 @@ class KotlinSafeDeleteProcessor : JavaSafeDeleteProcessor() {
|
||||
|
||||
is SafeDeleteReferenceJavaDeleteUsageInfo ->
|
||||
usageInfo.element?.let { usageElement ->
|
||||
if (usageElement.getNonStrictParentOfType<KtValueArgumentName>() != null) null
|
||||
else {
|
||||
usageElement.getNonStrictParentOfType<KtImportDirective>()?.let { importDirective ->
|
||||
SafeDeleteImportDirectiveUsageInfo(importDirective, element.unwrapped as KtDeclaration)
|
||||
} ?: if (forceReferencedElementUnwrapping) {
|
||||
SafeDeleteReferenceJavaDeleteUsageInfo(usageElement, element.unwrapped, usageInfo.isSafeDelete)
|
||||
} else usageInfo
|
||||
when {
|
||||
usageElement.getNonStrictParentOfType<KtValueArgumentName>() != null -> null
|
||||
ignoranceCondition.value(usageElement) -> null
|
||||
else -> {
|
||||
usageElement.getNonStrictParentOfType<KtImportDirective>()?.let { importDirective ->
|
||||
SafeDeleteImportDirectiveUsageInfo(importDirective, element.unwrapped as KtDeclaration)
|
||||
} ?: if (forceReferencedElementUnwrapping) {
|
||||
SafeDeleteReferenceJavaDeleteUsageInfo(usageElement, element.unwrapped, usageInfo.isSafeDelete)
|
||||
} else usageInfo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
class J implements T {
|
||||
T u;
|
||||
|
||||
@Override
|
||||
public void foo() {
|
||||
u.foo();
|
||||
}
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
class J implements T {
|
||||
T u;
|
||||
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
interface T {
|
||||
fun <caret>foo()
|
||||
}
|
||||
|
||||
class A(val t: T) : T {
|
||||
override fun foo() {
|
||||
t.foo()
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
interface T {
|
||||
}
|
||||
|
||||
class A(val t: T) : T {
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
abstract class I implements T {
|
||||
T u;
|
||||
|
||||
@Override
|
||||
public int getFoo() {
|
||||
return u.getFoo();
|
||||
}
|
||||
}
|
||||
|
||||
class J implements T {
|
||||
T u;
|
||||
|
||||
@Override
|
||||
public int getFoo() {
|
||||
return u.getFoo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFoo(int value) {
|
||||
u.setFoo(value);
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
abstract class I implements T {
|
||||
T u;
|
||||
|
||||
}
|
||||
|
||||
class J implements T {
|
||||
T u;
|
||||
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
interface T {
|
||||
var <caret>foo: Int
|
||||
}
|
||||
|
||||
class A(val t: T) : T {
|
||||
override var foo: Int
|
||||
get() = t.foo
|
||||
set(value) {
|
||||
t.foo = value
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
interface T {
|
||||
}
|
||||
|
||||
class A(val t: T) : T {
|
||||
}
|
||||
+12
@@ -384,6 +384,12 @@ public class SafeDeleteTestGenerated extends AbstractSafeDeleteTest {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/safeDelete/deleteFunction/kotlinFunctionWithJava/secondaryConstructor.kt");
|
||||
doFunctionTestWithJava(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("usageInOverrideToDelete.kt")
|
||||
public void testUsageInOverrideToDelete() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/safeDelete/deleteFunction/kotlinFunctionWithJava/usageInOverrideToDelete.kt");
|
||||
doFunctionTestWithJava(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/refactoring/safeDelete/deleteFunction/javaFunctionWithKotlin")
|
||||
@@ -627,6 +633,12 @@ public class SafeDeleteTestGenerated extends AbstractSafeDeleteTest {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/safeDelete/deleteProperty/kotlinPropertyWithJava/propertyExt.kt");
|
||||
doPropertyTestWithJava(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("usageInOverrideToDelete.kt")
|
||||
public void testUsageInOverrideToDelete() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/safeDelete/deleteProperty/kotlinPropertyWithJava/usageInOverrideToDelete.kt");
|
||||
doPropertyTestWithJava(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/refactoring/safeDelete/deleteProperty/javaPropertyWithKotlin")
|
||||
|
||||
Reference in New Issue
Block a user