/** * SMI-4293: Python Incremental Parser Controller * * Couples the WASM tree-sitter parser, per-file tree cache, and edit-based * incremental parsing into a single entry point for the Python adapter. * * Responsibilities: * - Lazy-init the WASM parser (via web-tree-sitter) and Python language * grammar (from tree-sitter-wasms). * - Cache parse trees per file path with LRU eviction (max 100 trees) and * proper `.delete()` lifecycle. * - Apply tree.edit() and reuse the previous tree when content changes * incrementally; fall back to full parse on cache miss or corruption. * - Delegate extraction to pythonExtractor (query-based, replaces regex). * * @see docs/internal/implementation/github-wave-5c-tree-sitter-incremental.md * @module analysis/tree-sitter/pythonIncremental */ import type { ParseResult } from '../types.js'; import type { TreeSitterLanguage, TreeSitterParser } from './manager.js'; import { type QueryCtor } from './pythonExtractor.js'; /** * Full-jitter backoff: a random point in `[0, base * 2^(attempt-1))` ms for the * 1-based `attempt` that just failed. Jitter (not a fixed delay) is deliberate — * the failure mode is many workers colliding during WASM instantiation, so a * fixed delay would make them retry in lockstep and collide again (SMI-5567, * plan-review finding #11). Exported for unit testing of the jitter bounds. */ export declare function jitteredInitBackoffMs(attempt: number): number; /** Resolve the path to the Python WASM grammar distributed via tree-sitter-wasms. */ export declare function resolvePythonWasmPath(): string; /** Options for PythonIncrementalParser. */ export interface PythonIncrementalParserOptions { /** Maximum cached trees (default 100). */ maxTrees?: number; /** Override path to the Python WASM grammar (tests). */ wasmPath?: string; /** * Bounded attempts to boot the WASM runtime + grammar under transient * contention (default 3). SMI-5567. */ maxInitAttempts?: number; /** * Backoff (ms) to wait before the next init attempt, given the 1-based * attempt number that just failed. Defaults to {@link jitteredInitBackoffMs}. * Tests inject `() => 0` for deterministic, delay-free runs. SMI-5567. */ initBackoffMs?: (attempt: number) => number; } /** Resolver that returns the WASM dependencies. Exposed for tests. */ export interface WebTreeSitterDeps { Parser: new () => TreeSitterParser; Language: { load(path: string): Promise; }; Query: QueryCtor; init: () => Promise; } /** Default loader uses web-tree-sitter. Tests may inject a stub. */ export type WebTreeSitterLoader = () => Promise; /** * Incremental Python parser: lazily boots web-tree-sitter, parses with * `tree.edit()` reuse when possible, falls back gracefully otherwise. */ export declare class PythonIncrementalParser { private readonly maxTrees; private readonly wasmPath; private readonly loader; private readonly maxInitAttempts; private readonly initBackoffMs; private readonly cache; private parser; private language; private queries; private initPromise; private initFailed; private useCounter; constructor(options?: PythonIncrementalParserOptions, loader?: WebTreeSitterLoader); /** True when the WASM runtime and Python grammar loaded successfully. */ get isReady(): boolean; /** True when a prior init attempt failed; callers should use regex fallback. */ get hasFailedInit(): boolean; /** * Ensure the WASM parser + Python grammar are loaded. Callers should * `await` this once before relying on `parseSync` for a synchronous path. */ ensureReady(): Promise; /** * Parse asynchronously: ensures init, then delegates to the sync path. * Returns null if init has permanently failed (caller falls back to regex). */ parse(content: string, filePath: string): Promise; /** * Synchronous parse: usable only after `ensureReady()` has resolved. Uses * the previous tree via `tree.edit()` when content changed incrementally. * * Returns null when the parser isn't ready or any parse/extract step fails; * callers should fall back to regex extraction in that case. */ parseSync(content: string, filePath: string): ParseResult | null; /** Invalidate a single file's cache entry and free its tree. */ invalidate(filePath: string): void; /** Clear and dispose all cached trees. */ dispose(): void; /** Current cache size (exposed for tests and instrumentation). */ get cacheSize(): number; private ensureInit; private doInit; private store; private touch; private evictLRU; private safeDelete; /** Free a parser allocated on a failed init attempt (SMI-5567). */ private safeDeleteParser; } //# sourceMappingURL=pythonIncremental.d.ts.map