public static void doRename( final PsiElement element, String newName, UsageInfo[] usages, final Project project, @Nullable final RefactoringElementListener listener) throws IncorrectOperationException { final RenamePsiElementProcessor processor = RenamePsiElementProcessor.forElement(element); final String fqn = element instanceof PsiFile ? ((PsiFile) element).getVirtualFile().getPath() : CopyReferenceAction.elementToFqn(element); if (fqn != null) { UndoableAction action = new BasicUndoableAction() { public void undo() throws UnexpectedUndoException { if (listener instanceof UndoRefactoringElementListener) { ((UndoRefactoringElementListener) listener).undoElementMovedOrRenamed(element, fqn); } } @Override public void redo() throws UnexpectedUndoException {} }; UndoManager.getInstance(project).undoableActionPerformed(action); } processor.renameElement(element, newName, usages, listener); }
public void prepareRenaming( @NotNull final PsiElement element, final String newName, final LinkedHashMap<PsiElement, String> allRenames) { final List<RenamePsiElementProcessor> processors = RenamePsiElementProcessor.allForElement(element); myForceShowPreview = false; for (RenamePsiElementProcessor processor : processors) { if (processor.canProcessElement(element)) { processor.prepareRenaming(element, newName, allRenames); myForceShowPreview |= processor.forcesShowPreview(); } } }
private static String getStringToReplace( PsiElement element, String newName, boolean nonJava, final RenamePsiElementProcessor theProcessor) { if (element instanceof PsiMetaOwner) { final PsiMetaOwner psiMetaOwner = (PsiMetaOwner) element; final PsiMetaData metaData = psiMetaOwner.getMetaData(); if (metaData != null) { return metaData.getName(); } } if (theProcessor != null) { String result = theProcessor.getQualifiedNameAfterRename(element, newName, nonJava); if (result != null) { return result; } } if (element instanceof PsiNamedElement) { return newName; } else { LOG.error("Unknown element type"); return null; } }
public void performRefactoring(UsageInfo[] usages) { final int[] choice = myAllRenames.size() > 1 ? new int[] {-1} : null; String message = null; try { for (Iterator<Map.Entry<PsiElement, String>> iterator = myAllRenames.entrySet().iterator(); iterator.hasNext(); ) { Map.Entry<PsiElement, String> entry = iterator.next(); if (entry.getKey() instanceof PsiFile) { final PsiFile file = (PsiFile) entry.getKey(); final PsiDirectory containingDirectory = file.getContainingDirectory(); if (CopyFilesOrDirectoriesHandler.checkFileExist( containingDirectory, choice, file, entry.getValue(), "Rename")) { iterator.remove(); continue; } } RenameUtil.checkRename(entry.getKey(), entry.getValue()); } } catch (IncorrectOperationException e) { message = e.getMessage(); } if (message != null) { CommonRefactoringUtil.showErrorMessage( RefactoringBundle.message("rename.title"), message, getHelpID(), myProject); return; } List<Runnable> postRenameCallbacks = new ArrayList<Runnable>(); final MultiMap<PsiElement, UsageInfo> classified = classifyUsages(myAllRenames.keySet(), usages); for (final PsiElement element : myAllRenames.keySet()) { String newName = myAllRenames.get(element); final RefactoringElementListener elementListener = getTransaction().getElementListener(element); final RenamePsiElementProcessor renamePsiElementProcessor = RenamePsiElementProcessor.forElement(element); Runnable postRenameCallback = renamePsiElementProcessor.getPostRenameCallback(element, newName, elementListener); final Collection<UsageInfo> infos = classified.get(element); try { RenameUtil.doRename( element, newName, infos.toArray(new UsageInfo[infos.size()]), myProject, elementListener); } catch (final IncorrectOperationException e) { RenameUtil.showErrorMessage(e, element, myProject); return; } if (postRenameCallback != null) { postRenameCallbacks.add(postRenameCallback); } } for (Runnable runnable : postRenameCallbacks) { runnable.run(); } List<NonCodeUsageInfo> nonCodeUsages = new ArrayList<NonCodeUsageInfo>(); for (UsageInfo usage : usages) { if (usage instanceof NonCodeUsageInfo) { nonCodeUsages.add((NonCodeUsageInfo) usage); } } myNonCodeUsages = nonCodeUsages.toArray(new NonCodeUsageInfo[nonCodeUsages.size()]); if (!mySkippedUsages.isEmpty()) { if (!ApplicationManager.getApplication().isUnitTestMode() && !ApplicationManager.getApplication().isHeadlessEnvironment()) { ApplicationManager.getApplication() .invokeLater( new Runnable() { public void run() { final IdeFrame ideFrame = WindowManager.getInstance().getIdeFrame(myProject); if (ideFrame != null) { StatusBarEx statusBar = (StatusBarEx) ideFrame.getStatusBar(); HyperlinkListener listener = new HyperlinkListener() { public void hyperlinkUpdate(HyperlinkEvent e) { if (e.getEventType() != HyperlinkEvent.EventType.ACTIVATED) return; Messages.showMessageDialog( "<html>" + StringUtil.join( mySkippedUsages, new Function<UnresolvableCollisionUsageInfo, String>() { public String fun( UnresolvableCollisionUsageInfo unresolvableCollisionUsageInfo) { return unresolvableCollisionUsageInfo .getDescription(); } }, "<br>") + "</html>", "Don't panic! They are safe to skip", null); } }; statusBar.notifyProgressByBalloon( MessageType.WARNING, "<html><body>Unable to rename certain usages. <a href=\"\">Browse</a></body></html>", null, listener); } } }, ModalityState.NON_MODAL); } } }
public boolean preprocessUsages(final Ref<UsageInfo[]> refUsages) { UsageInfo[] usagesIn = refUsages.get(); MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>(); RenameUtil.addConflictDescriptions(usagesIn, conflicts); RenamePsiElementProcessor.forElement(myPrimaryElement) .findExistingNameConflicts(myPrimaryElement, myNewName, conflicts); if (!conflicts.isEmpty()) { if (ApplicationManager.getApplication().isUnitTestMode()) { throw new ConflictsInTestsException(conflicts.values()); } ConflictsDialog conflictsDialog = prepareConflictsDialog(conflicts, refUsages.get()); conflictsDialog.show(); if (!conflictsDialog.isOK()) { if (conflictsDialog.isShowConflicts()) prepareSuccessful(); return false; } } final List<UsageInfo> variableUsages = new ArrayList<UsageInfo>(); if (!myRenamers.isEmpty()) { if (!findRenamedVariables(variableUsages)) return false; final LinkedHashMap<PsiElement, String> renames = new LinkedHashMap<PsiElement, String>(); for (final AutomaticRenamer renamer : myRenamers) { final List<? extends PsiNamedElement> variables = renamer.getElements(); for (final PsiNamedElement variable : variables) { final String newName = renamer.getNewName(variable); if (newName != null) { addElement(variable, newName); prepareRenaming(variable, newName, renames); } } } if (!renames.isEmpty()) { myAllRenames.putAll(renames); final Runnable runnable = new Runnable() { public void run() { for (Map.Entry<PsiElement, String> entry : renames.entrySet()) { final UsageInfo[] usages = RenameUtil.findUsages( entry.getKey(), entry.getValue(), mySearchInComments, mySearchTextOccurrences, myAllRenames); Collections.addAll(variableUsages, usages); } } }; if (!ProgressManager.getInstance() .runProcessWithProgressSynchronously( runnable, RefactoringBundle.message("searching.for.variables"), true, myProject)) { return false; } } } final Set<UsageInfo> usagesSet = new HashSet<UsageInfo>(Arrays.asList(usagesIn)); usagesSet.addAll(variableUsages); final List<UnresolvableCollisionUsageInfo> conflictUsages = RenameUtil.removeConflictUsages(usagesSet); if (conflictUsages != null) { mySkippedUsages.addAll(conflictUsages); } refUsages.set(usagesSet.toArray(new UsageInfo[usagesSet.size()])); prepareSuccessful(); return true; }
@Nullable private String getHelpID() { return RenamePsiElementProcessor.forElement(myPrimaryElement).getHelpID(myPrimaryElement); }
@NotNull public static UsageInfo[] findUsages( final PsiElement element, final String newName, boolean searchInStringsAndComments, boolean searchForTextOccurrences, Map<? extends PsiElement, String> allRenames) { final List<UsageInfo> result = Collections.synchronizedList(new ArrayList<UsageInfo>()); PsiManager manager = element.getManager(); GlobalSearchScope projectScope = GlobalSearchScope.projectScope(manager.getProject()); RenamePsiElementProcessor processor = RenamePsiElementProcessor.forElement(element); Collection<PsiReference> refs = processor.findReferences(element, searchInStringsAndComments); for (final PsiReference ref : refs) { if (ref == null) { LOG.error("null reference from processor " + processor); continue; } PsiElement referenceElement = ref.getElement(); result.add( new MoveRenameUsageInfo( referenceElement, ref, ref.getRangeInElement().getStartOffset(), ref.getRangeInElement().getEndOffset(), element, ref.resolve() == null)); } processor.findCollisions(element, newName, allRenames, result); final PsiElement searchForInComments = processor.getElementToSearchInStringsAndComments(element); if (searchInStringsAndComments && searchForInComments != null) { String stringToSearch = ElementDescriptionUtil.getElementDescription( searchForInComments, NonCodeSearchDescriptionLocation.STRINGS_AND_COMMENTS); if (stringToSearch.length() > 0) { final String stringToReplace = getStringToReplace(element, newName, false, processor); TextOccurrencesUtil.UsageInfoFactory factory = new NonCodeUsageInfoFactory(searchForInComments, stringToReplace); TextOccurrencesUtil.addUsagesInStringsAndComments( searchForInComments, stringToSearch, result, factory); } } if (searchForTextOccurrences && searchForInComments != null) { String stringToSearch = ElementDescriptionUtil.getElementDescription( searchForInComments, NonCodeSearchDescriptionLocation.NON_JAVA); if (stringToSearch.length() > 0) { final String stringToReplace = getStringToReplace(element, newName, true, processor); addTextOccurrence( searchForInComments, result, projectScope, stringToSearch, stringToReplace); } final Pair<String, String> additionalStringToSearch = processor.getTextOccurrenceSearchStrings(searchForInComments, newName); if (additionalStringToSearch != null && additionalStringToSearch.first.length() > 0) { addTextOccurrence( searchForInComments, result, projectScope, additionalStringToSearch.first, additionalStringToSearch.second); } } return result.toArray(new UsageInfo[result.size()]); }