// src/detect/adapters/query-helpers.ts
import { Query } from "web-tree-sitter";
var InvalidQueryError = class extends Error {
  queryName;
  querySource;
  cause;
  constructor(queryName, querySource, cause) {
    const causeMsg = cause instanceof Error ? cause.message : String(cause);
    super(
      `[query-helpers] Invalid Tree-sitter query "${queryName}": ${causeMsg}
Query source:
${querySource}`
    );
    this.name = "InvalidQueryError";
    this.queryName = queryName;
    this.querySource = querySource;
    this.cause = cause;
  }
};
var queryCache = /* @__PURE__ */ new WeakMap();
function compileQuery(language, source, queryName) {
  let perLang = queryCache.get(language);
  if (!perLang) {
    perLang = /* @__PURE__ */ new Map();
    queryCache.set(language, perLang);
  }
  const cached = perLang.get(source);
  if (cached) return cached;
  let q;
  try {
    q = new Query(language, source);
  } catch (e) {
    throw new InvalidQueryError(queryName, source, e);
  }
  perLang.set(source, q);
  return q;
}
function runQuery(parser, source, queryText, queryName, filePath) {
  const language = parser.language;
  if (!language) {
    throw new InvalidQueryError(
      queryName,
      queryText,
      new Error("Parser has no language assigned")
    );
  }
  const query = compileQuery(language, queryText, queryName);
  const tree = parser.parse(source);
  if (!tree) return [];
  let matches;
  try {
    matches = query.matches(tree.rootNode);
  } catch (e) {
    throw new InvalidQueryError(queryName, queryText, e);
  }
  const out = [];
  for (const match of matches) {
    if (!match.captures || match.captures.length === 0) continue;
    const captures = {};
    let earliestLine = Number.POSITIVE_INFINITY;
    for (const cap of match.captures) {
      const node = cap.node;
      captures[cap.name] = node.text;
      if (node.startPosition.row + 1 < earliestLine) {
        earliestLine = node.startPosition.row + 1;
      }
    }
    out.push({
      captures,
      file: filePath,
      line: Number.isFinite(earliestLine) ? earliestLine : 1,
      queryName
    });
  }
  try {
    tree.delete();
  } catch {
  }
  return out;
}
export {
  InvalidQueryError,
  compileQuery,
  runQuery
};
