SafeDeleteProcessor: small refactorings

This commit is contained in:
Alexey Sedunov
2013-07-24 15:02:09 +04:00
parent 639336b2f5
commit 206d5ec9ca
3 changed files with 84 additions and 88 deletions
@@ -57,7 +57,7 @@ import java.util.List;
* Revision: 14aa2e2 * Revision: 14aa2e2
* (replace PsiMethod formatting) * (replace PsiMethod formatting)
*/ */
class KotlinOverridingMethodsDialog extends DialogWrapper { class KotlinOverridingDialog extends DialogWrapper {
private final List<UsageInfo> myOverridingMethods; private final List<UsageInfo> myOverridingMethods;
private final String[] myMethodText; private final String[] myMethodText;
private final boolean[] myChecked; private final boolean[] myChecked;
@@ -66,7 +66,7 @@ class KotlinOverridingMethodsDialog extends DialogWrapper {
private JBTable myTable; private JBTable myTable;
private final UsagePreviewPanel myUsagePreviewPanel; private final UsagePreviewPanel myUsagePreviewPanel;
public KotlinOverridingMethodsDialog(Project project, List<UsageInfo> overridingMethods) { public KotlinOverridingDialog(Project project, List<UsageInfo> overridingMethods) {
super(project, true); super(project, true);
myOverridingMethods = overridingMethods; myOverridingMethods = overridingMethods;
myChecked = new boolean[myOverridingMethods.size()]; myChecked = new boolean[myOverridingMethods.size()];
@@ -102,13 +102,14 @@ class KotlinOverridingMethodsDialog extends DialogWrapper {
} }
} }
assert element instanceof PsiMethod; assert element instanceof PsiMethod
: "Method accepts only kotlin functions/properties and java methods, but '" + element.getText() + "' was found";
return KotlinSafeDeleteProcessor.formatPsiMethod((PsiMethod) element, true, false); return KotlinSafeDeleteProcessor.formatPsiMethod((PsiMethod) element, true, false);
} }
@Override @Override
protected String getDimensionServiceKey() { protected String getDimensionServiceKey() {
return "#org.jetbrains.jet.plugin.refactoring.safeDelete.KotlinOverridingMethodsDialog"; return "#org.jetbrains.jet.plugin.refactoring.safeDelete.KotlinOverridingDialog";
} }
public ArrayList<UsageInfo> getSelected() { public ArrayList<UsageInfo> getSelected() {
@@ -29,7 +29,6 @@ import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.*; import com.intellij.psi.util.*;
import com.intellij.refactoring.safeDelete.JavaSafeDeleteProcessor; import com.intellij.refactoring.safeDelete.JavaSafeDeleteProcessor;
import com.intellij.refactoring.safeDelete.NonCodeUsageSearchInfo; import com.intellij.refactoring.safeDelete.NonCodeUsageSearchInfo;
import com.intellij.refactoring.safeDelete.SafeDeleteProcessor;
import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteOverridingMethodUsageInfo; import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteOverridingMethodUsageInfo;
import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteReferenceSimpleDeleteUsageInfo; import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteReferenceSimpleDeleteUsageInfo;
import com.intellij.usageView.UsageInfo; import com.intellij.usageView.UsageInfo;
@@ -64,10 +63,24 @@ public class KotlinSafeDeleteProcessor extends JavaSafeDeleteProcessor {
return canDeleteElement(element); return canDeleteElement(element);
} }
protected static NonCodeUsageSearchInfo getDefaultNonCodeUsageSearchInfo( protected static NonCodeUsageSearchInfo getSearchInfo(
@NotNull PsiElement element, @NotNull PsiElement[] allElementsToDelete @NotNull PsiElement element, @NotNull final Collection<? extends PsiElement> ignoredElements
) { ) {
return new NonCodeUsageSearchInfo(SafeDeleteProcessor.getDefaultInsideDeletedCondition(allElementsToDelete), element);
return new NonCodeUsageSearchInfo(
new Condition<PsiElement>() {
@Override
public boolean value(PsiElement usage) {
if (usage instanceof JetFile) return false;
return isInside(usage, ignoredElements);
}
},
element
);
}
protected static NonCodeUsageSearchInfo getSearchInfo(@NotNull PsiElement element, @NotNull PsiElement[] ignoredElements) {
return getSearchInfo(element, Arrays.asList(ignoredElements));
} }
@Nullable @Nullable
@@ -90,11 +103,11 @@ public class KotlinSafeDeleteProcessor extends JavaSafeDeleteProcessor {
JetProperty property = (JetProperty) element; JetProperty property = (JetProperty) element;
if (property.isLocal()) { if (property.isLocal()) {
return findLocalPropertyUsages(property, allElementsToDelete, result); return findLocalVariableUsages(property, allElementsToDelete, result);
} }
return findNonLocalPropertyUsages(property, allElementsToDelete, result); return findPropertyUsages(property, allElementsToDelete, result);
} }
return getDefaultNonCodeUsageSearchInfo(element, allElementsToDelete); return getSearchInfo(element, allElementsToDelete);
} }
private static PsiElement getObjectDeclarationOrFail(PsiElement element) { private static PsiElement getObjectDeclarationOrFail(PsiElement element) {
@@ -148,7 +161,7 @@ public class KotlinSafeDeleteProcessor extends JavaSafeDeleteProcessor {
} }
}); });
return getDefaultNonCodeUsageSearchInfo(referencedElement, allElementsToDelete); return getSearchInfo(referencedElement, allElementsToDelete);
} }
protected NonCodeUsageSearchInfo findPsiMethodUsages( protected NonCodeUsageSearchInfo findPsiMethodUsages(
@@ -178,58 +191,54 @@ public class KotlinSafeDeleteProcessor extends JavaSafeDeleteProcessor {
return list; return list;
} }
private static void processDeclarationUsages(
JetDeclaration declaration,
PsiElement[] allElementsToDelete,
List<UsageInfo> result,
Collection<PsiReference> references,
List<? extends PsiElement> 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 findFunctionUsages( protected static NonCodeUsageSearchInfo findFunctionUsages(
JetNamedFunction function, JetNamedFunction function,
final PsiElement[] allElementsToDelete, PsiElement[] allElementsToDelete,
List<UsageInfo> result List<UsageInfo> result
) { ) {
PsiMethod lightMethod = LightClassUtil.getLightClassMethod(function); PsiMethod lightMethod = LightClassUtil.getLightClassMethod(function);
if (lightMethod == null) { if (lightMethod == null) {
return getDefaultNonCodeUsageSearchInfo(function, allElementsToDelete); return getSearchInfo(function, allElementsToDelete);
} }
Collection<PsiReference> references = ReferencesSearch.search(function).findAll(); Collection<PsiReference> references = ReferencesSearch.search(function).findAll();
List<PsiMethod> overridingMethods = difference(OverridingMethodsSearch.search(lightMethod, true).findAll(), allElementsToDelete); List<PsiMethod> overridingMethods = difference(OverridingMethodsSearch.search(lightMethod, true).findAll(), allElementsToDelete);
for (PsiReference reference : references) { processDeclarationUsages(function, allElementsToDelete, result, references, overridingMethods);
PsiElement element = reference.getElement();
if (!isInside(element, allElementsToDelete) && !isInside(element, overridingMethods)) {
JetImportDirective importDirective = PsiTreeUtil.getParentOfType(element, JetImportDirective.class, false);
if (importDirective != null) {
result.add(new SafeDeleteImportDirectiveUsageInfo(importDirective, function));
}
else {
result.add(new SafeDeleteReferenceSimpleDeleteUsageInfo(element, function, false));
}
}
}
HashMap<PsiMethod, Collection<PsiReference>> methodToReferences = new HashMap<PsiMethod, Collection<PsiReference>>(); Map<PsiMethod, Collection<PsiReference>> methodToReferences = getOverridingUsagesMap(overridingMethods);
for (PsiMethod overridingMethod : overridingMethods) { Set<PsiMethod> safeOverriding =
Collection<PsiReference> overridingReferences =
ReferencesSearch.search(
overridingMethod instanceof JetClsMethod ? ((JetClsMethod) overridingMethod).getOrigin() : overridingMethod
).findAll();
methodToReferences.put(overridingMethod, overridingReferences);
}
final Set<PsiMethod> safeOverriding =
filterSafeOverridingMethods(lightMethod, references, overridingMethods, methodToReferences, result, allElementsToDelete); filterSafeOverridingMethods(lightMethod, references, overridingMethods, methodToReferences, result, allElementsToDelete);
return new NonCodeUsageSearchInfo( List<PsiElement> ignoredElements = new ArrayList<PsiElement>(safeOverriding);
new Condition<PsiElement>() { ContainerUtil.addAll(ignoredElements, allElementsToDelete);
@Override return getSearchInfo(function, ignoredElements);
public boolean value(PsiElement usage) {
if (usage instanceof JetFile) return false;
return isInside(usage, allElementsToDelete) || isInside(usage, safeOverriding);
}
},
function
);
} }
protected static NonCodeUsageSearchInfo findNonLocalPropertyUsages( protected static NonCodeUsageSearchInfo findPropertyUsages(
JetProperty property, JetProperty property,
final PsiElement[] allElementsToDelete, PsiElement[] allElementsToDelete,
List<UsageInfo> result List<UsageInfo> result
) { ) {
LightClassUtil.PropertyAccessorsPsiMethods propertyMethods = LightClassUtil.getLightClassPropertyMethods(property); LightClassUtil.PropertyAccessorsPsiMethods propertyMethods = LightClassUtil.getLightClassPropertyMethods(property);
@@ -248,20 +257,22 @@ public class KotlinSafeDeleteProcessor extends JavaSafeDeleteProcessor {
overridingMethods.addAll(setterOverriding); overridingMethods.addAll(setterOverriding);
overridingMethods = difference(overridingMethods, allElementsToDelete); overridingMethods = difference(overridingMethods, allElementsToDelete);
for (PsiReference reference : references) { processDeclarationUsages(property, allElementsToDelete, result, references, overridingMethods);
PsiElement element = reference.getElement();
if (!isInside(element, allElementsToDelete) && !isInside(element, overridingMethods)) {
JetImportDirective importDirective = PsiTreeUtil.getParentOfType(element, JetImportDirective.class, false);
if (importDirective != null) {
result.add(new SafeDeleteImportDirectiveUsageInfo(importDirective, property));
}
else {
result.add(new SafeDeleteReferenceSimpleDeleteUsageInfo(element, property, false));
}
}
}
HashMap<PsiMethod, Collection<PsiReference>> methodToReferences = new HashMap<PsiMethod, Collection<PsiReference>>(); Map<PsiMethod, Collection<PsiReference>> methodToReferences = getOverridingUsagesMap(overridingMethods);
Set<PsiMethod> safeGetterOverriding =
filterSafeOverridingMethods(getter, references, getterOverriding, methodToReferences, result, allElementsToDelete);
Set<PsiMethod> safeSetterOverriding =
filterSafeOverridingMethods(setter, references, setterOverriding, methodToReferences, result, allElementsToDelete);
List<PsiElement> ignoredElements = new ArrayList<PsiElement>(safeGetterOverriding);
ignoredElements.addAll(safeSetterOverriding);
ContainerUtil.addAll(ignoredElements, allElementsToDelete);
return getSearchInfo(property, ignoredElements);
}
private static Map<PsiMethod, Collection<PsiReference>> getOverridingUsagesMap(List<PsiMethod> overridingMethods) {
Map<PsiMethod, Collection<PsiReference>> methodToReferences = new HashMap<PsiMethod, Collection<PsiReference>>();
for (PsiMethod overridingMethod : overridingMethods) { for (PsiMethod overridingMethod : overridingMethods) {
Collection<PsiReference> overridingReferences = Collection<PsiReference> overridingReferences =
ReferencesSearch.search( ReferencesSearch.search(
@@ -269,26 +280,10 @@ public class KotlinSafeDeleteProcessor extends JavaSafeDeleteProcessor {
).findAll(); ).findAll();
methodToReferences.put(overridingMethod, overridingReferences); methodToReferences.put(overridingMethod, overridingReferences);
} }
final Set<PsiMethod> safeGetterOverriding = return methodToReferences;
filterSafeOverridingMethods(getter, references, getterOverriding, methodToReferences, result, allElementsToDelete);
final Set<PsiMethod> safeSetterOverriding =
filterSafeOverridingMethods(setter, references, setterOverriding, methodToReferences, result, allElementsToDelete);
return new NonCodeUsageSearchInfo(
new Condition<PsiElement>() {
@Override
public boolean value(PsiElement usage) {
if (usage instanceof JetFile) return false;
return isInside(usage, allElementsToDelete)
|| isInside(usage, safeGetterOverriding)
|| isInside(usage, safeSetterOverriding) ;
}
},
property
);
} }
protected static NonCodeUsageSearchInfo findLocalPropertyUsages( protected static NonCodeUsageSearchInfo findLocalVariableUsages(
final JetProperty property, final JetProperty property,
final PsiElement[] allElementsToDelete, final PsiElement[] allElementsToDelete,
final List<UsageInfo> result final List<UsageInfo> result
@@ -304,7 +299,7 @@ public class KotlinSafeDeleteProcessor extends JavaSafeDeleteProcessor {
} }
}); });
return getDefaultNonCodeUsageSearchInfo(property, allElementsToDelete); return getSearchInfo(property, allElementsToDelete);
} }
/* /*
@@ -314,7 +309,8 @@ public class KotlinSafeDeleteProcessor extends JavaSafeDeleteProcessor {
*/ */
private static Set<PsiMethod> filterSafeOverridingMethods( private static Set<PsiMethod> filterSafeOverridingMethods(
PsiMethod originalMethod, Collection<PsiReference> originalReferences, PsiMethod originalMethod, Collection<PsiReference> originalReferences,
Collection<PsiMethod> overridingMethods, HashMap<PsiMethod, Collection<PsiReference>> methodToReferences, Collection<PsiMethod> overridingMethods,
Map<PsiMethod, Collection<PsiReference>> methodToReferences,
List<UsageInfo> usages, List<UsageInfo> usages,
PsiElement[] allElementsToDelete PsiElement[] allElementsToDelete
) { ) {
@@ -366,7 +362,7 @@ public class KotlinSafeDeleteProcessor extends JavaSafeDeleteProcessor {
@SuppressWarnings("MethodOverridesPrivateMethodOfSuperclass") @SuppressWarnings("MethodOverridesPrivateMethodOfSuperclass")
private static boolean isMultipleInterfacesImplementation(PsiMethod method, PsiMethod originalMethod, PsiElement[] ignore) { private static boolean isMultipleInterfacesImplementation(PsiMethod method, PsiMethod originalMethod, PsiElement[] ignore) {
PsiMethod[] methods = method.findSuperMethods(); PsiMethod[] methods = method.findSuperMethods();
for (PsiMethod superMethod: methods) { for (PsiMethod superMethod : methods) {
PsiElement relevantElement = superMethod instanceof JetClsMethod ? ((JetClsMethod) superMethod).getOrigin() : superMethod; PsiElement relevantElement = superMethod instanceof JetClsMethod ? ((JetClsMethod) superMethod).getOrigin() : superMethod;
relevantElement = JetPsiUtil.ascendIfPropertyAccessor(relevantElement); relevantElement = JetPsiUtil.ascendIfPropertyAccessor(relevantElement);
if (ArrayUtilRt.find(ignore, relevantElement) < 0 && !MethodSignatureUtil.isSuperMethod(originalMethod, superMethod)) { if (ArrayUtilRt.find(ignore, relevantElement) < 0 && !MethodSignatureUtil.isSuperMethod(originalMethod, superMethod)) {
@@ -495,7 +491,7 @@ public class KotlinSafeDeleteProcessor extends JavaSafeDeleteProcessor {
result.addAll(overridingMethodUsages); result.addAll(overridingMethodUsages);
} }
else { else {
KotlinOverridingMethodsDialog dialog = new KotlinOverridingMethodsDialog(project, overridingMethodUsages); KotlinOverridingDialog dialog = new KotlinOverridingDialog(project, overridingMethodUsages);
dialog.show(); dialog.show();
if (!dialog.isOK()) return null; if (!dialog.isOK()) return null;
result.addAll(dialog.getSelected()); result.addAll(dialog.getSelected());
@@ -562,15 +558,16 @@ public class KotlinSafeDeleteProcessor extends JavaSafeDeleteProcessor {
private static boolean checkPsiMethodEquality(PsiMethod method1, PsiMethod method2) { private static boolean checkPsiMethodEquality(PsiMethod method1, PsiMethod method2) {
if (method1 instanceof JetClsMethod && method2 instanceof JetClsMethod) { if (method1 instanceof JetClsMethod && method2 instanceof JetClsMethod) {
return ((JetClsMethod) method1).getOrigin() == ((JetClsMethod) method2).getOrigin(); return ((JetClsMethod) method1).getOrigin().equals(((JetClsMethod) method2).getOrigin());
} }
return method1 == method2; return method1.equals(method2);
} }
private static void cleanUpOverrides(PsiMethod method) { private static void cleanUpOverrides(PsiMethod method) {
Collection<PsiMethod> superMethods = Arrays.asList(method.findSuperMethods(true)); Collection<PsiMethod> superMethods = Arrays.asList(method.findSuperMethods(true));
Collection<PsiMethod> overridingMethods = OverridingMethodsSearch.search(method, true).findAll(); Collection<PsiMethod> overridingMethods = OverridingMethodsSearch.search(method, true).findAll();
overrideLoop: for (PsiMethod overridingMethod : overridingMethods) { overrideLoop:
for (PsiMethod overridingMethod : overridingMethods) {
PsiElement overridingElement = overridingMethod instanceof JetClsMethod PsiElement overridingElement = overridingMethod instanceof JetClsMethod
? ((JetClsMethod) overridingMethod).getOrigin() ? ((JetClsMethod) overridingMethod).getOrigin()
: overridingMethod; : overridingMethod;
@@ -578,7 +575,7 @@ public class KotlinSafeDeleteProcessor extends JavaSafeDeleteProcessor {
Collection<PsiMethod> currentSuperMethods = new ArrayList<PsiMethod>(); Collection<PsiMethod> currentSuperMethods = new ArrayList<PsiMethod>();
ContainerUtil.addAll(currentSuperMethods, overridingMethod.findSuperMethods(true)); ContainerUtil.addAll(currentSuperMethods, overridingMethod.findSuperMethods(true));
currentSuperMethods.addAll(superMethods); currentSuperMethods.addAll(superMethods);
for (PsiMethod superMethod: currentSuperMethods) { for (PsiMethod superMethod : currentSuperMethods) {
if (!checkPsiMethodEquality(superMethod, method)) continue overrideLoop; if (!checkPsiMethodEquality(superMethod, method)) continue overrideLoop;
} }
@@ -47,8 +47,6 @@ public class KotlinReferencesSearcher extends QueryExecutorBase<PsiReference, Re
} }
} }
@Override @Override
public void processQuery(@NotNull ReferencesSearch.SearchParameters queryParameters, @NotNull Processor<PsiReference> consumer) { public void processQuery(@NotNull ReferencesSearch.SearchParameters queryParameters, @NotNull Processor<PsiReference> consumer) {
PsiElement element = queryParameters.getElementToSearch(); PsiElement element = queryParameters.getElementToSearch();