diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/safeDelete/KotlinSafeDeleteProcessor.java b/idea/src/org/jetbrains/jet/plugin/refactoring/safeDelete/KotlinSafeDeleteProcessor.java index 4e26bc12239..db0e17abc3d 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/safeDelete/KotlinSafeDeleteProcessor.java +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/safeDelete/KotlinSafeDeleteProcessor.java @@ -22,10 +22,10 @@ import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.Conditions; import com.intellij.psi.*; import com.intellij.psi.search.searches.OverridingMethodsSearch; import com.intellij.psi.search.searches.ReferencesSearch; -import com.intellij.psi.util.MethodSignatureUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.safeDelete.JavaSafeDeleteProcessor; import com.intellij.refactoring.safeDelete.NonCodeUsageSearchInfo; @@ -34,7 +34,6 @@ import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteOverridingMethodU import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteReferenceJavaDeleteUsageInfo; import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteReferenceSimpleDeleteUsageInfo; import com.intellij.usageView.UsageInfo; -import com.intellij.util.ArrayUtilRt; import com.intellij.util.IncorrectOperationException; import com.intellij.util.Processor; import com.intellij.util.containers.ContainerUtil; @@ -106,7 +105,7 @@ public class KotlinSafeDeleteProcessor extends JavaSafeDeleteProcessor { if (element instanceof JetNamedFunction) { JetNamedFunction function = (JetNamedFunction) element; if (function.isLocal()) { - return findLocalDeclarationUsages(function, allElementsToDelete, result); + return findKotlinDeclarationUsages(function, allElementsToDelete, result); } PsiMethod method = LightClassUtil.getLightClassMethod((JetNamedFunction) element); if (method != null) return delegateToJavaProcessor(method, allElementsToDelete, result); @@ -118,11 +117,21 @@ public class KotlinSafeDeleteProcessor extends JavaSafeDeleteProcessor { } if (element instanceof JetProperty) { JetProperty property = (JetProperty) element; + NonCodeUsageSearchInfo searchInfo = findKotlinDeclarationUsages(property, allElementsToDelete, result); - if (property.isLocal()) { - return findLocalDeclarationUsages(property, allElementsToDelete, result); + if (property.isLocal()) return searchInfo; + + Condition insideDeleted = searchInfo.getInsideDeletedCondition(); + for (PsiMethod method: LightClassUtil.getLightClassPropertyMethods(property)) { + NonCodeUsageSearchInfo accessorSearchInfo = delegateToJavaProcessor(method, allElementsToDelete, result); + if (accessorSearchInfo == null) continue; + + insideDeleted = Conditions.or(insideDeleted, accessorSearchInfo.getInsideDeletedCondition()); } - return findPropertyUsages(property, allElementsToDelete, result); + + return insideDeleted != null + ? new NonCodeUsageSearchInfo(insideDeleted, element) + : getSearchInfo(element, allElementsToDelete); } if (element instanceof JetTypeParameter) { return findTypeParameterUsages((JetTypeParameter) element, allElementsToDelete, result); @@ -222,88 +231,7 @@ public class KotlinSafeDeleteProcessor extends JavaSafeDeleteProcessor { } @NotNull - private static List difference(@NotNull Collection from, @NotNull T[] a) { - List list = new ArrayList(from); - list.removeAll(Arrays.asList(a)); - return list; - } - - private static void processDeclarationUsages( - @NotNull JetDeclaration declaration, - @NotNull PsiElement[] allElementsToDelete, - @NotNull List result, - @NotNull Collection references, - @NotNull List overridingDeclarations - ) { - for (PsiReference reference : references) { - PsiElement element = reference.getElement(); - if (!isInside(element, allElementsToDelete) && !isInside(element, overridingDeclarations)) { - JetImportDirective importDirective = PsiTreeUtil.getParentOfType(element, JetImportDirective.class, false); - if (importDirective != null) { - result.add(new SafeDeleteImportDirectiveUsageInfo(importDirective, declaration)); - } - else { - result.add(new SafeDeleteReferenceSimpleDeleteUsageInfo(element, declaration, false)); - } - } - } - } - - protected static NonCodeUsageSearchInfo findPropertyUsages( - @NotNull JetProperty property, - @NotNull PsiElement[] allElementsToDelete, - @NotNull List result - ) { - LightClassUtil.PropertyAccessorsPsiMethods propertyMethods = LightClassUtil.getLightClassPropertyMethods(property); - PsiMethod getter = propertyMethods.getGetter(); - PsiMethod setter = propertyMethods.getSetter(); - - Collection references = ReferencesSearch.search(property).findAll(); - - Collection getterOverriding = - (getter != null) ? OverridingMethodsSearch.search(getter, true).findAll() : Collections.emptyList(); - Collection setterOverriding = - (setter != null) ? OverridingMethodsSearch.search(setter, true).findAll() : Collections.emptyList(); - - List overridingMethods = new ArrayList(); - overridingMethods.addAll(getterOverriding); - overridingMethods.addAll(setterOverriding); - overridingMethods = difference(overridingMethods, allElementsToDelete); - - processDeclarationUsages(property, allElementsToDelete, result, references, overridingMethods); - - Map> methodToReferences = getOverridingUsagesMap(overridingMethods); - Set safeGetterOverriding = - getter != null - ? filterSafeOverridingMethods(getter, references, getterOverriding, methodToReferences, result, allElementsToDelete) - : Collections.emptySet(); - Set safeSetterOverriding = - setter != null - ? filterSafeOverridingMethods(setter, references, setterOverriding, methodToReferences, result, allElementsToDelete) - : Collections.emptySet(); - - List ignoredElements = new ArrayList(safeGetterOverriding); - ignoredElements.addAll(safeSetterOverriding); - ContainerUtil.addAll(ignoredElements, allElementsToDelete); - return getSearchInfo(property, ignoredElements); - } - - @NotNull - private static Map> getOverridingUsagesMap(@NotNull List overridingMethods) { - Map> methodToReferences = new HashMap>(); - for (PsiMethod overridingMethod : overridingMethods) { - Collection overridingReferences = - ReferencesSearch.search( - overridingMethod instanceof KotlinLightMethod - ? ((KotlinLightMethod) overridingMethod).getOrigin() : overridingMethod - ).findAll(); - methodToReferences.put(overridingMethod, overridingReferences); - } - return methodToReferences; - } - - @NotNull - protected static NonCodeUsageSearchInfo findLocalDeclarationUsages( + protected static NonCodeUsageSearchInfo findKotlinDeclarationUsages( @NotNull final JetDeclaration declaration, @NotNull final PsiElement[] allElementsToDelete, @NotNull final List result @@ -313,7 +241,13 @@ public class KotlinSafeDeleteProcessor extends JavaSafeDeleteProcessor { public boolean process(PsiReference reference) { PsiElement element = reference.getElement(); if (!isInside(element, allElementsToDelete)) { - result.add(new SafeDeleteReferenceSimpleDeleteUsageInfo(element, declaration, false)); + JetImportDirective importDirective = PsiTreeUtil.getParentOfType(element, JetImportDirective.class, false); + if (importDirective != null) { + result.add(new SafeDeleteImportDirectiveUsageInfo(importDirective, declaration)); + } + else { + result.add(new SafeDeleteReferenceSimpleDeleteUsageInfo(element, declaration, false)); + } } return true; } @@ -497,80 +431,6 @@ public class KotlinSafeDeleteProcessor extends JavaSafeDeleteProcessor { } } - /* - * Mostly copied from JavaSafeDeleteProcessor.validateOverridingMethods - * Revision: d4fc033 - * (simplified and implemented proper treatment of light methods) - */ - private static Set filterSafeOverridingMethods( - @NotNull PsiMethod originalMethod, - @NotNull Collection originalReferences, - @NotNull Collection overridingMethods, - @NotNull Map> methodToReferences, - @NotNull List usages, - @NotNull PsiElement[] allElementsToDelete - ) { - Set validOverriding = new LinkedHashSet(overridingMethods); - boolean anyNewBadRefs; - do { - anyNewBadRefs = false; - for (PsiMethod overridingMethod : overridingMethods) { - if (validOverriding.contains(overridingMethod)) { - Collection overridingReferences = methodToReferences.get(overridingMethod); - boolean anyOverridingRefs = false; - for (PsiReference overridingReference : overridingReferences) { - PsiElement element = overridingReference.getElement(); - if (!isInside(element, allElementsToDelete) && !isInside(element, validOverriding)) { - anyOverridingRefs = true; - break; - } - } - - if (!anyOverridingRefs && isMultipleInterfacesImplementation(overridingMethod, originalMethod, allElementsToDelete)) { - anyOverridingRefs = true; - } - - if (anyOverridingRefs) { - validOverriding.remove(overridingMethod); - anyNewBadRefs = true; - - for (PsiReference reference : originalReferences) { - PsiElement element = reference.getElement(); - if (!isInside(element, allElementsToDelete) && !isInside(element, overridingMethods)) { - validOverriding.clear(); - } - } - } - } - } - } - while (anyNewBadRefs && !validOverriding.isEmpty()); - - for (PsiMethod method : validOverriding) { - if (method != originalMethod) { - usages.add(new KotlinSafeDeleteOverridingUsageInfo(method, originalMethod)); - } - } - - return validOverriding; - } - - @SuppressWarnings("MethodOverridesPrivateMethodOfSuperclass") - private static boolean isMultipleInterfacesImplementation( - @NotNull PsiMethod method, @NotNull PsiMethod originalMethod, @NotNull PsiElement[] ignore - ) { - PsiMethod[] methods = method.findSuperMethods(); - for (PsiMethod superMethod : methods) { - PsiElement relevantElement = superMethod instanceof KotlinLightMethod - ? ((KotlinLightMethod) superMethod).getOrigin() : superMethod; - relevantElement = JetPsiUtil.ascendIfPropertyAccessor(relevantElement); - if (ArrayUtilRt.find(ignore, relevantElement) < 0 && !MethodSignatureUtil.isSuperMethod(originalMethod, superMethod)) { - return true; - } - } - return false; - } - @Override @Nullable public Collection findConflicts(@NotNull PsiElement element, @NotNull PsiElement[] allElementsToDelete) {