private static boolean allSuperMethodsSelectedToDelete( List<PsiMethod> unselectedMethods, PsiMethod method) { final ArrayList<PsiMethod> superMethods = new ArrayList<>(Arrays.asList(method.findSuperMethods())); superMethods.retainAll(unselectedMethods); return superMethods.isEmpty(); }
@Nullable private static Condition<PsiElement> findMethodUsages( final PsiMethod psiMethod, final PsiElement[] allElementsToDelete, List<UsageInfo> usages) { final Collection<PsiReference> references = ReferencesSearch.search(psiMethod).findAll(); if (psiMethod.isConstructor()) { return findConstructorUsages(psiMethod, references, usages, allElementsToDelete); } final PsiMethod[] overridingMethods = removeDeletedMethods( OverridingMethodsSearch.search(psiMethod).toArray(PsiMethod.EMPTY_ARRAY), allElementsToDelete); findFunctionalExpressions(usages, ArrayUtil.prepend(psiMethod, overridingMethods)); final HashMap<PsiMethod, Collection<PsiReference>> methodToReferences = new HashMap<>(); for (PsiMethod overridingMethod : overridingMethods) { final Collection<PsiReference> overridingReferences = ReferencesSearch.search(overridingMethod).findAll(); methodToReferences.put(overridingMethod, overridingReferences); } final Set<PsiMethod> validOverriding = validateOverridingMethods( psiMethod, references, Arrays.asList(overridingMethods), methodToReferences, usages, allElementsToDelete); for (PsiReference reference : references) { final PsiElement element = reference.getElement(); if (!isInside(element, allElementsToDelete) && !isInside(element, validOverriding)) { usages.add( new SafeDeleteReferenceJavaDeleteUsageInfo( element, psiMethod, PsiTreeUtil.getParentOfType(element, PsiImportStaticStatement.class) != null)); } } final List<PsiMethod> calleesSafeToDelete = SafeDeleteJavaCalleeChooser.computeCalleesSafeToDelete(psiMethod); if (calleesSafeToDelete != null) { for (PsiMethod method : calleesSafeToDelete) { usages.add(new SafeDeleteMethodCalleeUsageInfo(method, psiMethod)); } } return usage -> { if (usage instanceof PsiFile) return false; return isInside(usage, allElementsToDelete) || isInside(usage, validOverriding); }; }
@Nullable @Override public Collection<? extends PsiElement> getElementsToSearch( @NotNull PsiElement element, @Nullable Module module, @NotNull Collection<PsiElement> allElementsToDelete) { Project project = element.getProject(); if (element instanceof PsiPackage && module != null) { final PsiDirectory[] directories = ((PsiPackage) element).getDirectories(module.getModuleScope()); if (directories.length == 0) return null; return Arrays.asList(directories); } else if (element instanceof PsiMethod) { final PsiMethod[] methods = SuperMethodWarningUtil.checkSuperMethods( (PsiMethod) element, RefactoringBundle.message("to.delete.with.usage.search"), allElementsToDelete); if (methods.length == 0) return null; final ArrayList<PsiMethod> psiMethods = new ArrayList<>(Arrays.asList(methods)); psiMethods.add((PsiMethod) element); return psiMethods; } else if (element instanceof PsiParameter && ((PsiParameter) element).getDeclarationScope() instanceof PsiMethod) { PsiMethod method = (PsiMethod) ((PsiParameter) element).getDeclarationScope(); final Set<PsiParameter> parametersToDelete = new HashSet<>(); parametersToDelete.add((PsiParameter) element); final int parameterIndex = method.getParameterList().getParameterIndex((PsiParameter) element); final List<PsiMethod> superMethods = new ArrayList<>(Arrays.asList(method.findDeepestSuperMethods())); if (superMethods.isEmpty()) { superMethods.add(method); } for (PsiMethod superMethod : superMethods) { parametersToDelete.add(superMethod.getParameterList().getParameters()[parameterIndex]); OverridingMethodsSearch.search(superMethod) .forEach( overrider -> { parametersToDelete.add( overrider.getParameterList().getParameters()[parameterIndex]); return true; }); } if (parametersToDelete.size() > 1 && !ApplicationManager.getApplication().isUnitTestMode()) { String message = RefactoringBundle.message( "0.is.a.part.of.method.hierarchy.do.you.want.to.delete.multiple.parameters", UsageViewUtil.getLongName(method)); int result = Messages.showYesNoCancelDialog( project, message, SafeDeleteHandler.REFACTORING_NAME, Messages.getQuestionIcon()); if (result == Messages.CANCEL) return null; if (result == Messages.NO) return Collections.singletonList(element); } return parametersToDelete; } else if (element instanceof PsiTypeParameter) { final PsiTypeParameterListOwner owner = ((PsiTypeParameter) element).getOwner(); if (owner instanceof PsiMethod && !owner.hasModifierProperty(PsiModifier.STATIC)) { final PsiTypeParameterList typeParameterList = owner.getTypeParameterList(); if (typeParameterList != null) { final int index = typeParameterList.getTypeParameterIndex((PsiTypeParameter) element); if (index >= 0) { final ArrayList<PsiTypeParameter> overriders = new ArrayList<>(); overriders.add((PsiTypeParameter) element); OverridingMethodsSearch.search((PsiMethod) owner) .forEach( overrider -> { final PsiTypeParameter[] typeParameters = overrider.getTypeParameters(); if (index < typeParameters.length) { overriders.add(typeParameters[index]); } return true; }); if (overriders.size() > 1) { String message = RefactoringBundle.message( "0.is.a.part.of.method.hierarchy.do.you.want.to.delete.multiple.type.parameters", UsageViewUtil.getLongName(owner)); int result = ApplicationManager.getApplication().isUnitTestMode() ? Messages.YES : Messages.showYesNoCancelDialog( project, message, SafeDeleteHandler.REFACTORING_NAME, Messages.getQuestionIcon()); if (result == Messages.CANCEL) return null; if (result == Messages.YES) return overriders; } } } } } return Collections.singletonList(element); }
private static boolean isInside(PsiElement place, PsiElement[] ancestors) { return isInside(place, Arrays.asList(ancestors)); }