@colbymchenry/codegraph-darwin-x64 1.0.1 → 1.1.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/lib/dist/bin/codegraph.js +111 -11
- package/lib/dist/bin/codegraph.js.map +1 -1
- package/lib/dist/db/index.d.ts +22 -1
- package/lib/dist/db/index.d.ts.map +1 -1
- package/lib/dist/db/index.js +46 -1
- package/lib/dist/db/index.js.map +1 -1
- package/lib/dist/db/queries.d.ts +14 -0
- package/lib/dist/db/queries.d.ts.map +1 -1
- package/lib/dist/db/queries.js +25 -0
- package/lib/dist/db/queries.js.map +1 -1
- package/lib/dist/directory.d.ts +43 -0
- package/lib/dist/directory.d.ts.map +1 -1
- package/lib/dist/directory.js +121 -0
- package/lib/dist/directory.js.map +1 -1
- package/lib/dist/extraction/grammars.d.ts +11 -3
- package/lib/dist/extraction/grammars.d.ts.map +1 -1
- package/lib/dist/extraction/grammars.js +14 -5
- package/lib/dist/extraction/grammars.js.map +1 -1
- package/lib/dist/extraction/index.d.ts.map +1 -1
- package/lib/dist/extraction/index.js +161 -34
- package/lib/dist/extraction/index.js.map +1 -1
- package/lib/dist/extraction/languages/c-cpp.d.ts.map +1 -1
- package/lib/dist/extraction/languages/c-cpp.js +47 -2
- package/lib/dist/extraction/languages/c-cpp.js.map +1 -1
- package/lib/dist/extraction/languages/csharp.d.ts.map +1 -1
- package/lib/dist/extraction/languages/csharp.js +20 -0
- package/lib/dist/extraction/languages/csharp.js.map +1 -1
- package/lib/dist/extraction/languages/dart.d.ts.map +1 -1
- package/lib/dist/extraction/languages/dart.js +22 -0
- package/lib/dist/extraction/languages/dart.js.map +1 -1
- package/lib/dist/extraction/languages/java.d.ts.map +1 -1
- package/lib/dist/extraction/languages/java.js +213 -9
- package/lib/dist/extraction/languages/java.js.map +1 -1
- package/lib/dist/extraction/languages/kotlin.d.ts.map +1 -1
- package/lib/dist/extraction/languages/kotlin.js +51 -0
- package/lib/dist/extraction/languages/kotlin.js.map +1 -1
- package/lib/dist/extraction/languages/scala.d.ts.map +1 -1
- package/lib/dist/extraction/languages/scala.js +19 -9
- package/lib/dist/extraction/languages/scala.js.map +1 -1
- package/lib/dist/extraction/parse-worker.js +4 -1
- package/lib/dist/extraction/parse-worker.js.map +1 -1
- package/lib/dist/extraction/tree-sitter-types.d.ts +13 -0
- package/lib/dist/extraction/tree-sitter-types.d.ts.map +1 -1
- package/lib/dist/extraction/tree-sitter.d.ts +119 -0
- package/lib/dist/extraction/tree-sitter.d.ts.map +1 -1
- package/lib/dist/extraction/tree-sitter.js +890 -11
- package/lib/dist/extraction/tree-sitter.js.map +1 -1
- package/lib/dist/index.d.ts +33 -0
- package/lib/dist/index.d.ts.map +1 -1
- package/lib/dist/index.js +68 -7
- package/lib/dist/index.js.map +1 -1
- package/lib/dist/installer/index.d.ts.map +1 -1
- package/lib/dist/installer/index.js +33 -67
- package/lib/dist/installer/index.js.map +1 -1
- package/lib/dist/installer/instructions-template.d.ts +3 -3
- package/lib/dist/installer/instructions-template.d.ts.map +1 -1
- package/lib/dist/installer/instructions-template.js +4 -4
- package/lib/dist/installer/targets/claude.d.ts +18 -12
- package/lib/dist/installer/targets/claude.d.ts.map +1 -1
- package/lib/dist/installer/targets/claude.js +78 -6
- package/lib/dist/installer/targets/claude.js.map +1 -1
- package/lib/dist/installer/targets/shared.d.ts +12 -2
- package/lib/dist/installer/targets/shared.d.ts.map +1 -1
- package/lib/dist/installer/targets/shared.js +13 -12
- package/lib/dist/installer/targets/shared.js.map +1 -1
- package/lib/dist/installer/targets/types.d.ts +7 -0
- package/lib/dist/installer/targets/types.d.ts.map +1 -1
- package/lib/dist/mcp/engine.d.ts.map +1 -1
- package/lib/dist/mcp/engine.js +8 -0
- package/lib/dist/mcp/engine.js.map +1 -1
- package/lib/dist/mcp/server-instructions.d.ts +18 -14
- package/lib/dist/mcp/server-instructions.d.ts.map +1 -1
- package/lib/dist/mcp/server-instructions.js +57 -52
- package/lib/dist/mcp/server-instructions.js.map +1 -1
- package/lib/dist/mcp/session.d.ts.map +1 -1
- package/lib/dist/mcp/session.js +23 -18
- package/lib/dist/mcp/session.js.map +1 -1
- package/lib/dist/mcp/tools.d.ts +51 -1
- package/lib/dist/mcp/tools.d.ts.map +1 -1
- package/lib/dist/mcp/tools.js +585 -151
- package/lib/dist/mcp/tools.js.map +1 -1
- package/lib/dist/project-config.d.ts +19 -0
- package/lib/dist/project-config.d.ts.map +1 -0
- package/lib/dist/project-config.js +180 -0
- package/lib/dist/project-config.js.map +1 -0
- package/lib/dist/reasoning/config.d.ts +45 -0
- package/lib/dist/reasoning/config.d.ts.map +1 -0
- package/lib/dist/reasoning/config.js +171 -0
- package/lib/dist/reasoning/config.js.map +1 -0
- package/lib/dist/reasoning/credentials.d.ts +5 -0
- package/lib/dist/reasoning/credentials.d.ts.map +1 -0
- package/lib/dist/reasoning/credentials.js +83 -0
- package/lib/dist/reasoning/credentials.js.map +1 -0
- package/lib/dist/reasoning/login.d.ts +21 -0
- package/lib/dist/reasoning/login.d.ts.map +1 -0
- package/lib/dist/reasoning/login.js +85 -0
- package/lib/dist/reasoning/login.js.map +1 -0
- package/lib/dist/reasoning/reasoner.d.ts +43 -0
- package/lib/dist/reasoning/reasoner.d.ts.map +1 -0
- package/lib/dist/reasoning/reasoner.js +308 -0
- package/lib/dist/reasoning/reasoner.js.map +1 -0
- package/lib/dist/resolution/c-fnptr-synthesizer.d.ts +33 -0
- package/lib/dist/resolution/c-fnptr-synthesizer.d.ts.map +1 -0
- package/lib/dist/resolution/c-fnptr-synthesizer.js +352 -0
- package/lib/dist/resolution/c-fnptr-synthesizer.js.map +1 -0
- package/lib/dist/resolution/callback-synthesizer.d.ts +6 -1
- package/lib/dist/resolution/callback-synthesizer.d.ts.map +1 -1
- package/lib/dist/resolution/callback-synthesizer.js +1109 -1
- package/lib/dist/resolution/callback-synthesizer.js.map +1 -1
- package/lib/dist/resolution/frameworks/goframe.d.ts +41 -0
- package/lib/dist/resolution/frameworks/goframe.d.ts.map +1 -0
- package/lib/dist/resolution/frameworks/goframe.js +112 -0
- package/lib/dist/resolution/frameworks/goframe.js.map +1 -0
- package/lib/dist/resolution/frameworks/index.d.ts +1 -0
- package/lib/dist/resolution/frameworks/index.d.ts.map +1 -1
- package/lib/dist/resolution/frameworks/index.js +5 -1
- package/lib/dist/resolution/frameworks/index.js.map +1 -1
- package/lib/dist/resolution/frameworks/react.d.ts.map +1 -1
- package/lib/dist/resolution/frameworks/react.js +17 -60
- package/lib/dist/resolution/frameworks/react.js.map +1 -1
- package/lib/dist/resolution/goframe-synthesizer.d.ts +28 -0
- package/lib/dist/resolution/goframe-synthesizer.d.ts.map +1 -0
- package/lib/dist/resolution/goframe-synthesizer.js +158 -0
- package/lib/dist/resolution/goframe-synthesizer.js.map +1 -0
- package/lib/dist/resolution/name-matcher.d.ts.map +1 -1
- package/lib/dist/resolution/name-matcher.js +48 -8
- package/lib/dist/resolution/name-matcher.js.map +1 -1
- package/lib/dist/resolution/strip-comments.d.ts +1 -1
- package/lib/dist/resolution/strip-comments.d.ts.map +1 -1
- package/lib/dist/resolution/strip-comments.js +2 -0
- package/lib/dist/resolution/strip-comments.js.map +1 -1
- package/lib/dist/sync/watcher.d.ts +68 -1
- package/lib/dist/sync/watcher.d.ts.map +1 -1
- package/lib/dist/sync/watcher.js +212 -14
- package/lib/dist/sync/watcher.js.map +1 -1
- package/lib/dist/telemetry/index.d.ts +0 -3
- package/lib/dist/telemetry/index.d.ts.map +1 -1
- package/lib/dist/telemetry/index.js +4 -7
- package/lib/dist/telemetry/index.js.map +1 -1
- package/lib/dist/upgrade/index.d.ts.map +1 -1
- package/lib/dist/upgrade/index.js +40 -4
- package/lib/dist/upgrade/index.js.map +1 -1
- package/lib/dist/utils.d.ts +14 -1
- package/lib/dist/utils.d.ts.map +1 -1
- package/lib/dist/utils.js +20 -2
- package/lib/dist/utils.js.map +1 -1
- package/lib/node_modules/.package-lock.json +1 -1
- package/lib/package.json +2 -2
- package/package.json +1 -1
|
@@ -167,8 +167,12 @@ exports.EXTENSION_MAP = {
|
|
|
167
167
|
* Whether a file is one CodeGraph can parse, based purely on its extension.
|
|
168
168
|
* This is the single source of truth for "should we index this file" — derived
|
|
169
169
|
* from EXTENSION_MAP so parser support and indexing selection never drift.
|
|
170
|
+
*
|
|
171
|
+
* `overrides` is the project's validated custom extension → language map (from
|
|
172
|
+
* `codegraph.json`); when present its extensions count as indexable in addition
|
|
173
|
+
* to the built-ins. Omitting it is byte-identical to the zero-config behavior.
|
|
170
174
|
*/
|
|
171
|
-
function isSourceFile(filePath) {
|
|
175
|
+
function isSourceFile(filePath, overrides) {
|
|
172
176
|
if (isPlayRoutesFile(filePath))
|
|
173
177
|
return true; // Play `conf/routes` is extensionless
|
|
174
178
|
if (isShopifyLiquidJson(filePath))
|
|
@@ -176,7 +180,8 @@ function isSourceFile(filePath) {
|
|
|
176
180
|
const dot = filePath.lastIndexOf('.');
|
|
177
181
|
if (dot < 0)
|
|
178
182
|
return false;
|
|
179
|
-
|
|
183
|
+
const ext = filePath.slice(dot).toLowerCase();
|
|
184
|
+
return ext in exports.EXTENSION_MAP || (!!overrides && ext in overrides);
|
|
180
185
|
}
|
|
181
186
|
/**
|
|
182
187
|
* Shopify OS 2.0 JSON template (`templates/*.json`) or section group
|
|
@@ -295,9 +300,13 @@ function getParser(language) {
|
|
|
295
300
|
return parser;
|
|
296
301
|
}
|
|
297
302
|
/**
|
|
298
|
-
* Detect language from file extension
|
|
303
|
+
* Detect language from file extension.
|
|
304
|
+
*
|
|
305
|
+
* `overrides` is the project's validated custom extension → language map (from
|
|
306
|
+
* `codegraph.json`); when present its mappings take precedence over the built-in
|
|
307
|
+
* `EXTENSION_MAP`. Omitting it is byte-identical to the zero-config behavior.
|
|
299
308
|
*/
|
|
300
|
-
function detectLanguage(filePath, source) {
|
|
309
|
+
function detectLanguage(filePath, source, overrides) {
|
|
301
310
|
// Play `conf/routes` has no grammar — route through the no-symbol path; the
|
|
302
311
|
// Play framework resolver extracts route nodes from it.
|
|
303
312
|
if (isPlayRoutesFile(filePath))
|
|
@@ -307,7 +316,7 @@ function detectLanguage(filePath, source) {
|
|
|
307
316
|
// links each section `"type"` to its `sections/<type>.liquid`).
|
|
308
317
|
if (isShopifyLiquidJson(filePath))
|
|
309
318
|
return 'liquid';
|
|
310
|
-
const lang = exports.EXTENSION_MAP[ext] || 'unknown';
|
|
319
|
+
const lang = (overrides && overrides[ext]) || exports.EXTENSION_MAP[ext] || 'unknown';
|
|
311
320
|
// .h files could be C, C++, or Objective-C — check source content
|
|
312
321
|
if (lang === 'c' && ext === '.h' && source) {
|
|
313
322
|
if (looksLikeCpp(source))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grammars.js","sourceRoot":"","sources":["../../src/extraction/grammars.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"grammars.js","sourceRoot":"","sources":["../../src/extraction/grammars.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/extraction/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAKzB,OAAO,EAGL,gBAAgB,EAChB,eAAe,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/extraction/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -55,6 +55,7 @@ const crypto = __importStar(require("crypto"));
|
|
|
55
55
|
const child_process_1 = require("child_process");
|
|
56
56
|
const tree_sitter_1 = require("./tree-sitter");
|
|
57
57
|
const grammars_1 = require("./grammars");
|
|
58
|
+
const project_config_1 = require("../project-config");
|
|
58
59
|
const directory_1 = require("../directory");
|
|
59
60
|
const errors_1 = require("../errors");
|
|
60
61
|
const utils_1 = require("../utils");
|
|
@@ -65,6 +66,17 @@ const frameworks_1 = require("../resolution/frameworks");
|
|
|
65
66
|
* File reads are I/O-bound; batching overlaps I/O wait with CPU parse work.
|
|
66
67
|
*/
|
|
67
68
|
const FILE_IO_BATCH_SIZE = 10;
|
|
69
|
+
/**
|
|
70
|
+
* How many files the `sync()` reconcile processes between cooperative yields to
|
|
71
|
+
* the event loop. The reconcile runs two O(files) loops of synchronous `fs`
|
|
72
|
+
* calls (existsSync for removals, statSync for adds/mods); on a very large repo
|
|
73
|
+
* (~100k files) an un-yielded run wedges the main thread for minutes, which both
|
|
74
|
+
* trips the liveness watchdog (it SIGKILLs a process whose loop stops turning)
|
|
75
|
+
* and blocks the first MCP tool call behind the catch-up gate (issue #905).
|
|
76
|
+
* Yielding every N files keeps the socket, the watchdog heartbeat, and any
|
|
77
|
+
* concurrent read query responsive while the reconcile runs.
|
|
78
|
+
*/
|
|
79
|
+
const SYNC_RECONCILE_YIELD_INTERVAL = 1000;
|
|
68
80
|
// PARSER_RESET_INTERVAL moved to parse-worker.ts (runs in worker thread)
|
|
69
81
|
/**
|
|
70
82
|
* Maximum time (ms) to wait for a single file to parse in the worker thread.
|
|
@@ -240,6 +252,20 @@ function buildDefaultIgnore(rootDir) {
|
|
|
240
252
|
function defaultsOnlyIgnore() {
|
|
241
253
|
return (0, ignore_1.default)().add(DEFAULT_IGNORE_PATTERNS);
|
|
242
254
|
}
|
|
255
|
+
/**
|
|
256
|
+
* `git ls-files --directory` collapses a wholly-untracked/ignored directory into
|
|
257
|
+
* one entry — and when the command's own cwd is such a directory (the indexed
|
|
258
|
+
* root is itself a git-ignored subdir of an enclosing repo), git emits the
|
|
259
|
+
* literal `./` meaning "this entire directory". That sentinel is not a real
|
|
260
|
+
* nested path: feeding it to the `ignore` matcher throws ("path should be a
|
|
261
|
+
* `path.relative()`d string, but got "./""), which used to abort `buildScopeIgnore`
|
|
262
|
+
* and so break the MCP daemon's watcher/auto-sync on connect; and joining it back
|
|
263
|
+
* onto `repoDir` would just re-point at the cwd. Drop it wherever we consume
|
|
264
|
+
* `--directory` output. (#936)
|
|
265
|
+
*/
|
|
266
|
+
function isWholeCwdEntry(entry) {
|
|
267
|
+
return entry === './' || entry === '.' || entry === '';
|
|
268
|
+
}
|
|
243
269
|
/**
|
|
244
270
|
* List the gitignored DIRECTORIES of a repo (collapsed, trailing-slash form),
|
|
245
271
|
* relative to `repoDir`. These are invisible to every other `git ls-files` /
|
|
@@ -250,7 +276,7 @@ function defaultsOnlyIgnore() {
|
|
|
250
276
|
function listIgnoredDirs(repoDir) {
|
|
251
277
|
try {
|
|
252
278
|
const out = (0, child_process_1.execFileSync)('git', ['ls-files', '-z', '-o', '-i', '--exclude-standard', '--directory'], { cwd: repoDir, encoding: 'utf-8', timeout: 30000, maxBuffer: 50 * 1024 * 1024, stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true });
|
|
253
|
-
return out.split('\0').filter((e) => e.endsWith('/'));
|
|
279
|
+
return out.split('\0').filter((e) => e.endsWith('/') && !isWholeCwdEntry(e));
|
|
254
280
|
}
|
|
255
281
|
catch {
|
|
256
282
|
return [];
|
|
@@ -268,8 +294,10 @@ const EMBEDDED_REPO_SEARCH_ENTRIES = 2000;
|
|
|
268
294
|
* - A `.git` **file** is a pointer (`gitdir: …`). A git **worktree** points into
|
|
269
295
|
* the host repo's own `.git/worktrees/<name>`, so it is a second working view
|
|
270
296
|
* of a repo CodeGraph already indexes — indexing it just duplicates the whole
|
|
271
|
-
* graph N times; skip it (#848). A **submodule** points into
|
|
272
|
-
*
|
|
297
|
+
* graph N times; skip it (#848). A **submodule worktree** points into
|
|
298
|
+
* `.git/modules/<module>/worktrees/<name>` — same duplication, so skip it too
|
|
299
|
+
* (#945). A **submodule** checkout points into `.git/modules/<module>` (no
|
|
300
|
+
* `worktrees/` segment) and is distinct code, so index it as before.
|
|
273
301
|
*
|
|
274
302
|
* Returns `'none'` when there is no `.git` entry here.
|
|
275
303
|
*/
|
|
@@ -287,9 +315,12 @@ function classifyGitDir(absDir) {
|
|
|
287
315
|
return 'none';
|
|
288
316
|
try {
|
|
289
317
|
const gitdir = fs.readFileSync(path.join(absDir, '.git'), 'utf8').match(/^gitdir:\s*(.+)$/m)?.[1]?.trim();
|
|
290
|
-
// A
|
|
318
|
+
// A worktree's gitdir lives under some repo's `.git/worktrees/<name>` —
|
|
319
|
+
// either the top-level repo's (`.git/worktrees/`) or, for a worktree of a
|
|
320
|
+
// submodule, that submodule's gitdir (`.git/modules/<module>/worktrees/`).
|
|
321
|
+
// The optional `modules/<module>` segment covers the submodule case (#945).
|
|
291
322
|
// Match both separators so a Windows-style pointer is recognized too.
|
|
292
|
-
if (gitdir && /(^|[\\/])\.git[\\/]worktrees[\\/]/.test(gitdir))
|
|
323
|
+
if (gitdir && /(^|[\\/])\.git[\\/](modules[\\/][^\\/]+[\\/])?worktrees[\\/]/.test(gitdir))
|
|
293
324
|
return 'worktree';
|
|
294
325
|
}
|
|
295
326
|
catch {
|
|
@@ -416,7 +447,7 @@ function discoverEmbeddedRepoRoots(rootDir) {
|
|
|
416
447
|
try {
|
|
417
448
|
const o = (0, child_process_1.execFileSync)('git', ['ls-files', '-z', '-o', '--exclude-standard', '--directory'], { cwd: repoAbs, encoding: 'utf-8', timeout: 30000, maxBuffer: 50 * 1024 * 1024, stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true });
|
|
418
449
|
for (const e of o.split('\0')) {
|
|
419
|
-
if (e.endsWith('/') && !defaults.ignores(e)) {
|
|
450
|
+
if (e.endsWith('/') && !isWholeCwdEntry(e) && !defaults.ignores(e)) {
|
|
420
451
|
candidates.push(...findNestedGitRepos(path.join(repoAbs, e), e));
|
|
421
452
|
}
|
|
422
453
|
}
|
|
@@ -565,15 +596,29 @@ function getGitVisibleFiles(rootDir) {
|
|
|
565
596
|
function getGitChangedFiles(rootDir) {
|
|
566
597
|
try {
|
|
567
598
|
const changes = { modified: [], added: [], deleted: [] };
|
|
568
|
-
|
|
599
|
+
// Custom extension → language overrides from the project's codegraph.json,
|
|
600
|
+
// so change detection sees the same custom-extension files the full index does.
|
|
601
|
+
const overrides = (0, project_config_1.loadExtensionOverrides)(rootDir);
|
|
602
|
+
collectGitStatus(rootDir, '', changes, overrides);
|
|
569
603
|
return changes;
|
|
570
604
|
}
|
|
571
605
|
catch {
|
|
572
606
|
return null;
|
|
573
607
|
}
|
|
574
608
|
}
|
|
575
|
-
function collectGitStatus(repoDir, prefix, out) {
|
|
609
|
+
function collectGitStatus(repoDir, prefix, out, overrides) {
|
|
576
610
|
const output = (0, child_process_1.execFileSync)('git', ['status', '--porcelain', '--no-renames'], { cwd: repoDir, encoding: 'utf-8', timeout: 10000, maxBuffer: 50 * 1024 * 1024, stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true });
|
|
611
|
+
// This repo's own ignore rules — built-in defaults (#407) plus its .gitignore.
|
|
612
|
+
// Change detection must exclude the SAME files the full index does, but git
|
|
613
|
+
// status hides neither: it ignores nothing for *tracked* paths, and the
|
|
614
|
+
// built-in defaults aren't gitignore at all. Without this filter a committed
|
|
615
|
+
// vendor/ dir, or a tracked file under a .gitignored dir, surfaces here as a
|
|
616
|
+
// change — so `codegraph status` (which reads getChangedFiles) reports a
|
|
617
|
+
// pending edit the full index never tracks and `sync` never clears. Matching
|
|
618
|
+
// repo-relative `rel` at each recursion level mirrors getGitVisibleFiles'
|
|
619
|
+
// ScopeIgnore: every embedded repo is judged by ITS OWN rules, never the
|
|
620
|
+
// parent's. (#766)
|
|
621
|
+
const ig = buildDefaultIgnore(repoDir);
|
|
577
622
|
const untrackedDirs = [];
|
|
578
623
|
for (const line of output.split('\n')) {
|
|
579
624
|
if (line.length < 4)
|
|
@@ -587,15 +632,22 @@ function collectGitStatus(repoDir, prefix, out) {
|
|
|
587
632
|
continue;
|
|
588
633
|
}
|
|
589
634
|
const filePath = (0, utils_1.normalizePath)(prefix + rel);
|
|
590
|
-
|
|
591
|
-
|
|
635
|
+
if (!(0, grammars_1.isSourceFile)(filePath, overrides))
|
|
636
|
+
continue;
|
|
637
|
+
if (statusCode.includes('D')) {
|
|
638
|
+
// Deletions stay unfiltered: getChangedFiles acts on one only when the
|
|
639
|
+
// path is already tracked in the DB, where removal is always correct — and
|
|
640
|
+
// that lets a newly-excluded dir's stale rows clean themselves up. (#766)
|
|
641
|
+
out.deleted.push(filePath);
|
|
642
|
+
continue;
|
|
643
|
+
}
|
|
644
|
+
// Added (`??`) / modified files inside an excluded dir must not enter the
|
|
645
|
+
// index — match against the repo-relative path, same as the full scan. (#766)
|
|
646
|
+
if (ig.ignores(rel))
|
|
592
647
|
continue;
|
|
593
648
|
if (statusCode === '??') {
|
|
594
649
|
out.added.push(filePath);
|
|
595
650
|
}
|
|
596
|
-
else if (statusCode.includes('D')) {
|
|
597
|
-
out.deleted.push(filePath);
|
|
598
|
-
}
|
|
599
651
|
else {
|
|
600
652
|
// M, MM, AM, A (staged), etc. — treat as modified
|
|
601
653
|
out.modified.push(filePath);
|
|
@@ -605,11 +657,11 @@ function collectGitStatus(repoDir, prefix, out) {
|
|
|
605
657
|
// nested deeper) and under this repo's gitignored dirs.
|
|
606
658
|
for (const rel of untrackedDirs) {
|
|
607
659
|
for (const repoRel of findNestedGitRepos(path.join(repoDir, rel), rel)) {
|
|
608
|
-
collectGitStatus(path.join(repoDir, repoRel), prefix + repoRel, out);
|
|
660
|
+
collectGitStatus(path.join(repoDir, repoRel), prefix + repoRel, out, overrides);
|
|
609
661
|
}
|
|
610
662
|
}
|
|
611
663
|
for (const rel of findIgnoredEmbeddedRepos(repoDir)) {
|
|
612
|
-
collectGitStatus(path.join(repoDir, rel), prefix + rel, out);
|
|
664
|
+
collectGitStatus(path.join(repoDir, rel), prefix + rel, out, overrides);
|
|
613
665
|
}
|
|
614
666
|
}
|
|
615
667
|
/**
|
|
@@ -620,13 +672,15 @@ function collectGitStatus(repoDir, prefix, out) {
|
|
|
620
672
|
* projects, falls back to a filesystem walk that parses .gitignore itself.
|
|
621
673
|
*/
|
|
622
674
|
function scanDirectory(rootDir, onProgress) {
|
|
675
|
+
// Custom extension → language overrides from the project's codegraph.json.
|
|
676
|
+
const overrides = (0, project_config_1.loadExtensionOverrides)(rootDir);
|
|
623
677
|
// Fast path: use git to get all visible files (respects .gitignore everywhere)
|
|
624
678
|
const gitFiles = getGitVisibleFiles(rootDir);
|
|
625
679
|
if (gitFiles) {
|
|
626
680
|
const files = [];
|
|
627
681
|
let count = 0;
|
|
628
682
|
for (const filePath of gitFiles) {
|
|
629
|
-
if ((0, grammars_1.isSourceFile)(filePath)) {
|
|
683
|
+
if ((0, grammars_1.isSourceFile)(filePath, overrides)) {
|
|
630
684
|
files.push(filePath);
|
|
631
685
|
count++;
|
|
632
686
|
onProgress?.(count, filePath);
|
|
@@ -642,12 +696,14 @@ function scanDirectory(rootDir, onProgress) {
|
|
|
642
696
|
* allowing worker threads to receive and render progress messages.
|
|
643
697
|
*/
|
|
644
698
|
async function scanDirectoryAsync(rootDir, onProgress) {
|
|
699
|
+
// Custom extension → language overrides from the project's codegraph.json.
|
|
700
|
+
const overrides = (0, project_config_1.loadExtensionOverrides)(rootDir);
|
|
645
701
|
const gitFiles = getGitVisibleFiles(rootDir);
|
|
646
702
|
if (gitFiles) {
|
|
647
703
|
const files = [];
|
|
648
704
|
let count = 0;
|
|
649
705
|
for (const filePath of gitFiles) {
|
|
650
|
-
if ((0, grammars_1.isSourceFile)(filePath)) {
|
|
706
|
+
if ((0, grammars_1.isSourceFile)(filePath, overrides)) {
|
|
651
707
|
files.push(filePath);
|
|
652
708
|
count++;
|
|
653
709
|
onProgress?.(count, filePath);
|
|
@@ -668,6 +724,8 @@ function scanDirectoryWalk(rootDir, onProgress) {
|
|
|
668
724
|
const files = [];
|
|
669
725
|
let count = 0;
|
|
670
726
|
const visitedDirs = new Set();
|
|
727
|
+
// Custom extension → language overrides from the project's codegraph.json.
|
|
728
|
+
const overrides = (0, project_config_1.loadExtensionOverrides)(rootDir);
|
|
671
729
|
const loadIgnore = (dir) => {
|
|
672
730
|
const giPath = path.join(dir, '.gitignore');
|
|
673
731
|
if (!fs.existsSync(giPath))
|
|
@@ -734,7 +792,7 @@ function scanDirectoryWalk(rootDir, onProgress) {
|
|
|
734
792
|
}
|
|
735
793
|
}
|
|
736
794
|
else if (stat.isFile()) {
|
|
737
|
-
if (!isIgnored(fullPath, false, active) && (0, grammars_1.isSourceFile)(relativePath)) {
|
|
795
|
+
if (!isIgnored(fullPath, false, active) && (0, grammars_1.isSourceFile)(relativePath, overrides)) {
|
|
738
796
|
files.push(relativePath);
|
|
739
797
|
count++;
|
|
740
798
|
onProgress?.(count, relativePath);
|
|
@@ -752,7 +810,7 @@ function scanDirectoryWalk(rootDir, onProgress) {
|
|
|
752
810
|
}
|
|
753
811
|
}
|
|
754
812
|
else if (entry.isFile()) {
|
|
755
|
-
if (!isIgnored(fullPath, false, active) && (0, grammars_1.isSourceFile)(relativePath)) {
|
|
813
|
+
if (!isIgnored(fullPath, false, active) && (0, grammars_1.isSourceFile)(relativePath, overrides)) {
|
|
756
814
|
files.push(relativePath);
|
|
757
815
|
count++;
|
|
758
816
|
onProgress?.(count, relativePath);
|
|
@@ -866,6 +924,10 @@ class ExtractionOrchestrator {
|
|
|
866
924
|
let filesErrored = 0;
|
|
867
925
|
let totalNodes = 0;
|
|
868
926
|
let totalEdges = 0;
|
|
927
|
+
// Custom extension → language overrides from the project's codegraph.json.
|
|
928
|
+
// Threaded into language detection so custom-extension files load the right
|
|
929
|
+
// grammar and store under the mapped language.
|
|
930
|
+
const overrides = (0, project_config_1.loadExtensionOverrides)(this.rootDir);
|
|
869
931
|
const log = verbose
|
|
870
932
|
? (msg) => { console.log(`[worker] ${msg}`); }
|
|
871
933
|
: (_msg) => { };
|
|
@@ -915,7 +977,7 @@ class ExtractionOrchestrator {
|
|
|
915
977
|
});
|
|
916
978
|
await new Promise(resolve => setImmediate(resolve));
|
|
917
979
|
// Detect needed languages and load grammars in the parse worker
|
|
918
|
-
const neededLanguages = [...new Set(files.map((f) => (0, grammars_1.detectLanguage)(f)))];
|
|
980
|
+
const neededLanguages = [...new Set(files.map((f) => (0, grammars_1.detectLanguage)(f, undefined, overrides)))];
|
|
919
981
|
// .h files default to 'c' but may be C++ — ensure cpp grammar is loaded when c is needed
|
|
920
982
|
if (neededLanguages.includes('c') && !neededLanguages.includes('cpp')) {
|
|
921
983
|
neededLanguages.push('cpp');
|
|
@@ -1014,9 +1076,13 @@ class ExtractionOrchestrator {
|
|
|
1014
1076
|
w.terminate().catch(() => { });
|
|
1015
1077
|
}
|
|
1016
1078
|
async function requestParse(filePath, content) {
|
|
1079
|
+
// Resolve the language on the main thread (where the project's
|
|
1080
|
+
// codegraph.json overrides are loaded) and hand it to the worker, so the
|
|
1081
|
+
// worker never needs the override map itself.
|
|
1082
|
+
const language = (0, grammars_1.detectLanguage)(filePath, content, overrides);
|
|
1017
1083
|
if (!WorkerClass) {
|
|
1018
1084
|
// In-process fallback
|
|
1019
|
-
return (0, tree_sitter_1.extractFromSource)(filePath, content,
|
|
1085
|
+
return (0, tree_sitter_1.extractFromSource)(filePath, content, language, frameworkNames);
|
|
1020
1086
|
}
|
|
1021
1087
|
// Recycle the worker before the next parse if we've hit the threshold.
|
|
1022
1088
|
// This destroys the WASM linear memory (which can grow but never shrink)
|
|
@@ -1041,7 +1107,7 @@ class ExtractionOrchestrator {
|
|
|
1041
1107
|
worker.terminate().catch(() => { });
|
|
1042
1108
|
}, timeoutMs);
|
|
1043
1109
|
pendingParses.set(id, { resolve, reject, timer });
|
|
1044
|
-
worker.postMessage({ type: 'parse', id, filePath, content, frameworkNames });
|
|
1110
|
+
worker.postMessage({ type: 'parse', id, filePath, content, frameworkNames, language });
|
|
1045
1111
|
});
|
|
1046
1112
|
}
|
|
1047
1113
|
for (let i = 0; i < files.length; i += FILE_IO_BATCH_SIZE) {
|
|
@@ -1063,7 +1129,10 @@ class ExtractionOrchestrator {
|
|
|
1063
1129
|
// Read files in parallel (with path validation before any I/O)
|
|
1064
1130
|
const fileContents = await Promise.all(batch.map(async (fp) => {
|
|
1065
1131
|
try {
|
|
1066
|
-
|
|
1132
|
+
// Indexing read: follow in-root symlinks the directory walk already
|
|
1133
|
+
// descended into (the `../` guard still applies) so files reached
|
|
1134
|
+
// via an in-root symlink-to-outside still index (#935).
|
|
1135
|
+
const fullPath = (0, utils_1.validatePathWithinRoot)(this.rootDir, fp, { allowSymlinkEscape: true });
|
|
1067
1136
|
if (!fullPath) {
|
|
1068
1137
|
(0, errors_1.logWarn)('Path traversal blocked in batch reader', { filePath: fp });
|
|
1069
1138
|
return { filePath: fp, content: null, stats: null, error: new Error('Path traversal blocked') };
|
|
@@ -1147,7 +1216,7 @@ class ExtractionOrchestrator {
|
|
|
1147
1216
|
processed++;
|
|
1148
1217
|
// Store in database on main thread (SQLite is not thread-safe)
|
|
1149
1218
|
if (result.nodes.length > 0 || result.errors.length === 0) {
|
|
1150
|
-
const language = (0, grammars_1.detectLanguage)(filePath, content);
|
|
1219
|
+
const language = (0, grammars_1.detectLanguage)(filePath, content, overrides);
|
|
1151
1220
|
this.storeExtractionResult(filePath, content, language, stats, result);
|
|
1152
1221
|
}
|
|
1153
1222
|
if (result.errors.length > 0) {
|
|
@@ -1169,7 +1238,7 @@ class ExtractionOrchestrator {
|
|
|
1169
1238
|
// Files with no symbols but no errors (yaml, twig, properties) are
|
|
1170
1239
|
// tracked at the file level — count them as indexed so the CLI
|
|
1171
1240
|
// doesn't misleadingly report "No files found to index".
|
|
1172
|
-
const lang = (0, grammars_1.detectLanguage)(filePath, content);
|
|
1241
|
+
const lang = (0, grammars_1.detectLanguage)(filePath, content, overrides);
|
|
1173
1242
|
if ((0, grammars_1.isFileLevelOnlyLanguage)(lang)) {
|
|
1174
1243
|
filesIndexed++;
|
|
1175
1244
|
}
|
|
@@ -1222,7 +1291,7 @@ class ExtractionOrchestrator {
|
|
|
1222
1291
|
continue;
|
|
1223
1292
|
}
|
|
1224
1293
|
if (result.nodes.length > 0 || result.errors.length === 0) {
|
|
1225
|
-
const language = (0, grammars_1.detectLanguage)(filePath, content);
|
|
1294
|
+
const language = (0, grammars_1.detectLanguage)(filePath, content, overrides);
|
|
1226
1295
|
const stats = await fsp.stat(path.join(this.rootDir, filePath));
|
|
1227
1296
|
this.storeExtractionResult(filePath, content, language, stats, result);
|
|
1228
1297
|
const idx = errors.indexOf(errEntry);
|
|
@@ -1270,7 +1339,7 @@ class ExtractionOrchestrator {
|
|
|
1270
1339
|
continue;
|
|
1271
1340
|
}
|
|
1272
1341
|
if (result.nodes.length > 0 || result.errors.length === 0) {
|
|
1273
|
-
const language = (0, grammars_1.detectLanguage)(filePath, fullContent);
|
|
1342
|
+
const language = (0, grammars_1.detectLanguage)(filePath, fullContent, overrides);
|
|
1274
1343
|
const stats = await fsp.stat(path.join(this.rootDir, filePath));
|
|
1275
1344
|
this.storeExtractionResult(filePath, fullContent, language, stats, result);
|
|
1276
1345
|
const idx = errors.indexOf(errEntry);
|
|
@@ -1350,7 +1419,8 @@ class ExtractionOrchestrator {
|
|
|
1350
1419
|
* Index a single file
|
|
1351
1420
|
*/
|
|
1352
1421
|
async indexFile(relativePath) {
|
|
1353
|
-
|
|
1422
|
+
// Indexing read: follow in-root symlinks (the `../` guard still applies), #935.
|
|
1423
|
+
const fullPath = (0, utils_1.validatePathWithinRoot)(this.rootDir, relativePath, { allowSymlinkEscape: true });
|
|
1354
1424
|
if (!fullPath) {
|
|
1355
1425
|
return {
|
|
1356
1426
|
nodes: [],
|
|
@@ -1390,8 +1460,8 @@ class ExtractionOrchestrator {
|
|
|
1390
1460
|
* Used by the parallel batch reader to avoid redundant file I/O.
|
|
1391
1461
|
*/
|
|
1392
1462
|
async indexFileWithContent(relativePath, content, stats) {
|
|
1393
|
-
// Prevent
|
|
1394
|
-
const fullPath = (0, utils_1.validatePathWithinRoot)(this.rootDir, relativePath);
|
|
1463
|
+
// Prevent `../` traversal; follow in-root symlinks like the directory walk (#935).
|
|
1464
|
+
const fullPath = (0, utils_1.validatePathWithinRoot)(this.rootDir, relativePath, { allowSymlinkEscape: true });
|
|
1395
1465
|
if (!fullPath) {
|
|
1396
1466
|
(0, errors_1.logWarn)('Path traversal blocked in indexFileWithContent', { relativePath });
|
|
1397
1467
|
return {
|
|
@@ -1419,8 +1489,8 @@ class ExtractionOrchestrator {
|
|
|
1419
1489
|
durationMs: 0,
|
|
1420
1490
|
};
|
|
1421
1491
|
}
|
|
1422
|
-
// Detect language
|
|
1423
|
-
const language = (0, grammars_1.detectLanguage)(relativePath, content);
|
|
1492
|
+
// Detect language (honoring the project's codegraph.json extension overrides)
|
|
1493
|
+
const language = (0, grammars_1.detectLanguage)(relativePath, content, (0, project_config_1.loadExtensionOverrides)(this.rootDir));
|
|
1424
1494
|
if (!(0, grammars_1.isLanguageSupported)(language)) {
|
|
1425
1495
|
return {
|
|
1426
1496
|
nodes: [],
|
|
@@ -1451,6 +1521,25 @@ class ExtractionOrchestrator {
|
|
|
1451
1521
|
if (existingFile && existingFile.contentHash === contentHash) {
|
|
1452
1522
|
return; // No changes
|
|
1453
1523
|
}
|
|
1524
|
+
// Snapshot incoming cross-file edges BEFORE deleting this file's nodes.
|
|
1525
|
+
// `deleteFile` cascades to delete every edge whose source OR target is a
|
|
1526
|
+
// node in this file (edges.FK ... ON DELETE CASCADE). Edges whose SOURCE is
|
|
1527
|
+
// in this file are re-emitted by the extractor below, but edges whose SOURCE
|
|
1528
|
+
// is in a *different* (unchanged) file are not — they would be silently
|
|
1529
|
+
// dropped, which is issue #899: re-indexing a callee file severs `calls`/
|
|
1530
|
+
// `references` edges from callers that import it via module-attribute
|
|
1531
|
+
// access (`pkg.mod.fn(...)`).
|
|
1532
|
+
//
|
|
1533
|
+
// We snapshot the edge plus the target node's (name, kind) so we can
|
|
1534
|
+
// re-resolve to the re-indexed target's NEW id. Node ids are
|
|
1535
|
+
// `sha256(filePath:kind:name:line)`, so any line shift in the callee file
|
|
1536
|
+
// (e.g. a docstring-only edit above the symbol) changes every target id and
|
|
1537
|
+
// a naive re-insert by old id would silently drop every edge. Matching by
|
|
1538
|
+
// (filePath, kind, name) is stable across line shifts; if the symbol was
|
|
1539
|
+
// renamed/removed, no match is found and the edge stays dropped (correct).
|
|
1540
|
+
const crossFileIncomingEdges = existingFile
|
|
1541
|
+
? this.queries.getCrossFileIncomingEdgesWithTarget(filePath)
|
|
1542
|
+
: [];
|
|
1454
1543
|
// Delete existing data for this file
|
|
1455
1544
|
if (existingFile) {
|
|
1456
1545
|
this.queries.deleteFile(filePath);
|
|
@@ -1471,6 +1560,31 @@ class ExtractionOrchestrator {
|
|
|
1471
1560
|
this.queries.insertEdges(validEdges);
|
|
1472
1561
|
}
|
|
1473
1562
|
}
|
|
1563
|
+
// Re-insert cross-file incoming edges snapshotted before the delete,
|
|
1564
|
+
// re-resolving each edge's target to the re-indexed node's new id by
|
|
1565
|
+
// (filePath, kind, name). Node ids include the source line, so any line
|
|
1566
|
+
// shift in the callee file (e.g. a docstring-only edit above the symbol)
|
|
1567
|
+
// changes every target id and a naive re-insert by old id would drop them
|
|
1568
|
+
// all. `insertEdges` still filters to endpoints that exist, so edges whose
|
|
1569
|
+
// caller (source) was deleted, or whose callee (target) was renamed/removed
|
|
1570
|
+
// during the re-index (no match in `newTargetIds`), are dropped. This
|
|
1571
|
+
// closes the #899 edge-drop on `sync`.
|
|
1572
|
+
if (crossFileIncomingEdges.length > 0) {
|
|
1573
|
+
const newNodesByKindName = new Map();
|
|
1574
|
+
for (const n of validNodes) {
|
|
1575
|
+
newNodesByKindName.set(`${n.kind}\0${n.name}`, n.id);
|
|
1576
|
+
}
|
|
1577
|
+
const reinserted = [];
|
|
1578
|
+
for (const e of crossFileIncomingEdges) {
|
|
1579
|
+
const newTargetId = newNodesByKindName.get(`${e.targetKind}\0${e.targetName}`);
|
|
1580
|
+
if (newTargetId) {
|
|
1581
|
+
reinserted.push({ source: e.source, target: newTargetId, kind: e.kind, metadata: e.metadata, line: e.line, column: e.column, provenance: e.provenance });
|
|
1582
|
+
}
|
|
1583
|
+
}
|
|
1584
|
+
if (reinserted.length > 0) {
|
|
1585
|
+
this.queries.insertEdges(reinserted);
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1474
1588
|
// Insert unresolved references in batch with denormalized filePath/language
|
|
1475
1589
|
if (result.unresolvedReferences.length > 0) {
|
|
1476
1590
|
const insertedIds = new Set(validNodes.map((n) => n.id));
|
|
@@ -1530,7 +1644,7 @@ class ExtractionOrchestrator {
|
|
|
1530
1644
|
// whether or not the project uses git, and crucially also catches committed
|
|
1531
1645
|
// changes from `git pull`/`checkout`/`merge`/`rebase` — which `git status`
|
|
1532
1646
|
// cannot see, because the working tree is clean afterward.
|
|
1533
|
-
const currentFiles =
|
|
1647
|
+
const currentFiles = await scanDirectoryAsync(this.rootDir);
|
|
1534
1648
|
filesChecked = currentFiles.length;
|
|
1535
1649
|
const currentSet = new Set(currentFiles);
|
|
1536
1650
|
const trackedFiles = this.queries.getAllFiles();
|
|
@@ -1541,14 +1655,26 @@ class ExtractionOrchestrator {
|
|
|
1541
1655
|
// Removals: tracked in the DB but no longer a present source file. Check the
|
|
1542
1656
|
// filesystem directly — `scanDirectory` (via `git ls-files`) still lists a
|
|
1543
1657
|
// file deleted from disk but not yet staged, so set membership alone misses it.
|
|
1658
|
+
// `reconcileChecks` drives the cooperative yield shared with the adds/mods loop
|
|
1659
|
+
// below (see SYNC_RECONCILE_YIELD_INTERVAL / issue #905).
|
|
1660
|
+
let reconcileChecks = 0;
|
|
1544
1661
|
for (const tracked of trackedFiles) {
|
|
1545
1662
|
if (!currentSet.has(tracked.path) || !fs.existsSync(path.join(this.rootDir, tracked.path))) {
|
|
1546
1663
|
this.queries.deleteFile(tracked.path);
|
|
1547
1664
|
filesRemoved++;
|
|
1548
1665
|
}
|
|
1666
|
+
if (++reconcileChecks % SYNC_RECONCILE_YIELD_INTERVAL === 0) {
|
|
1667
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
1668
|
+
}
|
|
1549
1669
|
}
|
|
1550
1670
|
// Adds / modifications.
|
|
1551
1671
|
for (const filePath of currentFiles) {
|
|
1672
|
+
// Same cooperative yield as the removals loop — this is the other O(files)
|
|
1673
|
+
// synchronous-stat loop that wedges the main thread on a large repo (#905).
|
|
1674
|
+
// Yield at the top of the body so the `continue` fast-paths below still hit it.
|
|
1675
|
+
if (++reconcileChecks % SYNC_RECONCILE_YIELD_INTERVAL === 0) {
|
|
1676
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
1677
|
+
}
|
|
1552
1678
|
const fullPath = path.join(this.rootDir, filePath);
|
|
1553
1679
|
const tracked = trackedMap.get(filePath);
|
|
1554
1680
|
// Cheap pre-filter: an already-indexed file whose size AND mtime both match
|
|
@@ -1591,7 +1717,8 @@ class ExtractionOrchestrator {
|
|
|
1591
1717
|
}
|
|
1592
1718
|
// Load only grammars needed for changed files
|
|
1593
1719
|
if (filesToIndex.length > 0) {
|
|
1594
|
-
const
|
|
1720
|
+
const overrides = (0, project_config_1.loadExtensionOverrides)(this.rootDir);
|
|
1721
|
+
const neededLanguages = [...new Set(filesToIndex.map((f) => (0, grammars_1.detectLanguage)(f, undefined, overrides)))];
|
|
1595
1722
|
// .h files default to 'c' but may be C++ — ensure cpp grammar is loaded
|
|
1596
1723
|
if (neededLanguages.includes('c') && !neededLanguages.includes('cpp')) {
|
|
1597
1724
|
neededLanguages.push('cpp');
|