Bug 560686: Add BasicHeuristicTokenScanner.scanForward for multiple
strings
Change-Id: Ib15024535b02b438e3418bd7aa28964a39e6a12b
diff --git a/ltk/org.eclipse.statet.ltk.core/src/org/eclipse/statet/ecommons/text/BasicHeuristicTokenScanner.java b/ltk/org.eclipse.statet.ltk.core/src/org/eclipse/statet/ecommons/text/BasicHeuristicTokenScanner.java
index f70392f..11eb491 100644
--- a/ltk/org.eclipse.statet.ltk.core/src/org/eclipse/statet/ecommons/text/BasicHeuristicTokenScanner.java
+++ b/ltk/org.eclipse.statet.ltk.core/src/org/eclipse/statet/ecommons/text/BasicHeuristicTokenScanner.java
@@ -25,6 +25,8 @@
import org.eclipse.statet.jcommons.collections.IntArrayList;
import org.eclipse.statet.jcommons.collections.IntList;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
import org.eclipse.statet.ecommons.text.core.PartitionConstraint;
import org.eclipse.statet.ecommons.text.core.sections.DocContentSections;
@@ -37,6 +39,7 @@
*
* @since 0.2
*/
+@NonNullByDefault
public class BasicHeuristicTokenScanner implements ITokenScanner {
@@ -84,7 +87,7 @@
*/
protected abstract class PartitionBasedCondition extends StopCondition {
- private ITypedRegion currentPartition;
+ private @Nullable ITypedRegion currentPartition;
private boolean currentPartitionMatched;
private int currentPartitionStart;
private int currentPartitionEnd;
@@ -98,10 +101,11 @@
if (this.currentPartitionMatched && this.currentPartitionStart <= BasicHeuristicTokenScanner.this.pos && BasicHeuristicTokenScanner.this.pos < this.currentPartitionEnd) {
return matchesChar();
}
- this.currentPartition= getPartition();
- this.currentPartitionStart= this.currentPartition.getOffset();
- this.currentPartitionEnd= this.currentPartitionStart+this.currentPartition.getLength();
- if (BasicHeuristicTokenScanner.this.partitionConstraint.matches(this.currentPartition.getType())) {
+ final ITypedRegion partition= getPartition();
+ this.currentPartition= partition;
+ this.currentPartitionStart= partition.getOffset();
+ this.currentPartitionEnd= this.currentPartitionStart + partition.getLength();
+ if (BasicHeuristicTokenScanner.this.partitionConstraint.matches(partition.getType())) {
this.currentPartitionMatched= true;
return matchesChar();
}
@@ -209,36 +213,48 @@
protected class StringMatchCondition extends PartitionBasedCondition {
- protected final String fString;
- private final char fEscapeChar;
- private int fLastEscapeOffset= -100;
+ protected final String[] strings;
+ private final int escapeChar;
+ private int lastEscapeOffset= Integer.MIN_VALUE;
/**
* Creates a new instance.
* @param ch the string to match
*/
- public StringMatchCondition(final String s, final char escapeChar) {
- this.fString= s;
- this.fEscapeChar= escapeChar;
+ public StringMatchCondition(final String s, final int escapeChar) {
+ this.strings= new String[] { s };
+ this.escapeChar= escapeChar;
+ }
+
+ /**
+ * Creates a new instance.
+ * @param ch the string to match
+ */
+ public StringMatchCondition(final String[] s, final int escapeChar) {
+ this.strings= s;
+ this.escapeChar= escapeChar;
}
@Override
protected boolean matchesChar() {
- if (BasicHeuristicTokenScanner.this.pos == this.fLastEscapeOffset+1) {
+ if (BasicHeuristicTokenScanner.this.pos == this.lastEscapeOffset + 1) {
return false;
}
- if (this.fString.charAt(0) == BasicHeuristicTokenScanner.this.ch) {
- try {
- if (this.fString.regionMatches(1, BasicHeuristicTokenScanner.this.document.get(BasicHeuristicTokenScanner.this.pos+1, this.fString.length()-1),
- 0, this.fString.length()-1 )) {
- return true;
+ if (this.escapeChar == BasicHeuristicTokenScanner.this.ch) {
+ this.lastEscapeOffset= BasicHeuristicTokenScanner.this.pos;
+ return false;
+ }
+ try {
+ for (final String string : this.strings) {
+ if (string.charAt(0) == BasicHeuristicTokenScanner.this.ch) {
+ if (string.regionMatches(1, BasicHeuristicTokenScanner.this.document.get(
+ BasicHeuristicTokenScanner.this.pos + 1, string.length() - 1),
+ 0, string.length() - 1 )) {
+ return true;
+ }
}
- } catch (final BadLocationException e) {}
- }
- if (this.fEscapeChar == BasicHeuristicTokenScanner.this.ch) {
- this.fLastEscapeOffset= BasicHeuristicTokenScanner.this.pos;
- return false;
- }
+ }
+ } catch (final BadLocationException e) {}
return false;
}
@@ -264,10 +280,11 @@
/** the most recently read line of position (only if used). */
private int line;
- private StopCondition nonWSCondition;
- private StopCondition nonWSorLRCondition;
+ private @Nullable StopCondition nonWSCondition;
+ private @Nullable StopCondition nonWSorLRCondition;
+ @SuppressWarnings("null")
public BasicHeuristicTokenScanner(final DocContentSections documentContentInfo,
final PartitionConstraint defaultContentConstraint) {
this.partitioning= documentContentInfo.getPartitioning();
@@ -300,51 +317,59 @@
}
protected final StopCondition getAnyNonWSCondition() {
- if (this.nonWSCondition == null) {
- this.nonWSCondition= new StopCondition() {
+ StopCondition nonWSCondition= this.nonWSCondition;
+ if (nonWSCondition == null) {
+ nonWSCondition= new StopCondition() {
@Override
public boolean stop() {
return (!isWhitespace());
}
};
+ this.nonWSCondition= nonWSCondition;
}
- return this.nonWSCondition;
+ return nonWSCondition;
}
protected final StopCondition getAnyNonWSorLRCondition() {
- if (this.nonWSorLRCondition == null) {
- this.nonWSorLRCondition= new StopCondition() {
+ StopCondition nonWSorLRCondition= this.nonWSorLRCondition;
+ if (nonWSorLRCondition == null) {
+ nonWSorLRCondition= new StopCondition() {
@Override
public boolean stop() {
return (!isWhitespace() && BasicHeuristicTokenScanner.this.ch != '\r' && BasicHeuristicTokenScanner.this.ch != '\n');
}
};
+ this.nonWSorLRCondition= nonWSorLRCondition;
}
- return this.nonWSorLRCondition;
+ return nonWSorLRCondition;
}
protected final StopCondition getNonWSCondition() {
- if (this.nonWSCondition == null) {
- this.nonWSCondition= new PartitionBasedCondition() {
+ StopCondition nonWSCondition= this.nonWSCondition;
+ if (nonWSCondition == null) {
+ nonWSCondition= new PartitionBasedCondition() {
@Override
protected boolean matchesChar() {
return (!isWhitespace());
}
};
+ this.nonWSCondition= nonWSCondition;
}
- return this.nonWSCondition;
+ return nonWSCondition;
}
protected final StopCondition getNonWSorLRCondition() {
- if (this.nonWSorLRCondition == null) {
- this.nonWSorLRCondition= new PartitionBasedCondition() {
+ StopCondition nonWSorLRCondition= this.nonWSorLRCondition;
+ if (nonWSorLRCondition == null) {
+ nonWSorLRCondition= new PartitionBasedCondition() {
@Override
protected boolean matchesChar() {
return (!isWhitespace() && BasicHeuristicTokenScanner.this.ch != '\r' && BasicHeuristicTokenScanner.this.ch != '\n');
}
};
+ this.nonWSorLRCondition= nonWSorLRCondition;
}
- return this.nonWSorLRCondition;
+ return nonWSorLRCondition;
}
/**
@@ -621,11 +646,11 @@
getNonWSorLRCondition() : getNonWSCondition());
}
- public IRegion findBlankRegion(final int position, final boolean linebreakIsBlank) {
+ public @Nullable IRegion findBlankRegion(final int position, final boolean linebreakIsBlank) {
return findRegion(position, linebreakIsBlank ?
getAnyNonWSorLRCondition() : getAnyNonWSCondition());
}
-
+
public boolean isBlankLine(final int position) throws BadLocationException {
final IRegion line= this.document.getLineInformationOfOffset(position);
if (line.getLength() > 0) {
@@ -635,7 +660,7 @@
return true;
}
- public final IRegion findCommonWord(final int position) {
+ public final @Nullable IRegion findCommonWord(final int position) {
return findRegion(position, new StopCondition() {
@Override
public boolean stop() {
@@ -657,7 +682,7 @@
}
- private final int[] preScanBackward(final int start, final int bound, final StopCondition condition) throws BadLocationException {
+ private final int @Nullable [] preScanBackward(final int start, final int bound, final StopCondition condition) throws BadLocationException {
final IntList list= new IntArrayList();
int scanEnd= start+1;
@@ -747,14 +772,20 @@
return scanForward(position, bound, new CharacterMatchCondition(chars));
}
- /** Provisional / Not Tested */
- public final int scanForward(final int position, int bound, final String s, final char escapeChar) {
+ public final int scanForward(final int position, int bound, final String s, final int escapeChar) {
if (bound == UNBOUND) {
bound= this.document.getLength();
}
bound-= s.length();
return scanForward(position, bound, new StringMatchCondition(s, escapeChar));
}
+ public final int scanForward(final int position, int bound, final String[] s, final int escapeChar) {
+ if (bound == UNBOUND) {
+ bound= this.document.getLength();
+ }
+ bound-= s[0].length();
+ return scanForward(position, bound, new StringMatchCondition(s, escapeChar));
+ }
/**
* Finds the highest position <code>p</code> in <code>document</code> such that <code>bound</code> < <code>p</code> <= <code>start</code>
@@ -831,11 +862,11 @@
}
- protected final IRegion findRegion(final int position, final StopCondition condition) {
+ protected final @Nullable IRegion findRegion(final int position, final StopCondition condition) {
return findRegion(position, condition, false);
}
- protected final IRegion findRegion(final int position, final StopCondition condition, final boolean allowClosing) {
+ protected final @Nullable IRegion findRegion(final int position, final StopCondition condition, final boolean allowClosing) {
int start= position;
int end= scanForward(position, UNBOUND, condition);
if (end == NOT_FOUND) {
@@ -861,7 +892,7 @@
* @return the content type at <code>position</code> or a dummy zero-length
* partition if accessing the document fails
*/
- protected final String getContentType() {
+ protected final @Nullable String getContentType() {
try {
return TextUtilities.getContentType(this.document, this.partitioning, this.pos, false);
}