mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-02-04 23:39:07 +07:00
[mod-commands] Support rename inside injection; better rename support in tests
GitOrigin-RevId: b2ce440cb969796c8a470ba763fa777c331fe148
This commit is contained in:
committed by
intellij-monorepo-bot
parent
c95abb6185
commit
7d779bbbe9
@@ -5,6 +5,7 @@ import com.intellij.codeInsight.template.Expression;
|
||||
import com.intellij.codeInsight.template.ExpressionContext;
|
||||
import com.intellij.codeInsight.template.Result;
|
||||
import com.intellij.codeInsight.template.TextResult;
|
||||
import com.intellij.injected.editor.DocumentWindow;
|
||||
import com.intellij.injected.editor.InjectionEditService;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.lang.injection.InjectedLanguageManager;
|
||||
@@ -73,6 +74,7 @@ final class PsiUpdateImpl {
|
||||
private final @NotNull PsiFile myOrigFile;
|
||||
private final @NotNull PsiFile myCopyFile;
|
||||
private final @NotNull PsiDocumentManager myManager;
|
||||
private final @Nullable PsiFile myInjectedFileCopy;
|
||||
private boolean myDeleted;
|
||||
|
||||
FileTracker(@NotNull PsiFile origFile) {
|
||||
@@ -86,10 +88,10 @@ final class PsiUpdateImpl {
|
||||
PsiLanguageInjectionHost host = Objects.requireNonNull(injectionManager.getInjectionHost(origFile));
|
||||
PsiFile hostFile = host.getContainingFile();
|
||||
PsiFile hostFileCopy = (PsiFile)hostFile.copy();
|
||||
PsiFile injectedFileCopy = getInjectedFileCopy(host, hostFileCopy, origFile.getLanguage());
|
||||
myHostCopy = injectionManager.getInjectionHost(injectedFileCopy);
|
||||
myInjectedFileCopy = getInjectedFileCopy(host, hostFileCopy, origFile.getLanguage());
|
||||
myHostCopy = injectionManager.getInjectionHost(myInjectedFileCopy);
|
||||
Disposable disposable = ApplicationManager.getApplication().getService(InjectionEditService.class)
|
||||
.synchronizeWithFragment(injectedFileCopy, myDocument);
|
||||
.synchronizeWithFragment(myInjectedFileCopy, myDocument);
|
||||
Disposer.register(this, disposable);
|
||||
myTargetFile = hostFileCopy;
|
||||
origFile = hostFile;
|
||||
@@ -99,6 +101,7 @@ final class PsiUpdateImpl {
|
||||
myHostCopy = null;
|
||||
myTargetFile = myCopyFile;
|
||||
myPositionDocument = myDocument;
|
||||
myInjectedFileCopy = null;
|
||||
}
|
||||
myPositionDocument.addDocumentListener(this, this);
|
||||
myOrigText = myTargetFile.getText();
|
||||
@@ -321,7 +324,14 @@ final class PsiUpdateImpl {
|
||||
SmartPsiElementPointer<PsiElement> pointer = SmartPointerManager.createPointer(element);
|
||||
myTracker.unblock();
|
||||
Segment range = pointer.getRange();
|
||||
return range == null ? null : TextRange.create(range);
|
||||
if (range == null) return null;
|
||||
if (myTracker.myInjectedFileCopy != null) {
|
||||
InjectedLanguageManager instance = InjectedLanguageManager.getInstance(myTracker.myProject);
|
||||
int start = instance.mapUnescapedOffsetToInjected(myTracker.myInjectedFileCopy, range.getStartOffset());
|
||||
int end = instance.mapUnescapedOffsetToInjected(myTracker.myInjectedFileCopy, range.getEndOffset());
|
||||
return ((DocumentWindow)myTracker.myInjectedFileCopy.getViewProvider().getDocument()).injectedToHost(TextRange.create(start, end));
|
||||
}
|
||||
return TextRange.create(range);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.diff.fragments.DiffFragment;
|
||||
import com.intellij.ide.util.MemberChooser;
|
||||
import com.intellij.lang.LangBundle;
|
||||
import com.intellij.lang.LanguageRefactoringSupport;
|
||||
import com.intellij.lang.injection.InjectedLanguageManager;
|
||||
import com.intellij.lang.refactoring.RefactoringSupportProvider;
|
||||
import com.intellij.modcommand.*;
|
||||
import com.intellij.modcommand.ModChooseMember.SelectionMode;
|
||||
@@ -68,10 +69,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import javax.swing.*;
|
||||
import java.awt.datatransfer.StringSelection;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import static java.util.Objects.requireNonNullElse;
|
||||
@@ -407,37 +405,52 @@ public class ModCommandExecutorImpl implements ModCommandExecutor {
|
||||
if (file == null) return false;
|
||||
PsiFile psiFile = PsiManagerEx.getInstanceEx(project).findFile(file);
|
||||
if (psiFile == null) return false;
|
||||
PsiNamedElement element =
|
||||
PsiTreeUtil.getNonStrictParentOfType(psiFile.findElementAt(rename.symbolRange().range().getStartOffset()), PsiNamedElement.class);
|
||||
if (element == null) return false;
|
||||
TextRange range = rename.symbolRange().range();
|
||||
PsiElement injectedElement = InjectedLanguageManager.getInstance(project).findInjectedElementAt(psiFile, range.getStartOffset());
|
||||
PsiElement psiElement = injectedElement != null ? injectedElement : psiFile.findElementAt(range.getStartOffset());
|
||||
PsiNamedElement namedElement = PsiTreeUtil.getNonStrictParentOfType(psiElement, PsiNamedElement.class);
|
||||
if (namedElement == null) return false;
|
||||
Editor finalEditor = getEditor(project, editor, file);
|
||||
if (finalEditor == null) return false;
|
||||
PsiElement nameIdentifier = element instanceof PsiNameIdentifierOwner owner ? owner.getNameIdentifier() : null;
|
||||
if (TemplateManager.getInstance(project) instanceof TemplateManagerImpl manager &&
|
||||
manager.shouldSkipInTests()) {
|
||||
if (nameIdentifier == null) return true;
|
||||
int offset = nameIdentifier.getTextRange().getEndOffset();
|
||||
return executeNavigate(project, new ModNavigate(file, offset, offset, offset));
|
||||
}
|
||||
final RenamePsiElementProcessor processor = RenamePsiElementProcessor.forElement(element);
|
||||
processor.substituteElementToRename(element, finalEditor, new Pass<>() {
|
||||
PsiElement nameIdentifier = namedElement instanceof PsiNameIdentifierOwner owner ? owner.getNameIdentifier() : null;
|
||||
final RenamePsiElementProcessor processor = RenamePsiElementProcessor.forElement(namedElement);
|
||||
processor.substituteElementToRename(namedElement, finalEditor, new Pass<>() {
|
||||
@Override
|
||||
public void pass(PsiElement substitutedElement) {
|
||||
RefactoringSupportProvider supportProvider = LanguageRefactoringSupport.INSTANCE.forContext(element);
|
||||
RefactoringSupportProvider supportProvider = LanguageRefactoringSupport.INSTANCE.forContext(namedElement);
|
||||
if (supportProvider != null &&
|
||||
supportProvider.isInplaceRenameAvailable(element, element)) {
|
||||
finalEditor.getCaretModel().moveToOffset(Objects.requireNonNullElse(nameIdentifier, element).getTextOffset());
|
||||
final MemberInplaceRenamer renamer = new MemberInplaceRenamer(element, substitutedElement, finalEditor);
|
||||
supportProvider.isInplaceRenameAvailable(namedElement, namedElement)) {
|
||||
if (TemplateManager.getInstance(project) instanceof TemplateManagerImpl manager &&
|
||||
manager.shouldSkipInTests()) {
|
||||
if (nameIdentifier != null) {
|
||||
int offset = nameIdentifier.getTextRange().getEndOffset();
|
||||
executeNavigate(project, new ModNavigate(file, offset, offset, offset));
|
||||
}
|
||||
return;
|
||||
}
|
||||
finalEditor.getCaretModel().moveToOffset(requireNonNullElse(nameIdentifier, namedElement).getTextOffset());
|
||||
final MemberInplaceRenamer renamer = new MemberInplaceRenamer(namedElement, substitutedElement, finalEditor);
|
||||
final LinkedHashSet<String> nameSuggestions = new LinkedHashSet<>(rename.nameSuggestions());
|
||||
renamer.performInplaceRefactoring(nameSuggestions);
|
||||
}
|
||||
else {
|
||||
new RenameDialog(project, element, null, finalEditor) {
|
||||
RenameDialog dialog = new RenameDialog(project, namedElement, null, finalEditor) {
|
||||
@Override
|
||||
public String[] getSuggestedNames() {
|
||||
return ArrayUtil.toStringArray(rename.nameSuggestions());
|
||||
}
|
||||
}.show();
|
||||
};
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
try {
|
||||
dialog.performRename(rename.nameSuggestions().stream().min(Comparator.naturalOrder()).orElse("undefined"));
|
||||
}
|
||||
finally {
|
||||
dialog.close();
|
||||
}
|
||||
}
|
||||
else {
|
||||
dialog.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user