diff --git a/platform/platform-api/src/com/intellij/lexer/LookAheadLexer.java b/platform/platform-api/src/com/intellij/lexer/LookAheadLexer.java index b162d3cab6c3..b388f6892c28 100644 --- a/platform/platform-api/src/com/intellij/lexer/LookAheadLexer.java +++ b/platform/platform-api/src/com/intellij/lexer/LookAheadLexer.java @@ -17,8 +17,7 @@ package com.intellij.lexer; import com.intellij.psi.tree.IElementType; import com.intellij.util.containers.ImmutableUserMap; - -import java.util.LinkedList; +import com.intellij.util.containers.Queue; /** * @author peter @@ -29,20 +28,27 @@ public abstract class LookAheadLexer extends LexerBase{ private final Lexer myBaseLexer; private int myTokenStart; - private final LinkedList myTypeCache = new LinkedList(); - private final LinkedList myEndOffsetCache = new LinkedList(); + private final Queue myTypeCache; + private final Queue myEndOffsetCache; + + public LookAheadLexer(final Lexer baseLexer, int capacity) { + myBaseLexer = baseLexer; + myTypeCache = new Queue(capacity); + myEndOffsetCache = new Queue(capacity); + } public LookAheadLexer(final Lexer baseLexer) { - myBaseLexer = baseLexer; + this(baseLexer, 64); } + protected void addToken(IElementType type) { addToken(myBaseLexer.getTokenEnd(), type); } protected void addToken(int endOffset, IElementType type) { - myTypeCache.add(type); - myEndOffsetCache.add(endOffset); + myTypeCache.addLast(type); + myEndOffsetCache.addLast(endOffset); } protected void lookAhead(Lexer baseLexer) { @@ -51,8 +57,8 @@ public abstract class LookAheadLexer extends LexerBase{ public void advance() { if (!myTypeCache.isEmpty()) { - myTypeCache.removeFirst(); - myTokenStart = myEndOffsetCache.removeFirst(); + myTypeCache.pullFirst(); + myTokenStart = myEndOffsetCache.pullFirst(); } if (myTypeCache.isEmpty()) { doLookAhead(); @@ -92,7 +98,7 @@ public abstract class LookAheadLexer extends LexerBase{ } public int getTokenEnd() { - return myEndOffsetCache.getFirst(); + return myEndOffsetCache.peekFirst(); } public int getTokenStart() { @@ -115,7 +121,7 @@ public abstract class LookAheadLexer extends LexerBase{ } public IElementType getTokenType() { - return myTypeCache.getFirst(); + return myTypeCache.peekFirst(); } @Override diff --git a/platform/util/src/com/intellij/util/containers/Queue.java b/platform/util/src/com/intellij/util/containers/Queue.java index 94e5b230c5eb..46652e7227b4 100644 --- a/platform/util/src/com/intellij/util/containers/Queue.java +++ b/platform/util/src/com/intellij/util/containers/Queue.java @@ -50,6 +50,18 @@ public class Queue { myLast = 0; } } + + public T removeLast() { + if (myLast == 0) { + isWrapped = !isWrapped; + myLast = myArray.length; + } + myLast--; + T result = (T)myArray[myLast]; + myArray[myLast] = null; + return result; + } + public boolean isEmpty() { return size() == 0; diff --git a/platform/util/testSrc/com/intellij/util/containers/QueueTest.java b/platform/util/testSrc/com/intellij/util/containers/QueueTest.java index 1435d96e2b6f..aa9879ddee4d 100644 --- a/platform/util/testSrc/com/intellij/util/containers/QueueTest.java +++ b/platform/util/testSrc/com/intellij/util/containers/QueueTest.java @@ -57,6 +57,28 @@ public class QueueTest extends TestCase { assertEquals(xxx,x); assertTrue(queue.isEmpty()); } + + public void testRemoving() { + com.intellij.util.containers.Queue queue = new com.intellij.util.containers.Queue(10); + for (int i = 0; i < 9; i++) { + queue.addLast(String.valueOf(i)); + } + for (int i = 0; i < 4; i++) { + Object first = queue.pullFirst(); + queue.addLast(first); + } + for (int i = 3; i >= 0; i--) { + Assert.assertEquals(String.valueOf(i), queue.removeLast()); + } + for (int i = 8; i >= 6; i--) { + Assert.assertEquals(String.valueOf(i), queue.removeLast()); + } + for (int i = 4; i <= 5; i++) { + Assert.assertEquals(String.valueOf(i), queue.pullFirst()); + } + } + + public void testCycling() { com.intellij.util.containers.Queue queue = new com.intellij.util.containers.Queue(10); for (int i = 0; i < 9; i++) {