All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.treesitter.TSQueryCursor Maven / Gradle / Ivy

The newest version!
package org.treesitter;

import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.function.BiFunction;

import static org.treesitter.TSParser.*;
import static org.treesitter.TSParser.ts_query_cursor_next_match;

public class TSQueryCursor {

    private final long ptr;
    private boolean executed = false;

    private static class TSQueryCursorCleanAction implements Runnable {
        private final long ptr;

        public TSQueryCursorCleanAction(long ptr) {
            this.ptr = ptr;
        }

        @Override
        public void run() {
            ts_query_cursor_delete(ptr);
        }
    }

    private TSQueryCursor(long ptr) {
        this.ptr = ptr;
        CleanerRunner.register(this, new TSQueryCursorCleanAction(ptr));
    }

    /**
     * Create a new cursor for executing a given query.
* * The cursor stores the state that is needed to iteratively search * for matches. To use the query cursor, first call {@link #exec(TSQuery, TSNode) exec()} * to start running a given query on a given syntax node. Then, there are * two options for consuming the results of the query: *
    *
  1. Repeatedly call {@link #nextMatch(TSQueryMatch) nextMatch()} to iterate over all of the * *matches* in the order that they were found. Each match contains the * index of the pattern that matched, and an array of captures. Because * multiple patterns can match the same set of nodes, one match may contain * captures that appear *before* some of the captures from a previous match.
  2. *
  3. Repeatedly call {@link #nextCapture(TSQueryMatch) nextCapture()} to iterate over all of the * individual *captures* in the order that they appear. This is useful if * don't care about which pattern matched, and just want a single ordered * sequence of captures.
  4. *
* If you don't care about consuming all the results, you can stop calling * {@link #nextMatch(TSQueryMatch) nextMatch()} or {@link #nextCapture(TSQueryMatch) nextCapture()} at any point. * You can then start executing another query on another node by calling * {@link #exec(TSQuery, TSNode) exec()} again. */ public TSQueryCursor() { this(TSParser.ts_query_cursor_new()); } /** * Start running a given query on a given node. * * @param query The query to run. * @param node The node to run the query on. */ public void exec(TSQuery query, TSNode node){ executed = true; ts_query_cursor_exec(ptr, query.getPtr(), node); } public boolean didExceedMatchLimit(){ return ts_query_cursor_did_exceed_match_limit(ptr); } public int getMatchLimit(){ return ts_query_cursor_match_limit(ptr); } /** * Set the maximum number of in-progress matches allowed by this query * cursor.
* * Query cursors have an optional maximum capacity for storing lists of * in-progress captures. If this capacity is exceeded, then the * earliest-starting match will silently be dropped to make room for further * matches. This maximum capacity is optional by default, query cursors allow * any number of pending matches, dynamically allocating new space for them as * needed as the query is executed. * * @param limit The maximum number of in-progress matches allowed by this query cursor. */ public void setMatchLimit(int limit){ ts_query_cursor_set_match_limit(ptr, limit); } /** * Set the range of bytes in which the query * will be executed. * * @param startByte The index of the start byte in the range. * @param endByte The index of the end byte in the range. */ public void setByteRange(int startByte, int endByte){ ts_query_cursor_set_byte_range(ptr, startByte, endByte); } /** * Set the (row, column) positions in which the query * will be executed. * * @param startPoint The start point of the range. * @param endPoint The end point of the range. */ public void setPointRange(TSPoint startPoint, TSPoint endPoint){ ts_query_cursor_set_point_range(ptr, startPoint, endPoint); } /** * Advance to the next match of the currently running query.
* * If there is a match, write it to match and return true. * Otherwise, return false.
* * NOTE: More Java-ish method is {@link TSQueryCursor#getMatches()}. * * @param match The match to write to. * * @return Whether there was a match. * * @throws TSException if the query has not been executed yet. */ public boolean nextMatch(TSQueryMatch match){ assertExecuted(); return ts_query_cursor_next_match(ptr, match); } public void removeMatch(int matchId){ ts_query_cursor_remove_match(ptr, matchId); } /** * Advance to the next capture of the currently running query.
* * If there is a capture, write its match to match and its index within * the match's capture list to captureIndex. Otherwise, return false.
* * NOTE: More Java-ish method is {@link TSQueryCursor#getCaptures()}. * * @param match The match to write to. * * @return Whether there was a capture. * * @throws TSException if the query has not been executed yet. * */ @SuppressWarnings("deprecation") public boolean nextCapture(TSQueryMatch match){ assertExecuted(); return ts_query_cursor_next_capture(ptr, match); } private void assertExecuted(){ if(!executed){ throw new TSException("Query not executed, call exec() first."); } } /** * Get the match iterator.
* * @return An iterator over the matches. * */ public TSMatchIterator getMatches(){ return new TSMatchIterator(TSParser::ts_query_cursor_next_match); } /** * Get the capture iterator.
* * @return An iterator over the captures. * */ public TSMatchIterator getCaptures(){ return new TSMatchIterator(TSParser::ts_query_cursor_next_capture); } public class TSMatchIterator implements Iterator{ private TSQueryMatch tempMatch = null; private TSQueryMatch lastMatch = null; private BiFunction nextFunction; public TSMatchIterator(BiFunction nextFunction) { this.nextFunction = nextFunction; } private TSQueryMatch nextMatch(){ assertExecuted(); TSQueryMatch match = new TSQueryMatch(); boolean ret = nextFunction.apply(ptr, match); if(ret){ return match; }else{ return null; } } @Override public boolean hasNext() { TSQueryMatch match = nextMatch(); if(match != null){ tempMatch = match; return true; }else{ return false; } } @Override public TSQueryMatch next() { if(tempMatch != null){ TSQueryMatch newMatch = tempMatch; tempMatch = null; return newMatch; }else{ TSQueryMatch match = nextMatch(); if(match != null){ lastMatch = match; return match; }else{ throw new NoSuchElementException(); } } } @Override public void remove() { if(lastMatch == null){ throw new IllegalStateException(); } ts_query_cursor_remove_match(ptr, tempMatch.getId()); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy