mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
WEB-43327 React.js: "Expand selection" works incorrectly in Redirect tag expression - improve code readability
IDEA-CR-57481 GitOrigin-RevId: 1fe3993dfde741666dd102255e29065c3c5c37aa
This commit is contained in:
committed by
intellij-monorepo-bot
parent
e2c4eb74d7
commit
eb94c86d0d
+38
-32
@@ -19,6 +19,9 @@ import one.util.streamex.StreamEx;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import static com.intellij.util.ObjectUtils.notNull;
|
||||
|
||||
/**
|
||||
* This selectioner tries to guess location of file segments within a particular element.
|
||||
@@ -44,18 +47,14 @@ public class InjectedFileReferenceSelectioner extends AbstractWordSelectioner {
|
||||
|
||||
PsiElement valueElement = findValueElement(host, realRange);
|
||||
|
||||
List<TextRange> nonLeafChildren = StreamEx.of(valueElement.getChildren())
|
||||
.filter(child -> !(child instanceof LeafPsiElement))
|
||||
.map(PsiElement::getTextRange)
|
||||
.sorted(Comparator.comparing(TextRange::getStartOffset).reversed())
|
||||
.toList();
|
||||
|
||||
realRange = limitToCurrentLineAndStripWhiteSpace(editorText, cursorOffset, realRange);
|
||||
|
||||
Set<Integer> charEscapeLocations = isWithinLiteral(e, host) ? findCharEscapeLocations(editor, editorText, host.getTextRange())
|
||||
: Collections.emptySet();
|
||||
BitSet charEscapeLocations = isWithinLiteral(e, host)
|
||||
? findCharEscapeLocations(editor, editorText, host.getTextRange(), realRange.getStartOffset())
|
||||
: new BitSet(0);
|
||||
|
||||
List<TextRange> segments = buildSegments(editorText, cursorOffset, charEscapeLocations, realRange, nonLeafChildren);
|
||||
BitSet compositeIndexes = createCompositeIndexesSet(valueElement, realRange.getStartOffset());
|
||||
List<TextRange> segments = buildSegments(editorText, cursorOffset, realRange, charEscapeLocations, compositeIndexes);
|
||||
if (!segments.isEmpty()) {
|
||||
int endOffsetAlignment = segments.get(segments.size() - 1).getEndOffset();
|
||||
for (ListIterator<TextRange> it = segments.listIterator(); it.hasNext(); ) {
|
||||
@@ -70,19 +69,19 @@ public class InjectedFileReferenceSelectioner extends AbstractWordSelectioner {
|
||||
|
||||
@NotNull
|
||||
private static PsiElement findValueElement(@NotNull PsiElement host, @NotNull TextRange valueRange) {
|
||||
PsiElement result = host.getContainingFile().findElementAt(valueRange.getStartOffset());
|
||||
while (result != null && result != host && !result.getTextRange().contains(valueRange)) {
|
||||
result = result.getParent();
|
||||
}
|
||||
return result != null ? result : host;
|
||||
return notNull(
|
||||
PsiTreeUtil.findFirstParent(
|
||||
host.getContainingFile().findElementAt(valueRange.getStartOffset()), false,
|
||||
parent -> parent == host || parent.getTextRange().contains(valueRange)),
|
||||
host);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<TextRange> buildSegments(@NotNull CharSequence editorText,
|
||||
final int cursorOffset,
|
||||
@NotNull Set<Integer> charEscapeLocations,
|
||||
@NotNull TextRange range,
|
||||
List<TextRange> nonLeafChildren) {
|
||||
@NotNull BitSet charEscapeLocations,
|
||||
@NotNull BitSet compositeIndexes) {
|
||||
if (range.getLength() == 0) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
@@ -94,11 +93,14 @@ public class InjectedFileReferenceSelectioner extends AbstractWordSelectioner {
|
||||
boolean segmentsFinished = false;
|
||||
int hardSegmentCount = 0;
|
||||
|
||||
for (int i = hostTextOffset; i < hostTextEndOffset; i = findNextIndexInLeafElement(i, nonLeafChildren)) {
|
||||
for (int i = hostTextOffset; i < hostTextEndOffset; i++) {
|
||||
if (compositeIndexes.get(i - hostTextOffset)) {
|
||||
continue;
|
||||
}
|
||||
char ch = editorText.charAt(i);
|
||||
if (!segmentsFinished) {
|
||||
if (ch == '/'
|
||||
|| (ch == '\\' && !charEscapeLocations.contains(i))
|
||||
|| (ch == '\\' && !charEscapeLocations.get(i - hostTextOffset))
|
||||
//treat space as soft segment marker
|
||||
|| (ch == ' ' && i <= cursorOffset)) {
|
||||
if (rangeStart < i) {
|
||||
@@ -120,7 +122,7 @@ public class InjectedFileReferenceSelectioner extends AbstractWordSelectioner {
|
||||
// URLs - expand to content after '?' first, but count it as soft segment
|
||||
else if (ch == '?') {
|
||||
segments.add(new TextRange(rangeStart, i));
|
||||
if (i + 1< hostTextEndOffset) {
|
||||
if (i + 1 < hostTextEndOffset) {
|
||||
segments.add(new TextRange(i + 1, hostTextEndOffset));
|
||||
}
|
||||
segments.add(new TextRange(rangeStart, hostTextEndOffset));
|
||||
@@ -142,15 +144,15 @@ public class InjectedFileReferenceSelectioner extends AbstractWordSelectioner {
|
||||
return segments;
|
||||
}
|
||||
|
||||
private static int findNextIndexInLeafElement(int currentIndex, List<TextRange> nonLeafChildren) {
|
||||
// skip any non leaf children - ranges sorted backwards to optimize element removal
|
||||
while (!nonLeafChildren.isEmpty() && nonLeafChildren.get(nonLeafChildren.size() - 1).getStartOffset() <= currentIndex) {
|
||||
TextRange nonLeafRange = nonLeafChildren.remove(nonLeafChildren.size() - 1);
|
||||
if (nonLeafRange.getEndOffset() - 1 > currentIndex) {
|
||||
return nonLeafRange.getEndOffset();
|
||||
}
|
||||
}
|
||||
return currentIndex + 1;
|
||||
@NotNull
|
||||
private static BitSet createCompositeIndexesSet(@NotNull PsiElement valueElement, int indexesOffset) {
|
||||
return StreamEx.of(valueElement.getChildren())
|
||||
.filter(child -> !(child instanceof LeafPsiElement))
|
||||
.map(PsiElement::getTextRange)
|
||||
.flatMapToInt(range -> IntStream.range(range.getStartOffset(), range.getEndOffset()))
|
||||
.map(index -> index - indexesOffset)
|
||||
.atLeast(0)
|
||||
.toBitSet();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -178,17 +180,21 @@ public class InjectedFileReferenceSelectioner extends AbstractWordSelectioner {
|
||||
|| SkipAutopopupInStrings.isInStringLiteral(e);
|
||||
}
|
||||
|
||||
private static Set<Integer> findCharEscapeLocations(@NotNull Editor editor, @NotNull CharSequence text, @NotNull TextRange range) {
|
||||
private static BitSet findCharEscapeLocations(@NotNull Editor editor,
|
||||
@NotNull CharSequence text,
|
||||
@NotNull TextRange range,
|
||||
int indexesOffset) {
|
||||
HighlighterIterator iterator =
|
||||
((EditorEx)editor).getHighlighter().createIterator(range.getStartOffset());
|
||||
int rangeEnd = range.getEndOffset();
|
||||
|
||||
Set<Integer> locations = new HashSet<>();
|
||||
BitSet locations = new BitSet(range.getLength());
|
||||
int pos;
|
||||
while (!iterator.atEnd() && (pos = iterator.getStart()) < rangeEnd) {
|
||||
if (text.charAt(pos) == '\\'
|
||||
&& (pos + 1 >= rangeEnd || text.charAt(pos + 1) != '\\')) {
|
||||
locations.add(pos);
|
||||
&& (pos + 1 >= rangeEnd || text.charAt(pos + 1) != '\\')
|
||||
&& pos >= indexesOffset) {
|
||||
locations.set(pos - indexesOffset);
|
||||
}
|
||||
iterator.advance();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user