From c2e584b07404cd79eaadaec514309a7927ac251b Mon Sep 17 00:00:00 2001 From: Peter Gromov Date: Tue, 7 Jul 2020 08:51:14 +0200 Subject: [PATCH] partially support model branches in rename refactoring (only for modifications inside files so far) GitOrigin-RevId: ec98bd14a8eaa9b6127ffbc637704f2457b36a00 --- .../moveMembers/MoveMembersProcessor.java | 14 +-- .../rename/RenameJavaMethodProcessor.java | 5 +- .../JavaBranchRefactoringTest.java | 8 ++ .../refactoring/util/MoveRenameUsageInfo.java | 72 +++++++++++++- .../src/com/intellij/model/ModelBranch.java | 7 ++ .../com/intellij/model/ModelBranchImpl.java | 39 +++++++- .../psi/impl/file/PsiFileImplUtil.java | 25 +++-- .../refactoring/rename/RenameProcessor.java | 96 +++++++++++++++++-- .../refactoring/rename/RenameUtil.java | 12 ++- .../inplace/VariableInplaceRenamer.java | 3 +- 10 files changed, 241 insertions(+), 40 deletions(-) diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveMembersProcessor.java b/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveMembersProcessor.java index 9c870f41fa28..4cbea576c5d7 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveMembersProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveMembersProcessor.java @@ -187,7 +187,7 @@ public class MoveMembersProcessor extends BaseRefactoringProcessor { PsiClass targetCopy = branch.obtainPsiCopy(targetClass); Set membersToMove = new LinkedHashSet<>(ContainerUtil.map(myMembersToMove, branch::obtainPsiCopy)); - List usages = ContainerUtil.map(originalUsages, u -> ((MoveMembersUsageInfo)u).branched(branch)); + List usages = ContainerUtil.map(originalUsages, u -> (MoveMembersUsageInfo)((MoveMembersUsageInfo)u).branched(branch)); Map> movedMembers = performMove(targetCopy, membersToMove, usages); @@ -421,17 +421,5 @@ public class MoveMembersProcessor extends BaseRefactoringProcessor { reference = element; } - @NotNull - MoveMembersProcessor.MoveMembersUsageInfo branched(ModelBranch branch) { - PsiElement element = branch.obtainPsiCopy(reference); - PsiElement highlightElement = getElement(); - PsiReference psiReference = getReference(); - return new MoveMembersUsageInfo( - branch.findPsiCopy(member), - element, - qualifierClass == null ? null : branch.findPsiCopy(qualifierClass), - highlightElement == null ? null : branch.findPsiCopy(highlightElement), - psiReference == null ? null : branch.findReferenceCopy(psiReference)); - } } } diff --git a/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaMethodProcessor.java b/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaMethodProcessor.java index 5835d6620315..c71630cffd9d 100644 --- a/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaMethodProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaMethodProcessor.java @@ -9,6 +9,7 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Pass; import com.intellij.psi.*; +import com.intellij.psi.impl.light.LightElement; import com.intellij.psi.impl.light.LightRecordMethod; import com.intellij.psi.search.PsiElementProcessor; import com.intellij.psi.search.SearchScope; @@ -112,9 +113,9 @@ public class RenameJavaMethodProcessor extends RenameJavaMemberProcessor { qualifyOuterMemberReferences(outerHides); qualifyStaticImportReferences(staticImportHides); - if (!method.isConstructor() && method.isPhysical() && method.findDeepestSuperMethods().length == 0) { + if (!method.isConstructor() && !(method instanceof LightElement) && method.findDeepestSuperMethods().length == 0) { PsiAnnotation annotation = AnnotationUtil.findAnnotation(method, true, CommonClassNames.JAVA_LANG_OVERRIDE); - if (annotation != null && annotation.isPhysical()) { + if (annotation != null) { annotation.delete(); } } diff --git a/java/java-tests/testSrc/com/intellij/java/refactoring/JavaBranchRefactoringTest.java b/java/java-tests/testSrc/com/intellij/java/refactoring/JavaBranchRefactoringTest.java index 14b161a12d43..9d822218c262 100644 --- a/java/java-tests/testSrc/com/intellij/java/refactoring/JavaBranchRefactoringTest.java +++ b/java/java-tests/testSrc/com/intellij/java/refactoring/JavaBranchRefactoringTest.java @@ -19,6 +19,14 @@ public class JavaBranchRefactoringTest { public static Test suite() { TestSuite suite = new TestSuite(); List> testsToWrap = Arrays.asList( + //RenameClassTest.class, + //RenameCollisionsTest.class, + //RenameDirectoryTest.class, + RenameFieldMultiTest.class, + RenameFieldTest.class, + RenameLocalTest.class, + RenameMethodMultiTest.class, + MoveMembersTest.class, ConvertToInstanceMethodTest.class, ConvertToInstance8MethodTest.class diff --git a/platform/analysis-api/src/com/intellij/refactoring/util/MoveRenameUsageInfo.java b/platform/analysis-api/src/com/intellij/refactoring/util/MoveRenameUsageInfo.java index 133eb5fb3fdd..6e280eaaf9df 100644 --- a/platform/analysis-api/src/com/intellij/refactoring/util/MoveRenameUsageInfo.java +++ b/platform/analysis-api/src/com/intellij/refactoring/util/MoveRenameUsageInfo.java @@ -15,17 +15,27 @@ */ package com.intellij.refactoring.util; +import com.intellij.model.ModelBranch; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.RangeMarker; +import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.usageView.UsageInfo; +import com.intellij.util.BitUtil; import com.intellij.util.Function; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class MoveRenameUsageInfo extends UsageInfo{ +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.Objects; + +public class MoveRenameUsageInfo extends UsageInfo implements Cloneable { private static final Logger LOG = Logger.getInstance(MoveRenameUsageInfo.class); private SmartPsiElementPointer myReferencedElementPointer = null; private PsiElement myReferencedElement; @@ -126,4 +136,64 @@ public class MoveRenameUsageInfo extends UsageInfo{ } return reference; } + + @NotNull + @ApiStatus.Experimental + public MoveRenameUsageInfo branched(@NotNull ModelBranch branch) { + try { + MoveRenameUsageInfo copy = (MoveRenameUsageInfo)clone(); + Class aClass = copy.getClass(); + while (aClass != null) { + for (Field field : aClass.getDeclaredFields()) { + if (BitUtil.isSet(field.getModifiers(), Modifier.STATIC)) continue; + + field.setAccessible(true); + Object valueCopy = obtainBranchCopy(branch, field.get(copy)); + if (valueCopy != null) { + field.set(copy, valueCopy); + } + } + aClass = aClass.getSuperclass(); + } + return copy; + } + catch (CloneNotSupportedException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + private Object obtainBranchCopy(ModelBranch branch, Object fieldValue) { + if (fieldValue instanceof PsiElement) { + return branch.obtainPsiCopy((PsiElement)fieldValue); + } + if (fieldValue instanceof PsiReference) { + return branch.obtainReferenceCopy((PsiReference)fieldValue); + } + if (fieldValue instanceof SmartPsiFileRange) { + return SmartPointerManager.getInstance(getProject()) + .createSmartPsiFileRangePointer( + branch.obtainPsiCopy(Objects.requireNonNull(((SmartPsiFileRange)fieldValue).getContainingFile())), + TextRange.create(Objects.requireNonNull(((SmartPsiFileRange)fieldValue).getRange()))); + } + if (fieldValue instanceof SmartPsiElementPointer) { + return SmartPointerManager.createPointer( + branch.obtainPsiCopy(Objects.requireNonNull(((SmartPsiElementPointer)fieldValue).getElement()))); + } + if (fieldValue instanceof RangeMarker) { + return obtainMarkerCopy(branch, (RangeMarker)fieldValue); + } + return null; + } + + private static RangeMarker obtainMarkerCopy(@NotNull ModelBranch branch, RangeMarker original) { + Document document = original.getDocument(); + VirtualFile file = FileDocumentManager.getInstance().getFile(document); + VirtualFile fileCopy = branch.findFileCopy(Objects.requireNonNull(file)); + Document docCopy = FileDocumentManager.getInstance().getDocument(Objects.requireNonNull(fileCopy)); + assert docCopy != null; + RangeMarker marker = docCopy.createRangeMarker(original.getStartOffset(), original.getEndOffset()); + marker.setGreedyToLeft(original.isGreedyToLeft()); + marker.setGreedyToRight(original.isGreedyToRight()); + return marker; + } } diff --git a/platform/core-api/src/com/intellij/model/ModelBranch.java b/platform/core-api/src/com/intellij/model/ModelBranch.java index ab88c359faba..81e6365de0d6 100644 --- a/platform/core-api/src/com/intellij/model/ModelBranch.java +++ b/platform/core-api/src/com/intellij/model/ModelBranch.java @@ -60,6 +60,13 @@ public interface ModelBranch { */ @NotNull T obtainPsiCopy(@NotNull T original); + /** + * Finds or creates a non-physical copy of the given PSI reference in this branch. + * This may only be called for references which occur in {@link PsiElement#getReferences()}, + * and the corresponding document should be committed. + */ + @NotNull T obtainReferenceCopy(@NotNull T original); + // ----------------- find originals by branched model diff --git a/platform/core-impl/src/com/intellij/model/ModelBranchImpl.java b/platform/core-impl/src/com/intellij/model/ModelBranchImpl.java index 1eba56db4998..82cbdc529841 100644 --- a/platform/core-impl/src/com/intellij/model/ModelBranchImpl.java +++ b/platform/core-impl/src/com/intellij/model/ModelBranchImpl.java @@ -13,9 +13,11 @@ import com.intellij.openapi.util.SimpleModificationTracker; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; +import com.intellij.psi.impl.file.PsiFileImplUtil; import com.intellij.psi.search.DelegatingGlobalSearchScope; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.IncorrectOperationException; import com.intellij.util.LocalTimeCounter; import com.intellij.util.Processor; import com.intellij.util.containers.ContainerUtil; @@ -23,6 +25,7 @@ import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.io.IOException; import java.util.*; import java.util.function.Consumer; @@ -129,15 +132,31 @@ public final class ModelBranchImpl implements ModelBranch { return fileCopy == null ? null : PsiTreeUtil.findSameElementInCopy(original, fileCopy); } + @Override + @NotNull + public T obtainReferenceCopy(@NotNull T original) { + PsiElement psiCopy = obtainPsiCopy(original.getElement()); + TextRange range = original.getRangeInElement(); + PsiReference[] refs = psiCopy.getReferences(); + T found = findSimilarReference(original, range, refs); + if (found == null) throw new AssertionError("Cannot find " + original + + " of " + original.getClass() + + " at " + range + + " in the copy, where references are " + Arrays.toString(refs)); + return found; + } + @Override @Nullable public T findReferenceCopy(@NotNull T original) { PsiElement psiCopy = findPsiCopy(original.getElement()); - if (psiCopy == null) return null; + return psiCopy == null ? null : findSimilarReference(original, original.getRangeInElement(), psiCopy.getReferences()); + } - TextRange range = original.getRangeInElement(); + @Nullable + private static T findSimilarReference(@NotNull T original, TextRange range, PsiReference[] references) { //noinspection unchecked - return (T)ContainerUtil.find(psiCopy.getReferences(), r -> r.getClass() == original.getClass() && range.equals(r.getRangeInElement())); + return (T)ContainerUtil.find(references, r -> r.getClass() == original.getClass() && range.equals(r.getRangeInElement())); } @Override @@ -171,6 +190,20 @@ public final class ModelBranchImpl implements ModelBranch { assert !myMerged; myMerged = true; + for (Map.Entry entry : myVFileCopies.entrySet()) { + VirtualFile original = entry.getKey(); + String copyName = entry.getValue().getName(); + if (!original.getName().equals(copyName)) { + PsiFileImplUtil.saveDocumentIfFileWillBecomeBinary(original, copyName); + try { + original.rename(this, copyName); + } + catch (IOException e) { + throw new IncorrectOperationException(e); + } + } + } + for (Document document : myDocumentChanges.keySet()) { VirtualFile file = Objects.requireNonNull(FileDocumentManager.getInstance().getFile(document)); DocumentImpl original = (DocumentImpl) FileDocumentManager.getInstance().getDocument(findOriginalFile(file)); diff --git a/platform/core-impl/src/com/intellij/psi/impl/file/PsiFileImplUtil.java b/platform/core-impl/src/com/intellij/psi/impl/file/PsiFileImplUtil.java index 7b82e5cc8aa2..7a689c8da08f 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/file/PsiFileImplUtil.java +++ b/platform/core-impl/src/com/intellij/psi/impl/file/PsiFileImplUtil.java @@ -11,6 +11,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import com.intellij.psi.impl.PsiManagerImpl; import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import java.io.IOException; @@ -19,20 +20,26 @@ public final class PsiFileImplUtil { private PsiFileImplUtil() { } + // before the file becomes non-openable in the editor, save it to prevent data loss + @ApiStatus.Internal + public static void saveDocumentIfFileWillBecomeBinary(VirtualFile vFile, @NotNull String newName) { + final FileType newFileType = FileTypeRegistry.getInstance().getFileTypeByFileName(newName); + if (UnknownFileType.INSTANCE.equals(newFileType) || newFileType.isBinary()) { + final FileDocumentManager fdm = FileDocumentManager.getInstance(); + final Document doc = fdm.getCachedDocument(vFile); + if (doc != null) { + fdm.saveDocumentAsIs(doc); + } + } + } + + public static PsiFile setName(@NotNull PsiFile file, @NotNull String newName) throws IncorrectOperationException { VirtualFile vFile = file.getViewProvider().getVirtualFile(); PsiManagerImpl manager = (PsiManagerImpl)file.getManager(); try{ - final FileType newFileType = FileTypeRegistry.getInstance().getFileTypeByFileName(newName); - if (UnknownFileType.INSTANCE.equals(newFileType) || newFileType.isBinary()) { - // before the file becomes unknown or a binary (thus, not openable in the editor), save it to prevent data loss - final FileDocumentManager fdm = FileDocumentManager.getInstance(); - final Document doc = fdm.getCachedDocument(vFile); - if (doc != null) { - fdm.saveDocumentAsIs(doc); - } - } + saveDocumentIfFileWillBecomeBinary(vFile, newName); vFile.rename(manager, newName); } diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/RenameProcessor.java b/platform/lang-impl/src/com/intellij/refactoring/rename/RenameProcessor.java index 82721f66255f..513cb21f88da 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/RenameProcessor.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/RenameProcessor.java @@ -8,6 +8,7 @@ import com.intellij.internal.statistic.eventLog.VarargEventId; import com.intellij.internal.statistic.utils.PluginInfoDetectorKt; import com.intellij.lang.LangBundle; import com.intellij.lang.findUsages.DescriptiveNameUtil; +import com.intellij.model.ModelBranch; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.application.ReadAction; @@ -45,6 +46,7 @@ import com.intellij.usageView.UsageInfo; import com.intellij.usageView.UsageViewDescriptor; import com.intellij.usageView.UsageViewUtil; import com.intellij.util.IncorrectOperationException; +import com.intellij.util.ReflectionUtil; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NotNull; @@ -369,24 +371,73 @@ public class RenameProcessor extends BaseRefactoringProcessor { @Override public void performRefactoring(UsageInfo @NotNull [] usages) { + doPerformRefactoring(usages, null); + } + + @Override + protected boolean canPerformRefactoringInBranch() { + return true; + } + + @Override + protected void performRefactoringInBranch(UsageInfo @NotNull [] usages, @NotNull ModelBranch branch) { + Class syncDefinition = ReflectionUtil.getMethodDeclaringClass(getClass(), "performRefactoring", UsageInfo[].class); + Class asyncDefinition = ReflectionUtil.getMethodDeclaringClass(getClass(), "performRefactoringInBranch", UsageInfo[].class, ModelBranch.class); + if (asyncDefinition != RenameProcessor.class && syncDefinition != asyncDefinition) { + throw new UnsupportedOperationException("performRefactoringInBranch should be implemented in " + syncDefinition); + } + doPerformRefactoring(usages, branch); + } + + private void doPerformRefactoring(UsageInfo @NotNull [] usages, @Nullable ModelBranch branch) { logScopeStatistics(RenameUsagesCollector.executed); List postRenameCallbacks = new ArrayList<>(); - final MultiMap classified = classifyUsages(myAllRenames.keySet(), usages); + Map elementsToChange = new IdentityHashMap<>(); + for (PsiElement element : myAllRenames.keySet()) { + elementsToChange.put(element, branch != null ? branch.obtainPsiCopy(element) : element); + } + + MultiMap> renameEvents = MultiMap.createLinked(); + + MultiMap classified = classifyUsages( + elementsToChange.values(), + branch == null ? Arrays.asList(usages) + : ContainerUtil.mapNotNull(usages, info -> shouldSkip(info) ? null : ((MoveRenameUsageInfo)info).branched(branch))); for (final PsiElement element : myAllRenames.keySet()) { + PsiElement toChange = elementsToChange.get(element); if (!element.isValid()) { LOG.error(new PsiInvalidElementAccessException(element)); continue; } + if (!toChange.isValid()) { + LOG.error(new PsiInvalidElementAccessException(toChange)); + continue; + } 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 infos = classified.get(element); + Collection infos = classified.get(toChange); try { - RenameUtil.doRename(element, newName, infos.toArray(UsageInfo.EMPTY_ARRAY), myProject, elementListener); + nowOrAfterMerge(branch, () -> RenameUtil.registerUndoableRename(element, elementListener)); + renamePsiElementProcessor.renameElement(toChange, newName, infos.toArray(UsageInfo.EMPTY_ARRAY), new RefactoringElementListener() { + @Override + public void elementMoved(@NotNull PsiElement newElement) { + throw new UnsupportedOperationException(); + } + + @Override + public void elementRenamed(@NotNull PsiElement newElement) { + if (!newElement.isValid()) return; + if (branch != null) { + assert branch == ModelBranch.getPsiBranch(newElement); + } + renameEvents.putValue(elementListener, SmartPointerManager.createPointer(newElement)); + } + }); } catch (final IncorrectOperationException e) { RenameUtil.showErrorMessage(e, element, myProject); @@ -397,6 +448,34 @@ public class RenameProcessor extends BaseRefactoringProcessor { } } + nowOrAfterMerge(branch, () -> afterRename(postRenameCallbacks, usages, renameEvents, branch)); + } + + private static void nowOrAfterMerge(@Nullable ModelBranch branch, Runnable runnable) { + if (branch == null) { + runnable.run(); + } else { + branch.runAfterMerge(runnable); + } + } + + private void afterRename(List postRenameCallbacks, + UsageInfo[] usages, + MultiMap> renameEvents, + @Nullable ModelBranch branch) { + PsiDocumentManager.getInstance(myProject).commitAllDocuments(); + for (Map.Entry>> entry : renameEvents.entrySet()) { + for (SmartPsiElementPointer pointer : entry.getValue()) { + PsiElement element = pointer.getElement(); + if (branch != null && element != null) { + element = branch.findOriginalPsi(element); + } + if (element != null) { + entry.getKey().elementRenamed(element); + } + } + } + for (Runnable runnable : postRenameCallbacks) { runnable.run(); } @@ -439,12 +518,12 @@ public class RenameProcessor extends BaseRefactoringProcessor { return myCommandName; } - public static MultiMap classifyUsages(Collection elements, UsageInfo[] usages) { + public static MultiMap classifyUsages(Collection elements, Collection usages) { final MultiMap result = new MultiMap<>(); for (UsageInfo usage : usages) { LOG.assertTrue(usage instanceof MoveRenameUsageInfo); - if (usage.getReference() instanceof LightElement) { - continue; //filter out implicit references (e.g. from derived class to super class' default constructor) + if (shouldSkip(usage)) { + continue; } MoveRenameUsageInfo usageInfo = (MoveRenameUsageInfo)usage; if (usage instanceof RelatedUsageInfo) { @@ -468,6 +547,11 @@ public class RenameProcessor extends BaseRefactoringProcessor { return result; } + //filter out implicit references (e.g. from derived class to super class' default constructor) + private static boolean shouldSkip(UsageInfo usage) { + return usage.getReference() instanceof LightElement; + } + public Collection getNewNames() { return myAllRenames.values(); } diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/RenameUtil.java b/platform/lang-impl/src/com/intellij/refactoring/rename/RenameUtil.java index 148f387bc828..c44f021f7421 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/RenameUtil.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/RenameUtil.java @@ -219,9 +219,7 @@ public final class RenameUtil { } } - 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); + static void registerUndoableRename(PsiElement element, @Nullable RefactoringElementListener listener) { final String fqn = element instanceof PsiFile ? ((PsiFile)element).getVirtualFile().getPath() : CopyReferenceAction.elementToFqn(element); if (fqn != null) { UndoableAction action = new BasicUndoableAction() { @@ -236,8 +234,14 @@ public final class RenameUtil { public void redo() { } }; - UndoManager.getInstance(project).undoableActionPerformed(action); + UndoManager.getInstance(element.getProject()).undoableActionPerformed(action); } + } + + public static void doRename(final PsiElement element, String newName, UsageInfo[] usages, final Project project, + @Nullable final RefactoringElementListener listener) throws IncorrectOperationException{ + registerUndoableRename(element, listener); + RenamePsiElementProcessor processor = RenamePsiElementProcessor.forElement(element); processor.renameElement(element, newName, usages, listener); } diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java index d7507c074c1e..6cb5f92479ef 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java @@ -263,8 +263,7 @@ public class VariableInplaceRenamer extends InplaceRefactoring { if (!CommonRefactoringUtil.checkReadOnlyStatus(myProject, PsiUtilCore.toPsiElementArray(renamer.getElements()))) return; final ThrowableRunnable performAutomaticRename = () -> { CommandProcessor.getInstance().markCurrentCommandAsGlobal(myProject); - final UsageInfo[] usageInfos = usages.toArray(UsageInfo.EMPTY_ARRAY); - final MultiMap classified = RenameProcessor.classifyUsages(renamer.getElements(), usageInfos); + MultiMap classified = RenameProcessor.classifyUsages(renamer.getElements(), usages); for (final PsiNamedElement element : renamer.getElements()) { final String newElementName = renamer.getNewName(element); if (newElementName != null) {