Skip to content

Commit

Permalink
feat!: separate QueryCursor class
Browse files Browse the repository at this point in the history
  • Loading branch information
ObserverOfTime committed Feb 28, 2025
1 parent c48b4e1 commit b01c35e
Show file tree
Hide file tree
Showing 10 changed files with 738 additions and 365 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package io.github.treesitter.jtreesitter;

import static io.github.treesitter.jtreesitter.internal.TreeSitter.C_INT;
import static io.github.treesitter.jtreesitter.internal.TreeSitter.ts_query_cursor_next_capture;

import io.github.treesitter.jtreesitter.internal.TSQueryMatch;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.SegmentAllocator;
import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;

@NullMarked
class CapturesIterator extends Spliterators.AbstractSpliterator<SimpleImmutableEntry<Integer, QueryMatch>> {
private final @Nullable BiPredicate<QueryPredicate, QueryMatch> predicate;
private final Tree tree;
private final SegmentAllocator allocator;
private final Query query;
private final MemorySegment cursor;

public CapturesIterator(
Query query,
MemorySegment cursor,
Tree tree,
SegmentAllocator allocator,
@Nullable BiPredicate<QueryPredicate, QueryMatch> predicate) {
super(Long.MAX_VALUE, Spliterator.IMMUTABLE | Spliterator.NONNULL);
this.predicate = predicate;
this.tree = tree;
this.allocator = allocator;
this.query = query;
this.cursor = cursor;
}

@Override
public boolean tryAdvance(Consumer<? super SimpleImmutableEntry<Integer, QueryMatch>> action) {
var hasNoText = tree.getText() == null;
MemorySegment match = allocator.allocate(TSQueryMatch.layout());
MemorySegment index = allocator.allocate(C_INT);
var captureNames = query.getCaptureNames();
while (ts_query_cursor_next_capture(cursor, match, index)) {
var result = QueryMatch.from(match, captureNames, tree, allocator);
if (hasNoText || query.matches(predicate, result)) {
var entry = new SimpleImmutableEntry<>(index.get(C_INT, 0), result);
action.accept(entry);
return true;
}
}
return false;
}
}
2 changes: 2 additions & 0 deletions src/main/java/io/github/treesitter/jtreesitter/Language.java
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,9 @@ public LookaheadIterator lookaheadIterator(@Unsigned short state) throws Illegal
* Create a new query from a string containing one or more S-expression patterns.
*
* @throws QueryError If an error occurred while creating the query.
* @deprecated Use the {@link Query#Query(Language, String) Query} constructor instead.
*/
@Deprecated(since = "0.25.0")
public Query query(String source) throws QueryError {
return new Query(this, source);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package io.github.treesitter.jtreesitter;

import static io.github.treesitter.jtreesitter.internal.TreeSitter.ts_query_cursor_next_match;

import io.github.treesitter.jtreesitter.internal.TSQueryMatch;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.SegmentAllocator;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;

@NullMarked
class MatchesIterator extends Spliterators.AbstractSpliterator<QueryMatch> {
private final @Nullable BiPredicate<QueryPredicate, QueryMatch> predicate;
private final Tree tree;
private final SegmentAllocator allocator;
private final Query query;
private final MemorySegment cursor;

public MatchesIterator(
Query query,
MemorySegment cursor,
Tree tree,
SegmentAllocator allocator,
@Nullable BiPredicate<QueryPredicate, QueryMatch> predicate) {
super(Long.MAX_VALUE, Spliterator.IMMUTABLE | Spliterator.NONNULL);
this.predicate = predicate;
this.tree = tree;
this.allocator = allocator;
this.query = query;
this.cursor = cursor;
}

@Override
public boolean tryAdvance(Consumer<? super QueryMatch> action) {
var hasNoText = tree.getText() == null;
MemorySegment match = allocator.allocate(TSQueryMatch.layout());
var captureNames = query.getCaptureNames();
while (ts_query_cursor_next_match(cursor, match)) {
var result = QueryMatch.from(match, captureNames, tree, allocator);
if (hasNoText || query.matches(predicate, result)) {
action.accept(result);
return true;
}
}
return false;
}
}
Loading

0 comments on commit b01c35e

Please sign in to comment.