processOverlapping should iterate in order

This commit is contained in:
Alexey Kudravtsev
2014-05-16 14:33:38 +04:00
parent cf632d0941
commit 53b9222ced
6 changed files with 56 additions and 58 deletions
@@ -21,7 +21,6 @@ import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.ex.DisposableIterator;
import com.intellij.openapi.editor.ex.MarkupModelEx;
import com.intellij.openapi.editor.ex.RangeHighlighterEx;
import com.intellij.openapi.editor.ex.SweepProcessor;
import com.intellij.openapi.editor.impl.event.MarkupModelListener;
import com.intellij.openapi.editor.markup.HighlighterTargetArea;
import com.intellij.openapi.editor.markup.RangeHighlighter;
@@ -151,12 +150,6 @@ public class MarkupModelWindow extends UserDataHolderBase implements MarkupModel
return myHostModel.overlappingIterator(startOffset, endOffset);
}
@Override
public boolean sweep(int start, int end, @NotNull SweepProcessor<RangeHighlighterEx> sweepProcessor) {
// todo convert
return myHostModel.sweep(start, end, sweepProcessor);
}
@Override
public void fireAttributesChanged(@NotNull RangeHighlighterEx segmentHighlighter, boolean renderersChanged) {
@@ -72,6 +72,4 @@ public interface MarkupModelEx extends MarkupModel {
// runs change attributes action and fires highlighterChanged event if there were changes
void changeAttributesInBatch(@NotNull RangeHighlighterEx highlighter, @NotNull Consumer<RangeHighlighterEx> changeAttributesAction);
boolean sweep(int start, int end, @NotNull final SweepProcessor<RangeHighlighterEx> sweepProcessor);
}
@@ -20,7 +20,6 @@ import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.ex.DisposableIterator;
import com.intellij.openapi.editor.ex.MarkupModelEx;
import com.intellij.openapi.editor.ex.RangeHighlighterEx;
import com.intellij.openapi.editor.ex.SweepProcessor;
import com.intellij.openapi.editor.impl.event.MarkupModelListener;
import com.intellij.openapi.editor.markup.HighlighterTargetArea;
import com.intellij.openapi.editor.markup.RangeHighlighter;
@@ -144,11 +143,6 @@ public class EmptyMarkupModel implements MarkupModelEx {
return DisposableIterator.EMPTY;
}
@Override
public boolean sweep(int start, int end, @NotNull SweepProcessor<RangeHighlighterEx> sweepProcessor) {
return false;
}
@Override
public void fireAttributesChanged(@NotNull RangeHighlighterEx segmentHighlighter, boolean renderersChanged) {
@@ -44,7 +44,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.NoSuchElementException;
@@ -258,9 +257,18 @@ public class MarkupModelImpl extends UserDataHolderBase implements MarkupModelEx
@Override
public boolean processRangeHighlightersOverlappingWith(int start, int end, @NotNull Processor<? super RangeHighlighterEx> processor) {
if (!myHighlighterTree.processOverlappingWith(start, end, processor)) return false;
TextRangeInterval lines = roundToLineBoundaries(start, end);
return myHighlighterTreeForLines.processOverlappingWith(lines.getStartOffset(), lines.getEndOffset(), processor);
DisposableIterator<RangeHighlighterEx> iterator = overlappingIterator(start, end);
try {
while (iterator.hasNext()) {
if (!processor.process(iterator.next())) {
return false;
}
}
return true;
}
finally {
iterator.dispose();
}
}
@Override
@@ -272,7 +280,8 @@ public class MarkupModelImpl extends UserDataHolderBase implements MarkupModelEx
@Override
@NotNull
public DisposableIterator<RangeHighlighterEx> overlappingIterator(int startOffset, int endOffset) {
IntervalTreeImpl.PeekableIterator<RangeHighlighterEx> exact = myHighlighterTree.overlappingIterator(new TextRangeInterval(startOffset, endOffset));
startOffset = Math.max(0,startOffset);
IntervalTreeImpl.PeekableIterator<RangeHighlighterEx> exact = myHighlighterTree.overlappingIterator(new TextRangeInterval(startOffset, Math.max(startOffset, endOffset)));
IntervalTreeImpl.PeekableIterator<RangeHighlighterEx> lines = myHighlighterTreeForLines.overlappingIterator(roundToLineBoundaries(startOffset, endOffset));
return merge(exact, lines);
}
@@ -319,25 +328,4 @@ public class MarkupModelImpl extends UserDataHolderBase implements MarkupModelEx
int lineEndOffset = endOffset <= 0 ? 0 : endOffset >= document.getTextLength() ? document.getTextLength() : document.getLineEndOffset(document.getLineNumber(endOffset));
return new TextRangeInterval(lineStartOffset, lineEndOffset);
}
@Override
public boolean sweep(int start, int end, @NotNull SweepProcessor<RangeHighlighterEx> sweepProcessor) {
TextRangeInterval lines = roundToLineBoundaries(start, end);
List<RangeHighlighterEx> linesInRange = new ArrayList<RangeHighlighterEx>();
myHighlighterTreeForLines.processOverlappingWith(lines.getStartOffset(), lines.getEndOffset(), new CommonProcessors.CollectProcessor<RangeHighlighterEx>(linesInRange));
if (linesInRange.isEmpty()) {
return myHighlighterTree.sweep(start, end, sweepProcessor);
}
final List<RangeHighlighterEx> highlighters = new ArrayList<RangeHighlighterEx>();
myHighlighterTree.processOverlappingWith(start, end, new CommonProcessors.CollectProcessor<RangeHighlighterEx>(highlighters));
highlighters.addAll(linesInRange);
Collections.sort(highlighters, RangeHighlighterEx.BY_AFFECTED_START_OFFSET);
return RangeMarkerTree.sweep(new RangeMarkerTree.Generator<RangeHighlighterEx>() {
@Override
public boolean generateInStartOffsetOrder(@NotNull Processor<RangeHighlighterEx> processor) {
return ContainerUtil.process(highlighters, processor);
}
}, sweepProcessor);
}
}
@@ -22,12 +22,10 @@ import com.intellij.openapi.command.undo.UndoManager;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.event.DocumentAdapter;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.editor.ex.DocumentEx;
import com.intellij.openapi.editor.ex.MarkupModelEx;
import com.intellij.openapi.editor.ex.RangeHighlighterEx;
import com.intellij.openapi.editor.ex.RangeMarkerEx;
import com.intellij.openapi.editor.ex.*;
import com.intellij.openapi.editor.markup.HighlighterTargetArea;
import com.intellij.openapi.editor.markup.MarkupModel;
import com.intellij.openapi.editor.markup.RangeHighlighter;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.ThrowableComputable;
@@ -45,10 +43,7 @@ import com.intellij.util.ThrowableRunnable;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.*;
/**
* @author mike
@@ -1090,4 +1085,15 @@ public class RangeMarkerTest extends LightPlatformTestCase {
}
}).assertTiming();
}
public void testRangeHighlighterIteratorOrder() throws Exception {
Document document = EditorFactory.getInstance().createDocument("1234567890");
final MarkupModelEx markupModel = (MarkupModelEx)DocumentMarkupModel.forDocument(document, ourProject, true);
RangeHighlighter exact = markupModel.addRangeHighlighter(3, 6, 0, null, HighlighterTargetArea.EXACT_RANGE);
RangeHighlighter line = markupModel.addRangeHighlighter(4, 5, 0, null, HighlighterTargetArea.LINES_IN_RANGE);
List<RangeHighlighter> list = new ArrayList<RangeHighlighter>();
markupModel.processRangeHighlightersOverlappingWith(2, 9, new CommonProcessors.CollectProcessor<RangeHighlighter>(list));
assertEquals(Arrays.asList(line,exact), list);
}
}
@@ -313,7 +313,7 @@ public class ContainerUtil extends ContainerUtilRt {
return CHM_FACTORY.createMap();
}
public static <K, V> ConcurrentMap<K,V> newConcurrentMap(TObjectHashingStrategy<K> hashStrategy) {
public static <K, V> ConcurrentMap<K,V> newConcurrentMap(@NotNull TObjectHashingStrategy<K> hashStrategy) {
return CHM_FACTORY.createMap(hashStrategy);
}
@@ -321,7 +321,7 @@ public class ContainerUtil extends ContainerUtilRt {
return CHM_FACTORY.createMap(initialCapacity);
}
public static <K, V> ConcurrentMap<K,V> newConcurrentMap(int initialCapacity, float loadFactor, int concurrencyLevel, TObjectHashingStrategy<K> hashStrategy) {
public static <K, V> ConcurrentMap<K,V> newConcurrentMap(int initialCapacity, float loadFactor, int concurrencyLevel, @NotNull TObjectHashingStrategy<K> hashStrategy) {
return CHM_FACTORY.createMap(initialCapacity, loadFactor, concurrencyLevel, hashStrategy);
}
@@ -704,6 +704,15 @@ public class ContainerUtil extends ContainerUtilRt {
return true;
}
public static <T> boolean process(@NotNull Iterator<T> iterator, @NotNull Processor<? super T> processor) {
while (iterator.hasNext()) {
if (!processor.process(iterator.next())) {
return false;
}
}
return true;
}
@Nullable
public static <T, V extends T> V find(@NotNull Iterable<V> iterable, @NotNull Condition<T> condition) {
return find(iterable.iterator(), condition);
@@ -2057,45 +2066,53 @@ public class ContainerUtil extends ContainerUtilRt {
}
private interface ConcurrentMapFactory {
<T, V> ConcurrentMap<T, V> createMap();
<T, V> ConcurrentMap<T, V> createMap(int initialCapacity);
<T, V> ConcurrentMap<T, V> createMap(TObjectHashingStrategy<T> hashStrategy);
<T, V> ConcurrentMap<T, V> createMap(int initialCapacity, float loadFactor, int concurrencyLevel);
<T, V> ConcurrentMap<T, V> createMap(int initialCapacity, float loadFactor, int concurrencyLevel, TObjectHashingStrategy<T> hashStrategy);
@NotNull <T, V> ConcurrentMap<T, V> createMap();
@NotNull <T, V> ConcurrentMap<T, V> createMap(int initialCapacity);
@NotNull <T, V> ConcurrentMap<T, V> createMap(@NotNull TObjectHashingStrategy<T> hashStrategy);
@NotNull <T, V> ConcurrentMap<T, V> createMap(int initialCapacity, float loadFactor, int concurrencyLevel);
@NotNull <T, V> ConcurrentMap<T, V> createMap(int initialCapacity, float loadFactor, int concurrencyLevel, @NotNull TObjectHashingStrategy<T> hashStrategy);
}
private static final ConcurrentMapFactory V8_MAP_FACTORY = new ConcurrentMapFactory() {
@NotNull
public <T, V> ConcurrentMap<T, V> createMap() {
return new ConcurrentHashMap<T,V>();
}
@NotNull
public <T, V> ConcurrentMap<T, V> createMap(int initialCapacity) {
return new ConcurrentHashMap<T,V>(initialCapacity);
}
public <T, V> ConcurrentMap<T, V> createMap(TObjectHashingStrategy<T> hashStrategy) {
@NotNull
public <T, V> ConcurrentMap<T, V> createMap(@NotNull TObjectHashingStrategy<T> hashStrategy) {
return new ConcurrentHashMap<T,V>(hashStrategy);
}
@NotNull
public <T, V> ConcurrentMap<T, V> createMap(int initialCapacity, float loadFactor, int concurrencyLevel) {
return new ConcurrentHashMap<T,V>(initialCapacity, loadFactor, concurrencyLevel);
}
@NotNull
public <T, V> ConcurrentMap<T, V> createMap(int initialCapacity, float loadFactor, int concurrencyLevel, @NotNull TObjectHashingStrategy<T> hashingStrategy) {
return new ConcurrentHashMap<T,V>(initialCapacity, loadFactor, concurrencyLevel, hashingStrategy);
}
};
private static final ConcurrentMapFactory PLATFORM_MAP_FACTORY = new ConcurrentMapFactory() {
@NotNull
public <T, V> ConcurrentMap<T, V> createMap() {
return createMap(16, 0.75f, DEFAULT_CONCURRENCY_LEVEL);
}
@NotNull
public <T, V> ConcurrentMap<T, V> createMap(int initialCapacity) {
return new java.util.concurrent.ConcurrentHashMap<T,V>(initialCapacity);
}
public <T, V> ConcurrentMap<T, V> createMap(TObjectHashingStrategy<T> hashingStrategy) {
@NotNull
public <T, V> ConcurrentMap<T, V> createMap(@NotNull TObjectHashingStrategy<T> hashingStrategy) {
if (hashingStrategy != canonicalStrategy()) {
throw new UnsupportedOperationException("Custom hashStrategy is not supported in java.util.concurrent.ConcurrentHashMap");
}
@@ -2103,10 +2120,12 @@ public class ContainerUtil extends ContainerUtilRt {
return createMap();
}
@NotNull
public <T, V> ConcurrentMap<T, V> createMap(int initialCapacity, float loadFactor, int concurrencyLevel) {
return new java.util.concurrent.ConcurrentHashMap<T,V>(initialCapacity, loadFactor, concurrencyLevel);
}
@NotNull
public <T, V> ConcurrentMap<T, V> createMap(int initialCapacity, float loadFactor, int concurrencyLevel, @NotNull TObjectHashingStrategy<T> hashingStrategy) {
if (hashingStrategy != canonicalStrategy()) {
throw new UnsupportedOperationException("Custom hashStrategy is not supported in java.util.concurrent.ConcurrentHashMap");