private void doRefactoring(@NotNull final Collection<UsageInfo> usageInfoSet) { for (Iterator<UsageInfo> iterator = usageInfoSet.iterator(); iterator.hasNext(); ) { UsageInfo usageInfo = iterator.next(); final PsiElement element = usageInfo.getElement(); if (element == null || !isToBeChanged(usageInfo)) { iterator.remove(); } } LocalHistoryAction action = LocalHistory.getInstance().startAction(getCommandName()); final UsageInfo[] writableUsageInfos = usageInfoSet.toArray(new UsageInfo[usageInfoSet.size()]); try { PsiDocumentManager.getInstance(myProject).commitAllDocuments(); RefactoringListenerManagerImpl listenerManager = (RefactoringListenerManagerImpl) RefactoringListenerManager.getInstance(myProject); myTransaction = listenerManager.startTransaction(); final Map<RefactoringHelper, Object> preparedData = new LinkedHashMap<>(); final Runnable prepareHelpersRunnable = new Runnable() { @Override public void run() { for (final RefactoringHelper helper : Extensions.getExtensions(RefactoringHelper.EP_NAME)) { Object operation = ApplicationManager.getApplication() .runReadAction( new Computable<Object>() { @Override public Object compute() { return helper.prepareOperation(writableUsageInfos); } }); preparedData.put(helper, operation); } } }; ProgressManager.getInstance() .runProcessWithProgressSynchronously( prepareHelpersRunnable, "Prepare ...", false, myProject); ApplicationManager.getApplication() .runWriteAction( new Runnable() { @Override public void run() { final String refactoringId = getRefactoringId(); if (refactoringId != null) { RefactoringEventData data = getBeforeData(); if (data != null) { data.addUsages(usageInfoSet); } myProject .getMessageBus() .syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC) .refactoringStarted(refactoringId, data); } try { if (refactoringId != null) { UndoableAction action = new UndoRefactoringAction(myProject, refactoringId); UndoManager.getInstance(myProject).undoableActionPerformed(action); } performRefactoring(writableUsageInfos); } finally { if (refactoringId != null) { myProject .getMessageBus() .syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC) .refactoringDone(refactoringId, getAfterData(writableUsageInfos)); } } } }); DumbService.getInstance(myProject).completeJustSubmittedTasks(); for (Map.Entry<RefactoringHelper, Object> e : preparedData.entrySet()) { //noinspection unchecked e.getKey().performOperation(myProject, e.getValue()); } myTransaction.commit(); ApplicationManager.getApplication() .runWriteAction( new Runnable() { @Override public void run() { performPsiSpoilingRefactoring(); } }); } finally { action.finish(); } int count = writableUsageInfos.length; if (count > 0) { StatusBarUtil.setStatusBarInfo( myProject, RefactoringBundle.message("statusBar.refactoring.result", count)); } else { if (!isPreviewUsages(writableUsageInfos)) { StatusBarUtil.setStatusBarInfo(myProject, RefactoringBundle.message("statusBar.noUsages")); } } }
@Nullable public UsageInfo[] preprocessUsages(final Project project, final UsageInfo[] usages) { final ArrayList<UsageInfo> result = new ArrayList<>(); final ArrayList<UsageInfo> overridingMethods = new ArrayList<>(); final ArrayList<SafeDeleteParameterCallHierarchyUsageInfo> delegatingParams = new ArrayList<>(); final ArrayList<SafeDeleteMethodCalleeUsageInfo> calleesSafeToDelete = new ArrayList<>(); for (UsageInfo usage : usages) { if (usage.isNonCodeUsage) { result.add(usage); } else if (usage instanceof SafeDeleteMethodCalleeUsageInfo) { calleesSafeToDelete.add((SafeDeleteMethodCalleeUsageInfo) usage); } else if (usage instanceof SafeDeleteOverridingMethodUsageInfo) { overridingMethods.add(usage); } else if (usage instanceof SafeDeleteParameterCallHierarchyUsageInfo) { delegatingParams.add((SafeDeleteParameterCallHierarchyUsageInfo) usage); } else if (usage instanceof SafeDeleteAnnotation) { result.add( new SafeDeleteAnnotation( (PsiAnnotation) usage.getElement(), ((SafeDeleteAnnotation) usage).getReferencedElement(), true)); } else { result.add(usage); } } if (!overridingMethods.isEmpty()) { if (ApplicationManager.getApplication().isUnitTestMode()) { result.addAll(overridingMethods); } else { OverridingMethodsDialog dialog = new OverridingMethodsDialog(project, overridingMethods); if (!dialog.showAndGet()) { return null; } final ArrayList<UsageInfo> selected = dialog.getSelected(); final Set<UsageInfo> unselected = new HashSet<>(overridingMethods); unselected.removeAll(selected); if (!unselected.isEmpty()) { final List<PsiMethod> unselectedMethods = ContainerUtil.map( unselected, info -> ((SafeDeleteOverridingMethodUsageInfo) info).getOverridingMethod()); for (Iterator<UsageInfo> iterator = result.iterator(); iterator.hasNext(); ) { final UsageInfo info = iterator.next(); if (info instanceof SafeDeleteOverrideAnnotation && !allSuperMethodsSelectedToDelete( unselectedMethods, ((SafeDeleteOverrideAnnotation) info).getMethod())) { iterator.remove(); } } } result.addAll(selected); } } if (!delegatingParams.isEmpty()) { final SafeDeleteParameterCallHierarchyUsageInfo parameterHierarchyUsageInfo = delegatingParams.get(0); if (ApplicationManager.getApplication().isUnitTestMode()) { result.addAll(delegatingParams); } else { final PsiMethod method = parameterHierarchyUsageInfo.getCalledMethod(); final PsiParameter parameter = parameterHierarchyUsageInfo.getReferencedElement(); final int parameterIndex = method.getParameterList().getParameterIndex(parameter); final JavaCallerChooser chooser = new SafeDeleteJavaCallerChooser(method, project, result) { @Override protected ArrayList<SafeDeleteParameterCallHierarchyUsageInfo> getTopLevelItems() { return delegatingParams; } @Override protected int getParameterIdx() { return parameterIndex; } }; TreeUtil.expand(chooser.getTree(), 2); if (!chooser.showAndGet()) { return null; } } } if (!calleesSafeToDelete.isEmpty()) { if (ApplicationManager.getApplication().isUnitTestMode()) { result.addAll(calleesSafeToDelete); } else { final PsiMethod method = calleesSafeToDelete.get(0).getCallerMethod(); final ArrayList<UsageInfo> list = new ArrayList<>(); JavaCallerChooser chooser = new SafeDeleteJavaCalleeChooser(method, project, list) { @Override protected ArrayList<SafeDeleteMethodCalleeUsageInfo> getTopLevelItems() { return calleesSafeToDelete; } }; TreeUtil.expand(chooser.getTree(), 2); if (!chooser.showAndGet()) { return null; } result.addAll(list); final List<PsiElement> methodsToDelete = new ArrayList<>(); for (UsageInfo info : list) { methodsToDelete.add(info.getElement()); } methodsToDelete.add(method); final Condition<PsiElement> insideDeletedCondition = getUsageInsideDeletedFilter( methodsToDelete.toArray(new PsiElement[methodsToDelete.size()])); for (UsageInfo info : list) { SafeDeleteProcessor.addNonCodeUsages( info.getElement(), result, insideDeletedCondition, JavaRefactoringSettings.getInstance().RENAME_SEARCH_FOR_TEXT_FOR_METHOD, JavaRefactoringSettings.getInstance().RENAME_SEARCH_IN_COMMENTS_FOR_METHOD); } } } return result.toArray(new UsageInfo[result.size()]); }