55import io .github .treesitter .jtreesitter .internal .*;
66import java .lang .foreign .Arena ;
77import java .lang .foreign .MemorySegment ;
8+ import java .lang .foreign .SegmentAllocator ;
89import java .util .*;
910import java .util .function .BiPredicate ;
1011import java .util .function .Consumer ;
@@ -480,10 +481,21 @@ public Map<String, Optional<String>> getPatternAssertions(@Unsigned int index, b
480481 /**
481482 * Iterate over all the matches in the order that they were found.
482483 *
484+ * @implNote The lifetime of the matches is bound to that of the query.
485+ *
483486 * @param node The node that the query will run on.
484487 */
485488 public Stream <QueryMatch > findMatches (Node node ) {
486- return findMatches (node , null );
489+ return findMatches (node , arena , null );
490+ }
491+
492+ /**
493+ * Iterate over all the matches in the order that they were found, using the given allocator.
494+ *
495+ * @since 0.25.0
496+ */
497+ public Stream <QueryMatch > findMatches (Node node , SegmentAllocator allocator ) {
498+ return findMatches (node , allocator , null );
487499 }
488500
489501 /**
@@ -500,14 +512,26 @@ public Stream<QueryMatch> findMatches(Node node) {
500512 * });
501513 * }
502514 *
515+ * @implNote The lifetime of the matches is bound to that of the query.
516+ *
503517 * @param node The node that the query will run on.
504518 * @param predicate A function that handles custom predicates.
505519 */
506520 public Stream <QueryMatch > findMatches (Node node , @ Nullable BiPredicate <QueryPredicate , QueryMatch > predicate ) {
521+ return findMatches (node , arena , predicate );
522+ }
523+
524+ /**
525+ * Iterate over all the matches in the order that they were found.
526+ *
527+ * @see #findMatches(Node, BiPredicate)
528+ */
529+ public Stream <QueryMatch > findMatches (
530+ Node node , SegmentAllocator allocator , @ Nullable BiPredicate <QueryPredicate , QueryMatch > predicate ) {
507531 try (var alloc = Arena .ofConfined ()) {
508532 ts_query_cursor_exec (cursor , query , node .copy (alloc ));
509533 }
510- return StreamSupport .stream (new MatchesIterator (node .getTree (), predicate ), false );
534+ return StreamSupport .stream (new MatchesIterator (node .getTree (), allocator , predicate ), false );
511535 }
512536
513537 @ Override
@@ -537,11 +561,14 @@ private void checkIndex(@Unsigned int index) throws IndexOutOfBoundsException {
537561 private final class MatchesIterator extends Spliterators .AbstractSpliterator <QueryMatch > {
538562 private final @ Nullable BiPredicate <QueryPredicate , QueryMatch > predicate ;
539563 private final Tree tree ;
564+ private final SegmentAllocator allocator ;
540565
541- public MatchesIterator (Tree tree , @ Nullable BiPredicate <QueryPredicate , QueryMatch > predicate ) {
566+ public MatchesIterator (
567+ Tree tree , SegmentAllocator allocator , @ Nullable BiPredicate <QueryPredicate , QueryMatch > predicate ) {
542568 super (Long .MAX_VALUE , Spliterator .IMMUTABLE | Spliterator .NONNULL );
543569 this .predicate = predicate ;
544570 this .tree = tree ;
571+ this .allocator = allocator ;
545572 }
546573
547574 @ Override
@@ -555,7 +582,7 @@ public boolean tryAdvance(Consumer<? super QueryMatch> action) {
555582 for (int i = 0 ; i < count ; ++i ) {
556583 var capture = TSQueryCapture .asSlice (matchCaptures , i );
557584 var name = captureNames .get (TSQueryCapture .index (capture ));
558- var node = TSNode .allocate (arena ).copyFrom (TSQueryCapture .node (capture ));
585+ var node = TSNode .allocate (allocator ).copyFrom (TSQueryCapture .node (capture ));
559586 captureList .add (new QueryCapture (name , new Node (node , tree )));
560587 }
561588 var patternIndex = TSQueryMatch .pattern_index (match );
0 commit comments