mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-19 21:11:28 +07:00
[java-refactoring] IDEA-92605 Detect conflicts for rename local variable
GitOrigin-RevId: 75ad577ef79dac053c689d9eb6d20dec3af222c7
This commit is contained in:
committed by
intellij-monorepo-bot
parent
29a66a2ae9
commit
696dfffffc
@@ -0,0 +1,8 @@
|
||||
class Test {
|
||||
void test(Object obj) {
|
||||
switch (obj) {
|
||||
case String s:
|
||||
int <caret>x = 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -112,6 +112,12 @@ public class RenameLocalTest extends LightRefactoringTestCase {
|
||||
() -> doTest("s"));
|
||||
}
|
||||
|
||||
public void testConflictWithPatternInline() {
|
||||
assertThrows(BaseRefactoringProcessor.ConflictsInTestsException.class,
|
||||
"An existing pattern variable s has the same name",
|
||||
() -> doTestInplaceRename("s"));
|
||||
}
|
||||
|
||||
public void testConflictWithFutureVar() {
|
||||
assertThrows(BaseRefactoringProcessor.ConflictsInTestsException.class,
|
||||
"An existing local variable <b><code>y</code></b> has the same name",
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.intellij.codeInsight.TargetElementUtil;
|
||||
import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
|
||||
import com.intellij.codeInsight.template.impl.TemplateState;
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.openapi.application.impl.NonBlockingReadActionImpl;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.Inlay;
|
||||
@@ -105,6 +106,7 @@ public class RenameMembersInplaceTest extends LightJavaCodeInsightTestCase {
|
||||
state = TemplateManagerImpl.getTemplateState(getEditor());
|
||||
assertNotNull(state);
|
||||
state.gotoEnd(false);
|
||||
NonBlockingReadActionImpl.waitForAsyncTaskCompletion();
|
||||
checkResultByFile(BASE_PATH + getTestName(false) + "_after.java");
|
||||
}
|
||||
|
||||
@@ -134,6 +136,7 @@ public class RenameMembersInplaceTest extends LightJavaCodeInsightTestCase {
|
||||
state = TemplateManagerImpl.getTemplateState(editor);
|
||||
assert state != null;
|
||||
state.gotoEnd(false);
|
||||
NonBlockingReadActionImpl.waitForAsyncTaskCompletion();
|
||||
|
||||
checkResultByFile(BASE_PATH + getTestName(false) + "_after.java");
|
||||
}
|
||||
|
||||
@@ -10,8 +10,7 @@ import com.intellij.codeInsight.lookup.impl.LookupImpl;
|
||||
import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
|
||||
import com.intellij.ide.IdeEventQueue;
|
||||
import com.intellij.modcommand.*;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.openapi.application.impl.NonBlockingReadActionImpl;
|
||||
import com.intellij.testFramework.LightProjectDescriptor;
|
||||
import com.intellij.ui.ChooserInterceptor;
|
||||
import com.intellij.ui.UiInterceptors;
|
||||
@@ -21,7 +20,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase.JAVA_21;
|
||||
import static com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase.JAVA_21_ANNOTATED;
|
||||
|
||||
public class ReplaceConstructorWithFactoryTest extends LightRefactoringTestCase {
|
||||
@@ -53,6 +51,7 @@ public class ReplaceConstructorWithFactoryTest extends LightRefactoringTestCase
|
||||
LookupElement newMain = ContainerUtil.find(lookup.getItems(), l -> l.getLookupString().equals("newMain"));
|
||||
assertNotNull(newMain);
|
||||
((LookupImpl)lookup).finishLookup('\n', newMain);
|
||||
NonBlockingReadActionImpl.waitForAsyncTaskCompletion();
|
||||
checkResultByFile("/refactoring/replaceConstructorWithFactory/afterWithSelection.java");
|
||||
}
|
||||
|
||||
|
||||
@@ -27094,6 +27094,7 @@ c:com.intellij.refactoring.rename.inplace.MemberInplaceRenamer
|
||||
- p:collectRefs(com.intellij.psi.search.SearchScope):java.util.Collection
|
||||
- p:createInplaceRenamerToRestart(com.intellij.psi.PsiNamedElement,com.intellij.openapi.editor.Editor,java.lang.String):com.intellij.refactoring.rename.inplace.VariableInplaceRenamer
|
||||
- p:createRenameProcessor(com.intellij.psi.PsiElement,java.lang.String):com.intellij.refactoring.rename.RenameProcessor
|
||||
- p:findCollision():com.intellij.refactoring.rename.UnresolvableCollisionUsageInfo
|
||||
- p:getNameIdentifier():com.intellij.psi.PsiElement
|
||||
- p:getRefactoringId():java.lang.String
|
||||
- p:getReferencesSearchScope(com.intellij.openapi.vfs.VirtualFile):com.intellij.psi.search.SearchScope
|
||||
@@ -27199,6 +27200,7 @@ c:com.intellij.refactoring.rename.inplace.VariableInplaceRenamer
|
||||
- p:collectAdditionalElementsToRename(java.util.List):V
|
||||
- p:createInplaceRenamerToRestart(com.intellij.psi.PsiNamedElement,com.intellij.openapi.editor.Editor,java.lang.String):com.intellij.refactoring.rename.inplace.VariableInplaceRenamer
|
||||
- p:createLookupExpression(com.intellij.psi.PsiElement):com.intellij.refactoring.rename.inplace.MyLookupExpression
|
||||
- p:findCollision():com.intellij.refactoring.rename.UnresolvableCollisionUsageInfo
|
||||
- finish(Z):V
|
||||
- p:getCommandName():java.lang.String
|
||||
- p:getRefactoringId():java.lang.String
|
||||
|
||||
@@ -16,8 +16,8 @@ import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.editor.impl.EditorImpl;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.project.DumbModeBlockedFunctionality;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
@@ -36,6 +36,7 @@ import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.refactoring.rename.RenameProcessor;
|
||||
import com.intellij.refactoring.rename.RenamePsiElementProcessor;
|
||||
import com.intellij.refactoring.rename.RenameUtil;
|
||||
import com.intellij.refactoring.rename.UnresolvableCollisionUsageInfo;
|
||||
import com.intellij.refactoring.rename.naming.AutomaticRenamerFactory;
|
||||
import com.intellij.refactoring.util.TextOccurrencesUtil;
|
||||
import com.intellij.usageView.UsageViewUtil;
|
||||
@@ -101,6 +102,12 @@ public class MemberInplaceRenamer extends VariableInplaceRenamer {
|
||||
return super.checkLocalScope();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable UnresolvableCollisionUsageInfo findCollision() {
|
||||
// Collisions for members are processed by RenameProcessor using normal conflicts dialog
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PsiElement getNameIdentifier() {
|
||||
final PsiFile currentFile = PsiDocumentManager.getInstance(myProject).getPsiFile(myEditor.getDocument());
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
package com.intellij.refactoring.rename.inplace;
|
||||
|
||||
import com.intellij.CommonBundle;
|
||||
import com.intellij.codeInsight.highlighting.HighlightManager;
|
||||
import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
|
||||
import com.intellij.codeInsight.template.impl.TemplateState;
|
||||
import com.intellij.ide.DataManager;
|
||||
@@ -11,15 +12,23 @@ import com.intellij.lang.LangBundle;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.lang.LanguageExtension;
|
||||
import com.intellij.lang.injection.InjectedLanguageManager;
|
||||
import com.intellij.modcommand.ActionContext;
|
||||
import com.intellij.modcommand.ModCommandExecutor;
|
||||
import com.intellij.modcommand.ModUpdateFileText;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.command.impl.FinishMarkAction;
|
||||
import com.intellij.openapi.command.impl.StartMarkAction;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.editor.SelectionModel;
|
||||
import com.intellij.openapi.editor.colors.EditorColors;
|
||||
import com.intellij.openapi.editor.impl.EditorImpl;
|
||||
import com.intellij.openapi.editor.markup.RangeHighlighter;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
@@ -30,7 +39,9 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.SuggestedNameInfo;
|
||||
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageEditorUtil;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.refactoring.BaseRefactoringProcessor;
|
||||
import com.intellij.refactoring.RefactoringActionHandler;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.refactoring.listeners.RefactoringElementListener;
|
||||
@@ -44,14 +55,13 @@ import com.intellij.refactoring.util.TextOccurrencesUtil;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.ThrowableRunnable;
|
||||
import com.intellij.util.concurrency.AppExecutorUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
public class VariableInplaceRenamer extends InplaceRefactoring {
|
||||
public static final LanguageExtension<ResolveSnapshotProvider> INSTANCE = new LanguageExtension<>(
|
||||
@@ -61,6 +71,9 @@ public class VariableInplaceRenamer extends InplaceRefactoring {
|
||||
private TextRange mySelectedRange;
|
||||
protected Language myLanguage;
|
||||
protected @Nullable SuggestedNameInfo mySuggestedNameInfo;
|
||||
private int myOrigOffset;
|
||||
private ModUpdateFileText myRevertCommand;
|
||||
private PsiNamedElement myElementInCopy;
|
||||
|
||||
public VariableInplaceRenamer(@NotNull PsiNamedElement elementToRename,
|
||||
@NotNull Editor editor) {
|
||||
@@ -135,6 +148,15 @@ public class VariableInplaceRenamer extends InplaceRefactoring {
|
||||
@NotNull Collection<Pair<PsiElement, TextRange>> stringUsages,
|
||||
final @NotNull PsiElement scope,
|
||||
final @NotNull PsiFile containingFile) {
|
||||
PsiFile fileCopy = (PsiFile)containingFile.copy();
|
||||
myOrigOffset = myEditor.getCaretModel().getOffset();
|
||||
try {
|
||||
myElementInCopy = PsiTreeUtil.findSameElementInCopy(myElementToRename, fileCopy);
|
||||
}
|
||||
catch (IllegalStateException | UnsupportedOperationException e) {
|
||||
// Unsupported synthetic element?
|
||||
myElementInCopy = null;
|
||||
}
|
||||
if (appendAdditionalElement(refs, stringUsages)) {
|
||||
return super.buildTemplateAndStart(refs, stringUsages, scope, containingFile);
|
||||
}
|
||||
@@ -268,10 +290,117 @@ public class VariableInplaceRenamer extends InplaceRefactoring {
|
||||
JBPopupFactory.getInstance()
|
||||
.createConfirmation(LangBundle.message("popup.title.inserted.identifier.valid"), IdeBundle.message("label.continue.editing"),
|
||||
CommonBundle.getCancelButtonText(),
|
||||
() -> createInplaceRenamerToRestart(variable, myEditor, newName).performInplaceRefactoring(nameSuggestions), 0).showInBestPositionFor(myEditor);
|
||||
() -> {
|
||||
startDumbIfPossible();
|
||||
rollBack();
|
||||
createInplaceRenamerToRestart(variable, myEditor, newName).performInplaceRefactoring(nameSuggestions);
|
||||
stopDumbLaterIfPossible();
|
||||
},
|
||||
() -> rollBack(), 0).showInBestPositionFor(myEditor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return unresolvable collision if it's desired to display it to the user; null if refactoring can proceed without additional question
|
||||
*/
|
||||
protected @Nullable UnresolvableCollisionUsageInfo findCollision() {
|
||||
if (myInsertedName.equals(myOldName)) return null;
|
||||
PsiNamedElement variable = myElementInCopy;
|
||||
if (variable == null) return null;
|
||||
String newName = myInsertedName;
|
||||
List<UsageInfo> result = new ArrayList<>();
|
||||
RenamePsiElementProcessor.forElement(variable).findCollisions(variable, newName, Map.of(variable, newName), result);
|
||||
return ContainerUtil.findInstance(result, UnresolvableCollisionUsageInfo.class);
|
||||
}
|
||||
|
||||
private @Nullable UnresolvableRenameProblem findProblem() {
|
||||
if (!isIdentifier(myInsertedName, myLanguage)) {
|
||||
return new IllegalIdentifierProblem();
|
||||
}
|
||||
UnresolvableCollisionUsageInfo collision = findCollision();
|
||||
if (collision != null) {
|
||||
return new Collision(collision);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private sealed interface UnresolvableRenameProblem {
|
||||
void showUI();
|
||||
}
|
||||
|
||||
private final class IllegalIdentifierProblem implements UnresolvableRenameProblem {
|
||||
@Override
|
||||
public void showUI() {
|
||||
performOnInvalidIdentifier(myInsertedName, myNameSuggestions);
|
||||
}
|
||||
}
|
||||
|
||||
private final class Collision implements UnresolvableRenameProblem {
|
||||
private final @NotNull UnresolvableCollisionUsageInfo collision;
|
||||
|
||||
private Collision(@NotNull UnresolvableCollisionUsageInfo collision) { this.collision = collision; }
|
||||
|
||||
@Override
|
||||
public void showUI() {
|
||||
RangeHighlighter highlighter = highlightConflictingElement(collision.getElement());
|
||||
String description = StringUtil.stripHtml(collision.getDescription(), false);
|
||||
final int offset = myElementInCopy.getTextOffset();
|
||||
restoreCaretOffset(offset);
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
throw new BaseRefactoringProcessor.ConflictsInTestsException(List.of(description));
|
||||
}
|
||||
JBPopupFactory.getInstance().createConfirmation(
|
||||
description, IdeBundle.message("label.refactor.anyway"),
|
||||
IdeBundle.message("label.continue.editing"),
|
||||
() -> {
|
||||
if (highlighter != null) {
|
||||
highlighter.dispose();
|
||||
}
|
||||
performRefactoringRename(myInsertedName, myMarkAction);
|
||||
},
|
||||
() -> {
|
||||
if (highlighter != null) {
|
||||
highlighter.dispose();
|
||||
}
|
||||
startDumbIfPossible();
|
||||
rollBack();
|
||||
PsiNamedElement var = getVariable();
|
||||
if (var != null) {
|
||||
createInplaceRenamerToRestart(var, myEditor, myInsertedName).performInplaceRefactoring(myNameSuggestions);
|
||||
}
|
||||
stopDumbLaterIfPossible();
|
||||
},
|
||||
0)
|
||||
.showInBestPositionFor(myEditor);
|
||||
}
|
||||
}
|
||||
|
||||
private void rollBack() {
|
||||
Document document = InjectedLanguageEditorUtil.getTopLevelEditor(myEditor).getDocument();
|
||||
PsiFile psiFile = Objects.requireNonNull(PsiDocumentManager.getInstance(myProject).getPsiFile(document));
|
||||
CommandProcessor.getInstance().executeCommand(myProject, () -> {
|
||||
ModCommandExecutor.getInstance().executeInBatch(ActionContext.from(null, psiFile), myRevertCommand);
|
||||
}, getCommandName(), null);
|
||||
myEditor.getCaretModel().moveToOffset(myOrigOffset);
|
||||
}
|
||||
|
||||
private @Nullable RangeHighlighter highlightConflictingElement(PsiElement conflictingElement) {
|
||||
if (conflictingElement != null) {
|
||||
TextRange range = conflictingElement.getTextRange();
|
||||
if (conflictingElement instanceof PsiNameIdentifierOwner owner) {
|
||||
PsiElement identifier = owner.getNameIdentifier();
|
||||
if (identifier != null) {
|
||||
range = identifier.getTextRange();
|
||||
}
|
||||
}
|
||||
List<RangeHighlighter> highlighters = new ArrayList<>();
|
||||
HighlightManager.getInstance(myProject).addRangeHighlight(
|
||||
myEditor, range.getStartOffset(), range.getEndOffset(), EditorColors.SEARCH_RESULT_ATTRIBUTES, false, true, highlighters);
|
||||
return ContainerUtil.getOnlyItem(highlighters);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void renameSynthetic(String newName) {
|
||||
}
|
||||
|
||||
@@ -354,6 +483,12 @@ public class VariableInplaceRenamer extends InplaceRefactoring {
|
||||
}
|
||||
}
|
||||
|
||||
private void startDumbIfPossible() {
|
||||
if (InjectedLanguageEditorUtil.getTopLevelEditor(myEditor) instanceof EditorImpl editor) {
|
||||
editor.startDumb();
|
||||
}
|
||||
}
|
||||
|
||||
protected void stopDumbLaterIfPossible() {
|
||||
if (InjectedLanguageEditorUtil.getTopLevelEditor(myEditor) instanceof EditorImpl editor) {
|
||||
editor.stopDumbLater();
|
||||
@@ -380,17 +515,34 @@ public class VariableInplaceRenamer extends InplaceRefactoring {
|
||||
}
|
||||
|
||||
bind = true;
|
||||
if (!isIdentifier(myInsertedName, myLanguage)) {
|
||||
performOnInvalidIdentifier(myInsertedName, myNameSuggestions);
|
||||
}
|
||||
else if (mySnapshot != null) {
|
||||
ApplicationManager.getApplication().runWriteAction(() -> mySnapshot.apply(myInsertedName));
|
||||
}
|
||||
performRefactoringRename(myInsertedName, myMarkAction);
|
||||
ReadAction.nonBlocking(() -> findProblem())
|
||||
.expireWhen(() -> myEditor.isDisposed() || myProject.isDisposed())
|
||||
.finishOnUiThread(ModalityState.nonModal(), problem -> {
|
||||
if (problem == null) {
|
||||
if (mySnapshot != null) {
|
||||
ApplicationManager.getApplication().runWriteAction(() -> mySnapshot.apply(myInsertedName));
|
||||
}
|
||||
performRefactoringRename(myInsertedName, myMarkAction);
|
||||
}
|
||||
else {
|
||||
problem.showUI();
|
||||
cancel();
|
||||
}
|
||||
})
|
||||
.submit(AppExecutorUtil.getAppExecutorService());
|
||||
}
|
||||
return bind;
|
||||
}
|
||||
|
||||
private void cancel() {
|
||||
try {
|
||||
stopDumbLaterIfPossible();
|
||||
}
|
||||
finally {
|
||||
FinishMarkAction.finish(myProject, myEditor, myMarkAction);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish(boolean success) {
|
||||
super.finish(success);
|
||||
@@ -402,9 +554,26 @@ public class VariableInplaceRenamer extends InplaceRefactoring {
|
||||
}
|
||||
}
|
||||
|
||||
protected void revertStateOnFinish() {
|
||||
if (myInsertedName == null || !isIdentifier(myInsertedName, myLanguage)) {
|
||||
revertState();
|
||||
private static @NotNull ModUpdateFileText getRevertModCommand(@NotNull Editor editor, String oldName) {
|
||||
TemplateState state = TemplateManagerImpl.getTemplateState(editor);
|
||||
int segmentsCount = state == null ? 0 : state.getSegmentsCount();
|
||||
Document document = editor.getDocument();
|
||||
String oldText = document.getText();
|
||||
StringBuilder newText = new StringBuilder();
|
||||
int lastPos = 0;
|
||||
List<ModUpdateFileText.Fragment> fragments = new ArrayList<>();
|
||||
for (int i = 0; i < segmentsCount; i++) {
|
||||
TextRange segmentRange = state.getSegmentRange(i);
|
||||
newText.append(oldText, lastPos, segmentRange.getStartOffset());
|
||||
fragments.add(new ModUpdateFileText.Fragment(newText.length(), segmentRange.getLength(), oldName.length()));
|
||||
newText.append(oldName);
|
||||
lastPos = segmentRange.getEndOffset();
|
||||
}
|
||||
newText.append(oldText, lastPos, oldText.length());
|
||||
return new ModUpdateFileText(editor.getVirtualFile(), oldText, newText.toString(), fragments);
|
||||
}
|
||||
|
||||
protected void revertStateOnFinish() {
|
||||
myRevertCommand = getRevertModCommand(InjectedLanguageEditorUtil.getTopLevelEditor(myEditor), myOldName);
|
||||
}
|
||||
}
|
||||
@@ -1994,6 +1994,7 @@ dialog.title.collect.troubleshooting.information=Collect Troubleshooting Informa
|
||||
link.reset.icon=Reset
|
||||
link.change.icon=Change\u2026
|
||||
dialog.title.can.t.create.0.sdk=Cannot Create {0} SDK
|
||||
label.refactor.anyway=Refactor anyway
|
||||
label.continue.editing=Continue editing
|
||||
button.continue.editing=Continue Editing
|
||||
button.save.anyway=Save Anyway
|
||||
|
||||
@@ -509,4 +509,5 @@ move.handler.is.dumb.during.indexing=Moving files while indexing is in progress
|
||||
|
||||
progress.title.collecting.suggested.names=Collecting suggested names
|
||||
dialog.message.selected.element.used.from.non.project.files=Selected element is used from non-project files. These usages won't be renamed. Proceed anyway?
|
||||
progress.title.prepare.to.delete=Prepare to delete
|
||||
progress.title.prepare.to.delete=Prepare to delete
|
||||
dialog.title.looking.for.collisions=Looking for Collisions
|
||||
@@ -2,7 +2,6 @@
|
||||
package com.intellij.testFramework.fixtures;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.*;
|
||||
import com.intellij.codeInsight.daemon.impl.AnnotationSessionImpl;
|
||||
import com.intellij.codeInsight.editorActions.smartEnter.SmartEnterProcessor;
|
||||
import com.intellij.codeInsight.editorActions.smartEnter.SmartEnterProcessors;
|
||||
import com.intellij.codeInsight.generation.surroundWith.SurroundWithHandler;
|
||||
@@ -19,7 +18,9 @@ import com.intellij.codeInsight.template.impl.TemplateState;
|
||||
import com.intellij.codeInsight.template.impl.actions.ListTemplatesAction;
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.injected.editor.EditorWindow;
|
||||
import com.intellij.lang.annotation.*;
|
||||
import com.intellij.lang.annotation.Annotation;
|
||||
import com.intellij.lang.annotation.Annotator;
|
||||
import com.intellij.lang.annotation.ExternalAnnotator;
|
||||
import com.intellij.lang.surroundWith.Surrounder;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
@@ -255,6 +256,7 @@ public final class CodeInsightTestUtil {
|
||||
state = TemplateManagerImpl.getTemplateState(editor);
|
||||
assert state != null;
|
||||
state.gotoEnd(false);
|
||||
NonBlockingReadActionImpl.waitForAsyncTaskCompletion();
|
||||
}
|
||||
finally {
|
||||
Disposer.dispose(disposable);
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.intellij.navigation.NavigationItem;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.LocalSearchScope;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -18,7 +19,7 @@ import org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.GrVariableEnhancer;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class ClosureSyntheticParameter extends GrLightParameter implements NavigationItem, GrRenameableLightElement {
|
||||
public class ClosureSyntheticParameter extends GrLightParameter implements NavigationItem, GrRenameableLightElement, SyntheticElement {
|
||||
private static final Function<ClosureSyntheticParameter,PsiType> TYPES_CALCULATOR = parameter -> {
|
||||
PsiType typeGroovy = GrVariableEnhancer.getEnhancedType(parameter);
|
||||
if (typeGroovy instanceof PsiIntersectionType) {
|
||||
@@ -40,6 +41,15 @@ public class ClosureSyntheticParameter extends GrLightParameter implements Navig
|
||||
return myClosure.getElement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull PsiElement findSameElementInCopy(@NotNull PsiFile copy) {
|
||||
GrClosableBlock block = myClosure.getElement();
|
||||
if (block == null) {
|
||||
throw new IllegalStateException("No parent closure");
|
||||
}
|
||||
return new ClosureSyntheticParameter(PsiTreeUtil.findSameElementInCopy(block, copy), isOptional());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement setName(@NotNull String newName) throws IncorrectOperationException {
|
||||
if (!newName.equals(getName())) {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.plugins.groovy.refactoring.rename
|
||||
|
||||
import com.intellij.openapi.command.WriteCommandAction
|
||||
|
||||
import com.intellij.openapi.command.CommandProcessor
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.impl.source.PostprocessReformattingAspect
|
||||
@@ -555,9 +556,10 @@ class Test {
|
||||
private def doInplaceRenameTest() {
|
||||
String prefix = "/${testName.capitalize()}"
|
||||
fixture.configureByFile prefix + ".groovy"
|
||||
WriteCommandAction.runWriteCommandAction project, {
|
||||
CodeInsightTestUtil.doInlineRename(new GrVariableInplaceRenameHandler(), "foo", fixture)
|
||||
}
|
||||
CommandProcessor.instance.executeCommand(
|
||||
project,
|
||||
{ CodeInsightTestUtil.doInlineRename(new GrVariableInplaceRenameHandler(), "foo", fixture) },
|
||||
"Rename", null)
|
||||
fixture.checkResultByFile prefix + "_after.groovy"
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ package com.jetbrains.python;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.codeInspection.LocalInspectionTool;
|
||||
import com.intellij.codeInspection.ex.InspectionProfileImpl;
|
||||
import com.intellij.openapi.application.impl.NonBlockingReadActionImpl;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.testFramework.LightProjectDescriptor;
|
||||
import com.intellij.testFramework.TestDataFile;
|
||||
@@ -831,6 +832,7 @@ public class PyQuickFixTest extends PyTestCase {
|
||||
}
|
||||
if (applyFix) {
|
||||
myFixture.launchAction(intentionActions.get(0));
|
||||
NonBlockingReadActionImpl.waitForAsyncTaskCompletion();
|
||||
myFixture.checkResultByFile(graftBeforeExt(testFiles[0], "_after"), true);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user