/** * Tree-sitter Parser Wrapper * * Handles parsing source code and extracting structural information. */ import { Language, ExtractionResult } from '../types'; export { generateNodeId } from './tree-sitter-helpers'; /** * TreeSitterExtractor - Main extraction class */ export declare class TreeSitterExtractor { private filePath; private language; private source; private tree; private nodes; private edges; private unresolvedReferences; private static readonly VALUE_REF_LANGS; private static readonly MAX_VALUE_REF_NODES; private readonly valueRefsEnabled; private fileScopeValues; private fileScopeValueCounts; private valueRefScopes; private errors; private extractor; private nodeStack; private methodIndex; private fnRefSpec; private fnRefCandidates; private vueStoreFile; constructor(filePath: string, source: string, language?: Language); /** * Parse and extract from the source code */ extract(): ExtractionResult; /** * Function-as-value capture (#756): if this node is one of the language's * value-position containers (call arguments, assignment RHS, struct/object * initializer, array/table literal), collect candidate function names from * it. Candidates are gated & flushed at end-of-file (flushFnRefCandidates). */ private maybeCaptureFnRefs; /** * Candidates-only scan of a subtree the main walkers won't traverse * (top-level variable initializers). No extraction side effects. Halts at * nested function definitions: their bodies are walked — and their * candidates attributed — by extractFunction's own body walk. */ private scanFnRefSubtree; /** * Gate captured function-as-value candidates and push survivors as * `function_ref` unresolved references. * * The gate bounds volume and protects precision: a candidate survives only * if its name matches a function/method DEFINED IN THIS FILE or a name this * file imports/references. Everything else (locals, params, fields passed * as arguments) is dropped before it ever reaches the database. Resolution * then matches survivors against function/method nodes only * (matchFunctionRef) and emits `references` edges — which callers/impact * already traverse. * * Known v1 limit, deliberate: a C/C++ callback registered in a DIFFERENT * translation unit than its definition (extern, no symbol imports to match) * is not captured. Same-file registration — the dominant C pattern (static * callback + same-file ops struct) — is. */ private flushFnRefCandidates; /** * Record value-reference bookkeeping as nodes are created: file-scope const/var symbols with * distinctive names become reference targets; function/method/const/var symbols become reader * scopes whose bodies flushValueRefs scans. */ private captureValueRefScope; /** * Emit same-file `references` edges from a symbol to the file-scope const/var it reads (TS/JS). * The engine doesn't edge const→consumer, so impact analysis misses "change this table, affect * its readers" (the ReScript-PR false positive). Same-file only (resolution is unambiguous), * distinctive target names only (dodges the local-shadowing precision trap documented on * function_ref), deduped per (reader, target). Default on (CODEGRAPH_VALUE_REFS=0 disables) + * additive. Shadowed targets are pruned — see below. */ private flushValueRefs; /** * Visit a node and extract information */ private visitNode; /** * Create a Node object */ private createNode; /** * Find first named child whose type is in the given list. * Used to locate inner type nodes (e.g. enum_specifier inside a typedef). */ private findChildByTypes; /** * Find a `packageTypes` child under the root, create a `namespace` node * for it, and return its id so the caller can scope top-level * declarations underneath. Returns null when no package header is * present (script files, .kts without a package). */ private extractFilePackage; /** * Build qualified name from node stack */ private buildQualifiedName; /** * Build an ExtractorContext for passing to language-specific visitNode hooks. */ private makeExtractorContext; /** * Check if the current node stack indicates we are inside a class-like node * (class, struct, interface, trait). File nodes do not count as class-like. */ private isInsideClassLikeNode; /** * Ruby `CONST = …` assignment whose LHS is a `constant` node — a class/module * (or top-level) constant worth extracting as a symbol even inside a class. * Other languages don't give an assignment a `constant`-typed LHS, so this * gate is effectively Ruby-only. */ private isClassScopeConstantAssignment; /** * Extract a function */ private extractFunction; /** * Detect a React component declared via an HOC wrapper whose result is itself a * component: `forwardRef(...)`, `memo(...)`, `React.forwardRef/memo(...)`, and * styled-components / emotion `styled.tag\`…\`` / `styled(Base)\`…\``. These * initializers are a call / tagged-template (not a bare arrow), so the const is * otherwise classified `constant` — and a constant is skipped by both the * JSX-render edge synthesizer and component resolution, so `