@wrongstack/tools 0.296.2 → 0.296.3
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/dist/browser/artifacts.d.ts +2 -0
- package/dist/browser/artifacts.d.ts.map +1 -1
- package/dist/browser/index.js +41 -0
- package/dist/browser/index.js.map +2 -2
- package/dist/builtin.js +557 -204
- package/dist/builtin.js.map +4 -4
- package/dist/codebase-index/dead-code-scan.d.ts +2 -2
- package/dist/codebase-index/dead-code-scan.d.ts.map +1 -1
- package/dist/codebase-index/index.js +468 -219
- package/dist/codebase-index/index.js.map +3 -3
- package/dist/codebase-index/project-server.js +222 -147
- package/dist/codebase-index/project-server.js.map +4 -4
- package/dist/codebase-index/ts-parser.d.ts.map +1 -1
- package/dist/codebase-index/worker.js +214 -145
- package/dist/codebase-index/worker.js.map +3 -3
- package/dist/codebase-index/writer.d.ts +19 -1
- package/dist/codebase-index/writer.d.ts.map +1 -1
- package/dist/index.js +559 -206
- package/dist/index.js.map +4 -4
- package/dist/pack.js +557 -204
- package/dist/pack.js.map +4 -4
- package/dist/read.d.ts +31 -0
- package/dist/read.d.ts.map +1 -1
- package/dist/read.js +5434 -78
- package/dist/read.js.map +4 -4
- package/dist/tool-tier.js +557 -204
- package/dist/tool-tier.js.map +4 -4
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -5137,11 +5137,18 @@ async function parseSymbols(opts) {
|
|
|
5137
5137
|
} else if (ts.isHeritageClause(node)) {
|
|
5138
5138
|
for (const t of node.types) {
|
|
5139
5139
|
const name = getTypeName(t.expression);
|
|
5140
|
-
if (name)
|
|
5140
|
+
if (name)
|
|
5141
|
+
refs.push({
|
|
5142
|
+
fromId: 0,
|
|
5143
|
+
toName: name,
|
|
5144
|
+
callType: node.token === ts.SyntaxKind.ExtendsKeyword ? "inherit" : "implement",
|
|
5145
|
+
line: lineNum
|
|
5146
|
+
});
|
|
5141
5147
|
}
|
|
5142
5148
|
} else if (ts.isImportDeclaration(node)) {
|
|
5143
|
-
|
|
5144
|
-
|
|
5149
|
+
emitImportSpecifierRefs(node, refs, lineNum);
|
|
5150
|
+
} else if (ts.isExportDeclaration(node) && node.moduleSpecifier) {
|
|
5151
|
+
emitExportSpecifierRefs(node, refs, lineNum);
|
|
5145
5152
|
}
|
|
5146
5153
|
const scopeIdx = scopeParts.length;
|
|
5147
5154
|
pushScopeName(node, scopeParts);
|
|
@@ -5157,11 +5164,6 @@ function getTypeName(name) {
|
|
|
5157
5164
|
if (ts.isQualifiedName(name)) return `${getTypeName(name.left)}.${name.right.text}`;
|
|
5158
5165
|
return "";
|
|
5159
5166
|
}
|
|
5160
|
-
function getModuleName(node) {
|
|
5161
|
-
const moduleSpecifier = node.moduleSpecifier;
|
|
5162
|
-
if (ts.isStringLiteral(moduleSpecifier)) return moduleSpecifier.text;
|
|
5163
|
-
return "";
|
|
5164
|
-
}
|
|
5165
5167
|
function deduplicateRefs(refs) {
|
|
5166
5168
|
const seen = /* @__PURE__ */ new Set();
|
|
5167
5169
|
return refs.filter((r) => {
|
|
@@ -5171,6 +5173,44 @@ function deduplicateRefs(refs) {
|
|
|
5171
5173
|
return true;
|
|
5172
5174
|
});
|
|
5173
5175
|
}
|
|
5176
|
+
function getImportSpecifierName(spec) {
|
|
5177
|
+
return spec.propertyName?.text ?? spec.name.text;
|
|
5178
|
+
}
|
|
5179
|
+
function emitImportSpecifierRefs(node, refs, lineNum) {
|
|
5180
|
+
const clause = node.importClause;
|
|
5181
|
+
if (!clause) return;
|
|
5182
|
+
if (clause.name) {
|
|
5183
|
+
refs.push({ fromId: 0, toName: clause.name.text, callType: "import", line: lineNum });
|
|
5184
|
+
}
|
|
5185
|
+
const bindings2 = clause.namedBindings;
|
|
5186
|
+
if (!bindings2) return;
|
|
5187
|
+
if (ts.isNamedImports(bindings2)) {
|
|
5188
|
+
for (const element of bindings2.elements) {
|
|
5189
|
+
refs.push({
|
|
5190
|
+
fromId: 0,
|
|
5191
|
+
toName: getImportSpecifierName(element),
|
|
5192
|
+
callType: "import",
|
|
5193
|
+
line: lineNum
|
|
5194
|
+
});
|
|
5195
|
+
}
|
|
5196
|
+
} else if (ts.isNamespaceImport(bindings2)) {
|
|
5197
|
+
refs.push({ fromId: 0, toName: bindings2.name.text, callType: "import", line: lineNum });
|
|
5198
|
+
}
|
|
5199
|
+
}
|
|
5200
|
+
function emitExportSpecifierRefs(node, refs, lineNum) {
|
|
5201
|
+
const clause = node.exportClause;
|
|
5202
|
+
if (clause && ts.isNamespaceExport(clause)) {
|
|
5203
|
+
refs.push({ fromId: 0, toName: clause.name.text, callType: "import", line: lineNum });
|
|
5204
|
+
return;
|
|
5205
|
+
}
|
|
5206
|
+
if (clause && ts.isNamedExports(clause)) {
|
|
5207
|
+
for (const element of clause.elements) {
|
|
5208
|
+
const originalName = element.propertyName?.text ?? element.name.text;
|
|
5209
|
+
refs.push({ fromId: 0, toName: originalName, callType: "import", line: lineNum });
|
|
5210
|
+
}
|
|
5211
|
+
return;
|
|
5212
|
+
}
|
|
5213
|
+
}
|
|
5174
5214
|
var ts, tsLoad, kindMapCache;
|
|
5175
5215
|
var init_ts_parser = __esm({
|
|
5176
5216
|
"src/codebase-index/ts-parser.ts"() {
|
|
@@ -8766,9 +8806,50 @@ import { createReadStream } from "node:fs";
|
|
|
8766
8806
|
import * as fs7 from "node:fs/promises";
|
|
8767
8807
|
import * as path10 from "node:path";
|
|
8768
8808
|
import { atomicWrite, ulid } from "@wrongstack/core/utils";
|
|
8809
|
+
var ARTIFACT_RETENTION_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
8810
|
+
var sweptRoots = /* @__PURE__ */ new Set();
|
|
8811
|
+
function sweepOldArtifacts(root) {
|
|
8812
|
+
if (sweptRoots.has(root)) return;
|
|
8813
|
+
sweptRoots.add(root);
|
|
8814
|
+
void (async () => {
|
|
8815
|
+
const cutoff = Date.now() - ARTIFACT_RETENTION_MS;
|
|
8816
|
+
let sessionDirs;
|
|
8817
|
+
try {
|
|
8818
|
+
const entries = await fs7.readdir(root, { withFileTypes: true });
|
|
8819
|
+
sessionDirs = entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
8820
|
+
} catch {
|
|
8821
|
+
return;
|
|
8822
|
+
}
|
|
8823
|
+
for (const sessionDir of sessionDirs) {
|
|
8824
|
+
const dir = path10.join(root, sessionDir);
|
|
8825
|
+
let names;
|
|
8826
|
+
try {
|
|
8827
|
+
names = await fs7.readdir(dir);
|
|
8828
|
+
} catch {
|
|
8829
|
+
continue;
|
|
8830
|
+
}
|
|
8831
|
+
let removed = 0;
|
|
8832
|
+
for (const name of names) {
|
|
8833
|
+
const target = path10.join(dir, name);
|
|
8834
|
+
try {
|
|
8835
|
+
const stat18 = await fs7.stat(target);
|
|
8836
|
+
if (stat18.isFile() && stat18.mtimeMs < cutoff) {
|
|
8837
|
+
await fs7.rm(target, { force: true });
|
|
8838
|
+
removed++;
|
|
8839
|
+
}
|
|
8840
|
+
} catch {
|
|
8841
|
+
}
|
|
8842
|
+
}
|
|
8843
|
+
if (removed === names.length && names.length > 0) {
|
|
8844
|
+
await fs7.rmdir(dir).catch(() => void 0);
|
|
8845
|
+
}
|
|
8846
|
+
}
|
|
8847
|
+
})();
|
|
8848
|
+
}
|
|
8769
8849
|
var BrowserArtifactStore = class {
|
|
8770
8850
|
constructor(root) {
|
|
8771
8851
|
this.root = root;
|
|
8852
|
+
sweepOldArtifacts(root);
|
|
8772
8853
|
}
|
|
8773
8854
|
root;
|
|
8774
8855
|
async write(sessionId, kind, extension, mimeType, content) {
|
|
@@ -10214,42 +10295,6 @@ import { expectDefined as expectDefined5 } from "@wrongstack/core/utils";
|
|
|
10214
10295
|
import * as fs14 from "node:fs";
|
|
10215
10296
|
import * as path21 from "node:path";
|
|
10216
10297
|
|
|
10217
|
-
// src/codebase-index/schema.ts
|
|
10218
|
-
var SCHEMA_VERSION = 3;
|
|
10219
|
-
|
|
10220
|
-
// src/codebase-index/lsp-kind.ts
|
|
10221
|
-
function lspKindToInternalKind(k) {
|
|
10222
|
-
switch (k) {
|
|
10223
|
-
case 5 /* Class */:
|
|
10224
|
-
return "class";
|
|
10225
|
-
case 6 /* Method */:
|
|
10226
|
-
return "method";
|
|
10227
|
-
case 7 /* Property */:
|
|
10228
|
-
case 8 /* Field */:
|
|
10229
|
-
return "property";
|
|
10230
|
-
case 9 /* Constructor */:
|
|
10231
|
-
return "class";
|
|
10232
|
-
case 10 /* Enum */:
|
|
10233
|
-
return "enum";
|
|
10234
|
-
case 11 /* Interface */:
|
|
10235
|
-
return "interface";
|
|
10236
|
-
case 12 /* Function */:
|
|
10237
|
-
return "function";
|
|
10238
|
-
case 13 /* Variable */:
|
|
10239
|
-
return "var";
|
|
10240
|
-
case 14 /* Constant */:
|
|
10241
|
-
return "const";
|
|
10242
|
-
case 22 /* EnumMember */:
|
|
10243
|
-
return "enum";
|
|
10244
|
-
case 26 /* TypeParameter */:
|
|
10245
|
-
return "type";
|
|
10246
|
-
case 3 /* Namespace */:
|
|
10247
|
-
return "namespace";
|
|
10248
|
-
default:
|
|
10249
|
-
return null;
|
|
10250
|
-
}
|
|
10251
|
-
}
|
|
10252
|
-
|
|
10253
10298
|
// src/codebase-index/bm25.ts
|
|
10254
10299
|
var K1 = 1.5;
|
|
10255
10300
|
var B = 0.75;
|
|
@@ -10339,6 +10384,42 @@ var Bm25Index = class {
|
|
|
10339
10384
|
}
|
|
10340
10385
|
};
|
|
10341
10386
|
|
|
10387
|
+
// src/codebase-index/lsp-kind.ts
|
|
10388
|
+
function lspKindToInternalKind(k) {
|
|
10389
|
+
switch (k) {
|
|
10390
|
+
case 5 /* Class */:
|
|
10391
|
+
return "class";
|
|
10392
|
+
case 6 /* Method */:
|
|
10393
|
+
return "method";
|
|
10394
|
+
case 7 /* Property */:
|
|
10395
|
+
case 8 /* Field */:
|
|
10396
|
+
return "property";
|
|
10397
|
+
case 9 /* Constructor */:
|
|
10398
|
+
return "class";
|
|
10399
|
+
case 10 /* Enum */:
|
|
10400
|
+
return "enum";
|
|
10401
|
+
case 11 /* Interface */:
|
|
10402
|
+
return "interface";
|
|
10403
|
+
case 12 /* Function */:
|
|
10404
|
+
return "function";
|
|
10405
|
+
case 13 /* Variable */:
|
|
10406
|
+
return "var";
|
|
10407
|
+
case 14 /* Constant */:
|
|
10408
|
+
return "const";
|
|
10409
|
+
case 22 /* EnumMember */:
|
|
10410
|
+
return "enum";
|
|
10411
|
+
case 26 /* TypeParameter */:
|
|
10412
|
+
return "type";
|
|
10413
|
+
case 3 /* Namespace */:
|
|
10414
|
+
return "namespace";
|
|
10415
|
+
default:
|
|
10416
|
+
return null;
|
|
10417
|
+
}
|
|
10418
|
+
}
|
|
10419
|
+
|
|
10420
|
+
// src/codebase-index/schema.ts
|
|
10421
|
+
var SCHEMA_VERSION = 3;
|
|
10422
|
+
|
|
10342
10423
|
// src/codebase-index/sqlite-runtime.ts
|
|
10343
10424
|
import { createRequire } from "node:module";
|
|
10344
10425
|
import { toErrorMessage as toErrorMessage2 } from "@wrongstack/core/utils";
|
|
@@ -10406,96 +10487,6 @@ function runSqliteWithRetry(fn) {
|
|
|
10406
10487
|
throw lastError;
|
|
10407
10488
|
}
|
|
10408
10489
|
|
|
10409
|
-
// src/codebase-index/writer-helpers.ts
|
|
10410
|
-
import { resolveWstackPaths as resolveWstackPaths2 } from "@wrongstack/core/utils";
|
|
10411
|
-
function escapeLike(value) {
|
|
10412
|
-
return value.replace(/[\\%_]/g, (char) => `\\${char}`);
|
|
10413
|
-
}
|
|
10414
|
-
function assignRefsToSymbols(refs, symbols) {
|
|
10415
|
-
if (refs.length === 0 || symbols.length === 0) return [];
|
|
10416
|
-
const ordered = [...symbols].sort((a, b) => a.line - b.line || a.col - b.col || a.id - b.id);
|
|
10417
|
-
const seen = /* @__PURE__ */ new Set();
|
|
10418
|
-
const assigned = [];
|
|
10419
|
-
for (const ref of refs) {
|
|
10420
|
-
let owner2;
|
|
10421
|
-
for (const symbol of ordered) {
|
|
10422
|
-
if (symbol.line > ref.line) break;
|
|
10423
|
-
owner2 = symbol;
|
|
10424
|
-
}
|
|
10425
|
-
if (!owner2 && ref.callType === "import") owner2 = ordered[0];
|
|
10426
|
-
if (!owner2 || owner2.id <= 0) continue;
|
|
10427
|
-
const key = `${owner2.id}:${ref.toName}:${ref.callType}`;
|
|
10428
|
-
if (seen.has(key)) continue;
|
|
10429
|
-
seen.add(key);
|
|
10430
|
-
assigned.push({ ...ref, fromId: owner2.id });
|
|
10431
|
-
}
|
|
10432
|
-
return assigned;
|
|
10433
|
-
}
|
|
10434
|
-
function resolveIndexDir(projectRoot, override) {
|
|
10435
|
-
return override ?? resolveWstackPaths2({ projectRoot }).projectCodebaseIndex;
|
|
10436
|
-
}
|
|
10437
|
-
function codebaseIndexDirOverride(ctx) {
|
|
10438
|
-
const v = ctx.meta?.["codebaseIndexDir"];
|
|
10439
|
-
return typeof v === "string" ? v : void 0;
|
|
10440
|
-
}
|
|
10441
|
-
|
|
10442
|
-
// src/codebase-index/writer-schema.ts
|
|
10443
|
-
var METADATA_TABLE_SQL = `
|
|
10444
|
-
CREATE TABLE IF NOT EXISTS metadata (
|
|
10445
|
-
key TEXT PRIMARY KEY,
|
|
10446
|
-
value TEXT NOT NULL
|
|
10447
|
-
);
|
|
10448
|
-
`;
|
|
10449
|
-
var CORE_TABLES_SQL = `
|
|
10450
|
-
CREATE TABLE IF NOT EXISTS files (
|
|
10451
|
-
file TEXT PRIMARY KEY,
|
|
10452
|
-
lang TEXT NOT NULL,
|
|
10453
|
-
mtime_ms INTEGER NOT NULL,
|
|
10454
|
-
symbol_count INTEGER NOT NULL DEFAULT 0,
|
|
10455
|
-
last_indexed INTEGER NOT NULL
|
|
10456
|
-
);
|
|
10457
|
-
CREATE TABLE IF NOT EXISTS symbols (
|
|
10458
|
-
id INTEGER PRIMARY KEY,
|
|
10459
|
-
lang TEXT NOT NULL,
|
|
10460
|
-
kind TEXT NOT NULL,
|
|
10461
|
-
name TEXT NOT NULL,
|
|
10462
|
-
file TEXT NOT NULL,
|
|
10463
|
-
line INTEGER NOT NULL,
|
|
10464
|
-
col INTEGER NOT NULL,
|
|
10465
|
-
signature TEXT NOT NULL DEFAULT '',
|
|
10466
|
-
doc_comment TEXT NOT NULL DEFAULT '',
|
|
10467
|
-
scope TEXT NOT NULL DEFAULT '',
|
|
10468
|
-
text TEXT NOT NULL DEFAULT '',
|
|
10469
|
-
file_fk TEXT NOT NULL
|
|
10470
|
-
);
|
|
10471
|
-
`;
|
|
10472
|
-
var SYMBOL_INDEX_SQL = [
|
|
10473
|
-
"CREATE INDEX IF NOT EXISTS idx_s_name ON symbols(name)",
|
|
10474
|
-
"CREATE INDEX IF NOT EXISTS idx_s_kind ON symbols(kind)",
|
|
10475
|
-
"CREATE INDEX IF NOT EXISTS idx_s_lang ON symbols(lang)",
|
|
10476
|
-
"CREATE INDEX IF NOT EXISTS idx_s_file ON symbols(file)",
|
|
10477
|
-
"CREATE INDEX IF NOT EXISTS idx_s_lang_kind ON symbols(lang, kind)",
|
|
10478
|
-
"CREATE INDEX IF NOT EXISTS idx_s_file_fk ON symbols(file_fk)",
|
|
10479
|
-
"CREATE INDEX IF NOT EXISTS idx_s_name_id ON symbols(name, id)"
|
|
10480
|
-
];
|
|
10481
|
-
var REFS_TABLE_SQL = `
|
|
10482
|
-
CREATE TABLE IF NOT EXISTS refs (
|
|
10483
|
-
id INTEGER PRIMARY KEY,
|
|
10484
|
-
from_id INTEGER NOT NULL,
|
|
10485
|
-
to_name TEXT NOT NULL,
|
|
10486
|
-
to_id INTEGER,
|
|
10487
|
-
call_type TEXT NOT NULL,
|
|
10488
|
-
line INTEGER NOT NULL
|
|
10489
|
-
);
|
|
10490
|
-
`;
|
|
10491
|
-
var REFS_INDEX_SQL = [
|
|
10492
|
-
"CREATE INDEX IF NOT EXISTS idx_r_from ON refs(from_id)",
|
|
10493
|
-
"CREATE INDEX IF NOT EXISTS idx_r_to_id ON refs(to_id)",
|
|
10494
|
-
"CREATE INDEX IF NOT EXISTS idx_r_to_name ON refs(to_name)",
|
|
10495
|
-
"CREATE INDEX IF NOT EXISTS idx_r_call_type ON refs(call_type)"
|
|
10496
|
-
];
|
|
10497
|
-
var SYMBOLS_FTS_SQL = "CREATE VIRTUAL TABLE IF NOT EXISTS symbols_fts USING fts5(text, tokenize = 'unicode61')";
|
|
10498
|
-
|
|
10499
10490
|
// src/codebase-index/writer-admin.ts
|
|
10500
10491
|
import * as fs13 from "node:fs";
|
|
10501
10492
|
import * as path19 from "node:path";
|
|
@@ -10968,6 +10959,39 @@ function getSymbolGraphWithStatement(stmt, fileFilter) {
|
|
|
10968
10959
|
return { nodes, edges };
|
|
10969
10960
|
}
|
|
10970
10961
|
|
|
10962
|
+
// src/codebase-index/writer-helpers.ts
|
|
10963
|
+
import { resolveWstackPaths as resolveWstackPaths2 } from "@wrongstack/core/utils";
|
|
10964
|
+
function escapeLike(value) {
|
|
10965
|
+
return value.replace(/[\\%_]/g, (char) => `\\${char}`);
|
|
10966
|
+
}
|
|
10967
|
+
function assignRefsToSymbols(refs, symbols) {
|
|
10968
|
+
if (refs.length === 0 || symbols.length === 0) return [];
|
|
10969
|
+
const ordered = [...symbols].sort((a, b) => a.line - b.line || a.col - b.col || a.id - b.id);
|
|
10970
|
+
const seen = /* @__PURE__ */ new Set();
|
|
10971
|
+
const assigned = [];
|
|
10972
|
+
for (const ref of refs) {
|
|
10973
|
+
let owner2;
|
|
10974
|
+
for (const symbol of ordered) {
|
|
10975
|
+
if (symbol.line > ref.line) break;
|
|
10976
|
+
owner2 = symbol;
|
|
10977
|
+
}
|
|
10978
|
+
if (!owner2 && ref.callType === "import") owner2 = ordered[0];
|
|
10979
|
+
if (!owner2 || owner2.id <= 0) continue;
|
|
10980
|
+
const key = `${owner2.id}:${ref.toName}:${ref.callType}`;
|
|
10981
|
+
if (seen.has(key)) continue;
|
|
10982
|
+
seen.add(key);
|
|
10983
|
+
assigned.push({ ...ref, fromId: owner2.id });
|
|
10984
|
+
}
|
|
10985
|
+
return assigned;
|
|
10986
|
+
}
|
|
10987
|
+
function resolveIndexDir(projectRoot, override) {
|
|
10988
|
+
return override ?? resolveWstackPaths2({ projectRoot }).projectCodebaseIndex;
|
|
10989
|
+
}
|
|
10990
|
+
function codebaseIndexDirOverride(ctx) {
|
|
10991
|
+
const v = ctx.meta?.["codebaseIndexDir"];
|
|
10992
|
+
return typeof v === "string" ? v : void 0;
|
|
10993
|
+
}
|
|
10994
|
+
|
|
10971
10995
|
// src/codebase-index/writer-pragmas.ts
|
|
10972
10996
|
import { sqliteCachePragmas } from "@wrongstack/core/utils";
|
|
10973
10997
|
function applyIndexStorePragmas(db) {
|
|
@@ -10986,6 +11010,63 @@ function applyIndexStorePragmas(db) {
|
|
|
10986
11010
|
}
|
|
10987
11011
|
}
|
|
10988
11012
|
|
|
11013
|
+
// src/codebase-index/writer-schema.ts
|
|
11014
|
+
var METADATA_TABLE_SQL = `
|
|
11015
|
+
CREATE TABLE IF NOT EXISTS metadata (
|
|
11016
|
+
key TEXT PRIMARY KEY,
|
|
11017
|
+
value TEXT NOT NULL
|
|
11018
|
+
);
|
|
11019
|
+
`;
|
|
11020
|
+
var CORE_TABLES_SQL = `
|
|
11021
|
+
CREATE TABLE IF NOT EXISTS files (
|
|
11022
|
+
file TEXT PRIMARY KEY,
|
|
11023
|
+
lang TEXT NOT NULL,
|
|
11024
|
+
mtime_ms INTEGER NOT NULL,
|
|
11025
|
+
symbol_count INTEGER NOT NULL DEFAULT 0,
|
|
11026
|
+
last_indexed INTEGER NOT NULL
|
|
11027
|
+
);
|
|
11028
|
+
CREATE TABLE IF NOT EXISTS symbols (
|
|
11029
|
+
id INTEGER PRIMARY KEY,
|
|
11030
|
+
lang TEXT NOT NULL,
|
|
11031
|
+
kind TEXT NOT NULL,
|
|
11032
|
+
name TEXT NOT NULL,
|
|
11033
|
+
file TEXT NOT NULL,
|
|
11034
|
+
line INTEGER NOT NULL,
|
|
11035
|
+
col INTEGER NOT NULL,
|
|
11036
|
+
signature TEXT NOT NULL DEFAULT '',
|
|
11037
|
+
doc_comment TEXT NOT NULL DEFAULT '',
|
|
11038
|
+
scope TEXT NOT NULL DEFAULT '',
|
|
11039
|
+
text TEXT NOT NULL DEFAULT '',
|
|
11040
|
+
file_fk TEXT NOT NULL
|
|
11041
|
+
);
|
|
11042
|
+
`;
|
|
11043
|
+
var SYMBOL_INDEX_SQL = [
|
|
11044
|
+
"CREATE INDEX IF NOT EXISTS idx_s_name ON symbols(name)",
|
|
11045
|
+
"CREATE INDEX IF NOT EXISTS idx_s_kind ON symbols(kind)",
|
|
11046
|
+
"CREATE INDEX IF NOT EXISTS idx_s_lang ON symbols(lang)",
|
|
11047
|
+
"CREATE INDEX IF NOT EXISTS idx_s_file ON symbols(file)",
|
|
11048
|
+
"CREATE INDEX IF NOT EXISTS idx_s_lang_kind ON symbols(lang, kind)",
|
|
11049
|
+
"CREATE INDEX IF NOT EXISTS idx_s_file_fk ON symbols(file_fk)",
|
|
11050
|
+
"CREATE INDEX IF NOT EXISTS idx_s_name_id ON symbols(name, id)"
|
|
11051
|
+
];
|
|
11052
|
+
var REFS_TABLE_SQL = `
|
|
11053
|
+
CREATE TABLE IF NOT EXISTS refs (
|
|
11054
|
+
id INTEGER PRIMARY KEY,
|
|
11055
|
+
from_id INTEGER NOT NULL,
|
|
11056
|
+
to_name TEXT NOT NULL,
|
|
11057
|
+
to_id INTEGER,
|
|
11058
|
+
call_type TEXT NOT NULL,
|
|
11059
|
+
line INTEGER NOT NULL
|
|
11060
|
+
);
|
|
11061
|
+
`;
|
|
11062
|
+
var REFS_INDEX_SQL = [
|
|
11063
|
+
"CREATE INDEX IF NOT EXISTS idx_r_from ON refs(from_id)",
|
|
11064
|
+
"CREATE INDEX IF NOT EXISTS idx_r_to_id ON refs(to_id)",
|
|
11065
|
+
"CREATE INDEX IF NOT EXISTS idx_r_to_name ON refs(to_name)",
|
|
11066
|
+
"CREATE INDEX IF NOT EXISTS idx_r_call_type ON refs(call_type)"
|
|
11067
|
+
];
|
|
11068
|
+
var SYMBOLS_FTS_SQL = "CREATE VIRTUAL TABLE IF NOT EXISTS symbols_fts USING fts5(text, tokenize = 'unicode61')";
|
|
11069
|
+
|
|
10989
11070
|
// src/codebase-index/writer-search-helpers.ts
|
|
10990
11071
|
function normalizeSearchLimit(limit) {
|
|
10991
11072
|
return typeof limit === "number" && Number.isFinite(limit) ? Math.max(0, Math.trunc(limit)) : void 0;
|
|
@@ -11194,9 +11275,15 @@ var IndexStore = class _IndexStore {
|
|
|
11194
11275
|
DROP TABLE IF EXISTS refs;
|
|
11195
11276
|
`);
|
|
11196
11277
|
this.db.exec("DROP TABLE IF EXISTS symbols_fts");
|
|
11197
|
-
this.stmt("UPDATE metadata SET value = ? WHERE key = ?").run(
|
|
11278
|
+
this.stmt("UPDATE metadata SET value = ? WHERE key = ?").run(
|
|
11279
|
+
String(SCHEMA_VERSION),
|
|
11280
|
+
"version"
|
|
11281
|
+
);
|
|
11198
11282
|
} else if (storedVersion === null) {
|
|
11199
|
-
this.stmt("INSERT INTO metadata(key, value) VALUES (?, ?)").run(
|
|
11283
|
+
this.stmt("INSERT INTO metadata(key, value) VALUES (?, ?)").run(
|
|
11284
|
+
"version",
|
|
11285
|
+
String(SCHEMA_VERSION)
|
|
11286
|
+
);
|
|
11200
11287
|
}
|
|
11201
11288
|
this.db.exec(CORE_TABLES_SQL);
|
|
11202
11289
|
for (const sql of SYMBOL_INDEX_SQL) this.db.exec(sql);
|
|
@@ -11213,7 +11300,9 @@ var IndexStore = class _IndexStore {
|
|
|
11213
11300
|
);
|
|
11214
11301
|
if (symbolCount !== ftsCount) {
|
|
11215
11302
|
this.db.exec("DELETE FROM symbols_fts");
|
|
11216
|
-
const rows = this.stmt(
|
|
11303
|
+
const rows = this.stmt(
|
|
11304
|
+
"SELECT id, name, signature, doc_comment FROM symbols ORDER BY id"
|
|
11305
|
+
).all();
|
|
11217
11306
|
bulkInsertFtsWithStatement(
|
|
11218
11307
|
(sql) => this.stmt(sql),
|
|
11219
11308
|
_IndexStore.MAX_SQL_VARS,
|
|
@@ -11435,7 +11524,9 @@ var IndexStore = class _IndexStore {
|
|
|
11435
11524
|
const limitSql = limit !== void 0 ? " LIMIT ?" : "";
|
|
11436
11525
|
const sql = `SELECT id, lang, kind, name, file, line, col, signature, doc_comment, text FROM symbols ${where}${limitSql}`;
|
|
11437
11526
|
const binds = limit !== void 0 ? [...values, limit] : values;
|
|
11438
|
-
const rows = this.stmt(sql).all(
|
|
11527
|
+
const rows = this.stmt(sql).all(
|
|
11528
|
+
...binds
|
|
11529
|
+
);
|
|
11439
11530
|
return rows.map((row) => mapWriterSearchRow(row, filter?.lspKind));
|
|
11440
11531
|
}
|
|
11441
11532
|
/** Shared WHERE builder for {@link search} / empty-query ranked totals. */
|
|
@@ -11611,7 +11702,9 @@ var IndexStore = class _IndexStore {
|
|
|
11611
11702
|
}
|
|
11612
11703
|
setLastIndexed(ts2) {
|
|
11613
11704
|
this.runWithRetry(() => {
|
|
11614
|
-
this.stmt("INSERT OR REPLACE INTO metadata(key, value) VALUES('last_indexed', ?)").run(
|
|
11705
|
+
this.stmt("INSERT OR REPLACE INTO metadata(key, value) VALUES('last_indexed', ?)").run(
|
|
11706
|
+
String(ts2)
|
|
11707
|
+
);
|
|
11615
11708
|
});
|
|
11616
11709
|
}
|
|
11617
11710
|
getMetadata(key) {
|
|
@@ -11722,7 +11815,9 @@ var IndexStore = class _IndexStore {
|
|
|
11722
11815
|
this.stmt(
|
|
11723
11816
|
`DELETE FROM refs WHERE from_id IN (SELECT id FROM symbols WHERE file IN (${placeholders}))`
|
|
11724
11817
|
).run(...options.deleteForFiles);
|
|
11725
|
-
this.stmt(`DELETE FROM symbols WHERE file IN (${placeholders})`).run(
|
|
11818
|
+
this.stmt(`DELETE FROM symbols WHERE file IN (${placeholders})`).run(
|
|
11819
|
+
...options.deleteForFiles
|
|
11820
|
+
);
|
|
11726
11821
|
}
|
|
11727
11822
|
const totalSymbols = entries.reduce((n, e) => n + e.symbols.length, 0);
|
|
11728
11823
|
let nextId = this.allocateSymbolIds(totalSymbols);
|
|
@@ -11766,11 +11861,7 @@ var IndexStore = class _IndexStore {
|
|
|
11766
11861
|
this.ftsAvailable,
|
|
11767
11862
|
ftsRows
|
|
11768
11863
|
);
|
|
11769
|
-
bulkInsertRefsWithStatement(
|
|
11770
|
-
(sql) => this.stmt(sql),
|
|
11771
|
-
_IndexStore.MAX_SQL_VARS,
|
|
11772
|
-
refsToInsert
|
|
11773
|
-
);
|
|
11864
|
+
bulkInsertRefsWithStatement((sql) => this.stmt(sql), _IndexStore.MAX_SQL_VARS, refsToInsert);
|
|
11774
11865
|
const upsertStmt = this.stmt(
|
|
11775
11866
|
`INSERT INTO files(file, lang, mtime_ms, symbol_count, last_indexed)
|
|
11776
11867
|
VALUES (?, ?, ?, ?, ?)
|
|
@@ -11799,7 +11890,9 @@ var IndexStore = class _IndexStore {
|
|
|
11799
11890
|
*/
|
|
11800
11891
|
deleteRefsForFile(file) {
|
|
11801
11892
|
this.runWithRetry(() => {
|
|
11802
|
-
this.stmt("DELETE FROM refs WHERE from_id IN (SELECT id FROM symbols WHERE file = ?)").run(
|
|
11893
|
+
this.stmt("DELETE FROM refs WHERE from_id IN (SELECT id FROM symbols WHERE file = ?)").run(
|
|
11894
|
+
file
|
|
11895
|
+
);
|
|
11803
11896
|
});
|
|
11804
11897
|
}
|
|
11805
11898
|
/**
|
|
@@ -11954,9 +12047,7 @@ var IndexStore = class _IndexStore {
|
|
|
11954
12047
|
* build the full symbol universe for the reachability scan.
|
|
11955
12048
|
*/
|
|
11956
12049
|
getAllSymbols() {
|
|
11957
|
-
return this.stmt(
|
|
11958
|
-
"SELECT id, name, file, kind, line FROM symbols ORDER BY id"
|
|
11959
|
-
).all().map((r) => ({ ...r, kind: r.kind }));
|
|
12050
|
+
return this.stmt("SELECT id, name, file, kind, line FROM symbols ORDER BY id").all().map((r) => ({ ...r, kind: r.kind }));
|
|
11960
12051
|
}
|
|
11961
12052
|
/**
|
|
11962
12053
|
* Returns every resolved reference (to_id IS NOT NULL). Used by
|
|
@@ -11968,6 +12059,25 @@ var IndexStore = class _IndexStore {
|
|
|
11968
12059
|
"SELECT from_id AS fromId, to_id AS toId, call_type AS callType FROM refs WHERE to_id IS NOT NULL"
|
|
11969
12060
|
).all();
|
|
11970
12061
|
}
|
|
12062
|
+
/**
|
|
12063
|
+
* Returns ALL import refs (including unresolved) with their source-file
|
|
12064
|
+
* path and resolved target id. Used by the dead-code scan's file-level
|
|
12065
|
+
* graph traversal to handle barrel-only entry points where no symbol
|
|
12066
|
+
* carries the ref.
|
|
12067
|
+
*
|
|
12068
|
+
* Refs whose `from_id` doesn't match a known symbol (e.g. pure-barrel
|
|
12069
|
+
* files with no declarations) will have `sourceFile === null`.
|
|
12070
|
+
*/
|
|
12071
|
+
getAllImportRefs() {
|
|
12072
|
+
return this.stmt(
|
|
12073
|
+
`SELECT s.file AS sourceFile, r.to_name AS toName, r.to_id AS toId,
|
|
12074
|
+
r.call_type AS callType, r.line
|
|
12075
|
+
FROM refs r
|
|
12076
|
+
LEFT JOIN symbols s ON r.from_id = s.id
|
|
12077
|
+
WHERE r.call_type = 'import'
|
|
12078
|
+
ORDER BY r.line`
|
|
12079
|
+
).all();
|
|
12080
|
+
}
|
|
11971
12081
|
close() {
|
|
11972
12082
|
this.stmtCache.clear();
|
|
11973
12083
|
this.bm25Dirty = true;
|
|
@@ -13852,6 +13962,7 @@ var codebaseStatsTool = {
|
|
|
13852
13962
|
};
|
|
13853
13963
|
|
|
13854
13964
|
// src/codebase-index/dead-code-scan.ts
|
|
13965
|
+
init_languages2();
|
|
13855
13966
|
import * as fs19 from "node:fs";
|
|
13856
13967
|
import * as path24 from "node:path";
|
|
13857
13968
|
var deadCodeScanTool = {
|
|
@@ -13920,7 +14031,15 @@ function discoverEntryPoints(projectRoot, userEntryPoints) {
|
|
|
13920
14031
|
if (rootPkg) {
|
|
13921
14032
|
addPkgJsonEntryPoints(projectRoot, rootPkg, entries);
|
|
13922
14033
|
}
|
|
13923
|
-
|
|
14034
|
+
let workspaces;
|
|
14035
|
+
if (rootPkg) {
|
|
14036
|
+
workspaces = extractWorkspaceGlobs(rootPkg, projectRoot);
|
|
14037
|
+
if (workspaces.length === 0) {
|
|
14038
|
+
workspaces = extractPnpmWorkspaceDirs(projectRoot);
|
|
14039
|
+
}
|
|
14040
|
+
} else {
|
|
14041
|
+
workspaces = [];
|
|
14042
|
+
}
|
|
13924
14043
|
for (const wsDir of workspaces) {
|
|
13925
14044
|
const pkgJsonPath = path24.join(wsDir, "package.json");
|
|
13926
14045
|
const pkg = tryReadJson(pkgJsonPath);
|
|
@@ -13942,77 +14061,189 @@ function discoverEntryPoints(projectRoot, userEntryPoints) {
|
|
|
13942
14061
|
}
|
|
13943
14062
|
return [...entries];
|
|
13944
14063
|
}
|
|
14064
|
+
var BUILD_OUTPUT_DIRS = ["dist", "out", "build", "release"];
|
|
14065
|
+
var BUILD_OUTPUT_DIR_NAMES = BUILD_OUTPUT_DIRS.map((d) => `${path24.sep}${d}${path24.sep}`);
|
|
14066
|
+
function trySourceEquivalent(resolved) {
|
|
14067
|
+
resolved = resolved.replace(/[/\\]/g, path24.sep);
|
|
14068
|
+
for (const marker of BUILD_OUTPUT_DIR_NAMES) {
|
|
14069
|
+
const idx = resolved.indexOf(marker);
|
|
14070
|
+
if (idx === -1) continue;
|
|
14071
|
+
const base = resolved.replace(marker, `${path24.sep}src${path24.sep}`);
|
|
14072
|
+
const candidate = base.replace(/\.(js|mjs|cjs)$/, ".ts");
|
|
14073
|
+
if (candidate !== base && fs19.existsSync(candidate)) {
|
|
14074
|
+
return candidate;
|
|
14075
|
+
}
|
|
14076
|
+
const dtsStripped = base.replace(/\.d\.ts$/, "");
|
|
14077
|
+
const candidateDts = dtsStripped + ".ts";
|
|
14078
|
+
if (candidateDts !== base && candidateDts !== candidate && fs19.existsSync(candidateDts)) {
|
|
14079
|
+
return candidateDts;
|
|
14080
|
+
}
|
|
14081
|
+
const candidateNoExt = base + ".ts";
|
|
14082
|
+
if (candidate !== candidateNoExt && candidateNoExt !== candidateDts && fs19.existsSync(candidateNoExt)) {
|
|
14083
|
+
return candidateNoExt;
|
|
14084
|
+
}
|
|
14085
|
+
}
|
|
14086
|
+
return null;
|
|
14087
|
+
}
|
|
14088
|
+
function tryAddEntryPath(pkgDir, rawPath, entries) {
|
|
14089
|
+
const resolved = resolveAgainst(pkgDir, rawPath);
|
|
14090
|
+
if (fs19.existsSync(resolved)) entries.add(resolved);
|
|
14091
|
+
const tsResolved = resolved.replace(/\.(js|mjs|cjs)$/, ".ts");
|
|
14092
|
+
if (tsResolved !== resolved && fs19.existsSync(tsResolved)) {
|
|
14093
|
+
entries.add(tsResolved);
|
|
14094
|
+
}
|
|
14095
|
+
const srcAlt = trySourceEquivalent(resolved);
|
|
14096
|
+
if (srcAlt) entries.add(srcAlt);
|
|
14097
|
+
}
|
|
13945
14098
|
function addPkgJsonEntryPoints(pkgDir, pkg, entries) {
|
|
13946
14099
|
if (typeof pkg.main === "string") {
|
|
13947
|
-
|
|
13948
|
-
if (fs19.existsSync(resolved)) entries.add(resolved);
|
|
13949
|
-
const tsResolved = resolved.replace(/\.(js|mjs|cjs)$/, ".ts");
|
|
13950
|
-
if (tsResolved !== resolved && fs19.existsSync(tsResolved)) {
|
|
13951
|
-
entries.add(tsResolved);
|
|
13952
|
-
}
|
|
14100
|
+
tryAddEntryPath(pkgDir, pkg.main, entries);
|
|
13953
14101
|
}
|
|
13954
14102
|
const bin = pkg.bin;
|
|
13955
14103
|
if (typeof bin === "string") {
|
|
13956
|
-
|
|
13957
|
-
if (fs19.existsSync(resolved)) entries.add(resolved);
|
|
14104
|
+
tryAddEntryPath(pkgDir, bin, entries);
|
|
13958
14105
|
} else if (bin && typeof bin === "object") {
|
|
13959
14106
|
for (const value of Object.values(bin)) {
|
|
13960
14107
|
if (typeof value === "string") {
|
|
13961
|
-
|
|
13962
|
-
if (fs19.existsSync(resolved)) entries.add(resolved);
|
|
14108
|
+
tryAddEntryPath(pkgDir, value, entries);
|
|
13963
14109
|
}
|
|
13964
14110
|
}
|
|
13965
14111
|
}
|
|
13966
14112
|
for (const key of ["types", "typings"]) {
|
|
13967
14113
|
if (typeof pkg[key] === "string") {
|
|
13968
|
-
|
|
13969
|
-
if (fs19.existsSync(resolved)) entries.add(resolved);
|
|
14114
|
+
tryAddEntryPath(pkgDir, pkg[key], entries);
|
|
13970
14115
|
}
|
|
13971
14116
|
}
|
|
13972
14117
|
const exports_ = pkg.exports;
|
|
13973
14118
|
if (exports_ && typeof exports_ === "object") {
|
|
13974
14119
|
for (const value of Object.values(exports_)) {
|
|
13975
14120
|
if (typeof value === "string") {
|
|
13976
|
-
|
|
13977
|
-
if (fs19.existsSync(resolved)) entries.add(resolved);
|
|
14121
|
+
tryAddEntryPath(pkgDir, value, entries);
|
|
13978
14122
|
} else if (value && typeof value === "object") {
|
|
13979
|
-
for (const nested of Object.values(
|
|
13980
|
-
value
|
|
13981
|
-
)) {
|
|
14123
|
+
for (const nested of Object.values(value)) {
|
|
13982
14124
|
if (typeof nested === "string") {
|
|
13983
|
-
|
|
13984
|
-
if (fs19.existsSync(resolved)) entries.add(resolved);
|
|
14125
|
+
tryAddEntryPath(pkgDir, nested, entries);
|
|
13985
14126
|
}
|
|
13986
14127
|
}
|
|
13987
14128
|
}
|
|
13988
14129
|
}
|
|
13989
14130
|
}
|
|
13990
14131
|
}
|
|
14132
|
+
function expandGlobPattern(entry, projectRoot) {
|
|
14133
|
+
const dirs = [];
|
|
14134
|
+
if (entry.includes("*")) {
|
|
14135
|
+
const base = entry.replace(/\/\*+$/, "");
|
|
14136
|
+
const baseDir = path24.resolve(projectRoot, base);
|
|
14137
|
+
try {
|
|
14138
|
+
const children = fs19.readdirSync(baseDir, { withFileTypes: true });
|
|
14139
|
+
for (const child of children) {
|
|
14140
|
+
if (child.isDirectory()) {
|
|
14141
|
+
dirs.push(path24.join(baseDir, child.name));
|
|
14142
|
+
}
|
|
14143
|
+
}
|
|
14144
|
+
} catch {
|
|
14145
|
+
}
|
|
14146
|
+
} else {
|
|
14147
|
+
dirs.push(path24.resolve(projectRoot, entry));
|
|
14148
|
+
}
|
|
14149
|
+
return dirs;
|
|
14150
|
+
}
|
|
13991
14151
|
function extractWorkspaceGlobs(pkg, projectRoot) {
|
|
13992
14152
|
const dirs = [];
|
|
13993
14153
|
const workspaces = pkg.workspaces;
|
|
13994
14154
|
if (Array.isArray(workspaces)) {
|
|
13995
14155
|
for (const entry of workspaces) {
|
|
13996
14156
|
if (typeof entry === "string") {
|
|
13997
|
-
|
|
13998
|
-
|
|
13999
|
-
|
|
14000
|
-
|
|
14001
|
-
|
|
14002
|
-
|
|
14003
|
-
|
|
14004
|
-
|
|
14005
|
-
|
|
14006
|
-
|
|
14007
|
-
|
|
14157
|
+
dirs.push(...expandGlobPattern(entry, projectRoot));
|
|
14158
|
+
}
|
|
14159
|
+
}
|
|
14160
|
+
}
|
|
14161
|
+
return dirs;
|
|
14162
|
+
}
|
|
14163
|
+
function extractPnpmWorkspaceDirs(projectRoot) {
|
|
14164
|
+
const yamlPath = path24.join(projectRoot, "pnpm-workspace.yaml");
|
|
14165
|
+
if (!fs19.existsSync(yamlPath)) return [];
|
|
14166
|
+
try {
|
|
14167
|
+
const content = fs19.readFileSync(yamlPath, "utf8");
|
|
14168
|
+
const dirs = [];
|
|
14169
|
+
let inPackages = false;
|
|
14170
|
+
const lines = content.split("\n");
|
|
14171
|
+
const itemRe = /^\s+-\s+"([^"]+)"|^\s+-\s+'([^']+)'|^\s+-\s+(\S+)/;
|
|
14172
|
+
for (const line of lines) {
|
|
14173
|
+
const trimmed = line.trim();
|
|
14174
|
+
if (/^packages\s*:\s*$/.test(trimmed)) {
|
|
14175
|
+
inPackages = true;
|
|
14176
|
+
continue;
|
|
14177
|
+
}
|
|
14178
|
+
if (inPackages && trimmed.length > 0 && !line.startsWith(" ") && !line.startsWith(" ")) {
|
|
14179
|
+
if (!trimmed.startsWith("-")) {
|
|
14180
|
+
inPackages = false;
|
|
14181
|
+
continue;
|
|
14182
|
+
}
|
|
14183
|
+
}
|
|
14184
|
+
if (inPackages) {
|
|
14185
|
+
const m = itemRe.exec(line);
|
|
14186
|
+
if (m) {
|
|
14187
|
+
const entry = m[1] ?? m[2] ?? m[3];
|
|
14188
|
+
if (entry) {
|
|
14189
|
+
dirs.push(...expandGlobPattern(entry, projectRoot));
|
|
14008
14190
|
}
|
|
14009
|
-
} else {
|
|
14010
|
-
dirs.push(path24.resolve(projectRoot, entry));
|
|
14011
14191
|
}
|
|
14012
14192
|
}
|
|
14013
14193
|
}
|
|
14194
|
+
return dirs;
|
|
14195
|
+
} catch {
|
|
14196
|
+
return [];
|
|
14197
|
+
}
|
|
14198
|
+
}
|
|
14199
|
+
function resolveModulePath(importerPath, moduleSpecifier, indexedFiles) {
|
|
14200
|
+
if (!moduleSpecifier.startsWith(".")) return [];
|
|
14201
|
+
const dir = path24.dirname(importerPath);
|
|
14202
|
+
const base = path24.resolve(dir, moduleSpecifier);
|
|
14203
|
+
const results = [];
|
|
14204
|
+
const stripped = base.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/, "");
|
|
14205
|
+
const skipBase = stripped !== base && /\.(ts|tsx|js|jsx|mjs|cjs)$/.test(base);
|
|
14206
|
+
const candidates = skipBase ? [stripped] : [base];
|
|
14207
|
+
for (const candidate of candidates) {
|
|
14208
|
+
if (indexedFiles.has(candidate + ".ts")) results.push(candidate + ".ts");
|
|
14209
|
+
if (indexedFiles.has(candidate + ".tsx")) results.push(candidate + ".tsx");
|
|
14210
|
+
if (indexedFiles.has(candidate + ".js")) results.push(candidate + ".js");
|
|
14211
|
+
if (indexedFiles.has(candidate + ".jsx")) results.push(candidate + ".jsx");
|
|
14212
|
+
if (indexedFiles.has(candidate + ".mjs")) results.push(candidate + ".mjs");
|
|
14213
|
+
if (indexedFiles.has(candidate + ".cjs")) results.push(candidate + ".cjs");
|
|
14214
|
+
if (indexedFiles.has(path24.join(candidate, "index.ts")))
|
|
14215
|
+
results.push(path24.join(candidate, "index.ts"));
|
|
14216
|
+
if (indexedFiles.has(path24.join(candidate, "index.tsx")))
|
|
14217
|
+
results.push(path24.join(candidate, "index.tsx"));
|
|
14218
|
+
if (indexedFiles.has(path24.join(candidate, "index.js")))
|
|
14219
|
+
results.push(path24.join(candidate, "index.js"));
|
|
14220
|
+
if (indexedFiles.has(path24.join(candidate, "index.jsx")))
|
|
14221
|
+
results.push(path24.join(candidate, "index.jsx"));
|
|
14222
|
+
if (indexedFiles.has(path24.join(candidate, "index.mjs")))
|
|
14223
|
+
results.push(path24.join(candidate, "index.mjs"));
|
|
14224
|
+
if (indexedFiles.has(path24.join(candidate, "index.cjs")))
|
|
14225
|
+
results.push(path24.join(candidate, "index.cjs"));
|
|
14226
|
+
}
|
|
14227
|
+
return [...new Set(results)];
|
|
14228
|
+
}
|
|
14229
|
+
function parseNamedExportSymbols(matchText) {
|
|
14230
|
+
const braceStart = matchText.indexOf("{");
|
|
14231
|
+
if (braceStart === -1) return null;
|
|
14232
|
+
const braceEnd = matchText.indexOf("}", braceStart);
|
|
14233
|
+
if (braceEnd === -1) return null;
|
|
14234
|
+
const inner = matchText.slice(braceStart + 1, braceEnd);
|
|
14235
|
+
const symbols = [];
|
|
14236
|
+
for (const part of inner.split(",")) {
|
|
14237
|
+
let s = part.trim();
|
|
14238
|
+
if (!s) continue;
|
|
14239
|
+
s = s.replace(/^type\s+/, "");
|
|
14240
|
+
const asIdx = s.search(/\s+as\s+/);
|
|
14241
|
+
if (asIdx !== -1) {
|
|
14242
|
+
s = s.slice(0, asIdx).trim();
|
|
14243
|
+
}
|
|
14244
|
+
if (s) symbols.push(s);
|
|
14014
14245
|
}
|
|
14015
|
-
return
|
|
14246
|
+
return symbols;
|
|
14016
14247
|
}
|
|
14017
14248
|
function runDeadCodeScan(projectRoot, opts = {}) {
|
|
14018
14249
|
const store = opts.store ?? indexStorePool.acquire(projectRoot, { indexDir: opts.indexDir });
|
|
@@ -14034,12 +14265,71 @@ function runDeadCodeScan(projectRoot, opts = {}) {
|
|
|
14034
14265
|
}
|
|
14035
14266
|
const discoveredFiles = discoverEntryPoints(projectRoot, opts.userEntryPoints);
|
|
14036
14267
|
const entryFileSet = new Set(discoveredFiles.map((f) => path24.resolve(f)));
|
|
14268
|
+
const indexedFiles = /* @__PURE__ */ new Set();
|
|
14269
|
+
for (const s of allSymbols) indexedFiles.add(s.file);
|
|
14270
|
+
for (const fm of store.getAllFileMetas()) indexedFiles.add(fm.file);
|
|
14037
14271
|
const seedIds = /* @__PURE__ */ new Set();
|
|
14038
14272
|
for (const s of allSymbols) {
|
|
14039
14273
|
if (entryFileSet.has(s.file)) {
|
|
14040
14274
|
seedIds.add(s.id);
|
|
14041
14275
|
}
|
|
14042
14276
|
}
|
|
14277
|
+
const fileToSymbolIds = /* @__PURE__ */ new Map();
|
|
14278
|
+
for (const s of allSymbols) {
|
|
14279
|
+
let byFile = fileToSymbolIds.get(s.file);
|
|
14280
|
+
if (!byFile) {
|
|
14281
|
+
byFile = [];
|
|
14282
|
+
fileToSymbolIds.set(s.file, byFile);
|
|
14283
|
+
}
|
|
14284
|
+
byFile.push(s.id);
|
|
14285
|
+
}
|
|
14286
|
+
const scannedBarrels = /* @__PURE__ */ new Set();
|
|
14287
|
+
const barrelWorkList = [...entryFileSet];
|
|
14288
|
+
while (barrelWorkList.length > 0) {
|
|
14289
|
+
const epFile = barrelWorkList.pop();
|
|
14290
|
+
if (scannedBarrels.has(epFile)) continue;
|
|
14291
|
+
scannedBarrels.add(epFile);
|
|
14292
|
+
try {
|
|
14293
|
+
const content = fs19.readFileSync(epFile, "utf8");
|
|
14294
|
+
const strippedContent = content.replace(/\/\*[\s\S]*?\*\//g, (m) => " ".repeat(m.length)).replace(/\/\/[^\n]*/g, (m) => " ".repeat(m.length));
|
|
14295
|
+
const reExportRe = /export\s+(?:(?:type\s+)?\{[\s\S]*?\}\s+from|\*\s+as\s+\w+\s+from|\*\s+from)\s+['"]([^'"]+)['"]/g;
|
|
14296
|
+
let match;
|
|
14297
|
+
while ((match = reExportRe.exec(strippedContent)) !== null) {
|
|
14298
|
+
const moduleSpec = match[1];
|
|
14299
|
+
const resolvedFiles = resolveModulePath(epFile, moduleSpec, indexedFiles);
|
|
14300
|
+
for (const rf of resolvedFiles) {
|
|
14301
|
+
const fileSyms = fileToSymbolIds.get(rf);
|
|
14302
|
+
if (fileSyms) {
|
|
14303
|
+
const namedSymbols = parseNamedExportSymbols(match[0]);
|
|
14304
|
+
if (namedSymbols) {
|
|
14305
|
+
const nameSet = new Set(namedSymbols);
|
|
14306
|
+
for (const sid of fileSyms) {
|
|
14307
|
+
const sym = symbolById.get(sid);
|
|
14308
|
+
if (sym && nameSet.has(sym.name)) seedIds.add(sid);
|
|
14309
|
+
}
|
|
14310
|
+
} else {
|
|
14311
|
+
for (const sid of fileSyms) seedIds.add(sid);
|
|
14312
|
+
}
|
|
14313
|
+
}
|
|
14314
|
+
if (!scannedBarrels.has(rf)) {
|
|
14315
|
+
barrelWorkList.push(rf);
|
|
14316
|
+
}
|
|
14317
|
+
}
|
|
14318
|
+
}
|
|
14319
|
+
} catch (err) {
|
|
14320
|
+
if (err instanceof Error && err.code !== "ENOENT") {
|
|
14321
|
+
console.warn(
|
|
14322
|
+
JSON.stringify({
|
|
14323
|
+
level: "warn",
|
|
14324
|
+
event: "dead_code_scan_barrel_read_failed",
|
|
14325
|
+
message: err.message,
|
|
14326
|
+
file: epFile,
|
|
14327
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
14328
|
+
})
|
|
14329
|
+
);
|
|
14330
|
+
}
|
|
14331
|
+
}
|
|
14332
|
+
}
|
|
14043
14333
|
const alive = new Set(seedIds);
|
|
14044
14334
|
const frontier = [...seedIds];
|
|
14045
14335
|
const visitedEdges = /* @__PURE__ */ new Set();
|
|
@@ -14073,8 +14363,7 @@ function runDeadCodeScan(projectRoot, opts = {}) {
|
|
|
14073
14363
|
dead.push({
|
|
14074
14364
|
name: s.name,
|
|
14075
14365
|
kind: s.kind,
|
|
14076
|
-
lang: "ts",
|
|
14077
|
-
// populated from symbol file metadata
|
|
14366
|
+
lang: detectLang(s.file) ?? "ts",
|
|
14078
14367
|
file: s.file,
|
|
14079
14368
|
line: s.line,
|
|
14080
14369
|
reason
|
|
@@ -14099,16 +14388,14 @@ function runDeadCodeScan(projectRoot, opts = {}) {
|
|
|
14099
14388
|
deadFiles.push({
|
|
14100
14389
|
file,
|
|
14101
14390
|
symbolCount: syms.length,
|
|
14102
|
-
lang:
|
|
14391
|
+
lang: detectLang(file) ?? "ts"
|
|
14103
14392
|
});
|
|
14104
14393
|
}
|
|
14105
14394
|
}
|
|
14106
14395
|
const deadPackages = [];
|
|
14107
14396
|
const pkgEntries = findPackageEntries(projectRoot);
|
|
14108
14397
|
for (const [pkgName, pkgDir] of pkgEntries) {
|
|
14109
|
-
const pkgFiles = allSymbols.filter(
|
|
14110
|
-
(s) => s.file.startsWith(pkgDir + path24.sep)
|
|
14111
|
-
);
|
|
14398
|
+
const pkgFiles = allSymbols.filter((s) => s.file.startsWith(pkgDir + path24.sep));
|
|
14112
14399
|
if (pkgFiles.length === 0) continue;
|
|
14113
14400
|
const pkgUsed = pkgFiles.filter((s) => alive.has(s.id));
|
|
14114
14401
|
if (pkgUsed.length === 0) {
|
|
@@ -14149,7 +14436,10 @@ function findPackageEntries(projectRoot) {
|
|
|
14149
14436
|
pkgMap.set(rootPkg.name, projectRoot);
|
|
14150
14437
|
}
|
|
14151
14438
|
if (rootPkg) {
|
|
14152
|
-
|
|
14439
|
+
let wsDirs = extractWorkspaceGlobs(rootPkg, projectRoot);
|
|
14440
|
+
if (wsDirs.length === 0) {
|
|
14441
|
+
wsDirs = extractPnpmWorkspaceDirs(projectRoot);
|
|
14442
|
+
}
|
|
14153
14443
|
for (const wsDir of wsDirs) {
|
|
14154
14444
|
const wsPkg = tryReadJson(path24.join(wsDir, "package.json"));
|
|
14155
14445
|
if (wsPkg && typeof wsPkg.name === "string") {
|
|
@@ -14766,7 +15056,7 @@ function processFile(content, absPath, _style, _overwrite, target) {
|
|
|
14766
15056
|
|
|
14767
15057
|
// src/e2e.ts
|
|
14768
15058
|
init_util();
|
|
14769
|
-
import { open, readdir as
|
|
15059
|
+
import { open, readdir as readdir6 } from "node:fs/promises";
|
|
14770
15060
|
import * as path27 from "node:path";
|
|
14771
15061
|
async function readBoundedText(filePath, maxBytes) {
|
|
14772
15062
|
let handle;
|
|
@@ -14884,7 +15174,7 @@ async function scanWorkspace(root, maxDepth, signal) {
|
|
|
14884
15174
|
}
|
|
14885
15175
|
let entries;
|
|
14886
15176
|
try {
|
|
14887
|
-
entries = await
|
|
15177
|
+
entries = await readdir6(current.directory, { withFileTypes: true });
|
|
14888
15178
|
} catch {
|
|
14889
15179
|
continue;
|
|
14890
15180
|
}
|
|
@@ -14943,7 +15233,7 @@ async function detectPackageManager3(projectRoot, scanRoot, declared) {
|
|
|
14943
15233
|
while (true) {
|
|
14944
15234
|
const names = /* @__PURE__ */ new Set();
|
|
14945
15235
|
try {
|
|
14946
|
-
for (const entry of await
|
|
15236
|
+
for (const entry of await readdir6(directory)) names.add(entry);
|
|
14947
15237
|
} catch {
|
|
14948
15238
|
}
|
|
14949
15239
|
if (names.has("pnpm-lock.yaml")) return "pnpm";
|
|
@@ -15011,7 +15301,7 @@ async function collectSpecs(root, framework, testDirectory, signal) {
|
|
|
15011
15301
|
if (scanned > MAX_SCAN_DIRECTORIES) return { count, samples, truncated: true };
|
|
15012
15302
|
let entries;
|
|
15013
15303
|
try {
|
|
15014
|
-
entries = await
|
|
15304
|
+
entries = await readdir6(directory, { withFileTypes: true });
|
|
15015
15305
|
} catch {
|
|
15016
15306
|
continue;
|
|
15017
15307
|
}
|
|
@@ -17468,7 +17758,7 @@ async function detectFixer(cwd) {
|
|
|
17468
17758
|
init_util();
|
|
17469
17759
|
import { spawn as spawn10 } from "node:child_process";
|
|
17470
17760
|
import { statSync as statSync4 } from "node:fs";
|
|
17471
|
-
import { dirname as
|
|
17761
|
+
import { dirname as dirname14, resolve as resolve13, sep as sep6 } from "node:path";
|
|
17472
17762
|
import { assessCommitSafety } from "@wrongstack/core/coordination";
|
|
17473
17763
|
import { buildChildEnv as buildChildEnv4 } from "@wrongstack/core/utils";
|
|
17474
17764
|
var TIMEOUT_MS2 = 3e4;
|
|
@@ -17630,7 +17920,7 @@ function findGitDir2(cwd, projectRoot) {
|
|
|
17630
17920
|
} catch {
|
|
17631
17921
|
}
|
|
17632
17922
|
if (dir === root) break;
|
|
17633
|
-
const parent =
|
|
17923
|
+
const parent = dirname14(dir);
|
|
17634
17924
|
if (parent === dir) break;
|
|
17635
17925
|
dir = parent;
|
|
17636
17926
|
}
|
|
@@ -19774,7 +20064,7 @@ function createKanbanPresenceWrapper(projectRoot, input, ctx) {
|
|
|
19774
20064
|
|
|
19775
20065
|
// src/session-kanban.ts
|
|
19776
20066
|
import { watch } from "node:fs";
|
|
19777
|
-
import { basename as basename12, dirname as
|
|
20067
|
+
import { basename as basename12, dirname as dirname15 } from "node:path";
|
|
19778
20068
|
import { getSharedProjectMailbox } from "@wrongstack/core/coordination";
|
|
19779
20069
|
import {
|
|
19780
20070
|
loadPlan,
|
|
@@ -20246,7 +20536,7 @@ function attachSessionKanbanMirror(context) {
|
|
|
20246
20536
|
const configureWatcher = () => {
|
|
20247
20537
|
const planPath = context.meta["plan.path"];
|
|
20248
20538
|
const taskPath = context.meta["task.path"];
|
|
20249
|
-
const candidate = typeof planPath === "string" && planPath ?
|
|
20539
|
+
const candidate = typeof planPath === "string" && planPath ? dirname15(planPath) : typeof taskPath === "string" && taskPath ? dirname15(taskPath) : "";
|
|
20250
20540
|
if (!candidate || candidate === watchedDir) return;
|
|
20251
20541
|
watcher?.close();
|
|
20252
20542
|
watcher = null;
|
|
@@ -22128,12 +22418,13 @@ init_util();
|
|
|
22128
22418
|
import * as fs28 from "node:fs/promises";
|
|
22129
22419
|
import { FsError, ToolValidationError as ToolValidationError5 } from "@wrongstack/core/types";
|
|
22130
22420
|
import { toErrorMessage as toErrorMessage4 } from "@wrongstack/core/utils";
|
|
22421
|
+
var ADVANCED_MODE_META_KEY = "tools.read.advancedMode";
|
|
22131
22422
|
var MAX_BYTES2 = 5 * 1024 * 1024;
|
|
22132
22423
|
var readTool = {
|
|
22133
22424
|
name: "read",
|
|
22134
22425
|
category: "Filesystem",
|
|
22135
|
-
description: "Read the contents of a file with line numbers. This is the primary way to inspect source code, configuration, or any text file before making changes. Lines are returned 1-indexed with a ` N| ` prefix for easy reference in edits.",
|
|
22136
|
-
usageHint: "FOUNDATIONAL TOOL \u2014 call this before almost any edit operation.\n\nBest practices:\n- Always read a file before using `edit`, `replace`, or `write` on it (the system often requires it for safety).\n- Use `offset` + `limit` for very large files instead of reading everything at once.\n- Default limit is generous (2000 lines) but can be increased.\n- The output format is designed to be directly usable as context for `edit` operations.",
|
|
22426
|
+
description: "Read the contents of a file with line numbers. This is the primary way to inspect source code, configuration, or any text file before making changes. Lines are returned 1-indexed with a ` N| ` prefix for easy reference in edits. When advanced mode is on or `includeSymbols` is set, the result also includes a `symbols` field listing codebase-index symbol names, kinds, and line numbers for the file (not file content).",
|
|
22427
|
+
usageHint: "FOUNDATIONAL TOOL \u2014 call this before almost any edit operation.\n\nBest practices:\n- Always read a file before using `edit`, `replace`, or `write` on it (the system often requires it for safety).\n- Use `offset` + `limit` for very large files instead of reading everything at once.\n- Default limit is generous (2000 lines) but can be increased.\n- The output format is designed to be directly usable as context for `edit` operations.\n- Set `includeSymbols: true` to also receive the codebase-index symbol listing for the file.\n- Enable advanced mode (`ctx.meta['tools.read.advancedMode'] = true`) to auto-inject symbols on every read.",
|
|
22137
22428
|
selection: {
|
|
22138
22429
|
doNotUseWhen: "you need to search many files for matching content.",
|
|
22139
22430
|
useInstead: ["grep"]
|
|
@@ -22163,11 +22454,15 @@ var readTool = {
|
|
|
22163
22454
|
type: "string",
|
|
22164
22455
|
enum: ["content", "summary"],
|
|
22165
22456
|
description: "Return full line-numbered content (default) or a compact file summary with imports/exports/symbols."
|
|
22457
|
+
},
|
|
22458
|
+
includeSymbols: {
|
|
22459
|
+
type: "boolean",
|
|
22460
|
+
description: "When true, include the codebase-index symbol list for this file as a structured `symbols` field in the result. Overrides the advanced-mode meta flag per-call."
|
|
22166
22461
|
}
|
|
22167
22462
|
},
|
|
22168
22463
|
required: ["path"]
|
|
22169
22464
|
},
|
|
22170
|
-
async execute(input, ctx) {
|
|
22465
|
+
async execute(input, ctx, execOpts) {
|
|
22171
22466
|
if (!input?.path) {
|
|
22172
22467
|
throw new ToolValidationError5({
|
|
22173
22468
|
message: "read: path is required",
|
|
@@ -22175,6 +22470,7 @@ var readTool = {
|
|
|
22175
22470
|
});
|
|
22176
22471
|
}
|
|
22177
22472
|
const absPath = await safeResolveReal(input.path, ctx);
|
|
22473
|
+
const shouldIncludeSymbols = input.includeSymbols === true || input.includeSymbols !== false && ctx.meta[ADVANCED_MODE_META_KEY] === true;
|
|
22178
22474
|
let stat18;
|
|
22179
22475
|
try {
|
|
22180
22476
|
stat18 = await fs28.stat(absPath);
|
|
@@ -22218,13 +22514,15 @@ var readTool = {
|
|
|
22218
22514
|
const requestedEnd = prior ? Math.min(offset + limit - 1, prior.totalLines) : offset + limit - 1;
|
|
22219
22515
|
if (input.mode !== "summary" && limit > 0 && prior && coversRange(prior, stat18.mtimeMs, offset, requestedEnd)) {
|
|
22220
22516
|
ctx.recordRead(absPath, stat18.mtimeMs);
|
|
22517
|
+
const symResult2 = shouldIncludeSymbols ? await fetchSymbolsForFile(absPath, ctx, execOpts?.signal) : void 0;
|
|
22221
22518
|
return {
|
|
22222
22519
|
text: `[unchanged since previous read: "${input.path}" mtime=${Math.round(stat18.mtimeMs)}; requested lines ${offset}-${requestedEnd} were already shown. Use offset/limit for a new range if needed.]`,
|
|
22223
22520
|
total_lines: prior.totalLines,
|
|
22224
22521
|
encoding: "utf8",
|
|
22225
22522
|
truncated: requestedEnd < prior.totalLines,
|
|
22226
22523
|
cached: true,
|
|
22227
|
-
note: "Repeated read suppressed to save tokens."
|
|
22524
|
+
note: mergeSymbolNote("Repeated read suppressed to save tokens.", symResult2?.note),
|
|
22525
|
+
...symResult2?.symbols ? { symbols: symResult2.symbols } : {}
|
|
22228
22526
|
};
|
|
22229
22527
|
}
|
|
22230
22528
|
const buf = await fs28.readFile(absPath);
|
|
@@ -22238,27 +22536,43 @@ var readTool = {
|
|
|
22238
22536
|
if (input.mode === "summary") {
|
|
22239
22537
|
ctx.recordRead(absPath, stat18.mtimeMs, "user", contentHash);
|
|
22240
22538
|
rememberReadRange(ctx, absPath, stat18.mtimeMs, total, 1, Math.min(total, 200));
|
|
22539
|
+
const symResult2 = shouldIncludeSymbols ? await fetchSymbolsForFile(absPath, ctx, execOpts?.signal) : void 0;
|
|
22241
22540
|
return {
|
|
22242
22541
|
text: summarizeFile(input.path, stat18.size, allLines),
|
|
22243
22542
|
total_lines: total,
|
|
22244
22543
|
encoding: "utf8",
|
|
22245
22544
|
truncated: total > 200,
|
|
22246
|
-
note:
|
|
22545
|
+
note: mergeSymbolNote(
|
|
22546
|
+
"Summary mode returned compact structure instead of full file content.",
|
|
22547
|
+
symResult2?.note
|
|
22548
|
+
),
|
|
22549
|
+
...symResult2?.symbols ? { symbols: symResult2.symbols } : {}
|
|
22247
22550
|
};
|
|
22248
22551
|
}
|
|
22249
22552
|
if (limit === 0) {
|
|
22250
22553
|
ctx.recordRead(absPath, stat18.mtimeMs, "user", contentHash);
|
|
22251
22554
|
rememberReadRange(ctx, absPath, stat18.mtimeMs, total, 1, 0);
|
|
22252
|
-
|
|
22555
|
+
const symResult2 = shouldIncludeSymbols ? await fetchSymbolsForFile(absPath, ctx, execOpts?.signal) : void 0;
|
|
22556
|
+
return {
|
|
22557
|
+
text: "",
|
|
22558
|
+
total_lines: total,
|
|
22559
|
+
encoding: "utf8",
|
|
22560
|
+
truncated: total > 0,
|
|
22561
|
+
...symResult2?.symbols ? { symbols: symResult2.symbols } : {},
|
|
22562
|
+
...symResult2?.note ? { note: symResult2.note } : {}
|
|
22563
|
+
};
|
|
22253
22564
|
}
|
|
22254
22565
|
if (offset > total) {
|
|
22255
22566
|
ctx.recordRead(absPath, stat18.mtimeMs, "user", contentHash);
|
|
22256
22567
|
rememberReadRange(ctx, absPath, stat18.mtimeMs, total, total + 1, total + 1);
|
|
22568
|
+
const symResult2 = shouldIncludeSymbols ? await fetchSymbolsForFile(absPath, ctx, execOpts?.signal) : void 0;
|
|
22257
22569
|
return {
|
|
22258
22570
|
text: `[offset ${offset} is past end of file "${input.path}" \u2014 file has ${total} line(s). Do not retry this offset.]`,
|
|
22259
22571
|
total_lines: total,
|
|
22260
22572
|
encoding: "utf8",
|
|
22261
|
-
truncated: false
|
|
22573
|
+
truncated: false,
|
|
22574
|
+
...symResult2?.symbols ? { symbols: symResult2.symbols } : {},
|
|
22575
|
+
...symResult2?.note ? { note: symResult2.note } : {}
|
|
22262
22576
|
};
|
|
22263
22577
|
}
|
|
22264
22578
|
const slice = allLines.slice(offset - 1, offset - 1 + limit);
|
|
@@ -22267,14 +22581,53 @@ var readTool = {
|
|
|
22267
22581
|
const numbered = slice.map((line, i) => `${String(offset + i).padStart(width, " ")}\u2192${line}`).join("\n");
|
|
22268
22582
|
ctx.recordRead(absPath, stat18.mtimeMs, "user", contentHash);
|
|
22269
22583
|
rememberReadRange(ctx, absPath, stat18.mtimeMs, total, offset, offset + slice.length - 1);
|
|
22584
|
+
const symResult = shouldIncludeSymbols ? await fetchSymbolsForFile(absPath, ctx, execOpts?.signal) : void 0;
|
|
22270
22585
|
return {
|
|
22271
22586
|
text: numbered,
|
|
22272
22587
|
total_lines: total,
|
|
22273
22588
|
encoding: "utf8",
|
|
22274
|
-
truncated
|
|
22589
|
+
truncated,
|
|
22590
|
+
...symResult?.symbols ? { symbols: symResult.symbols } : {},
|
|
22591
|
+
...symResult?.note ? { note: symResult.note } : {}
|
|
22275
22592
|
};
|
|
22276
22593
|
}
|
|
22277
22594
|
};
|
|
22595
|
+
async function fetchSymbolsForFile(absPath, ctx, signal) {
|
|
22596
|
+
try {
|
|
22597
|
+
const state = getIndexState();
|
|
22598
|
+
if (!state.ready) return {};
|
|
22599
|
+
const { results, total } = await searchCodebaseIndex(
|
|
22600
|
+
{
|
|
22601
|
+
projectRoot: ctx.projectRoot,
|
|
22602
|
+
indexDir: codebaseIndexDirOverride(ctx),
|
|
22603
|
+
query: "",
|
|
22604
|
+
file: absPath,
|
|
22605
|
+
limit: 500
|
|
22606
|
+
},
|
|
22607
|
+
{ signal }
|
|
22608
|
+
);
|
|
22609
|
+
if (results.length === 0) return {};
|
|
22610
|
+
const sorted = results.map((r) => ({
|
|
22611
|
+
name: r.name,
|
|
22612
|
+
kind: r.kind,
|
|
22613
|
+
line: r.line,
|
|
22614
|
+
col: r.col,
|
|
22615
|
+
signature: r.signature
|
|
22616
|
+
})).sort((a, b) => a.line - b.line || a.col - b.col);
|
|
22617
|
+
const result = { symbols: sorted };
|
|
22618
|
+
if (total > results.length) {
|
|
22619
|
+
result.note = `Symbol listing truncated to ${results.length} of ${total} entries.`;
|
|
22620
|
+
}
|
|
22621
|
+
return result;
|
|
22622
|
+
} catch {
|
|
22623
|
+
return {};
|
|
22624
|
+
}
|
|
22625
|
+
}
|
|
22626
|
+
function mergeSymbolNote(note, symNote) {
|
|
22627
|
+
if (!symNote) return note;
|
|
22628
|
+
if (!note) return symNote;
|
|
22629
|
+
return `${note} ${symNote}`;
|
|
22630
|
+
}
|
|
22278
22631
|
var READ_RANGES_META_KEY = "tools.read.ranges.v1";
|
|
22279
22632
|
function getReadRanges(ctx) {
|
|
22280
22633
|
const existing = ctx.meta[READ_RANGES_META_KEY];
|