import type { Node as SyntaxNode } from "web-tree-sitter"; import { reportParserError } from "../parser-errors.js"; /** * Shared low-level helpers for tree-sitter-based structural mappers * (rust.ts, cpp.ts, java.ts, and future C/Swift mappers in #194). */ export function normalizeWhitespace(value: string): string { return value.replaceAll(/\s+/g, " ").trim(); } export function getNodeText(node: SyntaxNode, source: string): string { return source.slice(node.startIndex, node.endIndex); } export function getLineRange(node: SyntaxNode): { startLine: number; endLine: number; } { return { startLine: node.startPosition.row + 1, endLine: node.endPosition.row + 1, }; } export function findFirstDescendant( node: SyntaxNode, types: string[] ): SyntaxNode | null { const stack = [...node.namedChildren]; while (stack.length > 0) { const current = stack.pop(); if (!current) { continue; } if (types.includes(current.type)) { return current; } for (const child of current.namedChildren) { stack.push(child); } } return null; } /** * Shared signature kernel: strip a single trailing semicolon (with trailing * whitespace) then collapse/trim whitespace. Matches the tail of the current * Rust and C++ formatSignature implementations exactly. */ export function finalizeSignature(text: string): string { return normalizeWhitespace(text.replace(/;\s*$/, "")); } interface Deletable { delete(): void; } /** Release both WASM objects without allowing one teardown failure to skip the other. */ export function disposeTreeAndParser( tree: Deletable | null, parser: Deletable, language: string, ): void { try { tree?.delete(); } catch (err) { reportParserError( `wasm:delete:${language}:tree:${err instanceof Error ? err.message : String(err)}`, err, { context: `${language} tree-sitter tree cleanup failed` }, ); } try { parser.delete(); } catch (err) { reportParserError( `wasm:delete:${language}:parser:${err instanceof Error ? err.message : String(err)}`, err, { context: `${language} tree-sitter parser cleanup failed` }, ); } }