Skip to content

Commit 94c284f

Browse files
Marcono1234ObserverOfTime
authored andcommitted
perf(query): implement predicate evaluation iteratively
The previous recursive implementation could lead to a StackOverflowError if a predicate returned `false` very often.
1 parent 4495e40 commit 94c284f

File tree

1 file changed

+18
-16
lines changed
  • src/main/java/io/github/treesitter/jtreesitter

1 file changed

+18
-16
lines changed

src/main/java/io/github/treesitter/jtreesitter/Query.java

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -542,24 +542,26 @@ public MatchesIterator(Tree tree, @Nullable BiPredicate<QueryPredicate, QueryMat
542542

543543
@Override
544544
public boolean tryAdvance(Consumer<? super QueryMatch> action) {
545+
var hasNoText = tree.getText() == null;
545546
MemorySegment match = arena.allocate(TSQueryMatch.layout());
546-
if (!ts_query_cursor_next_match(cursor, match)) return false;
547-
var count = Short.toUnsignedInt(TSQueryMatch.capture_count(match));
548-
var matchCaptures = TSQueryMatch.captures(match);
549-
var captureList = new ArrayList<QueryCapture>(count);
550-
for (int i = 0; i < count; ++i) {
551-
var capture = TSQueryCapture.asSlice(matchCaptures, i);
552-
var name = captureNames.get(TSQueryCapture.index(capture));
553-
var node = TSNode.allocate(arena).copyFrom(TSQueryCapture.node(capture));
554-
captureList.add(new QueryCapture(name, new Node(node, tree)));
555-
}
556-
var patternIndex = TSQueryMatch.pattern_index(match);
557-
var result = new QueryMatch(patternIndex, captureList);
558-
if (tree.getText() == null || matches(predicate, result)) {
559-
action.accept(result);
560-
return true;
547+
while (ts_query_cursor_next_match(cursor, match)) {
548+
var count = Short.toUnsignedInt(TSQueryMatch.capture_count(match));
549+
var matchCaptures = TSQueryMatch.captures(match);
550+
var captureList = new ArrayList<QueryCapture>(count);
551+
for (int i = 0; i < count; ++i) {
552+
var capture = TSQueryCapture.asSlice(matchCaptures, i);
553+
var name = captureNames.get(TSQueryCapture.index(capture));
554+
var node = TSNode.allocate(arena).copyFrom(TSQueryCapture.node(capture));
555+
captureList.add(new QueryCapture(name, new Node(node, tree)));
556+
}
557+
var patternIndex = TSQueryMatch.pattern_index(match);
558+
var result = new QueryMatch(patternIndex, captureList);
559+
if (hasNoText || matches(predicate, result)) {
560+
action.accept(result);
561+
return true;
562+
}
561563
}
562-
return tryAdvance(action);
564+
return false;
563565
}
564566
}
565567
}

0 commit comments

Comments
 (0)