scip-query 0.4.1 → 0.4.2
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/cli.js +280 -109
- package/dist/index.d.ts +18 -1
- package/dist/index.js +192 -24
- package/dist/reindex-worker.js +146 -5
- package/package.json +3 -1
package/dist/cli.js
CHANGED
|
@@ -115,7 +115,7 @@ var ScipDatabase = class {
|
|
|
115
115
|
// src/gitignore-filter.ts
|
|
116
116
|
import ignore from "ignore";
|
|
117
117
|
import { readFileSync, existsSync } from "fs";
|
|
118
|
-
import { join,
|
|
118
|
+
import { dirname, isAbsolute, join, relative, resolve } from "path";
|
|
119
119
|
function createGitignoreFilter(projectRoot) {
|
|
120
120
|
const ig = ignore();
|
|
121
121
|
let loaded = false;
|
|
@@ -132,8 +132,8 @@ function createGitignoreFilter(projectRoot) {
|
|
|
132
132
|
ig.add(DEFAULT_IGNORES);
|
|
133
133
|
}
|
|
134
134
|
return {
|
|
135
|
-
isIgnored: (relativePath) => ig
|
|
136
|
-
filter: (paths) => paths.filter((p) => !ig
|
|
135
|
+
isIgnored: (relativePath) => safeIgnores(ig, projectRoot, relativePath),
|
|
136
|
+
filter: (paths) => paths.filter((p) => !safeIgnores(ig, projectRoot, p))
|
|
137
137
|
};
|
|
138
138
|
}
|
|
139
139
|
function findGitignoreFiles(projectRoot) {
|
|
@@ -213,10 +213,35 @@ Thumbs.db
|
|
|
213
213
|
# Type definitions (often noise in queries)
|
|
214
214
|
*.d.ts
|
|
215
215
|
`;
|
|
216
|
+
function safeIgnores(ig, projectRoot, inputPath) {
|
|
217
|
+
const relativePath = normalizeForIgnore(projectRoot, inputPath);
|
|
218
|
+
if (!relativePath) {
|
|
219
|
+
return false;
|
|
220
|
+
}
|
|
221
|
+
try {
|
|
222
|
+
return ig.ignores(relativePath);
|
|
223
|
+
} catch {
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
function normalizeForIgnore(projectRoot, inputPath) {
|
|
228
|
+
if (!inputPath || inputPath === ".") {
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
if (!isAbsolute(inputPath) && !inputPath.startsWith("..")) {
|
|
232
|
+
return inputPath.replaceAll("\\", "/");
|
|
233
|
+
}
|
|
234
|
+
const absolutePath = isAbsolute(inputPath) ? inputPath : resolve(projectRoot, inputPath);
|
|
235
|
+
const relativePath = relative(projectRoot, absolutePath).replaceAll("\\", "/");
|
|
236
|
+
if (!relativePath || relativePath === "." || relativePath.startsWith("..")) {
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
239
|
+
return relativePath;
|
|
240
|
+
}
|
|
216
241
|
|
|
217
242
|
// src/config.ts
|
|
218
243
|
import { readFileSync as readFileSync2, writeFileSync, existsSync as existsSync2, mkdirSync } from "fs";
|
|
219
|
-
import { join as join2, resolve } from "path";
|
|
244
|
+
import { join as join2, resolve as resolve2 } from "path";
|
|
220
245
|
import { createHash } from "crypto";
|
|
221
246
|
import { homedir } from "os";
|
|
222
247
|
var CONFIG_FILENAME = ".scipquery.json";
|
|
@@ -247,10 +272,10 @@ function resolveWatchConfig(config) {
|
|
|
247
272
|
function resolveCacheDir(projectRoot, config) {
|
|
248
273
|
const envOverride = process.env["SCIP_QUERY_CACHE_DIR"];
|
|
249
274
|
if (envOverride) return ensureDir(envOverride);
|
|
250
|
-
if (config?.dbPath) return ensureDir(
|
|
275
|
+
if (config?.dbPath) return ensureDir(resolve2(projectRoot, config.dbPath));
|
|
251
276
|
const xdgCache = process.env["XDG_CACHE_HOME"];
|
|
252
277
|
const cacheBase = xdgCache || join2(homedir(), ".cache");
|
|
253
|
-
const projectHash = createHash("sha256").update(
|
|
278
|
+
const projectHash = createHash("sha256").update(resolve2(projectRoot)).digest("hex").slice(0, 12);
|
|
254
279
|
const dir = join2(cacheBase, "scip-query", "projects", projectHash);
|
|
255
280
|
return ensureDir(dir);
|
|
256
281
|
}
|
|
@@ -286,8 +311,8 @@ function ensureDir(dir) {
|
|
|
286
311
|
|
|
287
312
|
// src/reindex/index.ts
|
|
288
313
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
289
|
-
import { existsSync as existsSync6, renameSync } from "fs";
|
|
290
|
-
import { join as join6 } from "path";
|
|
314
|
+
import { existsSync as existsSync6, renameSync, rmSync } from "fs";
|
|
315
|
+
import { basename, dirname as dirname2, extname as extname2, join as join6 } from "path";
|
|
291
316
|
|
|
292
317
|
// src/scip-cli.ts
|
|
293
318
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
@@ -968,6 +993,128 @@ function resolveDotnetProject(projectRoot, suffixes) {
|
|
|
968
993
|
return null;
|
|
969
994
|
}
|
|
970
995
|
|
|
996
|
+
// src/reindex/merge.ts
|
|
997
|
+
import { readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
998
|
+
import { create } from "@bufbuild/protobuf";
|
|
999
|
+
import {
|
|
1000
|
+
deserializeSCIP,
|
|
1001
|
+
serializeSCIP,
|
|
1002
|
+
DocumentSchema,
|
|
1003
|
+
IndexSchema,
|
|
1004
|
+
SymbolInformationSchema
|
|
1005
|
+
} from "@c4312/scip";
|
|
1006
|
+
function mergeScipIndexes(indexes) {
|
|
1007
|
+
if (indexes.length === 0) {
|
|
1008
|
+
throw new Error("Cannot merge zero SCIP indexes");
|
|
1009
|
+
}
|
|
1010
|
+
if (indexes.length === 1) {
|
|
1011
|
+
return indexes[0];
|
|
1012
|
+
}
|
|
1013
|
+
const metadata = mergeMetadata(indexes);
|
|
1014
|
+
const documents = mergeDocuments(indexes.flatMap((index) => index.documents ?? []));
|
|
1015
|
+
const externalSymbols = mergeSymbolInfos(indexes.flatMap((index) => index.externalSymbols ?? []));
|
|
1016
|
+
return create(IndexSchema, {
|
|
1017
|
+
metadata,
|
|
1018
|
+
documents,
|
|
1019
|
+
externalSymbols
|
|
1020
|
+
});
|
|
1021
|
+
}
|
|
1022
|
+
function mergeScipFiles(inputPaths, outputPath) {
|
|
1023
|
+
if (inputPaths.length === 0) {
|
|
1024
|
+
throw new Error("Cannot merge zero SCIP files");
|
|
1025
|
+
}
|
|
1026
|
+
const indexes = inputPaths.map((path2) => deserializeSCIP(readFileSync3(path2)));
|
|
1027
|
+
const merged = mergeScipIndexes(indexes);
|
|
1028
|
+
writeFileSync2(outputPath, Buffer.from(serializeSCIP(merged)));
|
|
1029
|
+
return {
|
|
1030
|
+
documentCount: merged.documents.length,
|
|
1031
|
+
externalSymbolCount: merged.externalSymbols.length,
|
|
1032
|
+
inputCount: inputPaths.length
|
|
1033
|
+
};
|
|
1034
|
+
}
|
|
1035
|
+
function mergeMetadata(indexes) {
|
|
1036
|
+
const first = indexes[0]?.metadata;
|
|
1037
|
+
if (!first) {
|
|
1038
|
+
return void 0;
|
|
1039
|
+
}
|
|
1040
|
+
const expectedProjectRoot = first.projectRoot;
|
|
1041
|
+
for (const index of indexes.slice(1)) {
|
|
1042
|
+
const actualProjectRoot = index.metadata?.projectRoot;
|
|
1043
|
+
if (expectedProjectRoot && actualProjectRoot && actualProjectRoot !== expectedProjectRoot) {
|
|
1044
|
+
throw new Error(
|
|
1045
|
+
`Cannot merge SCIP indexes with different project roots: ${expectedProjectRoot} vs ${actualProjectRoot}`
|
|
1046
|
+
);
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
return first;
|
|
1050
|
+
}
|
|
1051
|
+
function mergeDocuments(documents) {
|
|
1052
|
+
const byPath = /* @__PURE__ */ new Map();
|
|
1053
|
+
for (const document of documents) {
|
|
1054
|
+
const existing = byPath.get(document.relativePath);
|
|
1055
|
+
if (!existing) {
|
|
1056
|
+
byPath.set(document.relativePath, document);
|
|
1057
|
+
continue;
|
|
1058
|
+
}
|
|
1059
|
+
byPath.set(document.relativePath, create(DocumentSchema, {
|
|
1060
|
+
language: existing.language || document.language,
|
|
1061
|
+
relativePath: existing.relativePath || document.relativePath,
|
|
1062
|
+
occurrences: [...existing.occurrences, ...document.occurrences],
|
|
1063
|
+
symbols: mergeSymbolInfos([...existing.symbols, ...document.symbols]),
|
|
1064
|
+
text: chooseText(existing.text, document.text),
|
|
1065
|
+
positionEncoding: existing.positionEncoding || document.positionEncoding
|
|
1066
|
+
}));
|
|
1067
|
+
}
|
|
1068
|
+
return [...byPath.values()];
|
|
1069
|
+
}
|
|
1070
|
+
function mergeSymbolInfos(symbols2) {
|
|
1071
|
+
const bySymbol = /* @__PURE__ */ new Map();
|
|
1072
|
+
for (const symbol of symbols2) {
|
|
1073
|
+
const existing = bySymbol.get(symbol.symbol);
|
|
1074
|
+
if (!existing) {
|
|
1075
|
+
bySymbol.set(symbol.symbol, symbol);
|
|
1076
|
+
continue;
|
|
1077
|
+
}
|
|
1078
|
+
bySymbol.set(symbol.symbol, create(SymbolInformationSchema, {
|
|
1079
|
+
symbol: existing.symbol,
|
|
1080
|
+
documentation: uniqueStrings([...existing.documentation, ...symbol.documentation]),
|
|
1081
|
+
relationships: mergeRelationships([...existing.relationships, ...symbol.relationships]),
|
|
1082
|
+
kind: existing.kind || symbol.kind,
|
|
1083
|
+
displayName: existing.displayName || symbol.displayName,
|
|
1084
|
+
enclosingSymbol: existing.enclosingSymbol || symbol.enclosingSymbol,
|
|
1085
|
+
signatureDocumentation: existing.signatureDocumentation ?? symbol.signatureDocumentation
|
|
1086
|
+
}));
|
|
1087
|
+
}
|
|
1088
|
+
return [...bySymbol.values()];
|
|
1089
|
+
}
|
|
1090
|
+
function mergeRelationships(relationships) {
|
|
1091
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1092
|
+
const merged = [];
|
|
1093
|
+
for (const relationship of relationships) {
|
|
1094
|
+
const key = [
|
|
1095
|
+
relationship.symbol,
|
|
1096
|
+
relationship.isReference ? "1" : "0",
|
|
1097
|
+
relationship.isImplementation ? "1" : "0",
|
|
1098
|
+
relationship.isTypeDefinition ? "1" : "0",
|
|
1099
|
+
relationship.isDefinition ? "1" : "0"
|
|
1100
|
+
].join("|");
|
|
1101
|
+
if (seen.has(key)) {
|
|
1102
|
+
continue;
|
|
1103
|
+
}
|
|
1104
|
+
seen.add(key);
|
|
1105
|
+
merged.push(relationship);
|
|
1106
|
+
}
|
|
1107
|
+
return merged;
|
|
1108
|
+
}
|
|
1109
|
+
function chooseText(left, right) {
|
|
1110
|
+
if (!left) return right;
|
|
1111
|
+
if (!right) return left;
|
|
1112
|
+
return left.length >= right.length ? left : right;
|
|
1113
|
+
}
|
|
1114
|
+
function uniqueStrings(values) {
|
|
1115
|
+
return [...new Set(values)];
|
|
1116
|
+
}
|
|
1117
|
+
|
|
971
1118
|
// src/reindex/index.ts
|
|
972
1119
|
async function reindex(opts) {
|
|
973
1120
|
const {
|
|
@@ -1003,7 +1150,11 @@ async function reindex(opts) {
|
|
|
1003
1150
|
...process.env,
|
|
1004
1151
|
NODE_OPTIONS: `--max-old-space-size=${maxHeapMb}`
|
|
1005
1152
|
};
|
|
1006
|
-
|
|
1153
|
+
const languageOutputs = languages.map((language, index) => ({
|
|
1154
|
+
language,
|
|
1155
|
+
scipPath: languages.length > 1 ? tempScipPath(outputScip, language, index) : outputScip
|
|
1156
|
+
}));
|
|
1157
|
+
for (const { language: lang, scipPath } of languageOutputs) {
|
|
1007
1158
|
const config = getIndexerConfig(lang);
|
|
1008
1159
|
const binaryLabel = describeIndexerBinary(config);
|
|
1009
1160
|
const projectLocalBinary = resolveProjectLocalIndexerBinary(config, projectRoot);
|
|
@@ -1033,7 +1184,7 @@ async function reindex(opts) {
|
|
|
1033
1184
|
const indexerEnv = getIndexerExecutionEnv(config, env, resolvedBinary);
|
|
1034
1185
|
const { binary, args } = config.indexArgs({
|
|
1035
1186
|
projectRoot,
|
|
1036
|
-
outputPath:
|
|
1187
|
+
outputPath: scipPath,
|
|
1037
1188
|
pnpmWorkspaces: opts.pnpmWorkspaces,
|
|
1038
1189
|
indexerBinary: resolvedBinary
|
|
1039
1190
|
});
|
|
@@ -1052,7 +1203,11 @@ Make sure ${binaryLabel} is installed and available on PATH.`,
|
|
|
1052
1203
|
{ cause: err }
|
|
1053
1204
|
);
|
|
1054
1205
|
}
|
|
1055
|
-
moveDefaultOutputIfNeeded(config, projectRoot,
|
|
1206
|
+
moveDefaultOutputIfNeeded(config, projectRoot, scipPath);
|
|
1207
|
+
}
|
|
1208
|
+
if (languageOutputs.length > 1) {
|
|
1209
|
+
onStatus(`Merging ${languageOutputs.length} language indexes...`);
|
|
1210
|
+
mergeScipFiles(languageOutputs.map((entry) => entry.scipPath), outputScip);
|
|
1056
1211
|
}
|
|
1057
1212
|
onStatus("Converting to SQLite...");
|
|
1058
1213
|
if (!existsSync6(outputScip)) {
|
|
@@ -1067,6 +1222,12 @@ Make sure ${binaryLabel} is installed and available on PATH.`,
|
|
|
1067
1222
|
} catch (err) {
|
|
1068
1223
|
const msg = err instanceof Error ? err.message : String(err);
|
|
1069
1224
|
throw new Error(`Failed to convert SCIP index to SQLite: ${msg}`, { cause: err });
|
|
1225
|
+
} finally {
|
|
1226
|
+
for (const { scipPath } of languageOutputs) {
|
|
1227
|
+
if (scipPath !== outputScip) {
|
|
1228
|
+
rmSync(scipPath, { force: true });
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1070
1231
|
}
|
|
1071
1232
|
const durationMs = Date.now() - start;
|
|
1072
1233
|
onStatus(`Done in ${(durationMs / 1e3).toFixed(1)}s`);
|
|
@@ -1081,11 +1242,16 @@ function moveDefaultOutputIfNeeded(config, projectRoot, outputScip) {
|
|
|
1081
1242
|
renameSync(defaultOutputPath, outputScip);
|
|
1082
1243
|
}
|
|
1083
1244
|
}
|
|
1245
|
+
function tempScipPath(outputScip, language, index) {
|
|
1246
|
+
const extension = extname2(outputScip) || ".scip";
|
|
1247
|
+
const stem = basename(outputScip, extension);
|
|
1248
|
+
return join6(dirname2(outputScip), `${stem}.${index + 1}.${language}${extension}`);
|
|
1249
|
+
}
|
|
1084
1250
|
|
|
1085
1251
|
// src/watch.ts
|
|
1086
1252
|
import { watch } from "fs";
|
|
1087
1253
|
import { existsSync as existsSync7, renameSync as renameSync2 } from "fs";
|
|
1088
|
-
import { join as join7, relative } from "path";
|
|
1254
|
+
import { join as join7, relative as relative2 } from "path";
|
|
1089
1255
|
import { fork } from "child_process";
|
|
1090
1256
|
import ignore2 from "ignore";
|
|
1091
1257
|
var Watcher = class {
|
|
@@ -1163,7 +1329,7 @@ var Watcher = class {
|
|
|
1163
1329
|
}
|
|
1164
1330
|
// ── Internal ─────────────────────────────────────────────
|
|
1165
1331
|
handleFileChange(filename) {
|
|
1166
|
-
const rel =
|
|
1332
|
+
const rel = relative2(this.projectRoot, join7(this.projectRoot, filename));
|
|
1167
1333
|
if (this.gitignoreFilter.isIgnored(rel)) return;
|
|
1168
1334
|
if (this.extraIgnore.ignores(rel)) return;
|
|
1169
1335
|
if (filename.endsWith("index.db") || filename.endsWith("index.scip") || filename.endsWith("index.db.tmp") || filename.endsWith(".scipquery.json")) {
|
|
@@ -1244,10 +1410,10 @@ var Watcher = class {
|
|
|
1244
1410
|
* Writes to index.db.tmp, then atomically renames to index.db.
|
|
1245
1411
|
*/
|
|
1246
1412
|
runReindex() {
|
|
1247
|
-
return new Promise((
|
|
1413
|
+
return new Promise((resolve5, reject) => {
|
|
1248
1414
|
const start = Date.now();
|
|
1249
1415
|
const tmpDb = this.indexPaths.dbPath + ".tmp";
|
|
1250
|
-
const tmpScip =
|
|
1416
|
+
const tmpScip = tempScipPath2(this.indexPaths.indexPath);
|
|
1251
1417
|
const child = fork(
|
|
1252
1418
|
new URL("./reindex-worker.js", import.meta.url).pathname,
|
|
1253
1419
|
[],
|
|
@@ -1272,7 +1438,7 @@ var Watcher = class {
|
|
|
1272
1438
|
if (existsSync7(tmpScip)) {
|
|
1273
1439
|
renameSync2(tmpScip, this.indexPaths.indexPath);
|
|
1274
1440
|
}
|
|
1275
|
-
|
|
1441
|
+
resolve5(Date.now() - start);
|
|
1276
1442
|
} catch (err) {
|
|
1277
1443
|
reject(new Error(`Atomic swap failed: ${err}`));
|
|
1278
1444
|
}
|
|
@@ -1288,7 +1454,7 @@ var Watcher = class {
|
|
|
1288
1454
|
this.onStatus(status);
|
|
1289
1455
|
}
|
|
1290
1456
|
};
|
|
1291
|
-
function
|
|
1457
|
+
function tempScipPath2(indexPath) {
|
|
1292
1458
|
return indexPath.endsWith(".scip") ? indexPath.slice(0, -".scip".length) + ".tmp.scip" : indexPath + ".tmp.scip";
|
|
1293
1459
|
}
|
|
1294
1460
|
|
|
@@ -1324,20 +1490,20 @@ function files(db, pattern) {
|
|
|
1324
1490
|
}
|
|
1325
1491
|
|
|
1326
1492
|
// src/query-support.ts
|
|
1327
|
-
import { basename as
|
|
1493
|
+
import { basename as basename3 } from "path";
|
|
1328
1494
|
|
|
1329
1495
|
// src/source-analysis.ts
|
|
1330
1496
|
import {
|
|
1331
1497
|
existsSync as existsSync8,
|
|
1332
|
-
readFileSync as
|
|
1498
|
+
readFileSync as readFileSync4
|
|
1333
1499
|
} from "fs";
|
|
1334
1500
|
import {
|
|
1335
|
-
basename,
|
|
1336
|
-
dirname as
|
|
1337
|
-
extname as
|
|
1501
|
+
basename as basename2,
|
|
1502
|
+
dirname as dirname3,
|
|
1503
|
+
extname as extname3,
|
|
1338
1504
|
join as join8,
|
|
1339
|
-
relative as
|
|
1340
|
-
resolve as
|
|
1505
|
+
relative as relative3,
|
|
1506
|
+
resolve as resolve3
|
|
1341
1507
|
} from "path";
|
|
1342
1508
|
var SOURCE_IMPORT_CACHE = /* @__PURE__ */ new WeakMap();
|
|
1343
1509
|
var SOURCE_EXPORT_CACHE = /* @__PURE__ */ new WeakMap();
|
|
@@ -1366,7 +1532,7 @@ function getSourceImports(db, relativePath) {
|
|
|
1366
1532
|
cache.set(normalized, []);
|
|
1367
1533
|
return [];
|
|
1368
1534
|
}
|
|
1369
|
-
const source =
|
|
1535
|
+
const source = readFileSync4(fullPath, "utf-8");
|
|
1370
1536
|
const parsed = isPythonSourcePath(normalized) ? parsePythonImports(db, normalized, source) : isJavaScriptSourcePath(normalized) ? parseJavaScriptImports(db, normalized, source) : isJvmSourcePath(normalized) ? parseJvmImports(db, normalized, source) : isRustSourcePath(normalized) ? parseRustImports(db, normalized, source) : isRubySourcePath(normalized) ? parseRubyImports(db, normalized, source) : isCLikeSourcePath(normalized) ? parseCLikeImports(db, normalized, source) : isDotNetSourcePath(normalized) ? parseDotNetImports(db, normalized, source) : isDartSourcePath(normalized) ? parseDartImports(db, normalized, source) : isPhpSourcePath(normalized) ? parsePhpImports(db, normalized, source) : [];
|
|
1371
1537
|
cache.set(normalized, parsed);
|
|
1372
1538
|
return parsed;
|
|
@@ -1383,7 +1549,7 @@ function getSourceExports(db, relativePath) {
|
|
|
1383
1549
|
cache.set(normalized, []);
|
|
1384
1550
|
return [];
|
|
1385
1551
|
}
|
|
1386
|
-
const source =
|
|
1552
|
+
const source = readFileSync4(fullPath, "utf-8");
|
|
1387
1553
|
const parsed = isDartSourcePath(normalized) ? parseDartExports(db, normalized, source) : isRustSourcePath(normalized) ? parseRustExports(db, normalized, source) : [];
|
|
1388
1554
|
cache.set(normalized, parsed);
|
|
1389
1555
|
return parsed;
|
|
@@ -1680,7 +1846,7 @@ function parseRubyImports(db, importerPath, source) {
|
|
|
1680
1846
|
return statements;
|
|
1681
1847
|
}
|
|
1682
1848
|
function rubyConstantName(specifier) {
|
|
1683
|
-
return
|
|
1849
|
+
return basename2(specifier).replace(/\.[^.]+$/, "").split("_").filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
|
|
1684
1850
|
}
|
|
1685
1851
|
function parseCLikeImports(db, importerPath, source) {
|
|
1686
1852
|
const statements = [];
|
|
@@ -1689,7 +1855,7 @@ function parseCLikeImports(db, importerPath, source) {
|
|
|
1689
1855
|
const full = match[0];
|
|
1690
1856
|
if (!specifier || !full || typeof match.index !== "number") continue;
|
|
1691
1857
|
const body = buildUsageBody(source, match.index, match.index + full.length);
|
|
1692
|
-
const localName =
|
|
1858
|
+
const localName = basename2(specifier).replace(/\.[^.]+$/, "");
|
|
1693
1859
|
statements.push({
|
|
1694
1860
|
importedName: specifier,
|
|
1695
1861
|
localName,
|
|
@@ -2164,16 +2330,16 @@ function resolveJavaScriptImportPath(db, importerPath, specifier) {
|
|
|
2164
2330
|
if (!specifier.startsWith(".") && !specifier.startsWith("/")) {
|
|
2165
2331
|
return null;
|
|
2166
2332
|
}
|
|
2167
|
-
const importerDir =
|
|
2168
|
-
const absolute =
|
|
2333
|
+
const importerDir = dirname3(join8(db.config.projectRoot, importerPath));
|
|
2334
|
+
const absolute = resolve3(importerDir, specifier);
|
|
2169
2335
|
const indexedPaths = getIndexedPaths(db);
|
|
2170
2336
|
for (const candidate of candidateImportPaths(absolute)) {
|
|
2171
|
-
const relativeCandidate = normalizePath(
|
|
2337
|
+
const relativeCandidate = normalizePath(relative3(db.config.projectRoot, candidate));
|
|
2172
2338
|
if (indexedPaths.has(relativeCandidate) || existsSync8(candidate)) {
|
|
2173
2339
|
return relativeCandidate;
|
|
2174
2340
|
}
|
|
2175
2341
|
}
|
|
2176
|
-
return normalizePath(
|
|
2342
|
+
return normalizePath(relative3(db.config.projectRoot, absolute));
|
|
2177
2343
|
}
|
|
2178
2344
|
function resolvePythonImportPath(db, importerPath, specifier) {
|
|
2179
2345
|
const indexedPaths = getIndexedPaths(db);
|
|
@@ -2183,16 +2349,16 @@ function resolvePythonImportPath(db, importerPath, specifier) {
|
|
|
2183
2349
|
if (!match) return null;
|
|
2184
2350
|
const dots = match[1].length;
|
|
2185
2351
|
const remainder = match[2].replace(/^\./, "");
|
|
2186
|
-
let baseDir =
|
|
2352
|
+
let baseDir = dirname3(join8(db.config.projectRoot, importerPath));
|
|
2187
2353
|
for (let i = 1; i < dots; i++) {
|
|
2188
|
-
baseDir =
|
|
2354
|
+
baseDir = dirname3(baseDir);
|
|
2189
2355
|
}
|
|
2190
|
-
basePath = remainder ?
|
|
2356
|
+
basePath = remainder ? resolve3(baseDir, remainder.replace(/\./g, "/")) : baseDir;
|
|
2191
2357
|
} else {
|
|
2192
|
-
basePath =
|
|
2358
|
+
basePath = resolve3(db.config.projectRoot, specifier.replace(/\./g, "/"));
|
|
2193
2359
|
}
|
|
2194
2360
|
for (const candidate of pythonCandidateImportPaths(basePath)) {
|
|
2195
|
-
const relativeCandidate = normalizePath(
|
|
2361
|
+
const relativeCandidate = normalizePath(relative3(db.config.projectRoot, candidate));
|
|
2196
2362
|
if (indexedPaths.has(relativeCandidate) || existsSync8(candidate)) {
|
|
2197
2363
|
return relativeCandidate;
|
|
2198
2364
|
}
|
|
@@ -2205,17 +2371,17 @@ function resolveRustImportPath(db, importerPath, specifier) {
|
|
|
2205
2371
|
if (!normalizedSpecifier.startsWith("crate::") && !normalizedSpecifier.startsWith("self::") && !normalizedSpecifier.startsWith("super::")) {
|
|
2206
2372
|
return null;
|
|
2207
2373
|
}
|
|
2208
|
-
const importerDir =
|
|
2374
|
+
const importerDir = dirname3(join8(db.config.projectRoot, importerPath));
|
|
2209
2375
|
let basePath;
|
|
2210
2376
|
if (normalizedSpecifier.startsWith("crate::")) {
|
|
2211
|
-
basePath =
|
|
2377
|
+
basePath = resolve3(db.config.projectRoot, "src", normalizedSpecifier.slice("crate::".length).replace(/::/g, "/"));
|
|
2212
2378
|
} else if (normalizedSpecifier.startsWith("self::")) {
|
|
2213
|
-
basePath =
|
|
2379
|
+
basePath = resolve3(importerDir, normalizedSpecifier.slice("self::".length).replace(/::/g, "/"));
|
|
2214
2380
|
} else {
|
|
2215
|
-
basePath =
|
|
2381
|
+
basePath = resolve3(dirname3(importerDir), normalizedSpecifier.slice("super::".length).replace(/::/g, "/"));
|
|
2216
2382
|
}
|
|
2217
2383
|
for (const candidate of rustCandidateImportPaths(basePath)) {
|
|
2218
|
-
const relativeCandidate = normalizePath(
|
|
2384
|
+
const relativeCandidate = normalizePath(relative3(db.config.projectRoot, candidate));
|
|
2219
2385
|
if (getIndexedPaths(db).has(relativeCandidate) || existsSync8(candidate)) {
|
|
2220
2386
|
return relativeCandidate;
|
|
2221
2387
|
}
|
|
@@ -2223,10 +2389,10 @@ function resolveRustImportPath(db, importerPath, specifier) {
|
|
|
2223
2389
|
return null;
|
|
2224
2390
|
}
|
|
2225
2391
|
function resolveRubyImportPath(db, importerPath, specifier) {
|
|
2226
|
-
const importerDir =
|
|
2227
|
-
const absolute =
|
|
2392
|
+
const importerDir = dirname3(join8(db.config.projectRoot, importerPath));
|
|
2393
|
+
const absolute = resolve3(importerDir, specifier);
|
|
2228
2394
|
for (const candidate of rubyCandidateImportPaths(absolute)) {
|
|
2229
|
-
const relativeCandidate = normalizePath(
|
|
2395
|
+
const relativeCandidate = normalizePath(relative3(db.config.projectRoot, candidate));
|
|
2230
2396
|
if (getIndexedPaths(db).has(relativeCandidate) || existsSync8(candidate)) {
|
|
2231
2397
|
return relativeCandidate;
|
|
2232
2398
|
}
|
|
@@ -2235,15 +2401,15 @@ function resolveRubyImportPath(db, importerPath, specifier) {
|
|
|
2235
2401
|
}
|
|
2236
2402
|
function resolveCLikeImportPath(db, importerPath, specifier) {
|
|
2237
2403
|
const indexedPaths = getIndexedPaths(db);
|
|
2238
|
-
const importerDir =
|
|
2404
|
+
const importerDir = dirname3(join8(db.config.projectRoot, importerPath));
|
|
2239
2405
|
const candidates = [
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2406
|
+
resolve3(importerDir, specifier),
|
|
2407
|
+
resolve3(db.config.projectRoot, specifier),
|
|
2408
|
+
resolve3(db.config.projectRoot, "include", specifier),
|
|
2409
|
+
resolve3(db.config.projectRoot, "src", specifier)
|
|
2244
2410
|
];
|
|
2245
2411
|
for (const candidate of candidates) {
|
|
2246
|
-
const relativeCandidate = normalizePath(
|
|
2412
|
+
const relativeCandidate = normalizePath(relative3(db.config.projectRoot, candidate));
|
|
2247
2413
|
if (indexedPaths.has(relativeCandidate) || existsSync8(candidate)) {
|
|
2248
2414
|
return relativeCandidate;
|
|
2249
2415
|
}
|
|
@@ -2261,10 +2427,10 @@ function resolveQualifiedImportPath(db, specifier, extensions) {
|
|
|
2261
2427
|
if (exact) return exact;
|
|
2262
2428
|
}
|
|
2263
2429
|
for (const ext of extensions) {
|
|
2264
|
-
const basenameMatch = [...indexedPaths].find((relativePath) =>
|
|
2430
|
+
const basenameMatch = [...indexedPaths].find((relativePath) => basename2(relativePath) === `${basenameOnly}${ext}`);
|
|
2265
2431
|
if (basenameMatch) return basenameMatch;
|
|
2266
2432
|
}
|
|
2267
|
-
const folderMatches = [...indexedPaths].filter((relativePath) => extensions.includes(
|
|
2433
|
+
const folderMatches = [...indexedPaths].filter((relativePath) => extensions.includes(extname3(relativePath).toLowerCase())).filter((relativePath) => relativePath.includes(`/${pathified}/`) || relativePath.includes(`/${basenameOnly}/`)).sort((left, right) => left.localeCompare(right));
|
|
2268
2434
|
if (folderMatches.length === 1) {
|
|
2269
2435
|
return folderMatches[0];
|
|
2270
2436
|
}
|
|
@@ -2281,10 +2447,10 @@ function resolveDartImportPath(db, importerPath, specifier) {
|
|
|
2281
2447
|
if (indexedPaths.has(candidate)) return candidate;
|
|
2282
2448
|
return null;
|
|
2283
2449
|
}
|
|
2284
|
-
const importerDir =
|
|
2285
|
-
const absolute =
|
|
2450
|
+
const importerDir = dirname3(join8(db.config.projectRoot, importerPath));
|
|
2451
|
+
const absolute = resolve3(importerDir, specifier);
|
|
2286
2452
|
for (const candidate of dartCandidateImportPaths(absolute)) {
|
|
2287
|
-
const relativeCandidate = normalizePath(
|
|
2453
|
+
const relativeCandidate = normalizePath(relative3(db.config.projectRoot, candidate));
|
|
2288
2454
|
if (indexedPaths.has(relativeCandidate) || existsSync8(candidate)) {
|
|
2289
2455
|
return relativeCandidate;
|
|
2290
2456
|
}
|
|
@@ -2292,7 +2458,7 @@ function resolveDartImportPath(db, importerPath, specifier) {
|
|
|
2292
2458
|
return null;
|
|
2293
2459
|
}
|
|
2294
2460
|
function pythonCandidateImportPaths(basePath) {
|
|
2295
|
-
const ext =
|
|
2461
|
+
const ext = extname3(basePath);
|
|
2296
2462
|
if (PYTHON_SOURCE_EXTENSIONS.includes(ext)) {
|
|
2297
2463
|
return [basePath];
|
|
2298
2464
|
}
|
|
@@ -2304,7 +2470,7 @@ function pythonCandidateImportPaths(basePath) {
|
|
|
2304
2470
|
];
|
|
2305
2471
|
}
|
|
2306
2472
|
function rustCandidateImportPaths(basePath) {
|
|
2307
|
-
const ext =
|
|
2473
|
+
const ext = extname3(basePath);
|
|
2308
2474
|
if (RUST_SOURCE_EXTENSIONS.includes(ext)) {
|
|
2309
2475
|
return [basePath];
|
|
2310
2476
|
}
|
|
@@ -2314,7 +2480,7 @@ function rustCandidateImportPaths(basePath) {
|
|
|
2314
2480
|
];
|
|
2315
2481
|
}
|
|
2316
2482
|
function rubyCandidateImportPaths(basePath) {
|
|
2317
|
-
const ext =
|
|
2483
|
+
const ext = extname3(basePath);
|
|
2318
2484
|
if (RUBY_SOURCE_EXTENSIONS.includes(ext)) {
|
|
2319
2485
|
return [basePath];
|
|
2320
2486
|
}
|
|
@@ -2324,14 +2490,14 @@ function rubyCandidateImportPaths(basePath) {
|
|
|
2324
2490
|
];
|
|
2325
2491
|
}
|
|
2326
2492
|
function dartCandidateImportPaths(basePath) {
|
|
2327
|
-
const ext =
|
|
2493
|
+
const ext = extname3(basePath);
|
|
2328
2494
|
if (DART_SOURCE_EXTENSIONS.includes(ext)) {
|
|
2329
2495
|
return [basePath];
|
|
2330
2496
|
}
|
|
2331
2497
|
return [`${basePath}.dart`, basePath];
|
|
2332
2498
|
}
|
|
2333
2499
|
function candidateImportPaths(absolute) {
|
|
2334
|
-
const ext =
|
|
2500
|
+
const ext = extname3(absolute);
|
|
2335
2501
|
const candidates = /* @__PURE__ */ new Set();
|
|
2336
2502
|
if (ext) {
|
|
2337
2503
|
candidates.add(absolute);
|
|
@@ -2374,34 +2540,34 @@ function normalizePath(path2) {
|
|
|
2374
2540
|
return path2.replace(/\\/g, "/");
|
|
2375
2541
|
}
|
|
2376
2542
|
function isJavaScriptSourcePath(relativePath) {
|
|
2377
|
-
return SOURCE_EXTENSIONS.includes(
|
|
2543
|
+
return SOURCE_EXTENSIONS.includes(extname3(relativePath).toLowerCase());
|
|
2378
2544
|
}
|
|
2379
2545
|
function isPythonSourcePath(relativePath) {
|
|
2380
|
-
return PYTHON_SOURCE_EXTENSIONS.includes(
|
|
2546
|
+
return PYTHON_SOURCE_EXTENSIONS.includes(extname3(relativePath).toLowerCase());
|
|
2381
2547
|
}
|
|
2382
2548
|
function isJvmSourcePath(relativePath) {
|
|
2383
|
-
return JVM_SOURCE_EXTENSIONS.includes(
|
|
2549
|
+
return JVM_SOURCE_EXTENSIONS.includes(extname3(relativePath).toLowerCase());
|
|
2384
2550
|
}
|
|
2385
2551
|
function isRustSourcePath(relativePath) {
|
|
2386
|
-
return RUST_SOURCE_EXTENSIONS.includes(
|
|
2552
|
+
return RUST_SOURCE_EXTENSIONS.includes(extname3(relativePath).toLowerCase());
|
|
2387
2553
|
}
|
|
2388
2554
|
function isRubySourcePath(relativePath) {
|
|
2389
|
-
return RUBY_SOURCE_EXTENSIONS.includes(
|
|
2555
|
+
return RUBY_SOURCE_EXTENSIONS.includes(extname3(relativePath).toLowerCase());
|
|
2390
2556
|
}
|
|
2391
2557
|
function isCLikeSourcePath(relativePath) {
|
|
2392
|
-
return C_LIKE_SOURCE_EXTENSIONS.includes(
|
|
2558
|
+
return C_LIKE_SOURCE_EXTENSIONS.includes(extname3(relativePath).toLowerCase());
|
|
2393
2559
|
}
|
|
2394
2560
|
function isDotNetSourcePath(relativePath) {
|
|
2395
|
-
return DOTNET_SOURCE_EXTENSIONS.includes(
|
|
2561
|
+
return DOTNET_SOURCE_EXTENSIONS.includes(extname3(relativePath).toLowerCase());
|
|
2396
2562
|
}
|
|
2397
2563
|
function isVisualBasicSourcePath(relativePath) {
|
|
2398
|
-
return
|
|
2564
|
+
return extname3(relativePath).toLowerCase() === ".vb";
|
|
2399
2565
|
}
|
|
2400
2566
|
function isDartSourcePath(relativePath) {
|
|
2401
|
-
return DART_SOURCE_EXTENSIONS.includes(
|
|
2567
|
+
return DART_SOURCE_EXTENSIONS.includes(extname3(relativePath).toLowerCase());
|
|
2402
2568
|
}
|
|
2403
2569
|
function isPhpSourcePath(relativePath) {
|
|
2404
|
-
return PHP_SOURCE_EXTENSIONS.includes(
|
|
2570
|
+
return PHP_SOURCE_EXTENSIONS.includes(extname3(relativePath).toLowerCase());
|
|
2405
2571
|
}
|
|
2406
2572
|
function extensionFamilyFor(relativePath) {
|
|
2407
2573
|
if (isJvmSourcePath(relativePath)) return JVM_SOURCE_EXTENSIONS;
|
|
@@ -2425,7 +2591,7 @@ function getSourceText(db, relativePath) {
|
|
|
2425
2591
|
cache.set(normalized, "");
|
|
2426
2592
|
return "";
|
|
2427
2593
|
}
|
|
2428
|
-
const source =
|
|
2594
|
+
const source = readFileSync4(fullPath, "utf-8");
|
|
2429
2595
|
cache.set(normalized, source);
|
|
2430
2596
|
return source;
|
|
2431
2597
|
}
|
|
@@ -4174,8 +4340,8 @@ function resolveDocumentCandidates(db, filePattern, opts) {
|
|
|
4174
4340
|
}
|
|
4175
4341
|
function scoreDocumentPath(relativePath, rawPattern) {
|
|
4176
4342
|
const normalizedPath = normalizeLookupPath(relativePath);
|
|
4177
|
-
const pathBase =
|
|
4178
|
-
const patternBase =
|
|
4343
|
+
const pathBase = basename3(normalizedPath);
|
|
4344
|
+
const patternBase = basename3(rawPattern);
|
|
4179
4345
|
let score = 0;
|
|
4180
4346
|
if (normalizedPath === rawPattern) score += 1200;
|
|
4181
4347
|
if (normalizedPath.endsWith(`/${rawPattern}`)) score += 1100;
|
|
@@ -4221,7 +4387,7 @@ function symbols(db, filePattern) {
|
|
|
4221
4387
|
}
|
|
4222
4388
|
|
|
4223
4389
|
// src/queries/methods.ts
|
|
4224
|
-
import { basename as
|
|
4390
|
+
import { basename as basename4 } from "path";
|
|
4225
4391
|
function methods(db, className) {
|
|
4226
4392
|
const classMatch = findFirstSymbolMatch(db, className);
|
|
4227
4393
|
if (!classMatch) {
|
|
@@ -4230,7 +4396,7 @@ function methods(db, className) {
|
|
|
4230
4396
|
const ownerName = leafName(classMatch.symbol);
|
|
4231
4397
|
const definitions = getDefinitionsForFile(db, classMatch.relativePath).filter((definition) => isCallableSymbol(definition.symbol));
|
|
4232
4398
|
const directMethods = definitions.filter((definition) => definition.parentTypeName === ownerName || definition.symbol.includes(ownerName));
|
|
4233
|
-
const fileScopedMethods = directMethods.length > 0 ? directMethods : stripExtension(
|
|
4399
|
+
const fileScopedMethods = directMethods.length > 0 ? directMethods : stripExtension(basename4(classMatch.relativePath)) === ownerName ? definitions.filter((definition) => definition.symbol.includes("<invalid-global-code>")) : [];
|
|
4234
4400
|
return fileScopedMethods.map((definition) => ({
|
|
4235
4401
|
startLine: definition.startLine,
|
|
4236
4402
|
endLine: definition.endLine,
|
|
@@ -4614,11 +4780,11 @@ function isWorkerEntrySurface(path2) {
|
|
|
4614
4780
|
function isStructuralEntrySurface(path2) {
|
|
4615
4781
|
const normalized = normalizePath2(path2);
|
|
4616
4782
|
const segments = normalized.split("/");
|
|
4617
|
-
const
|
|
4618
|
-
if (
|
|
4783
|
+
const basename6 = segments[segments.length - 1] ?? normalized;
|
|
4784
|
+
if (basename6 === "cli.ts" || basename6 === "cli.js" || basename6 === "postinstall.ts" || basename6 === "postinstall.js" || basename6 === "main.ts" || basename6 === "main.js" || basename6 === "main.rs" || basename6 === "main.go" || basename6 === "main.py") {
|
|
4619
4785
|
return true;
|
|
4620
4786
|
}
|
|
4621
|
-
if (
|
|
4787
|
+
if (basename6 === "index.ts" || basename6 === "index.js") {
|
|
4622
4788
|
return segments.length <= 2;
|
|
4623
4789
|
}
|
|
4624
4790
|
return normalized.endsWith("/mod.rs") || normalized.endsWith("/__init__.py");
|
|
@@ -6121,8 +6287,8 @@ function similarChains(db, opts = {}) {
|
|
|
6121
6287
|
}
|
|
6122
6288
|
const structuralNames = ["index.ts", "index.js", "cli.ts", "main.ts", "health.ts", "health.js"];
|
|
6123
6289
|
for (const node of nodeFreq.keys()) {
|
|
6124
|
-
const
|
|
6125
|
-
if (structuralNames.includes(
|
|
6290
|
+
const basename6 = node.split("/").pop() ?? "";
|
|
6291
|
+
if (structuralNames.includes(basename6)) infraNodes.add(node);
|
|
6126
6292
|
}
|
|
6127
6293
|
const filteredChains = [];
|
|
6128
6294
|
for (const chain of rawChains) {
|
|
@@ -6296,8 +6462,8 @@ function extractCandidates(db, opts = {}) {
|
|
|
6296
6462
|
const results = [];
|
|
6297
6463
|
for (const sym of symbols2) {
|
|
6298
6464
|
if (db.isIgnored(sym.relativePath)) continue;
|
|
6299
|
-
const
|
|
6300
|
-
if (
|
|
6465
|
+
const basename6 = sym.relativePath.split("/").pop() ?? "";
|
|
6466
|
+
if (basename6.includes("types")) continue;
|
|
6301
6467
|
const calleeChunks = getCalleeRowsForSymbol(db, sym);
|
|
6302
6468
|
const calleeSet = new Set(calleeChunks.map((c) => c.symbol));
|
|
6303
6469
|
if (calleeSet.size < minCallees) continue;
|
|
@@ -6809,21 +6975,21 @@ function isLikelyTypeOnlyDep(dep) {
|
|
|
6809
6975
|
function shouldSkipDriftFile(filePath) {
|
|
6810
6976
|
return isStructuralRole(path.basename(filePath)) || isTestLikePath(filePath);
|
|
6811
6977
|
}
|
|
6812
|
-
function isStructuralRole(
|
|
6813
|
-
if (
|
|
6814
|
-
if (
|
|
6815
|
-
if (
|
|
6816
|
-
if (
|
|
6978
|
+
function isStructuralRole(basename6) {
|
|
6979
|
+
if (basename6 === "index.ts" || basename6 === "index.js") return true;
|
|
6980
|
+
if (basename6 === "cli.ts" || basename6 === "main.ts" || basename6 === "main.rs") return true;
|
|
6981
|
+
if (basename6.includes("worker.") || basename6.includes("postinstall.")) return true;
|
|
6982
|
+
if (basename6 === "health.ts" || basename6 === "health.js") return true;
|
|
6817
6983
|
return false;
|
|
6818
6984
|
}
|
|
6819
6985
|
function isTestLikePath(filePath) {
|
|
6820
6986
|
const normalized = filePath.replace(/\\/g, "/");
|
|
6821
|
-
const
|
|
6822
|
-
return normalized.includes("/__tests__/") || normalized.includes("/tests/") || normalized.includes("/test/") || /\.(test|spec)\.[A-Za-z0-9]+$/.test(
|
|
6987
|
+
const basename6 = path.basename(normalized);
|
|
6988
|
+
return normalized.includes("/__tests__/") || normalized.includes("/tests/") || normalized.includes("/test/") || /\.(test|spec)\.[A-Za-z0-9]+$/.test(basename6) || /_(test|spec)\.[A-Za-z0-9]+$/.test(basename6) || /^test[_-]/.test(basename6) || /^test\./.test(basename6);
|
|
6823
6989
|
}
|
|
6824
6990
|
|
|
6825
6991
|
// src/queries/wrapper-candidates.ts
|
|
6826
|
-
import { basename as
|
|
6992
|
+
import { basename as basename5, extname as extname4 } from "path";
|
|
6827
6993
|
function wrapperCandidates(db, opts) {
|
|
6828
6994
|
const { scope, maxLoc = 15, limit = 30 } = opts ?? {};
|
|
6829
6995
|
const reverseFanIn = buildReverseFileFanIn(buildFileDepGraph(db, scope));
|
|
@@ -6831,10 +6997,10 @@ function wrapperCandidates(db, opts) {
|
|
|
6831
6997
|
const results = [];
|
|
6832
6998
|
for (const symbol of symbols2) {
|
|
6833
6999
|
if (db.isIgnored(symbol.relativePath) || !isFunctionLikeSymbol(symbol.symbol)) continue;
|
|
6834
|
-
const symbolStem =
|
|
7000
|
+
const symbolStem = basename5(symbol.relativePath, extname4(symbol.relativePath));
|
|
6835
7001
|
const callerRows = dedupeRows(
|
|
6836
7002
|
getCallerRowsForSymbol(db, symbol, { limit: 200 }).filter((row) => row.file !== symbol.relativePath)
|
|
6837
|
-
).filter((row) =>
|
|
7003
|
+
).filter((row) => basename5(row.file, extname4(row.file)) !== symbolStem);
|
|
6838
7004
|
if (callerRows.length !== 1) continue;
|
|
6839
7005
|
const caller = callerRows[0];
|
|
6840
7006
|
const callerDefinition = getDefinitionsForFile(db, caller.file).find((definition) => definition.symbol === caller.symbol);
|
|
@@ -6856,7 +7022,7 @@ function wrapperCandidates(db, opts) {
|
|
|
6856
7022
|
endLine: symbol.endLine,
|
|
6857
7023
|
loc: definitionLoc2(symbol),
|
|
6858
7024
|
singleCaller: caller.symbol,
|
|
6859
|
-
singleCallerShort: useDefinitionFanIn ? shortenSymbol(caller.symbol) :
|
|
7025
|
+
singleCallerShort: useDefinitionFanIn ? shortenSymbol(caller.symbol) : basename5(caller.file),
|
|
6860
7026
|
callerFanIn
|
|
6861
7027
|
});
|
|
6862
7028
|
}
|
|
@@ -6911,11 +7077,11 @@ function fallbackCallerFanIn(db, reverseFanIn, callerFile) {
|
|
|
6911
7077
|
if (direct > 0) {
|
|
6912
7078
|
return direct;
|
|
6913
7079
|
}
|
|
6914
|
-
const stem =
|
|
7080
|
+
const stem = basename5(callerFile, extname4(callerFile));
|
|
6915
7081
|
let best = 0;
|
|
6916
7082
|
for (const [file, fanIn2] of reverseFanIn) {
|
|
6917
7083
|
if (file === callerFile) continue;
|
|
6918
|
-
if (
|
|
7084
|
+
if (basename5(file, extname4(file)) !== stem) continue;
|
|
6919
7085
|
if (fanIn2 > best) {
|
|
6920
7086
|
best = fanIn2;
|
|
6921
7087
|
}
|
|
@@ -6996,8 +7162,8 @@ function getFilesWithFunctions(db, scope) {
|
|
|
6996
7162
|
return new Set(getScopedDefinitions4(db, scope).filter((definition) => definition.isFunctionLike).map((definition) => definition.relativePath));
|
|
6997
7163
|
}
|
|
6998
7164
|
function isTrueStaleAbstraction(row, filesWithFunctions) {
|
|
6999
|
-
const
|
|
7000
|
-
const isTypeFile =
|
|
7165
|
+
const basename6 = row.file.split("/").pop() ?? "";
|
|
7166
|
+
const isTypeFile = basename6.includes("types") || row.file.includes("/types/");
|
|
7001
7167
|
if (isTypeFile && row.consumers > 0) {
|
|
7002
7168
|
return false;
|
|
7003
7169
|
}
|
|
@@ -7395,7 +7561,7 @@ function convergence(db, symbolPatternA, symbolPatternB) {
|
|
|
7395
7561
|
}
|
|
7396
7562
|
|
|
7397
7563
|
// src/queries/code.ts
|
|
7398
|
-
import { readFileSync as
|
|
7564
|
+
import { readFileSync as readFileSync5 } from "fs";
|
|
7399
7565
|
import { join as join9 } from "path";
|
|
7400
7566
|
function code(db, symbolPattern, opts = {}) {
|
|
7401
7567
|
const { context = 0 } = opts;
|
|
@@ -7412,7 +7578,7 @@ function code(db, symbolPattern, opts = {}) {
|
|
|
7412
7578
|
const filePath = join9(db.config.projectRoot, match.relativePath);
|
|
7413
7579
|
let fileContent;
|
|
7414
7580
|
try {
|
|
7415
|
-
fileContent =
|
|
7581
|
+
fileContent = readFileSync5(filePath, "utf-8");
|
|
7416
7582
|
} catch {
|
|
7417
7583
|
return null;
|
|
7418
7584
|
}
|
|
@@ -7442,7 +7608,7 @@ function readFileRange(db, filePath, startLine, endLine, context) {
|
|
|
7442
7608
|
const fullPath = join9(db.config.projectRoot, doc.relative_path);
|
|
7443
7609
|
let fileContent;
|
|
7444
7610
|
try {
|
|
7445
|
-
fileContent =
|
|
7611
|
+
fileContent = readFileSync5(fullPath, "utf-8");
|
|
7446
7612
|
} catch {
|
|
7447
7613
|
return null;
|
|
7448
7614
|
}
|
|
@@ -7462,7 +7628,7 @@ function readFileRange(db, filePath, startLine, endLine, context) {
|
|
|
7462
7628
|
}
|
|
7463
7629
|
|
|
7464
7630
|
// src/queries/complexity.ts
|
|
7465
|
-
import { readFileSync as
|
|
7631
|
+
import { readFileSync as readFileSync6 } from "fs";
|
|
7466
7632
|
import { join as join10 } from "path";
|
|
7467
7633
|
function complexity(db, symbolPattern) {
|
|
7468
7634
|
const match = findFirstSymbolMatch(db, symbolPattern);
|
|
@@ -7475,7 +7641,7 @@ function complexity(db, symbolPattern) {
|
|
|
7475
7641
|
const filePath = join10(db.config.projectRoot, match.relativePath);
|
|
7476
7642
|
let source = "";
|
|
7477
7643
|
try {
|
|
7478
|
-
const lines =
|
|
7644
|
+
const lines = readFileSync6(filePath, "utf-8").split("\n");
|
|
7479
7645
|
source = lines.slice(match.startLine, match.endLine + 1).join("\n");
|
|
7480
7646
|
} catch {
|
|
7481
7647
|
}
|
|
@@ -8047,7 +8213,7 @@ import {
|
|
|
8047
8213
|
readlinkSync,
|
|
8048
8214
|
unlinkSync
|
|
8049
8215
|
} from "fs";
|
|
8050
|
-
import { join as join11, dirname as
|
|
8216
|
+
import { join as join11, dirname as dirname4, resolve as resolve4 } from "path";
|
|
8051
8217
|
import { homedir as homedir2, platform as platform3 } from "os";
|
|
8052
8218
|
import { fileURLToPath } from "url";
|
|
8053
8219
|
var IS_WINDOWS3 = platform3() === "win32";
|
|
@@ -8062,7 +8228,7 @@ function installSkills(opts = {}) {
|
|
|
8062
8228
|
const log = opts.quiet ? () => {
|
|
8063
8229
|
} : console.log;
|
|
8064
8230
|
const thisFile = fileURLToPath(import.meta.url);
|
|
8065
|
-
const skillsSource =
|
|
8231
|
+
const skillsSource = resolve4(dirname4(thisFile), "..", "skills");
|
|
8066
8232
|
const targets = [
|
|
8067
8233
|
join11(homedir2(), ".claude", "skills"),
|
|
8068
8234
|
join11(homedir2(), ".codex", "skills")
|
|
@@ -8073,7 +8239,7 @@ function installSkills(opts = {}) {
|
|
|
8073
8239
|
alreadyLinked: []
|
|
8074
8240
|
};
|
|
8075
8241
|
for (const targetDir of targets) {
|
|
8076
|
-
const parentDir =
|
|
8242
|
+
const parentDir = dirname4(targetDir);
|
|
8077
8243
|
if (!existsSync9(parentDir)) {
|
|
8078
8244
|
continue;
|
|
8079
8245
|
}
|
|
@@ -8089,7 +8255,7 @@ function installSkills(opts = {}) {
|
|
|
8089
8255
|
if (existsSync9(target)) {
|
|
8090
8256
|
try {
|
|
8091
8257
|
const existing = readlinkSync(target);
|
|
8092
|
-
if (
|
|
8258
|
+
if (resolve4(existing) === resolve4(source)) {
|
|
8093
8259
|
result.alreadyLinked.push(`${toolName}/${skill}`);
|
|
8094
8260
|
log(` ok: ${skill} \u2192 ${toolName} (already linked)`);
|
|
8095
8261
|
continue;
|
|
@@ -8216,11 +8382,15 @@ var queries = {
|
|
|
8216
8382
|
program.name("scip-query").description("Language-agnostic code intelligence CLI powered by SCIP indexes").version(cliVersion);
|
|
8217
8383
|
program.command("reindex").description("Index the codebase and convert to SQLite").option("-l, --language <lang>", "Index only this language (can be repeated)", collect, []).option("--pnpm-workspaces", "Enable pnpm workspace support (TypeScript)").action(async (opts) => {
|
|
8218
8384
|
const projectRoot = resolveProjectRoot();
|
|
8385
|
+
const config = loadProjectConfig(projectRoot);
|
|
8386
|
+
const paths = resolveIndexPaths(projectRoot, config);
|
|
8219
8387
|
try {
|
|
8220
8388
|
const result = await reindex({
|
|
8221
8389
|
projectRoot,
|
|
8222
|
-
languages: opts.language.length > 0 ? opts.language :
|
|
8223
|
-
|
|
8390
|
+
languages: opts.language.length > 0 ? opts.language : config.languages,
|
|
8391
|
+
outputScip: paths.indexPath,
|
|
8392
|
+
outputDb: paths.dbPath,
|
|
8393
|
+
pnpmWorkspaces: opts.pnpmWorkspaces || config.indexer?.typescript?.pnpmWorkspaces
|
|
8224
8394
|
});
|
|
8225
8395
|
console.log(`Indexed ${result.languages.join(", ")} in ${(result.durationMs / 1e3).toFixed(1)}s`);
|
|
8226
8396
|
} catch (err) {
|
|
@@ -9205,6 +9375,7 @@ program.command("watch").description("Watch for file changes and reindex automat
|
|
|
9205
9375
|
const watcher = new Watcher({
|
|
9206
9376
|
projectRoot,
|
|
9207
9377
|
config,
|
|
9378
|
+
languages: config.languages,
|
|
9208
9379
|
onStatus: (status) => {
|
|
9209
9380
|
process.stdout.write(`\r\x1B[K${formatStatus(status)}`);
|
|
9210
9381
|
},
|