mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[mod-command] EditorUpdater#select(TextRange); fix injection handling
GitOrigin-RevId: c1c412601661e7bf8231d12e024bb53109d010ba
This commit is contained in:
committed by
intellij-monorepo-bot
parent
427bdb73f2
commit
ff7bded456
+5
-3
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.psi.impl.source.tree.injected;
|
||||
|
||||
import com.intellij.codeInsight.editorActions.CopyPastePreProcessor;
|
||||
@@ -117,8 +117,10 @@ class OldJavaInjectedFileChangesHandler extends BaseInjectedFileChangesHandler {
|
||||
// reformat
|
||||
PsiDocumentManager.getInstance(myProject).commitDocument(myHostDocument);
|
||||
try {
|
||||
CodeStyleManager.getInstance(myProject).reformatRange(
|
||||
origPsiFile, hostStartOffset, myAltFullRange.getEndOffset(), true);
|
||||
if (origPsiFile != null && origPsiFile.isPhysical()) {
|
||||
CodeStyleManager.getInstance(myProject).reformatRange(
|
||||
origPsiFile, hostStartOffset, myAltFullRange.getEndOffset(), true);
|
||||
}
|
||||
}
|
||||
catch (IncorrectOperationException e1) {
|
||||
//LOG.error(e);
|
||||
|
||||
+3
-3
@@ -4,8 +4,8 @@ import java.util.stream.Stream;
|
||||
class Test {
|
||||
void foo(Stream<String> stringStream ) {
|
||||
stringStream.filter(name -> name.startsWith("A") && name.//comment2
|
||||
length() > 1//comment
|
||||
/*comment1*/
|
||||
).findAny();
|
||||
length() > 1//comment
|
||||
/*comment1*/
|
||||
).findAny();
|
||||
}
|
||||
}
|
||||
|
||||
+25
@@ -265,6 +265,31 @@ public final class InjectedLanguageManagerImpl extends InjectedLanguageManager i
|
||||
return visitor.unescapedOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int mapUnescapedOffsetToInjected(@NotNull PsiFile injectedFile, int offset) {
|
||||
if (offset < 0) return offset;
|
||||
var visitor = new PsiRecursiveElementWalkingVisitor() {
|
||||
int unescapedOffset = 0;
|
||||
int escapedOffset = 0;
|
||||
|
||||
@Override
|
||||
public void visitElement(@NotNull PsiElement element) {
|
||||
String leafText = InjectedLanguageUtilBase.getUnescapedLeafText(element, false);
|
||||
if (leafText != null) {
|
||||
unescapedOffset += leafText.length();
|
||||
escapedOffset += element.getTextLength();
|
||||
if (unescapedOffset >= offset) {
|
||||
escapedOffset -= unescapedOffset - offset;
|
||||
stopWalking();
|
||||
}
|
||||
}
|
||||
super.visitElement(element);
|
||||
}
|
||||
};
|
||||
injectedFile.accept(visitor);
|
||||
return visitor.escapedOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* intersection may spread over several injected fragments
|
||||
* @param rangeToEdit range in encoded(raw) PSI
|
||||
|
||||
@@ -64,6 +64,11 @@ public abstract class InjectedLanguageManager {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
public int mapUnescapedOffsetToInjected(@NotNull PsiFile injectedFile, int offset) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public abstract List<TextRange> intersectWithAllEditableFragments(@NotNull PsiFile injectedPsi, @NotNull TextRange rangeToEdit);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -21,6 +22,13 @@ public interface EditorUpdater {
|
||||
*/
|
||||
void select(@NotNull PsiElement element);
|
||||
|
||||
/**
|
||||
* Selects given range
|
||||
*
|
||||
* @param range range to select
|
||||
*/
|
||||
void select(@NotNull TextRange range);
|
||||
|
||||
/**
|
||||
* Navigates to a given element
|
||||
*
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.LocalTimeCounter;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
@@ -92,22 +93,25 @@ public final class ModCommands {
|
||||
PsiFile targetFile;
|
||||
Document positionDocument;
|
||||
boolean injected = injectionManager.isInjectedFragment(origFile);
|
||||
PsiLanguageInjectionHost hostCopy;
|
||||
if (injected) {
|
||||
PsiLanguageInjectionHost host = Objects.requireNonNull(injectionManager.getInjectionHost(origFile));
|
||||
PsiFile hostFile = host.getContainingFile();
|
||||
PsiFile hostFileCopy = (PsiFile)hostFile.copy();
|
||||
PsiFile injectedFileCopy = getInjectedFileCopy(host, hostFileCopy, orig.getLanguage());
|
||||
hostCopy = injectionManager.getInjectionHost(injectedFileCopy);
|
||||
disposable = ApplicationManager.getApplication().getService(InjectionEditService.class)
|
||||
.synchronizeWithFragment(injectedFileCopy, document);
|
||||
targetFile = hostFileCopy;
|
||||
origFile = hostFile;
|
||||
positionDocument = hostFileCopy.getViewProvider().getDocument();
|
||||
} else {
|
||||
hostCopy = null;
|
||||
disposable = null;
|
||||
targetFile = copyFile;
|
||||
positionDocument = document;
|
||||
}
|
||||
EditorUpdaterImpl context = new EditorUpdaterImpl(actionContext, positionDocument, manager, document, injected, targetFile, copyFile);
|
||||
EditorUpdaterImpl context = new EditorUpdaterImpl(actionContext, positionDocument, manager, document, hostCopy, copyFile);
|
||||
try {
|
||||
String oldText = targetFile.getText();
|
||||
aspect.postponeFormattingInside(
|
||||
@@ -190,8 +194,7 @@ public final class ModCommands {
|
||||
private final @NotNull Document myPositionDocument;
|
||||
private final @NotNull PsiDocumentManager myManager;
|
||||
private final @NotNull Document myDocument;
|
||||
private final boolean myInjected;
|
||||
private final @NotNull PsiFile myTargetFile;
|
||||
private final @Nullable PsiLanguageInjectionHost myHost;
|
||||
private final @NotNull PsiFile myCopyFile;
|
||||
private int myCaretOffset, mySelectionStart, mySelectionEnd;
|
||||
|
||||
@@ -199,14 +202,12 @@ public final class ModCommands {
|
||||
@NotNull Document positionDocument,
|
||||
@NotNull PsiDocumentManager manager,
|
||||
@NotNull Document document,
|
||||
boolean injected,
|
||||
@NotNull PsiFile targetFile,
|
||||
@Nullable PsiLanguageInjectionHost host,
|
||||
@NotNull PsiFile copyFile) {
|
||||
myPositionDocument = positionDocument;
|
||||
myManager = manager;
|
||||
myDocument = document;
|
||||
myInjected = injected;
|
||||
myTargetFile = targetFile;
|
||||
myHost = host;
|
||||
myCopyFile = copyFile;
|
||||
myCaretOffset = actionContext.offset();
|
||||
mySelectionStart = actionContext.selection().getStartOffset();
|
||||
@@ -218,28 +219,51 @@ public final class ModCommands {
|
||||
public void select(@NotNull PsiElement element) {
|
||||
validate(element);
|
||||
myManager.doPostponedOperationsAndUnblockDocument(myDocument);
|
||||
if (myInjected) {
|
||||
element = PsiTreeUtil.findSameElementInCopy(element, myTargetFile);
|
||||
}
|
||||
TextRange range = element.getTextRange();
|
||||
select(range);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void select(@NotNull TextRange range) {
|
||||
if (myHost != null) {
|
||||
InjectedLanguageManager instance = InjectedLanguageManager.getInstance(myCopyFile.getProject());
|
||||
PsiFile file = findInjectedFile(instance, myHost);
|
||||
int start = instance.mapUnescapedOffsetToInjected(file, range.getStartOffset());
|
||||
int end = instance.mapUnescapedOffsetToInjected(file, range.getEndOffset());
|
||||
range = instance.injectedToHost(file, TextRange.create(start, end));
|
||||
}
|
||||
mySelectionStart = range.getStartOffset();
|
||||
mySelectionEnd = range.getEndOffset();
|
||||
myCaretOffset = range.getStartOffset();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void moveTo(@NotNull PsiElement element) {
|
||||
validate(element);
|
||||
myManager.doPostponedOperationsAndUnblockDocument(myDocument);
|
||||
if (myInjected) {
|
||||
element = PsiTreeUtil.findSameElementInCopy(element, myTargetFile);
|
||||
}
|
||||
int offset = element.getTextRange().getStartOffset();
|
||||
moveToOffset(offset);
|
||||
if (myHost != null) {
|
||||
InjectedLanguageManager instance = InjectedLanguageManager.getInstance(myCopyFile.getProject());
|
||||
PsiFile file = findInjectedFile(instance, myHost);
|
||||
offset = instance.mapUnescapedOffsetToInjected(file, offset);
|
||||
offset = instance.injectedToHost(file, offset);
|
||||
}
|
||||
myCaretOffset = offset;
|
||||
}
|
||||
|
||||
private void moveToOffset(int offset) {
|
||||
myCaretOffset = offset;
|
||||
private PsiFile findInjectedFile(InjectedLanguageManager instance, PsiLanguageInjectionHost host) {
|
||||
var visitor = new PsiLanguageInjectionHost.InjectedPsiVisitor() {
|
||||
PsiFile myFile = null;
|
||||
|
||||
@Override
|
||||
public void visit(@NotNull PsiFile injectedPsi, @NotNull List<? extends PsiLanguageInjectionHost.Shred> places) {
|
||||
if (injectedPsi.getLanguage() == myCopyFile.getLanguage()) {
|
||||
myFile = injectedPsi;
|
||||
}
|
||||
}
|
||||
};
|
||||
instance.enumerate(host, visitor);
|
||||
return Objects.requireNonNull(visitor.myFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -248,7 +272,7 @@ public final class ModCommands {
|
||||
String text = myPositionDocument.getText();
|
||||
int idx = text.lastIndexOf(ch, myCaretOffset);
|
||||
if (idx == -1) return;
|
||||
moveToOffset(idx);
|
||||
myCaretOffset = idx;
|
||||
}
|
||||
|
||||
private void validate(@NotNull PsiElement element) {
|
||||
|
||||
Reference in New Issue
Block a user