package org.rubypeople.rdt.internal.ui.text;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.rules.IPartitionTokenScanner;
import org.eclipse.jface.text.rules.IToken;
import org.eclipse.jface.text.rules.Token;
/**
* Wraps the Ruby PartitonScanner and merges consecutive tokens with teh same data/partition marking. So if we have 10
* default tokens in a row, this will eat up the ten and return a token that spans all of them.
*
* @author Chris Williams
*/
public class MergingPartitionScanner implements IPartitionTokenScanner
{
private RubyPartitionScanner fScanner;
private int fOffset;
private int fLength;
private int newOffset = 0;
private int newLength = 0;
private IToken lastToken;
public MergingPartitionScanner()
{
fScanner = new RubyPartitionScanner();
}
public void setPartialRange(IDocument document, int offset, int length, String contentType, int partitionOffset)
{
clear();
fScanner.setPartialRange(document, offset, length, contentType, partitionOffset);
}
public int getTokenLength()
{
return fLength;
}
public int getTokenOffset()
{
return fOffset;
}
public IToken nextToken()
{
setLength(newLength);
setOffset(newOffset);
if (lastToken != null && lastToken.isEOF())
{
return lastToken;
}
IToken token = null;
while (!(token = fScanner.nextToken()).isEOF())
{
if (lastToken != null && token.getData().equals(lastToken.getData()))
{
continue;
}
if (lastToken == null)
{
lastToken = token;
setOffset(fScanner.getTokenOffset());
setLength(fScanner.getTokenLength());
continue;
}
return wrapUp(token);
}
if (lastToken == null)
{
return Token.EOF;
}
return wrapUp(token);
}
private IToken wrapUp(IToken token)
{
setLength(fScanner.getTokenOffset() - fOffset);
newOffset = fScanner.getTokenOffset();
newLength = fScanner.getTokenLength();
Assert.isTrue(newLength >= 0);
IToken returnToken = lastToken; // make a copy of the last token
lastToken = token; // save new token
return returnToken;
}
private void setOffset(int tokenOffset)
{
fOffset = tokenOffset;
}
private void setLength(int tokenLength)
{
Assert.isTrue(tokenLength >= 0);
fLength = tokenLength;
}
public void setRange(IDocument document, int offset, int length)
{
clear();
fScanner.setRange(document, offset, length);
}
private void clear()
{
lastToken = null;
fLength = 0;
fOffset = 0;
newLength = 0;
newOffset = 0;
}
}