fix todo duplication when several pattern match -> prefer finding match with last pattern (in settings list), thus default TODO pattern is matched last

This commit is contained in:
Maxim.Mossienko
2013-09-20 15:54:40 +02:00
parent a4d4371dca
commit eb22a991a4
4 changed files with 43 additions and 29 deletions
@@ -22,6 +22,7 @@ import com.intellij.psi.impl.cache.impl.id.IdTableBuilding;
import com.intellij.psi.search.IndexPattern;
import com.intellij.psi.search.UsageSearchContext;
import com.intellij.util.text.CharArrayUtil;
import gnu.trove.TIntArrayList;
import org.jetbrains.annotations.Nullable;
import java.util.regex.Matcher;
@@ -32,7 +33,7 @@ public abstract class BaseFilterLexer extends DelegateLexer implements IdTableBu
private int myTodoScannedBound = 0;
private int myOccurenceMask;
private TodoScanningData[] myTodoScanningData;
private TodoScanningState myTodoScanningState;
private CharSequence myCachedBufferSequence;
private char[] myCachedArraySequence;
@@ -49,49 +50,56 @@ public abstract class BaseFilterLexer extends DelegateLexer implements IdTableBu
if (start >= end) return; // this prevents scanning of the same comment twice
CharSequence input = myCachedBufferSequence.subSequence(start, end);
myTodoScanningData = advanceTodoItemsCount(input, myOccurrenceConsumer, myTodoScanningData);
myTodoScanningState = advanceTodoItemsCount(input, myOccurrenceConsumer, myTodoScanningState);
myTodoScannedBound = end;
}
public static class TodoScanningData {
final IndexPattern pattern;
final Matcher matcher;
public static class TodoScanningState {
final IndexPattern[] myPatterns;
final Matcher[] myMatchers;
TIntArrayList myOccurences;
public TodoScanningData(IndexPattern pattern, Matcher matcher) {
this.matcher = matcher;
this.pattern = pattern;
public TodoScanningState(IndexPattern[] patterns, Matcher[] matchers) {
myPatterns = patterns;
myMatchers = matchers;
myOccurences = new TIntArrayList(1);
}
}
public static TodoScanningData[] advanceTodoItemsCount(final CharSequence input, final OccurrenceConsumer consumer, TodoScanningData[] todoScanningData) {
if (todoScanningData == null) {
public static TodoScanningState advanceTodoItemsCount(final CharSequence input, final OccurrenceConsumer consumer, TodoScanningState todoScanningState) {
if (todoScanningState == null) {
IndexPattern[] patterns = IndexPatternUtil.getIndexPatterns();
todoScanningData = new TodoScanningData[patterns.length];
Matcher[] matchers = new Matcher[patterns.length];
todoScanningState = new TodoScanningState(patterns, matchers);
for (int i = 0; i < patterns.length; ++i) {
IndexPattern indexPattern = patterns[i];
Pattern pattern = indexPattern.getPattern();
Pattern pattern = patterns[i].getPattern();
if (pattern != null) {
todoScanningData [i] = new TodoScanningData(indexPattern, pattern.matcher(""));
matchers[i] = pattern.matcher("");
}
}
} else {
todoScanningState.myOccurences.resetQuick();
}
for (TodoScanningData data:todoScanningData) {
if (data == null) continue;
Matcher matcher = data.matcher;
for (int i = todoScanningState.myMatchers.length - 1; i >= 0; --i) {
Matcher matcher = todoScanningState.myMatchers[i];
if (matcher == null) continue;
matcher.reset(input);
while (matcher.find()) {
if (matcher.start() != matcher.end()) {
consumer.incTodoOccurrence(data.pattern);
int start = matcher.start();
if (start != matcher.end() && todoScanningState.myOccurences.indexOf(start) == -1) {
consumer.incTodoOccurrence(todoScanningState.myPatterns[i]);
todoScanningState.myOccurences.add(start);
}
}
}
return todoScanningData;
return todoScanningState;
}
@Override
@@ -173,7 +173,7 @@ public abstract class PlatformIdTableBuilding {
}
final int documentLength = chars.length();
BaseFilterLexer.TodoScanningData[] todoScanningDatas = null;
BaseFilterLexer.TodoScanningState todoScanningState = null;
final HighlighterIterator iterator = highlighter.createIterator(0);
while (!iterator.atEnd()) {
@@ -184,10 +184,10 @@ public abstract class PlatformIdTableBuilding {
if (start >= documentLength) break;
int end = iterator.getEnd();
todoScanningDatas = BaseFilterLexer.advanceTodoItemsCount(
todoScanningState = BaseFilterLexer.advanceTodoItemsCount(
chars.subSequence(start, Math.min(end, documentLength)),
occurrenceConsumer,
todoScanningDatas
todoScanningState
);
if (end > documentLength) break;
}
@@ -133,7 +133,7 @@ public class TodoIndex extends FileBasedIndexExtension<TodoIndexEntry, Integer>
@Override
public int getVersion() {
return 4;
return 5;
}
@Override
@@ -77,21 +77,24 @@ public class IndexPatternSearcher implements QueryExecutor<IndexPatternOccurrenc
final CharSequence chars = file.getViewProvider().getContents();
findCommentTokenRanges(file, chars, queryParameters.getRange(), commentStarts, commentEnds);
TIntArrayList occurrences = new TIntArrayList(1);
IndexPattern[] patterns = patternProvider != null ? patternProvider.getIndexPatterns() : null;
for (int i = 0; i < commentStarts.size(); i++) {
int commentStart = commentStarts.get(i);
int commentEnd = commentEnds.get(i);
occurrences.resetQuick();
if (patternProvider != null) {
for (final IndexPattern pattern : patternProvider.getIndexPatterns()) {
if (!collectPatternMatches(pattern, chars, commentStart, commentEnd, file, queryParameters.getRange(), consumer)) {
for (int j = patterns.length - 1; j >=0; --j) {
if (!collectPatternMatches(patterns[j], chars, commentStart, commentEnd, file, queryParameters.getRange(), consumer, occurrences)) {
return false;
}
}
}
else {
if (!collectPatternMatches(queryParameters.getPattern(), chars, commentStart, commentEnd, file, queryParameters.getRange(),
consumer)) {
consumer, occurrences)) {
return false;
}
}
@@ -236,7 +239,9 @@ public class IndexPatternSearcher implements QueryExecutor<IndexPatternOccurrenc
int commentEnd,
PsiFile file,
TextRange range,
Processor<IndexPatternOccurrence> consumer) {
Processor<IndexPatternOccurrence> consumer,
TIntArrayList matches
) {
Pattern pattern = indexPattern.getPattern();
if (pattern != null) {
ProgressManager.checkCanceled();
@@ -253,7 +258,8 @@ public class IndexPatternSearcher implements QueryExecutor<IndexPatternOccurrenc
int start = matcher.start() + commentStart;
int end = matcher.end() + commentStart;
if (start != end) {
if (range == null || range.getStartOffset() <= start && end <= range.getEndOffset()) {
if ((range == null || range.getStartOffset() <= start && end <= range.getEndOffset()) && matches.indexOf(start) == -1) {
matches.add(start);
if (!consumer.process(new IndexPatternOccurrenceImpl(file, start, end, indexPattern))) {
return false;
}