@colbymchenry/codegraph 1.1.6 → 1.2.0

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.
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  ## 🎉 1.0 Released!
6
6
 
7
- Already installed? Run `codegraph upgrade` to update in place.
7
+ Already installed? Run `codegraph upgrade`
8
8
 
9
9
  Follow [@getcodegraph](https://x.com/getcodegraph) on X for updates.
10
10
 
@@ -47,5 +47,22 @@ export declare const cExtractor: LanguageExtractor;
47
47
  * so C's heavier use of `struct TAG var;` never reaches it.
48
48
  */
49
49
  export declare function blankCppExportMacros(source: string): string;
50
+ export declare function blankCppInlineMacros(source: string): string;
51
+ /**
52
+ * Universal fallback (any macro, no list) for a C/C++ function name still mangled
53
+ * because a macro we don't blank sat in front of the return type: `MACRO Ret
54
+ * name(…)` / `Ret MACRO name(…)` misparse so the return type is glued onto the
55
+ * name ("Ret name", "char_t* to_str(double v)"). Recover the real identifier —
56
+ * the token immediately before the parameter list (or the last token). This runs
57
+ * AFTER the curated pre-parse blank, so it only ever sees the residual tail that
58
+ * blanking didn't already fix cleanly (which also recovers the return type).
59
+ *
60
+ * Safe by construction: only touches an ALREADY-mangled name — one with an
61
+ * internal space that isn't a legit `operator …`/destructor — so a well-formed
62
+ * name is returned unchanged. Guarded against the two ways it could mis-pick:
63
+ * the `Ret (name)` parenthesized-name idiom (left as-is, ambiguous), and a token
64
+ * that is a bare primitive/keyword rather than a real identifier.
65
+ */
66
+ export declare function recoverMangledCppName(name: string): string;
50
67
  export declare const cppExtractor: LanguageExtractor;
51
68
  //# sourceMappingURL=c-cpp.d.ts.map
@@ -114,6 +114,15 @@ export interface LanguageExtractor {
114
114
  returnField?: string;
115
115
  /** Override symbol name extraction (e.g. ObjC multi-part selectors). */
116
116
  resolveName?: (node: SyntaxNode, source: string) => string | undefined;
117
+ /**
118
+ * Post-process an already-extracted name to recover a real identifier from a
119
+ * name still mangled by a macro the pre-parse didn't blank (C/C++:
120
+ * `MACRO Ret name(` misparses to the name "Ret name"). Applied to every name
121
+ * this extractor produces, so it MUST be a no-op on a well-formed name — only
122
+ * C/C++ set it, because a mangled name there is unambiguous (an internal space),
123
+ * whereas e.g. Kotlin/Scala backtick identifiers legitimately contain spaces.
124
+ */
125
+ recoverMangledName?: (name: string) => string;
117
126
  /** Extract property name when the generic name walk fails (e.g. ObjC @property). */
118
127
  extractPropertyName?: (node: SyntaxNode, source: string) => string | null;
119
128
  /** Extract signature from node */
@@ -140,6 +149,14 @@ export interface LanguageExtractor {
140
149
  extraClassNodeTypes?: string[];
141
150
  /** Whether methods can be top-level without enclosing class (Go: true) */
142
151
  methodsAreTopLevel?: boolean;
152
+ /**
153
+ * Skip a bodiless class node as a forward declaration / elaborated type,
154
+ * mirroring the bodiless-struct/enum skip. Set only for languages where a
155
+ * bodiless `class` specifier is NOT a complete definition — C/C++
156
+ * (`class Foo;` is a forward decl). Leave unset for languages where a
157
+ * bodiless class IS complete (Kotlin `class Empty`, Scala `case object`). (#1093)
158
+ */
159
+ skipBodilessClass?: boolean;
143
160
  /** NodeKind to use for interface-like declarations (Rust: 'trait'). Default: 'interface' */
144
161
  interfaceKind?: NodeKind;
145
162
  /**
@@ -11,5 +11,5 @@ import type { ResolutionContext } from './types';
11
11
  * Sidekiq Worker.perform_async → #perform + Laravel event(new X) → listener handle).
12
12
  * Returns the count added. Never throws into indexing — callers wrap in try/catch.
13
13
  */
14
- export declare function synthesizeCallbackEdges(queries: QueryBuilder, ctx: ResolutionContext): number;
14
+ export declare function synthesizeCallbackEdges(queries: QueryBuilder, ctx: ResolutionContext): Promise<number>;
15
15
  //# sourceMappingURL=callback-synthesizer.d.ts.map
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Cooperative yielding for long synchronous resolution spans.
3
+ *
4
+ * Reference resolution and callback-edge synthesis run on the indexer's MAIN
5
+ * thread — unlike parsing, which is off-thread in the parse worker. The #850
6
+ * liveness watchdog (armed on `index`/`init` since #999) SIGKILLs the process
7
+ * when that thread doesn't turn its event loop for the timeout window (default
8
+ * 60s), because its heartbeat is a `setInterval` on that same thread. On a large
9
+ * repo, resolving refs + synthesizing dynamic-dispatch edges legitimately runs
10
+ * for minutes, so a span that never yields starves the heartbeat and the
11
+ * watchdog kills a VALID, in-progress index — the exact symptom of #1091 (the
12
+ * progress bar freezes at wherever it last rendered — 88% / 100% — then the
13
+ * process is killed).
14
+ *
15
+ * `createYielder` returns a `maybeYield()` that yields (via `setImmediate`) only
16
+ * once more than `budgetMs` of wall-clock has elapsed since the last yield, so
17
+ * fast repos pay essentially nothing while slow ones give the heartbeat a
18
+ * regular window to fire. Call it at natural boundaries in a long loop (between
19
+ * batches, between synthesis passes).
20
+ *
21
+ * This does NOT weaken the watchdog. A genuinely wedged loop — an infinite or
22
+ * non-terminating span, the case the watchdog exists to catch — never reaches a
23
+ * yield point, so the heartbeat still stops and the SIGKILL still fires. We only
24
+ * stop killing work that is demonstrably making progress.
25
+ */
26
+ /** Yield when more than `budgetMs` of wall-clock has passed since the last yield. */
27
+ export type MaybeYield = () => Promise<void>;
28
+ /** Default budget: well under the watchdog's minimum heartbeat cadence (~1s), so
29
+ * a heartbeat byte always has a chance to land between yields. */
30
+ export declare const DEFAULT_YIELD_BUDGET_MS = 250;
31
+ export declare function createYielder(budgetMs?: number): MaybeYield;
32
+ //# sourceMappingURL=cooperative-yield.d.ts.map
@@ -103,7 +103,16 @@ export declare class ReferenceResolver {
103
103
  * (re-resolving an already-resolved ref is a no-op since it's been deleted).
104
104
  * Returns the number of newly-created edges.
105
105
  */
106
- resolveChainedCallsViaConformance(): number;
106
+ resolveChainedCallsViaConformance(): Promise<number>;
107
+ /**
108
+ * Resolve one batch in smaller sub-chunks, yielding to the event loop between
109
+ * them so the #850 liveness heartbeat can fire on a slow/dense batch (#1091).
110
+ * Behaviourally identical to a single `resolveAll(batch)`: `warmCaches()` is
111
+ * idempotent (guarded) and `resolveOne` is independent per ref, so splitting
112
+ * and re-merging changes only timing, never which edges get created. Falls
113
+ * through to a plain `resolveAll` when the batch is already small.
114
+ */
115
+ private resolveBatchYielding;
107
116
  /**
108
117
  * Resolve and persist in batches to keep memory bounded.
109
118
  * Processes unresolved references in chunks, persisting edges and cleaning
@@ -172,7 +181,7 @@ export declare class ReferenceResolver {
172
181
  * Mirrors resolveChainedCallsViaConformance's lifecycle. Returns the number
173
182
  * of newly-created edges.
174
183
  */
175
- resolveDeferredThisMemberRefs(): number;
184
+ resolveDeferredThisMemberRefs(): Promise<number>;
176
185
  private gateLanguage;
177
186
  /**
178
187
  * Drop a FRAMEWORK-strategy resolution that crosses two *known* language
@@ -3,6 +3,7 @@
3
3
  *
4
4
  * Handles symbol name matching for reference resolution.
5
5
  */
6
+ import { Node } from '../types';
6
7
  import { UnresolvedRef, ResolvedRef, ResolutionContext } from './types';
7
8
  /**
8
9
  * Try to resolve a path-like reference (e.g., "snippets/drawer-menu.liquid")
@@ -47,6 +48,27 @@ export declare function matchByExactName(ref: UnresolvedRef, context: Resolution
47
48
  * Try to resolve by qualified name
48
49
  */
49
50
  export declare function matchByQualifiedName(ref: UnresolvedRef, context: ResolutionContext): ResolvedRef | null;
51
+ /**
52
+ * When a symbol name is ambiguous across files, prefer the candidate(s) declared
53
+ * in the call site's own file, keeping the rest in their original order (#1079).
54
+ * A same-file definition is the strongest language-agnostic signal for which of
55
+ * several same-named symbols a call means; without it, resolution collapses onto
56
+ * whichever was indexed first, so a call in `b/svc` wrongly targets `a/svc`.
57
+ * No-op when there are <2 candidates or none share the call site's file.
58
+ */
59
+ export declare function preferCallSiteFile(nodes: Node[], callSiteFile: string): Node[];
60
+ export declare function resolveMethodOnType(typeName: string, methodName: string, ref: UnresolvedRef, context: ResolutionContext, confidence: number, resolvedBy: ResolvedRef['resolvedBy'],
61
+ /**
62
+ * Optional FQN that identifies WHICH class declaration `typeName`
63
+ * refers to in the caller's file. When multiple candidates share
64
+ * the same qualifiedName (`FooConverter::convert` in both
65
+ * `dao/converter/` and `service/converter/`), the FQN's
66
+ * file-path-suffix picks the right one — the disambiguation
67
+ * signal Java imports carry but the call site doesn't (#314).
68
+ */
69
+ preferredFqn?: string,
70
+ /** Recursion guard for the supertype/conformance walk. */
71
+ depth?: number): ResolvedRef | null;
50
72
  /**
51
73
  * Resolve a C++ chained call whose receiver is itself a call — encoded by the
52
74
  * extractor as `<innerCallee>().<method>` (#645). The receiver's type is what
package/npm-shim.js CHANGED
@@ -45,7 +45,7 @@ async function main() {
45
45
  // Happy path: the npm-installed optional dependency. Fall back to a download
46
46
  // when the registry didn't deliver it.
47
47
  var resolved = resolveInstalledBundle() || (await selfHealBundle());
48
- var res = childProcess.spawnSync(resolved.command, resolved.args, { stdio: 'inherit' });
48
+ var res = childProcess.spawnSync(resolved.command, resolved.args, { stdio: 'inherit', windowsHide: true });
49
49
  if (res.error) {
50
50
  process.stderr.write('codegraph: ' + res.error.message + '\n');
51
51
  process.exit(1);
@@ -222,7 +222,7 @@ function extract(archive, destDir) {
222
222
  var args = isWindows
223
223
  ? ['-xf', archive, '-C', destDir, '--strip-components=1']
224
224
  : ['-xzf', archive, '-C', destDir, '--strip-components=1'];
225
- var res = childProcess.spawnSync('tar', args, { stdio: 'ignore' });
225
+ var res = childProcess.spawnSync('tar', args, { stdio: 'ignore', windowsHide: true });
226
226
  if (res.error) throw new Error('tar unavailable: ' + res.error.message);
227
227
  if (res.status !== 0) throw new Error('tar exited ' + res.status);
228
228
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@colbymchenry/codegraph",
3
- "version": "1.1.6",
3
+ "version": "1.2.0",
4
4
  "description": "Local-first code intelligence for AI agents (MCP). Self-contained — bundles its own runtime.",
5
5
  "bin": {
6
6
  "codegraph": "npm-shim.js"
@@ -15,12 +15,12 @@
15
15
  "./package.json": "./package.json"
16
16
  },
17
17
  "optionalDependencies": {
18
- "@colbymchenry/codegraph-darwin-arm64": "1.1.6",
19
- "@colbymchenry/codegraph-darwin-x64": "1.1.6",
20
- "@colbymchenry/codegraph-linux-arm64": "1.1.6",
21
- "@colbymchenry/codegraph-linux-x64": "1.1.6",
22
- "@colbymchenry/codegraph-win32-arm64": "1.1.6",
23
- "@colbymchenry/codegraph-win32-x64": "1.1.6"
18
+ "@colbymchenry/codegraph-darwin-arm64": "1.2.0",
19
+ "@colbymchenry/codegraph-darwin-x64": "1.2.0",
20
+ "@colbymchenry/codegraph-linux-arm64": "1.2.0",
21
+ "@colbymchenry/codegraph-linux-x64": "1.2.0",
22
+ "@colbymchenry/codegraph-win32-arm64": "1.2.0",
23
+ "@colbymchenry/codegraph-win32-x64": "1.2.0"
24
24
  },
25
25
  "files": [
26
26
  "npm-shim.js",