/** * Call Graph Analyzer * * Performs static analysis of function calls across source files using tree-sitter. * Supports TypeScript/JavaScript, Python, Go, Rust, Ruby, Java, Swift — no LLM, pure AST. * * Produces: * - FunctionNode[] — all identified functions/methods * - CallEdge[] — resolved function→function call relationships * - Hub functions — high-fanIn nodes (called by many others) * - Entry points — functions with no internal callers * - Layer violations — cross-layer calls in the wrong direction */ import type { ImportMap } from './import-resolver-bridge.js'; import type { CfgSpill } from './cfg-spill.js'; import { type FileStyleRaw } from './style-fingerprint.js'; import { type FileParseHealth } from './parse-health.js'; import { type ExtractionLaneOptions } from './extraction-pool.js'; import type { Pass1FactCache } from './pass1-fact-cache.js'; import type { FunctionNode, CallEdge, CallGraphResult, SerializedCallGraph, FileExtractResult } from './call-graph-types.js'; export type { EdgeConfidence, EdgeKind, CallType, FunctionNode, ExternalKind, CallEdge, LayerViolation, ClassNode, InheritanceEdge, CallGraphResult, SerializedCallGraph, AmbiguousCallSite, AmbiguousStrategy, FileExtractResult, } from './call-graph-types.js'; export { CALL_DISTANCE_COSTS, callDistance, layerOf, classifyLayerEdge, AMBIGUOUS_CANDIDATE_CAP } from './call-graph-types.js'; export { computeCyclomaticComplexity } from './call-graph-complexity.js'; /** The definition {@link computeEnclosing} implements. Exported for its differential test only. */ export declare function _enclosingByBruteForceForTesting(nodes: FunctionNode[], n: FunctionNode): FunctionNode | undefined; /** Test-only access to the swept version, so the two can be diffed. */ export declare function _computeEnclosingForTesting(nodes: FunctionNode[]): Map; /** * Did a grammar load attempt for this language already FAIL in this process? * * Every soft loader records `null` in the handle cache when a grammar cannot be loaded — an * optional dependency that was not installed, a native binding that will not build, a WASM file * that is absent. This reports that, so a caller can tell "the grammar is not here" apart from * "the grammar is here and produced nothing", which are the same empty result but very different * facts. `false` also means "not attempted yet"; drive an extraction first. * * Exists because the two are indistinguishable at the assertion site: when `tree-sitter-kotlin` * failed to install in CI, nine tests failed with messages like `expected [] to include 'main'`, * which reads exactly like a broken extractor and cost real time to diagnose as an install * problem. The grammars are `optionalDependencies` BY DESIGN (`loadGrammarSoft`, restricted * environments) — so a suite that cannot distinguish absence from breakage will keep going red * for reasons that are not defects. */ export declare function grammarLoadFailed(language: string): boolean; /** Reset loader caches — test-only hook for the graceful-degradation test. */ export declare function __resetGrammarCacheForTests(): void; /** * Languages for which `CallGraphBuilder.build()` extracts function/method nodes and * call edges. The authoritative source for the `callGraph` capability flag in the * declarative language-support registry (change: add-declarative-language-support-registry). * * MUST stay in sync with the per-language dispatch in `build()`: the native extractors * (Python/TS/JS/Go/Rust/Ruby/Java/C++/Swift/Elixir/Dart) plus the data-driven * `QUERY_LANG_SPECS` languages. A behavioral test asserts a fixture in each member * yields ≥1 node, so this set cannot silently over-claim. */ export declare const CALLGRAPH_LANGUAGES: ReadonlySet; /** Per-channel handler fan-out cap. Over-cap channels are DROPPED, never guessed. */ export declare const EVENT_CHANNEL_FANOUT_CAP = 8; /** Resolve a referenced simple name to a single internal function node, or undefined * when unknown or ambiguous (never guesses). Prefers a match in `preferFile`. */ type HandlerResolver = (name: string, preferFile: string) => FunctionNode | undefined; export declare function synthesizeDynamicDispatchEdges(files: Array<{ path: string; content: string; language: string; }>, allNodes: Map, resolveHandler: HandlerResolver): Promise; /** Construction-time options for {@link CallGraphBuilder}. */ export interface CallGraphBuilderOptions { /** * Controls for the Pass-1 extraction lane (change: optimize-parallel-extraction-pool). * Production passes nothing: the lane decides for itself from core count, file count, the * process-wide worker budget, and `OPENLORE_NO_WORKERS`. Tests use these to drive a stub * pool whose completion order and failure modes are deterministic. */ extraction?: ExtractionLaneOptions; /** * Memo of per-file Pass-1 facts (change: optimize-hash-keyed-analyze). When supplied, a file * whose content and extractor stamp match a stored row skips extraction entirely and its * cached facts are merged in its input position — the merge, and therefore every downstream * pass, cannot tell the two apart. Absent (the watcher's per-file rebuilds, tests, any * embedded caller) means today's behavior: extract everything. */ pass1Cache?: Pass1FactCache; /** * Off-heap destination for the CFG/def-use overlay (issue #304). When supplied, each file's * overlay is serialized into the spill as the file is merged and then DROPPED, so the overlay * never accumulates across the repository; `cfgs` comes back `undefined` and the caller drains * the spill into `cfg_overlay` instead. Absent (the watcher's per-file rebuilds, tests, any * embedded caller) means today's behavior: the overlay is returned in memory. */ cfgSpill?: CfgSpill; } export declare class CallGraphBuilder { private readonly extractionOptions; private readonly pass1Cache; private readonly cfgSpill; constructor(options?: CallGraphBuilderOptions); /** * Build a call graph from a list of source files. * * @param files Source files with path, content, and language * @param layers Optional layer map { layerName: [path prefix, ...] } * @param importMap Optional per-file import map (from ImportResolverBridge) * @param resolutionNodes Optional pre-existing nodes used only to seed the * call-resolution trie (not added to the returned nodes/edges). An * incremental subset rebuild passes the full set of known nodes so calls * into files outside the re-parsed subset resolve to their real node * instead of degrading to a synthetic `external::` leaf. */ build(files: Array<{ path: string; content: string; language: string; }>, layers?: Record, importMap?: ImportMap, resolutionNodes?: FunctionNode[]): Promise; private detectLayerViolations; } /** * Dispatch ONE file to its per-language extractor (Pass-1 only — nodes/edges/cfg/style/parseHealth, * no cross-file resolution). The single source of truth for the language→extractor mapping, shared * by the full build, the watcher's per-file refreshers, AND the extraction-pool worker * (change: optimize-parallel-extraction-pool) so the dispatch is never duplicated and the pooled * lane cannot drift from the serial one. Returns `undefined` for a language with no extractor. */ export declare function dispatchFileExtract(file: { path: string; content: string; language: string; }): Promise; /** * Tally ONE file's style fingerprint in isolation (change: add-codebase-style-fingerprint). * Reuses the same per-language extractor (and its single parse) the full build uses, returning * only the style counters. Used by the watcher to refresh a changed file's fingerprint without a * whole-graph rebuild. Fail-soft: an unsupported language or parse failure returns `undefined`. */ export declare function extractFileStyle(file: { path: string; content: string; language: string; }): Promise; /** * Record ONE file's parse health in isolation (change: add-parse-health-boundary-disclosure). Runs * the same per-language dispatch the full build uses (so it covers every callGraph language, not * just the style ones) over a single file — Pass 2 resolution over one file is trivial — and returns * only its parse-health record, or `undefined` for a clean file. Used by the watcher to keep * `parse-health.json` live for a changed file without a whole-graph rebuild. Fail-soft: a parse * failure is itself a parse-health signal, surfaced as `parseFailed`. */ export declare function extractFileParseHealth(file: { path: string; content: string; language: string; }): Promise; export declare function serializeCallGraph(result: CallGraphResult): SerializedCallGraph; //# sourceMappingURL=call-graph.d.ts.map