@colbymchenry/codegraph 0.9.9 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/README.md +120 -24
  2. package/dist/bin/codegraph.d.ts +1 -0
  3. package/dist/bin/fatal-handler.d.ts +20 -0
  4. package/dist/db/migrations.d.ts +1 -1
  5. package/dist/db/queries.d.ts +43 -0
  6. package/dist/db/sqlite-adapter.d.ts +7 -0
  7. package/dist/directory.d.ts +49 -2
  8. package/dist/extraction/astro-extractor.d.ts +79 -0
  9. package/dist/extraction/extraction-version.d.ts +25 -0
  10. package/dist/extraction/function-ref.d.ts +118 -0
  11. package/dist/extraction/grammars.d.ts +7 -1
  12. package/dist/extraction/index.d.ts +34 -0
  13. package/dist/extraction/languages/c-cpp.d.ts +8 -0
  14. package/dist/extraction/languages/csharp.d.ts +22 -0
  15. package/dist/extraction/languages/r.d.ts +3 -0
  16. package/dist/extraction/languages/typescript.d.ts +13 -0
  17. package/dist/extraction/liquid-extractor.d.ts +7 -0
  18. package/dist/extraction/razor-extractor.d.ts +42 -0
  19. package/dist/extraction/tree-sitter-types.d.ts +33 -0
  20. package/dist/extraction/tree-sitter.d.ts +211 -0
  21. package/dist/extraction/vue-extractor.d.ts +15 -0
  22. package/dist/index.d.ts +34 -2
  23. package/dist/installer/instructions-template.d.ts +34 -11
  24. package/dist/installer/targets/opencode.d.ts +9 -1
  25. package/dist/installer/targets/shared.d.ts +14 -0
  26. package/dist/mcp/daemon-manager.d.ts +42 -0
  27. package/dist/mcp/daemon-registry.d.ts +47 -0
  28. package/dist/mcp/daemon.d.ts +60 -1
  29. package/dist/mcp/dynamic-boundaries.d.ts +41 -0
  30. package/dist/mcp/index.d.ts +1 -0
  31. package/dist/mcp/liveness-watchdog.d.ts +18 -0
  32. package/dist/mcp/ppid-watchdog.d.ts +44 -0
  33. package/dist/mcp/proxy.d.ts +6 -0
  34. package/dist/mcp/server-instructions.d.ts +12 -1
  35. package/dist/mcp/session.d.ts +2 -0
  36. package/dist/mcp/stdin-teardown.d.ts +27 -0
  37. package/dist/mcp/tools.d.ts +71 -0
  38. package/dist/resolution/callback-synthesizer.d.ts +3 -3
  39. package/dist/resolution/frameworks/astro.d.ts +9 -0
  40. package/dist/resolution/frameworks/index.d.ts +1 -0
  41. package/dist/resolution/import-resolver.d.ts +10 -0
  42. package/dist/resolution/index.d.ts +80 -0
  43. package/dist/resolution/name-matcher.d.ts +61 -0
  44. package/dist/resolution/types.d.ts +27 -3
  45. package/dist/resolution/workspace-packages.d.ts +48 -0
  46. package/dist/search/query-utils.d.ts +17 -1
  47. package/dist/sync/watcher.d.ts +124 -32
  48. package/dist/telemetry/index.d.ts +146 -0
  49. package/dist/types.d.ts +17 -2
  50. package/dist/upgrade/index.d.ts +132 -0
  51. package/dist/utils.d.ts +30 -24
  52. package/package.json +7 -7
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Function-as-value capture (#756) — registration-linking for callbacks.
3
+ *
4
+ * A function name used as a VALUE — passed as a call argument
5
+ * (`register_handler(target_cb)`, `signal(SIGINT, handler)`), assigned to a
6
+ * field or function pointer (`o->cb = target_cb`, `OnFire := TargetCb`),
7
+ * placed in a struct/object initializer (`{ .recv_cb = my_cb }`,
8
+ * `{ recv: targetCb }`, `Ops{Cb: targetCb}`), or listed in a function table
9
+ * (`static cb_t table[] = { cb_a, cb_b }`) — is a real dependency that static
10
+ * call extraction misses entirely: `callers(target_cb)` showed nothing but
11
+ * direct calls, so every callback looked dead and its registration sites were
12
+ * invisible to impact analysis.
13
+ *
14
+ * This module captures those value positions during the AST walk as
15
+ * `function_ref` candidates. Capture is table-driven per language (the value
16
+ * positions and wrapper forms differ per grammar — `&fn` in C, `Main::fn` in
17
+ * Java, `::fn` in Kotlin, `#selector(fn)` in Swift, `@TargetCb` in Pascal,
18
+ * `method(:fn)` in Ruby). Candidates are GATED at end-of-file extraction
19
+ * (see `TreeSitterExtractor.flushFnRefCandidates`): only names matching a
20
+ * same-file function/method or an imported binding survive, which bounds
21
+ * volume and keeps precision high. Resolution then matches survivors against
22
+ * function/method nodes ONLY (`matchFunctionRef` in
23
+ * `src/resolution/name-matcher.ts`) and persists them as `references` edges,
24
+ * which `callers`/`impact` already traverse.
25
+ *
26
+ * Deliberately NOT covered (resolving the *dispatch* — `o->cb(x)` → the
27
+ * registered function — needs data-flow through struct fields; a wrong edge
28
+ * is worse than none): indirect-call resolution and `obj.method` member
29
+ * values where `obj` isn't `this`/`self` (the receiver's type is statically
30
+ * unknowable without local data-flow).
31
+ */
32
+ import type { Node as SyntaxNode } from 'web-tree-sitter';
33
+ export interface FnRefCandidate {
34
+ name: string;
35
+ line: number;
36
+ column: number;
37
+ /** Which capture position produced this candidate (gate policy keys on it). */
38
+ mode: CaptureMode;
39
+ /**
40
+ * True when the value was an explicit reference form (`&fn`, `&Cls::m`,
41
+ * `::fn`, `#selector`, `method(:sym)`) rather than a bare identifier —
42
+ * C++'s flush policy keys on it.
43
+ */
44
+ explicitRef: boolean;
45
+ /**
46
+ * Skip the same-file/import name gate for this candidate. Set for PHP
47
+ * string callables in known HOF positions: PHP global functions are
48
+ * referenced cross-file WITHOUT imports (global namespace), so the gate
49
+ * can't see them — the strong positional prior (a string argument to
50
+ * `usort`/`array_map`/…) plus resolution's unique-or-drop rule carry the
51
+ * precision instead.
52
+ */
53
+ skipGate?: boolean;
54
+ }
55
+ /** How to pull candidate value nodes out of a dispatched container node. */
56
+ type CaptureMode = 'args' | 'rhs' | 'value' | 'list' | 'varinit';
57
+ interface CaptureRule {
58
+ mode: CaptureMode;
59
+ /** Field holding the value for rhs/value/varinit (defaults per mode). */
60
+ field?: string;
61
+ }
62
+ export interface FnRefSpec {
63
+ /** Bare identifier node types that can act as a function value. */
64
+ idTypes: Set<string>;
65
+ /** Container node type → how to extract candidate values from it. */
66
+ dispatch: Map<string, CaptureRule>;
67
+ /**
68
+ * Transparent wrapper layers between a container and its values
69
+ * (`argument`, `value_argument`, `literal_element`, `expression_list`…).
70
+ * Value: the field to descend into, or null for "named children".
71
+ * `expression_list` fans out to ALL named children (Go multi-assign).
72
+ */
73
+ layers?: Map<string, string | null>;
74
+ /**
75
+ * Unary wrappers whose operand is the function value — C/C++ `&fn`
76
+ * (pointer_expression), Pascal `@Fn` (exprUnary), Scala eta `fn _`
77
+ * (postfix_expression). Value: operand field, or null for first named child.
78
+ */
79
+ unwrap?: Map<string, string | null>;
80
+ /**
81
+ * Whole-node reference forms needing bespoke name extraction —
82
+ * `method_reference` (Java), `callable_reference` / `navigation_expression`
83
+ * (Kotlin), `selector_expression` (Swift `#selector` / ObjC `@selector`),
84
+ * Ruby `method(:sym)` calls, and `this.method` member forms.
85
+ */
86
+ special?: Set<string>;
87
+ /**
88
+ * Capture modes whose candidates skip the same-file/import gate and rely on
89
+ * resolution's unique-or-drop rule instead. C-family only: an initializer
90
+ * value, function-pointer assignment RHS, or table element is a
91
+ * function-pointer position by construction, and C has no symbol imports —
92
+ * the dominant repo-scale pattern (`server.c`'s command table naming
93
+ * handlers defined across files) would otherwise be invisible. Call
94
+ * arguments stay gated everywhere (locals passed as args dwarf callbacks).
95
+ */
96
+ ungatedModes?: Set<CaptureMode>;
97
+ /**
98
+ * C++ only: in args/rhs/varinit positions, accept ONLY explicit reference
99
+ * forms (`&fn`, `&Cls::method`) — never bare identifiers. C++ codebases are
100
+ * dense with generic free-function/accessor names (`begin`, `end`, `out`,
101
+ * `size`, `data`) that collide with parameters and locals, and out-of-line
102
+ * member definitions extract as function-kind nodes — bare-id matching on
103
+ * fmt was mostly wrong edges. File-scope initializer tables (value/list)
104
+ * still accept bare identifiers, same as C.
105
+ */
106
+ addressOfOnly?: boolean;
107
+ }
108
+ /**
109
+ * Capture specs by language.
110
+ */
111
+ export declare const FN_REF_SPECS: Record<string, FnRefSpec | undefined>;
112
+ /**
113
+ * Extract candidate names from a dispatched container node. Returns the
114
+ * (name, position) pairs of every function-value-shaped expression found.
115
+ */
116
+ export declare function captureFnRefCandidates(container: SyntaxNode, rule: CaptureRule, spec: FnRefSpec, source: string): FnRefCandidate[];
117
+ export {};
118
+ //# sourceMappingURL=function-ref.d.ts.map
@@ -7,7 +7,7 @@
7
7
  */
8
8
  import { Parser } from 'web-tree-sitter';
9
9
  import { Language } from '../types';
10
- export type GrammarLanguage = Exclude<Language, 'svelte' | 'vue' | 'liquid' | 'yaml' | 'twig' | 'xml' | 'properties' | 'unknown'>;
10
+ export type GrammarLanguage = Exclude<Language, 'svelte' | 'vue' | 'astro' | 'liquid' | 'razor' | 'yaml' | 'twig' | 'xml' | 'properties' | 'unknown'>;
11
11
  /**
12
12
  * File extension to Language mapping
13
13
  */
@@ -18,6 +18,12 @@ export declare const EXTENSION_MAP: Record<string, Language>;
18
18
  * from EXTENSION_MAP so parser support and indexing selection never drift.
19
19
  */
20
20
  export declare function isSourceFile(filePath: string): boolean;
21
+ /**
22
+ * Shopify OS 2.0 JSON template (`templates/*.json`) or section group
23
+ * (`sections/*.json`) — these reference sections by `"type"`, so the Liquid
24
+ * extractor links them. (config/ + locales/ JSON have no section refs.)
25
+ */
26
+ export declare function isShopifyLiquidJson(filePath: string): boolean;
21
27
  /**
22
28
  * Play Framework routes file: the extensionless `conf/routes` (and included
23
29
  * `conf/*.routes`). No grammar — route extraction is done by the Play framework
@@ -53,6 +53,40 @@ export declare function hashContent(content: string): string;
53
53
  * it project code; the explicit `.gitignore` negation is the only opt-in).
54
54
  */
55
55
  export declare function buildDefaultIgnore(rootDir: string): Ignore;
56
+ /**
57
+ * Workspace-scope ignore matcher. Ordinary paths get the root's matcher
58
+ * (built-in defaults + root `.gitignore`); paths inside an EMBEDDED repo get
59
+ * that repo's own matcher (defaults + its root `.gitignore`) — the parent's
60
+ * `.gitignore` hides a child repo from git, not from the index (#514). A
61
+ * directory path (trailing slash) that is an ANCESTOR of an embedded root is
62
+ * never ignored, so directory-pruning callers (the Linux per-directory
63
+ * watcher) still descend to reach the embedded repos.
64
+ *
65
+ * Single source of truth for indexer and watcher scope — they must not diverge.
66
+ */
67
+ export declare class ScopeIgnore {
68
+ private rootMatcher;
69
+ private embedded;
70
+ private defaults;
71
+ constructor(rootMatcher: Ignore, embedded: Array<{
72
+ root: string;
73
+ matcher: Ignore;
74
+ }>);
75
+ ignores(rel: string): boolean;
76
+ }
77
+ /**
78
+ * Build the workspace-scope matcher. When the caller already knows the
79
+ * embedded roots (the scanner discovers them during collection), pass them to
80
+ * skip rediscovery; otherwise they're discovered here (the watcher path).
81
+ */
82
+ export declare function buildScopeIgnore(rootDir: string, embeddedRoots?: Iterable<string>): ScopeIgnore;
83
+ /**
84
+ * Standalone discovery of every embedded repo root under `rootDir` (relative,
85
+ * trailing-slashed) — both the untracked kind (#193) and the gitignored kind
86
+ * (#514), recursively (an embedded repo can embed further repos). Returns []
87
+ * for non-git roots: the filesystem walk handles nested repos there already.
88
+ */
89
+ export declare function discoverEmbeddedRepoRoots(rootDir: string): string[];
56
90
  /**
57
91
  * Recursively scan a directory for source files.
58
92
  *
@@ -1,4 +1,12 @@
1
1
  import type { LanguageExtractor } from '../tree-sitter-types';
2
+ /**
3
+ * Normalize a C++ return type to the bare class name a method could be called
4
+ * on. Unwraps smart-pointer / optional wrappers to their element type
5
+ * (`std::unique_ptr<Widget>` → `Widget`) so a factory's `->method()` resolves on
6
+ * the pointee. Strips cv-qualifiers, `&`/`*`, namespace qualifiers, and other
7
+ * template args. Returns undefined for primitives / void / `auto` / empty.
8
+ */
9
+ export declare function normalizeCppReturnType(raw: string): string | undefined;
2
10
  export declare const cExtractor: LanguageExtractor;
3
11
  export declare const cppExtractor: LanguageExtractor;
4
12
  //# sourceMappingURL=c-cpp.d.ts.map
@@ -1,3 +1,25 @@
1
1
  import type { LanguageExtractor } from '../tree-sitter-types';
2
+ /**
3
+ * Blank C# conditional-compilation directive lines (`#if` / `#elif` / `#else` /
4
+ * `#endif`) before parsing. The vendored tree-sitter-c-sharp grammar mis-parses
5
+ * a `#if` that appears *inside an enum member list* — the canonical
6
+ * multi-targeting shape:
7
+ *
8
+ * enum ReadType {
9
+ * #if HAVE_DATE_TIME_OFFSET
10
+ * ReadAsDateTimeOffset,
11
+ * #endif
12
+ * ReadAsDouble,
13
+ * }
14
+ *
15
+ * It emits an ERROR that, for a nested enum, detaches the *enclosing class's*
16
+ * member list, so most of the class's methods drop out of the index. Removing
17
+ * the directive lines (keeping the guarded code) sidesteps it. Both branches of
18
+ * an `#if/#else` are kept — the same behaviour the previous grammar produced,
19
+ * and the right default for a code graph (index every symbol regardless of
20
+ * build flags). Replacement preserves byte offsets (directive text → spaces,
21
+ * newlines kept) so every symbol's line/column stays exact. (#237)
22
+ */
23
+ export declare function blankCsharpPreprocessorDirectives(source: string): string;
2
24
  export declare const csharpExtractor: LanguageExtractor;
3
25
  //# sourceMappingURL=csharp.d.ts.map
@@ -0,0 +1,3 @@
1
+ import type { LanguageExtractor } from '../tree-sitter-types';
2
+ export declare const rExtractor: LanguageExtractor;
3
+ //# sourceMappingURL=r.d.ts.map
@@ -1,3 +1,16 @@
1
1
  import type { LanguageExtractor } from '../tree-sitter-types';
2
+ import type { Node as SyntaxNode } from 'web-tree-sitter';
3
+ /**
4
+ * A TS/JS class field (`public_field_definition` / `field_definition`) is a
5
+ * METHOD only when its value is callable — an arrow function, a function
6
+ * expression, or a HOF call wrapping one (`onScroll = throttle(() => {…})`),
7
+ * exactly mirroring what `resolveBody` below knows how to walk. Everything
8
+ * else (`public fonts: Fonts;`, `count = 0`, `static defaults = {…}`) is a
9
+ * PROPERTY. Previously every field extracted as method-kind (#808), which
10
+ * misrepresented class shape and defeated kind-based filtering — the reason
11
+ * #756's function-ref resolution had to restrict TS/JS bare identifiers to
12
+ * function targets.
13
+ */
14
+ export declare function classifyTsClassMember(node: SyntaxNode): 'method' | 'property';
2
15
  export declare const typescriptExtractor: LanguageExtractor;
3
16
  //# sourceMappingURL=typescript.d.ts.map
@@ -24,6 +24,13 @@ export declare class LiquidExtractor {
24
24
  * Create a file node for the Liquid template
25
25
  */
26
26
  private createFileNode;
27
+ /**
28
+ * Shopify OS 2.0 JSON template / section group. Both have a `sections` object
29
+ * mapping an id → `{ "type": "<section-name>", ... }`; the `type` names a
30
+ * `sections/<type>.liquid` file. Emit a `references` edge to each, so a section
31
+ * used only from a JSON template (the OS 2.0 norm) is no longer orphaned.
32
+ */
33
+ private extractShopifyJsonSections;
27
34
  /**
28
35
  * Extract {% render 'snippet' %} and {% include 'snippet' %} references
29
36
  */
@@ -0,0 +1,42 @@
1
+ import { ExtractionResult } from '../types';
2
+ export declare class RazorExtractor {
3
+ private filePath;
4
+ private source;
5
+ private nodes;
6
+ private edges;
7
+ private unresolvedReferences;
8
+ private errors;
9
+ constructor(filePath: string, source: string);
10
+ extract(): ExtractionResult;
11
+ private createComponentNode;
12
+ /** Last `.`-segment (`App.ViewModels.RegisterModel` → `RegisterModel`). */
13
+ private lastSegment;
14
+ /**
15
+ * Split a type expression into the capitalized type names it contains — base
16
+ * type plus any generic arguments (`Bar<Foo, Baz>` → `Bar`, `Foo`, `Baz`),
17
+ * each reduced to its last namespace segment. Lowercase/keyword tokens drop out.
18
+ */
19
+ private typeNames;
20
+ private pushRef;
21
+ private extractDirectives;
22
+ private extractComponentTags;
23
+ /**
24
+ * Find the matching `}` for the `{` at `openIdx`, skipping string literals and
25
+ * comments so a brace inside `"{"` / `// }` doesn't throw off the count.
26
+ * Returns the index of the closing brace, or -1 if unbalanced.
27
+ */
28
+ private matchBrace;
29
+ /** `@code { … }` / `@functions { … }` (Blazor) and `@{ … }` (Razor) C# blocks. */
30
+ private extractCodeBlocks;
31
+ /**
32
+ * Delegate each `@code`/`@functions`/`@{` block's C# to the tree-sitter C#
33
+ * extractor and attribute the block's external references (service/DTO calls,
34
+ * `new X()`, type uses) to the component. The block is wrapped in a synthetic
35
+ * class so tree-sitter parses the component's fields/methods in a class context
36
+ * (a Blazor `@code` body compiles into the component's partial class). We keep
37
+ * only the dependency references — coverage just needs the edges to external
38
+ * types, not per-member nodes. Degrades gracefully if the C# grammar isn't loaded.
39
+ */
40
+ private processCodeBlocks;
41
+ }
42
+ //# sourceMappingURL=razor-extractor.d.ts.map
@@ -69,6 +69,15 @@ export interface ExtractorContext {
69
69
  * language-specific details like signatures, visibility, and imports.
70
70
  */
71
71
  export interface LanguageExtractor {
72
+ /**
73
+ * Optional source transform applied immediately before the grammar parses the
74
+ * file. Used to work around grammar gaps that would otherwise corrupt the
75
+ * parse tree (e.g. C# blanks conditional-compilation directive lines the
76
+ * grammar mis-parses inside enum bodies). MUST preserve byte offsets (replace
77
+ * removed text with spaces, keep newlines) so node positions and getNodeText
78
+ * stay correct; the returned string is used for both parsing and extraction.
79
+ */
80
+ preParse?: (source: string) => string;
72
81
  /** Node types that represent functions */
73
82
  functionTypes: string[];
74
83
  /** Node types that represent classes */
@@ -119,6 +128,14 @@ export interface LanguageExtractor {
119
128
  isStatic?: (node: SyntaxNode) => boolean;
120
129
  /** Check if variable declaration is a constant (const vs let/var) */
121
130
  isConst?: (node: SyntaxNode) => boolean;
131
+ /**
132
+ * Extract extra symbol-level modifier keywords to persist on the node's
133
+ * `decorators` list (e.g. Kotlin `expect`/`actual` multiplatform markers).
134
+ * Called generically for every created node; return undefined/[] when none.
135
+ * Used by the resolver to link `expect` declarations to their `actual`
136
+ * implementations across source sets.
137
+ */
138
+ extractModifiers?: (node: SyntaxNode) => string[] | undefined;
122
139
  /** Additional node types to treat as class declarations (e.g. Dart: 'mixin_declaration') */
123
140
  extraClassNodeTypes?: string[];
124
141
  /** Whether methods can be top-level without enclosing class (Go: true) */
@@ -135,6 +152,14 @@ export interface LanguageExtractor {
135
152
  * for multiple concepts (e.g. Swift uses class_declaration for classes, structs, and enums).
136
153
  */
137
154
  classifyClassNode?: (node: SyntaxNode) => 'class' | 'struct' | 'enum' | 'interface' | 'trait';
155
+ /**
156
+ * Classify a methodTypes node when the grammar reuses one node type for
157
+ * both callable and data members (#808): TS/JS class FIELDS
158
+ * (`public_field_definition` / `field_definition`) are methods only when
159
+ * their value is callable (`onClick = () => {}`); a plain field
160
+ * (`public fonts: Fonts;`, `count = 0`) is a property. Default: 'method'.
161
+ */
162
+ classifyMethodNode?: (node: SyntaxNode) => 'method' | 'property';
138
163
  /**
139
164
  * Resolve the body node for a function/method/class when it's not a child field.
140
165
  * (e.g. Dart puts function_body as a sibling, not a child.)
@@ -156,6 +181,14 @@ export interface LanguageExtractor {
156
181
  * When present, the receiver type is included in the qualified name for better searchability.
157
182
  */
158
183
  getReceiverType?: (node: SyntaxNode, source: string) => string | undefined;
184
+ /**
185
+ * Extract a function/method's normalized return type name (bare class name,
186
+ * smart-pointer pointee unwrapped), stored on the node as `returnType`. Used
187
+ * by C/C++ so resolution can infer a chained receiver's type from what the
188
+ * inner call returns (`Foo::instance().bar()` → resolve `bar` on `Foo`,
189
+ * issue #645). Return undefined for primitives / void / constructors.
190
+ */
191
+ getReturnType?: (node: SyntaxNode, source: string) => string | undefined;
159
192
  /**
160
193
  * Resolve the actual node kind for a type alias declaration.
161
194
  * Used by Go where `type_spec` is the named declaration wrapper for structs/interfaces:
@@ -20,11 +20,45 @@ export declare class TreeSitterExtractor {
20
20
  private extractor;
21
21
  private nodeStack;
22
22
  private methodIndex;
23
+ private fnRefSpec;
24
+ private fnRefCandidates;
23
25
  constructor(filePath: string, source: string, language?: Language);
24
26
  /**
25
27
  * Parse and extract from the source code
26
28
  */
27
29
  extract(): ExtractionResult;
30
+ /**
31
+ * Function-as-value capture (#756): if this node is one of the language's
32
+ * value-position containers (call arguments, assignment RHS, struct/object
33
+ * initializer, array/table literal), collect candidate function names from
34
+ * it. Candidates are gated & flushed at end-of-file (flushFnRefCandidates).
35
+ */
36
+ private maybeCaptureFnRefs;
37
+ /**
38
+ * Candidates-only scan of a subtree the main walkers won't traverse
39
+ * (top-level variable initializers). No extraction side effects. Halts at
40
+ * nested function definitions: their bodies are walked — and their
41
+ * candidates attributed — by extractFunction's own body walk.
42
+ */
43
+ private scanFnRefSubtree;
44
+ /**
45
+ * Gate captured function-as-value candidates and push survivors as
46
+ * `function_ref` unresolved references.
47
+ *
48
+ * The gate bounds volume and protects precision: a candidate survives only
49
+ * if its name matches a function/method DEFINED IN THIS FILE or a name this
50
+ * file imports/references. Everything else (locals, params, fields passed
51
+ * as arguments) is dropped before it ever reaches the database. Resolution
52
+ * then matches survivors against function/method nodes only
53
+ * (matchFunctionRef) and emits `references` edges — which callers/impact
54
+ * already traverse.
55
+ *
56
+ * Known v1 limit, deliberate: a C/C++ callback registered in a DIFFERENT
57
+ * translation unit than its definition (extern, no symbol imports to match)
58
+ * is not captured. Same-file registration — the dominant C pattern (static
59
+ * callback + same-file ops struct) — is.
60
+ */
61
+ private flushFnRefCandidates;
28
62
  /**
29
63
  * Visit a node and extract information
30
64
  */
@@ -137,6 +171,14 @@ export declare class TreeSitterExtractor {
137
171
  * Returns true if children should be skipped (struct/interface handled body visiting).
138
172
  */
139
173
  private extractTypeAlias;
174
+ /**
175
+ * Extract the method specs of a Go `interface_type` body as `method` nodes
176
+ * contained by the interface (e.g. `Marshal`, `Unmarshal` of a `Core`
177
+ * interface). tree-sitter-go names these `method_elem` (newer) or
178
+ * `method_spec` (older). Embedded interfaces (`Reader` inside `ReadWriter`)
179
+ * are `type_identifier`s, not methods, and are left to inheritance extraction.
180
+ */
181
+ private extractGoInterfaceMethods;
140
182
  /**
141
183
  * Surface the members of a TypeScript `type X = { ... }` (or intersection
142
184
  * thereof) as `property` / `method` nodes under the type-alias node. Only
@@ -145,6 +187,34 @@ export declare class TreeSitterExtractor {
145
187
  * don't produce phantom members.
146
188
  */
147
189
  private extractTsTypeAliasMembers;
190
+ /**
191
+ * Surface the string-literal "names" of a TypeScript service/contract
192
+ * registry written as a tuple of generic instantiations:
193
+ *
194
+ * type MyServiceList = [
195
+ * Service<'query_apply_record', Req, Resp>,
196
+ * Service<'apply_confirm', Req, Resp>,
197
+ * ];
198
+ *
199
+ * Each `Service<'name', …>` tags an entry with a string-literal name that a
200
+ * dynamic factory (`createService<MyServiceList>()`) turns into a callable
201
+ * property (`api.query_apply_record(…)`). Static extraction otherwise never
202
+ * sees that name — it's a type argument, not a declaration — so
203
+ * `codegraph query query_apply_record` returned nothing (issue #634). We emit
204
+ * each name as a `method` node under the type alias (qualifiedName
205
+ * `MyServiceList::query_apply_record`) so it's searchable and resolvable as a
206
+ * symbol. (A call through the proxy, `api.query_apply_record(…)`, still
207
+ * resolves to the imported `api` binding — the receiver's type isn't known —
208
+ * so this fixes discoverability, not the per-method call edge.)
209
+ *
210
+ * Scope is deliberately narrow to avoid noise: only a string literal that is
211
+ * a DIRECT type argument of a `generic_type` that is itself a DIRECT element
212
+ * of a `tuple_type`. This excludes utility types (`Pick`/`Omit`/`Record` are
213
+ * never written as tuples) and string args nested deeper
214
+ * (`Service<'a', Pick<U, 'id'>>` yields only `a`, never `id`). Names must be
215
+ * valid identifiers, which also rules out route paths / arbitrary strings.
216
+ */
217
+ private extractTsTupleContractNames;
148
218
  /**
149
219
  * `foo: () => T` → property_signature whose type_annotation contains a
150
220
  * `function_type`. Treat that as a method-shaped contract member, since
@@ -158,6 +228,83 @@ export declare class TreeSitterExtractor {
158
228
  * Also creates unresolved references for resolution purposes.
159
229
  */
160
230
  private extractImport;
231
+ /**
232
+ * Emit one `imports` reference per named/default import binding (TS/JS family),
233
+ * attributed to the file node — so the resolver links each imported symbol to
234
+ * the file that DEFINES it.
235
+ *
236
+ * Importing a symbol IS a dependency, but extraction only emits references for
237
+ * calls, instantiations, type annotations, and inheritance. A symbol that's
238
+ * imported and then only re-exported (`export { X } from './x'`), placed in a
239
+ * registry array (`[expressResolver, …]`), passed as an argument, or used in
240
+ * JSX produced NO cross-file edge at all — so the providing file showed a
241
+ * false "0 dependents" and was invisible to blast-radius / `affected`. The
242
+ * resolver maps the local name (alias-aware) to the provider's definition and
243
+ * creates a cross-file `imports` edge; `getFileDependents` picks it up, while
244
+ * `getImpactRadius` keeps it as a bounded leaf (the importing file node).
245
+ *
246
+ * Namespace imports (`import * as NS`) bind a whole module: `NS.member` calls
247
+ * resolve on their own, but a namespace used ONLY via a value-member read
248
+ * (`NS.SOME_CONST`) would leave no edge — so we also emit the namespace local
249
+ * name, which the resolver links to the module FILE as a dependency backstop.
250
+ */
251
+ private emitImportBindingRefs;
252
+ /**
253
+ * Emit one `imports` reference per re-exported binding of a
254
+ * `export { A, B as C } from './y'` statement, attributed to the file node —
255
+ * so a barrel that re-exports from another module records a dependency on it.
256
+ *
257
+ * Links the SOURCE-side name (`A`, the `name` field — not the local alias
258
+ * `C`), since that is what the source module defines. `export * from './y'`
259
+ * has no named bindings to attribute and `export { default as X }` can't be
260
+ * name-matched, so both are skipped.
261
+ */
262
+ private emitReExportRefs;
263
+ /**
264
+ * Emit one `imports` reference per binding of a Rust `use` declaration —
265
+ * `use crate::m::Item`, `use crate::m::{A, B as C}`, `pub use self::sub::Item`.
266
+ * Emits the FULL path (e.g. `self::sub::Item`, not just `Item`) so the resolver
267
+ * can resolve the module prefix to a file and find the leaf symbol there —
268
+ * disambiguating common-name re-exports (`pub use self::read::read`, where the
269
+ * leaf `read` collides with many same-named symbols). Falls back to name-match
270
+ * on the leaf when the path can't be resolved. `use ...::*` has no leaf binding.
271
+ */
272
+ private emitRustUseBindingRefs;
273
+ /**
274
+ * Emit an `imports` reference for a single PHP `use Foo\Bar\Baz;` (grouped
275
+ * imports `use Foo\{A, B}` are handled where their per-item nodes are created).
276
+ * The reference targets the namespace-qualified `Foo\Bar::Baz` form classes are
277
+ * stored under (see the PHP `namespace` capture), so it resolves to the RIGHT
278
+ * definition — Laravel has many same-named contracts (`Factory`, `Dispatcher`,
279
+ * `Guard`) across namespaces that a bare-name match can't disambiguate.
280
+ */
281
+ private emitPhpUseRefs;
282
+ /**
283
+ * Ruby `require`/`require_relative` → an `imports` ref to the required FILE.
284
+ * `require "sidekiq/fetch"` is load-path-relative (matched by file-path suffix
285
+ * via {@link matchByFilePath}); `require_relative "../foo"` is resolved against
286
+ * this file's directory. Bare gem/stdlib requires (`require "json"`, no slash)
287
+ * are skipped — they're external. The path form (a `/` + `.rb`) makes the ref
288
+ * resolve to the file node, so a file pulled in only by `require` — not by a
289
+ * resolved constant/call — still records a cross-file dependency.
290
+ */
291
+ private emitRubyRequireRefs;
292
+ /** Convert a PHP FQN `Foo\Bar\Baz` to the stored `Foo\Bar::Baz` and emit an `imports` ref. */
293
+ private pushPhpUseRef;
294
+ /**
295
+ * Emit one `imports` reference per name imported in a Python
296
+ * `from module import A, B as C` statement, attributed to the file node — so
297
+ * the resolver links each imported name to the module that DEFINES it.
298
+ *
299
+ * Same recall gap as TS: extraction only emitted references for calls,
300
+ * instantiations, and inheritance, so a name imported and then used in a
301
+ * non-call position (a list/dict literal, a default argument, a decorator
302
+ * target, or simply re-exported through an `__init__.py` barrel) produced no
303
+ * cross-file edge — the providing module showed a false "0 dependents". Links
304
+ * the LOCAL name (alias when present, since that's what the resolver's import
305
+ * mapping keys on); `from module import *` has no names to attribute.
306
+ */
307
+ private emitPyFromImportRefs;
161
308
  /**
162
309
  * Extract a function call
163
310
  */
@@ -172,6 +319,18 @@ export declare class TreeSitterExtractor {
172
319
  * arguments (`new Foo(bar())`) get their own `calls` references.
173
320
  */
174
321
  private extractInstantiation;
322
+ /**
323
+ * Static-member / value-read pass. A type/enum/class used only via a member
324
+ * VALUE — `Enum.value`, `Type.CONST`, `Colors.red`, `Foo::BAR` — recorded no
325
+ * edge, because the body walker only handled CALLS (`Type.method()`). So a
326
+ * type referenced only by an enum value or a static field looked like nothing
327
+ * depended on it (the residual frontier across Dart/Java/C#/Swift/Kotlin/PHP).
328
+ * Emit a `references` edge to the capitalized receiver. Gated to languages
329
+ * where types are Capitalized by convention, and skipped when the access is a
330
+ * call's callee (the call extractor already links the method).
331
+ */
332
+ private extractStaticMemberRef;
333
+ private pushStaticMemberRef;
175
334
  /**
176
335
  * Find a `class_body` child of an `object_creation_expression` — the
177
336
  * marker for an anonymous class (`new T() { ... }`). Returns the body
@@ -216,6 +375,19 @@ export declare class TreeSitterExtractor {
216
375
  * tree-sitter to interpret the namespace block as a function_definition,
217
376
  * hiding real class/struct/enum nodes inside the "function body".
218
377
  */
378
+ /**
379
+ * Rocket route-registration macros — `routes![a::b::handler, c::d::other]`
380
+ * and `catchers![not_found]`. Tree-sitter leaves a macro body as a flat
381
+ * `token_tree` of raw tokens (`identifier`, `::`, `,`), so the handler paths
382
+ * are never seen as references and each handler fn looks like it has no caller
383
+ * — it's mounted by Rocket at runtime, not called by in-repo code, so its file
384
+ * shows 0 dependents. Walk the token tree, reconstruct each comma-separated
385
+ * path, and emit a `references` edge; the Rust path resolver
386
+ * (`resolveRustPathReference`) then links it to the handler fn. The handler
387
+ * names are explicit in source, so this is precise static extraction, not a
388
+ * heuristic — no false edges (resolution still validates each path).
389
+ */
390
+ private extractRustRouteMacro;
219
391
  private visitFunctionBody;
220
392
  /**
221
393
  * Extract inheritance relationships
@@ -234,6 +406,11 @@ export declare class TreeSitterExtractor {
234
406
  * Languages that support type annotations (TypeScript, etc.)
235
407
  */
236
408
  private readonly TYPE_ANNOTATION_LANGUAGES;
409
+ /**
410
+ * PHP pseudo-types and `self`/`static`/`parent` that aren't project symbols.
411
+ * (Scalar primitives parse as `primitive_type` and are skipped structurally.)
412
+ */
413
+ private readonly PHP_PSEUDO_TYPES;
237
414
  /**
238
415
  * Built-in/primitive type names that shouldn't create references
239
416
  */
@@ -256,12 +433,35 @@ export declare class TreeSitterExtractor {
256
433
  * `tuple_type`, …) — none of which are `type_identifier`. Closes #381.
257
434
  */
258
435
  private extractCsharpTypeRefs;
436
+ /**
437
+ * Record the dependencies declared by a C# PRIMARY CONSTRUCTOR
438
+ * (`class Svc(IRepo repo, [FromKeyedServices("k")] ICache cache) { … }`,
439
+ * C# 12+). The parameter list hangs off the class/struct/record declaration
440
+ * as an unnamed-field `parameter_list` child (not the `parameters` field a
441
+ * method uses), so it's found by node type. Each parameter's declared type
442
+ * becomes a `references` edge from the owning type — these are exactly the
443
+ * services a DI-registered type depends on, so impact/blast-radius and
444
+ * "who depends on this contract" now see them. No-op when there's no primary
445
+ * constructor. (#237)
446
+ */
447
+ private extractCsharpPrimaryCtorParamRefs;
259
448
  /**
260
449
  * Walk a C# subtree that is KNOWN to be in a type position
261
450
  * (return type, parameter type, property type, field type, generic
262
451
  * argument). Identifiers here are type names, not parameter names.
263
452
  */
264
453
  private walkCsharpTypePosition;
454
+ /**
455
+ * Extract PHP type references from a method/function/property declaration.
456
+ * Walks ONLY type positions: each parameter's type child (inside
457
+ * `formal_parameters`), the return type, and a property's type — all
458
+ * `named_type` / `optional_type` / `union_type` / … direct children. Parameter
459
+ * and property NAMES are `variable_name` (`$x`), never type nodes, so they
460
+ * can't be mis-emitted.
461
+ */
462
+ private extractPhpTypeRefs;
463
+ /** Walk a PHP subtree KNOWN to be in a type position; emit class/interface refs. */
464
+ private walkPhpTypePosition;
265
465
  /**
266
466
  * Extract type references from a variable's type annotation.
267
467
  */
@@ -301,6 +501,17 @@ export declare class TreeSitterExtractor {
301
501
  * Extract function calls from a Pascal expression
302
502
  */
303
503
  private extractPascalCall;
504
+ /**
505
+ * Extract a PAREN-LESS Pascal method/procedure call (`Obj.Method;`,
506
+ * `TFoo.GetInstance.DoIt;`). Pascal lets a no-arg method drop its parens, so it
507
+ * parses as a bare `exprDot` (not an `exprCall`). A bare `exprDot` is
508
+ * syntactically identical to a field/property access, so this is only ever
509
+ * called for a STATEMENT-level exprDot (caller-gated): a bare `Obj.Field;`
510
+ * statement is a no-op, so a statement-level dot expression is a call. (An
511
+ * exprDot in assignment LHS/RHS or a condition is left alone — there it really
512
+ * can be a field/property read.)
513
+ */
514
+ private extractPascalParenlessCall;
304
515
  /**
305
516
  * Recursively visit a Pascal block/statement tree for call expressions
306
517
  */