Reuse Java safe delete for non-local functions in Kotlin
This commit is contained in:
+35
-37
@@ -40,6 +40,7 @@ import com.intellij.util.Processor;
|
|||||||
import com.intellij.util.containers.ContainerUtil;
|
import com.intellij.util.containers.ContainerUtil;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.jet.asJava.AsJavaPackage;
|
||||||
import org.jetbrains.jet.asJava.LightClassUtil;
|
import org.jetbrains.jet.asJava.LightClassUtil;
|
||||||
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor;
|
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||||
@@ -101,7 +102,14 @@ public class KotlinSafeDeleteProcessor extends JavaSafeDeleteProcessor {
|
|||||||
return findClassOrObjectUsages(element, (JetClassOrObject) element, allElementsToDelete, result);
|
return findClassOrObjectUsages(element, (JetClassOrObject) element, allElementsToDelete, result);
|
||||||
}
|
}
|
||||||
if (element instanceof JetNamedFunction) {
|
if (element instanceof JetNamedFunction) {
|
||||||
return findFunctionUsages((JetNamedFunction) element, allElementsToDelete, result);
|
JetNamedFunction function = (JetNamedFunction) element;
|
||||||
|
if (function.isLocal()) {
|
||||||
|
return findLocalDeclarationUsages(function, allElementsToDelete, result);
|
||||||
|
}
|
||||||
|
PsiMethod method = LightClassUtil.getLightClassMethod((JetNamedFunction) element);
|
||||||
|
if (method != null) return findPsiMethodUsages(method, allElementsToDelete, result);
|
||||||
|
|
||||||
|
return getSearchInfo(element, allElementsToDelete);
|
||||||
}
|
}
|
||||||
if (element instanceof PsiMethod) {
|
if (element instanceof PsiMethod) {
|
||||||
return findPsiMethodUsages((PsiMethod) element, allElementsToDelete, result);
|
return findPsiMethodUsages((PsiMethod) element, allElementsToDelete, result);
|
||||||
@@ -110,7 +118,7 @@ public class KotlinSafeDeleteProcessor extends JavaSafeDeleteProcessor {
|
|||||||
JetProperty property = (JetProperty) element;
|
JetProperty property = (JetProperty) element;
|
||||||
|
|
||||||
if (property.isLocal()) {
|
if (property.isLocal()) {
|
||||||
return findLocalVariableUsages(property, allElementsToDelete, result);
|
return findLocalDeclarationUsages(property, allElementsToDelete, result);
|
||||||
}
|
}
|
||||||
return findPropertyUsages(property, allElementsToDelete, result);
|
return findPropertyUsages(property, allElementsToDelete, result);
|
||||||
}
|
}
|
||||||
@@ -198,11 +206,27 @@ public class KotlinSafeDeleteProcessor extends JavaSafeDeleteProcessor {
|
|||||||
}
|
}
|
||||||
else if (usageInfo instanceof SafeDeleteOverrideAnnotation) {
|
else if (usageInfo instanceof SafeDeleteOverrideAnnotation) {
|
||||||
SafeDeleteOverrideAnnotation overrideAnnotationUsageInfo = (SafeDeleteOverrideAnnotation) usageInfo;
|
SafeDeleteOverrideAnnotation overrideAnnotationUsageInfo = (SafeDeleteOverrideAnnotation) usageInfo;
|
||||||
usageInfo = new KotlinSafeDeleteOverrideAnnotation(
|
|
||||||
overrideAnnotationUsageInfo.getSmartPointer().getElement(), overrideAnnotationUsageInfo.getReferencedElement()
|
PsiElement targetElement = overrideAnnotationUsageInfo.getSmartPointer().getElement();
|
||||||
);
|
if (AsJavaPackage.getRepresentativeLightMethod(targetElement).findSuperMethods().length > 0) {
|
||||||
|
usageInfo = null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
usageInfo = new KotlinSafeDeleteOverrideAnnotation(targetElement, overrideAnnotationUsageInfo.getReferencedElement());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (usageInfo instanceof SafeDeleteReferenceJavaDeleteUsageInfo) {
|
||||||
|
SafeDeleteReferenceJavaDeleteUsageInfo javaDeleteUsageInfo = (SafeDeleteReferenceJavaDeleteUsageInfo) usageInfo;
|
||||||
|
PsiElement usageElement = javaDeleteUsageInfo.getElement();
|
||||||
|
JetImportDirective importDirective = PsiTreeUtil.getParentOfType(usageElement, JetImportDirective.class, false);
|
||||||
|
if (importDirective != null) {
|
||||||
|
usageInfo = SafeDeleteImportDirectiveUsageInfo.object$.create(importDirective,
|
||||||
|
(JetDeclaration) method.getNavigationElement());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (usageInfo != null) {
|
||||||
|
result.add(usageInfo);
|
||||||
}
|
}
|
||||||
result.add(usageInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return searchInfo;
|
return searchInfo;
|
||||||
@@ -236,32 +260,6 @@ public class KotlinSafeDeleteProcessor extends JavaSafeDeleteProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
protected static NonCodeUsageSearchInfo findFunctionUsages(
|
|
||||||
@NotNull JetNamedFunction function,
|
|
||||||
@NotNull PsiElement[] allElementsToDelete,
|
|
||||||
@NotNull List<UsageInfo> result
|
|
||||||
) {
|
|
||||||
PsiMethod lightMethod = LightClassUtil.getLightClassMethod(function);
|
|
||||||
if (lightMethod == null) {
|
|
||||||
return getSearchInfo(function, allElementsToDelete);
|
|
||||||
}
|
|
||||||
|
|
||||||
Collection<PsiReference> references = ReferencesSearch.search(function).findAll();
|
|
||||||
List<PsiMethod> overridingMethods = difference(OverridingMethodsSearch.search(lightMethod, true).findAll(), allElementsToDelete);
|
|
||||||
|
|
||||||
processDeclarationUsages(function, allElementsToDelete, result, references, overridingMethods);
|
|
||||||
|
|
||||||
Map<PsiMethod, Collection<PsiReference>> methodToReferences = getOverridingUsagesMap(overridingMethods);
|
|
||||||
Set<PsiMethod> safeOverriding =
|
|
||||||
filterSafeOverridingMethods(lightMethod, references, overridingMethods, methodToReferences, result, allElementsToDelete);
|
|
||||||
|
|
||||||
List<PsiElement> ignoredElements = new ArrayList<PsiElement>(safeOverriding);
|
|
||||||
ContainerUtil.addAll(ignoredElements, allElementsToDelete);
|
|
||||||
return getSearchInfo(function, ignoredElements);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
protected static NonCodeUsageSearchInfo findPropertyUsages(
|
protected static NonCodeUsageSearchInfo findPropertyUsages(
|
||||||
@NotNull JetProperty property,
|
@NotNull JetProperty property,
|
||||||
@NotNull PsiElement[] allElementsToDelete,
|
@NotNull PsiElement[] allElementsToDelete,
|
||||||
@@ -316,23 +314,23 @@ public class KotlinSafeDeleteProcessor extends JavaSafeDeleteProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
protected static NonCodeUsageSearchInfo findLocalVariableUsages(
|
protected static NonCodeUsageSearchInfo findLocalDeclarationUsages(
|
||||||
@NotNull final JetProperty property,
|
@NotNull final JetDeclaration declaration,
|
||||||
@NotNull final PsiElement[] allElementsToDelete,
|
@NotNull final PsiElement[] allElementsToDelete,
|
||||||
@NotNull final List<UsageInfo> result
|
@NotNull final List<UsageInfo> result
|
||||||
) {
|
) {
|
||||||
ReferencesSearch.search(property, property.getUseScope()).forEach(new Processor<PsiReference>() {
|
ReferencesSearch.search(declaration, declaration.getUseScope()).forEach(new Processor<PsiReference>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean process(PsiReference reference) {
|
public boolean process(PsiReference reference) {
|
||||||
PsiElement element = reference.getElement();
|
PsiElement element = reference.getElement();
|
||||||
if (!isInside(element, allElementsToDelete)) {
|
if (!isInside(element, allElementsToDelete)) {
|
||||||
result.add(new SafeDeleteReferenceSimpleDeleteUsageInfo(element, property, false));
|
result.add(new SafeDeleteReferenceSimpleDeleteUsageInfo(element, declaration, false));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return getSearchInfo(property, allElementsToDelete);
|
return getSearchInfo(declaration, allElementsToDelete);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
fun foo() {
|
||||||
|
fun <caret>bar() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bar()
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
function foo.bar has 1 usage that is not safe to delete.
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
fun foo() {
|
||||||
|
fun <caret>bar() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
println()
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
fun foo() {
|
||||||
|
|
||||||
|
println()
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
open class A {
|
||||||
|
open fun foo() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Z {
|
||||||
|
fun <caret>foo()
|
||||||
|
}
|
||||||
|
|
||||||
|
class B: A, Z {
|
||||||
|
override fun foo() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
open class A {
|
||||||
|
open fun foo() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Z {
|
||||||
|
}
|
||||||
|
|
||||||
|
class B: A, Z {
|
||||||
|
override fun foo() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -149,6 +149,16 @@ public class JetSafeDeleteTestGenerated extends AbstractJetSafeDeleteTest {
|
|||||||
doFunctionTest("idea/testData/safeDelete/deleteFunction/kotlinFunction/implement2.kt");
|
doFunctionTest("idea/testData/safeDelete/deleteFunction/kotlinFunction/implement2.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("localFun1.kt")
|
||||||
|
public void testLocalFun1() throws Exception {
|
||||||
|
doFunctionTest("idea/testData/safeDelete/deleteFunction/kotlinFunction/localFun1.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("localFun2.kt")
|
||||||
|
public void testLocalFun2() throws Exception {
|
||||||
|
doFunctionTest("idea/testData/safeDelete/deleteFunction/kotlinFunction/localFun2.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("noUsages.kt")
|
@TestMetadata("noUsages.kt")
|
||||||
public void testNoUsages() throws Exception {
|
public void testNoUsages() throws Exception {
|
||||||
doFunctionTest("idea/testData/safeDelete/deleteFunction/kotlinFunction/noUsages.kt");
|
doFunctionTest("idea/testData/safeDelete/deleteFunction/kotlinFunction/noUsages.kt");
|
||||||
@@ -174,6 +184,11 @@ public class JetSafeDeleteTestGenerated extends AbstractJetSafeDeleteTest {
|
|||||||
doFunctionTest("idea/testData/safeDelete/deleteFunction/kotlinFunction/overrideAndImplement2.kt");
|
doFunctionTest("idea/testData/safeDelete/deleteFunction/kotlinFunction/overrideAndImplement2.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("overrideAndImplement3.kt")
|
||||||
|
public void testOverrideAndImplement3() throws Exception {
|
||||||
|
doFunctionTest("idea/testData/safeDelete/deleteFunction/kotlinFunction/overrideAndImplement3.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("overrideWithUsages.kt")
|
@TestMetadata("overrideWithUsages.kt")
|
||||||
public void testOverrideWithUsages() throws Exception {
|
public void testOverrideWithUsages() throws Exception {
|
||||||
doFunctionTest("idea/testData/safeDelete/deleteFunction/kotlinFunction/overrideWithUsages.kt");
|
doFunctionTest("idea/testData/safeDelete/deleteFunction/kotlinFunction/overrideWithUsages.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user