mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
editor: fix incorrect union computation of two TextRange sets for FindInEditor
GitOrigin-RevId: a9741d0071633dca613ec71bb0d2ce26219f25e8
This commit is contained in:
committed by
intellij-monorepo-bot
parent
0b696be98d
commit
83d69a1b92
@@ -24,10 +24,12 @@ import com.intellij.ui.HintHint;
|
||||
import com.intellij.ui.LightweightHint;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.opentest4j.AssertionFailedError;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class FindInEditorTest extends LightPlatformCodeInsightTestCase {
|
||||
private LivePreviewController myLivePreviewController;
|
||||
@@ -343,4 +345,51 @@ public class FindInEditorTest extends LightPlatformCodeInsightTestCase {
|
||||
EditorFactory.getInstance().releaseEditor(editor);
|
||||
}
|
||||
}
|
||||
|
||||
public void testSearchAreaUnion() {
|
||||
SearchResults.SearchArea emptyArea = new SearchResults.SearchArea(new int[]{}, new int[]{});
|
||||
SearchResults.SearchArea area1 = new SearchResults.SearchArea(new int[]{10, 90}, new int[]{30, 95});
|
||||
SearchResults.SearchArea area2 = new SearchResults.SearchArea(new int[]{5, 25}, new int[]{15, 45});
|
||||
SearchResults.SearchArea area3 = new SearchResults.SearchArea(new int[]{5, 10, 85}, new int[]{6, 12, 90});
|
||||
|
||||
assertSameSearchAreas(area1.union(area1), area1);
|
||||
assertSameSearchAreas(area2.union(area2), area2);
|
||||
assertSameSearchAreas(area3.union(area3), area3);
|
||||
|
||||
assertSameSearchAreas(area1.union(area2), area2.union(area1));
|
||||
assertSameSearchAreas(area1.union(area3), area3.union(area1));
|
||||
assertSameSearchAreas(area2.union(area3), area3.union(area2));
|
||||
|
||||
assertSameSearchAreas(new SearchResults.SearchArea(new int[]{5, 90}, new int[]{45, 95}),
|
||||
area1.union(area2));
|
||||
assertSameSearchAreas(new SearchResults.SearchArea(new int[]{5, 10, 85}, new int[]{6, 30, 95}),
|
||||
area1.union(area3));
|
||||
assertSameSearchAreas(new SearchResults.SearchArea(new int[]{5, 25, 85}, new int[]{15, 45, 90}),
|
||||
area2.union(area3));
|
||||
|
||||
assertSameSearchAreas(new SearchResults.SearchArea(new int[]{5, 85}, new int[]{45, 95}),
|
||||
area1.union(area2).union(area3));
|
||||
|
||||
assertSameSearchAreas(emptyArea, emptyArea.union(emptyArea));
|
||||
assertSameSearchAreas(area1, emptyArea.union(area1));
|
||||
assertSameSearchAreas(area1, area1.union(emptyArea));
|
||||
}
|
||||
|
||||
private static void assertSameSearchAreas(SearchResults.SearchArea expected,
|
||||
SearchResults.SearchArea actual) {
|
||||
if (Arrays.equals(expected.startOffsets(), actual.startOffsets()) &&
|
||||
Arrays.equals(expected.endOffsets(), actual.endOffsets())) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new AssertionFailedError(null,
|
||||
"startOffsets:\n" +
|
||||
StringUtil.join(expected.startOffsets(), "\n") +
|
||||
"\n\nendOffsets:\n" +
|
||||
StringUtil.join(expected.endOffsets(), "\n"),
|
||||
"startOffsets:\n" +
|
||||
StringUtil.join(actual.startOffsets(), "\n") +
|
||||
"\n\nendOffsets:\n" +
|
||||
StringUtil.join(actual.endOffsets(), "\n"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.intellij.find.FindModel;
|
||||
import com.intellij.find.FindResult;
|
||||
import com.intellij.find.FindUtil;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Caret;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
@@ -28,6 +29,8 @@ import com.intellij.util.concurrency.annotations.RequiresEdt;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.Stack;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -275,58 +278,67 @@ public class SearchResults implements DocumentListener, CaretListener {
|
||||
|
||||
/**
|
||||
* Merges the given {@link SearchArea} with the current one.
|
||||
* <p/>
|
||||
* If the given areas intersect - union area will be returned.
|
||||
* If the given areas have no intersection - area contains all the given areas will be returned.
|
||||
*
|
||||
* @param area the area to merge with the current
|
||||
* @return a new merged area
|
||||
*/
|
||||
public @NotNull SearchArea merge(@NotNull SearchArea area) {
|
||||
int[] startOffsets1 = startOffsets;
|
||||
int[] endOffsets1 = endOffsets;
|
||||
public @NotNull SearchArea union(@NotNull SearchArea area) {
|
||||
int[] mergedStartOffsets = ArrayUtil.mergeArrays(startOffsets, area.startOffsets);
|
||||
int[] mergedEndOffsets = ArrayUtil.mergeArrays(endOffsets, area.endOffsets);
|
||||
Arrays.sort(mergedStartOffsets);
|
||||
Arrays.sort(mergedEndOffsets);
|
||||
|
||||
int[] startOffsets2 = area.startOffsets;
|
||||
int[] endOffsets2 = area.endOffsets;
|
||||
final IntList resultStartOffsets = new IntArrayList(mergedStartOffsets.length);
|
||||
final IntList resultEndOffsets = new IntArrayList(mergedStartOffsets.length);
|
||||
|
||||
List<TextRange> notIntersectedRanges = new ArrayList<>();
|
||||
new Object() {
|
||||
int counter = 0;
|
||||
int startsIndex = 0;
|
||||
int endsIndex = 0;
|
||||
|
||||
for (int i1 = 0; i1 < startOffsets1.length; i1++) {
|
||||
int startOffset1 = startOffsets1[i1];
|
||||
int endOffset1 = endOffsets1[i1];
|
||||
TextRange range1 = new TextRange(startOffset1, endOffset1);
|
||||
|
||||
boolean intersects = false;
|
||||
for (int i2 = 0; i2 < startOffsets2.length; i2++) {
|
||||
int startOffset2 = startOffsets2[i2];
|
||||
int endOffset2 = endOffsets2[i2];
|
||||
TextRange range2 = new TextRange(startOffset2, endOffset2);
|
||||
|
||||
if (range1.intersects(range2)) {
|
||||
TextRange union = range1.union(range2);
|
||||
startOffsets2[i2] = union.getStartOffset();
|
||||
endOffsets2[i2] = union.getEndOffset();
|
||||
intersects = true;
|
||||
break;
|
||||
void run() {
|
||||
while (startsIndex < mergedStartOffsets.length ||
|
||||
endsIndex < mergedEndOffsets.length) {
|
||||
if (endsIndex == mergedEndOffsets.length) {
|
||||
Logger.getInstance(SearchArea.class).error(String.format("Merging invalid SearchArea: %s - %s", this, area));
|
||||
nextStart();
|
||||
}
|
||||
else if (startsIndex == mergedStartOffsets.length) {
|
||||
nextEnd();
|
||||
}
|
||||
else {
|
||||
int start = mergedStartOffsets[startsIndex];
|
||||
int end = mergedEndOffsets[endsIndex];
|
||||
if (start <= end) {
|
||||
nextStart();
|
||||
}
|
||||
else {
|
||||
nextEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!intersects) {
|
||||
notIntersectedRanges.add(range1);
|
||||
void nextStart() {
|
||||
if (counter == 0) {
|
||||
int startOffset = mergedStartOffsets[startsIndex];
|
||||
resultStartOffsets.add(startOffset);
|
||||
}
|
||||
counter++;
|
||||
startsIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
int[] notIntersectedStartOffsets = new int[notIntersectedRanges.size()];
|
||||
int[] notIntersectedEndOffsets = new int[notIntersectedRanges.size()];
|
||||
for (int i = 0; i < notIntersectedRanges.size(); i++) {
|
||||
notIntersectedStartOffsets[i] = notIntersectedRanges.get(i).getStartOffset();
|
||||
notIntersectedEndOffsets[i] = notIntersectedRanges.get(i).getEndOffset();
|
||||
}
|
||||
void nextEnd() {
|
||||
counter--;
|
||||
if (counter == 0) {
|
||||
int endOffset = mergedEndOffsets[endsIndex];
|
||||
resultEndOffsets.add(endOffset);
|
||||
}
|
||||
if (counter < 0) {
|
||||
Logger.getInstance(SearchArea.class).error(String.format("Merging invalid SearchArea: %s - %s", this, area));
|
||||
}
|
||||
endsIndex++;
|
||||
}
|
||||
}.run();
|
||||
|
||||
int[] mergedStartOffsets = ArrayUtil.mergeArrays(notIntersectedStartOffsets, startOffsets2);
|
||||
int[] mergedEndOffsets = ArrayUtil.mergeArrays(notIntersectedEndOffsets, endOffsets2);
|
||||
|
||||
return create(mergedStartOffsets, mergedEndOffsets);
|
||||
return create(resultStartOffsets.toIntArray(), resultEndOffsets.toIntArray());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -366,7 +378,7 @@ public class SearchResults implements DocumentListener, CaretListener {
|
||||
searchArea = searchAreaFromEP;
|
||||
}
|
||||
else {
|
||||
searchArea = searchArea.merge(searchAreaFromEP);
|
||||
searchArea = searchArea.union(searchAreaFromEP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user