scip-query 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -43
- package/dist/chunk-2UELLEBI.js +1 -0
- package/dist/chunk-34JPTNRN.js +601 -0
- package/dist/{chunk-W4ALF422.js → chunk-3566TKJ5.js} +3 -3
- package/dist/{chunk-Z6YZJ36C.js → chunk-4ACRRQC4.js} +8 -4
- package/dist/{chunk-Z4GHE2HD.js → chunk-4BQFSNFI.js} +6 -2
- package/dist/{chunk-4XHWPRAX.js → chunk-6QSHLFSL.js} +3 -3
- package/dist/{chunk-4EXL2CUA.js → chunk-6WVR5K46.js} +16 -8
- package/dist/{chunk-ZQIIPFD7.js → chunk-75RQSBTK.js} +2 -2
- package/dist/{chunk-KPPHZCZJ.js → chunk-7HK5ZLOE.js} +28 -46
- package/dist/{chunk-MCUX5LA7.js → chunk-7JFZSOJ7.js} +3 -3
- package/dist/{chunk-6SXADWLW.js → chunk-AKMBBKWV.js} +2 -2
- package/dist/{chunk-NHBZIL2J.js → chunk-AMNISGYR.js} +3 -3
- package/dist/{chunk-2CKGIR6G.js → chunk-BFLULBEU.js} +3 -3
- package/dist/{chunk-HPFZLISB.js → chunk-CU62ZDHI.js} +2 -2
- package/dist/{chunk-EQYLEQCW.js → chunk-DY4AFG2W.js} +12 -10
- package/dist/{chunk-5RMYT5WH.js → chunk-F7XU27LU.js} +2 -2
- package/dist/{chunk-KCBMVQL5.js → chunk-GPJVPT3U.js} +2 -2
- package/dist/{chunk-NUZ4OMU3.js → chunk-GU2H5QRN.js} +2 -2
- package/dist/{chunk-UJQN5N3I.js → chunk-H6WCPKCX.js} +6 -3
- package/dist/{chunk-OVPLOMPY.js → chunk-HMYJJ3HY.js} +7 -4
- package/dist/chunk-IJKLB2JW.js +69 -0
- package/dist/{chunk-DGUPQSOR.js → chunk-IXPHLF6K.js} +2 -2
- package/dist/{chunk-7PBOG4YE.js → chunk-KBOQX573.js} +2 -2
- package/dist/{chunk-ZOGY2V3N.js → chunk-LLMPAG56.js} +93 -30
- package/dist/{chunk-BOVXCR46.js → chunk-LTJC5ZQL.js} +2 -2
- package/dist/{chunk-LAWMH22O.js → chunk-M3NPW3FC.js} +2 -2
- package/dist/{chunk-NWCE4CIC.js → chunk-M4QGEKKD.js} +5 -27
- package/dist/{chunk-63G7IQTD.js → chunk-MVH45PYK.js} +20 -40
- package/dist/chunk-N4C3H7LH.js +37 -0
- package/dist/chunk-NG5F43OU.js +200 -0
- package/dist/{chunk-D567NFIF.js → chunk-NVIIM34O.js} +3 -3
- package/dist/{chunk-BNN2RKD2.js → chunk-ORINICIZ.js} +3 -3
- package/dist/{chunk-4PDAL6IL.js → chunk-PMJKOXOT.js} +3 -3
- package/dist/{chunk-QOV2R2WT.js → chunk-QIXNAB5K.js} +42 -2
- package/dist/{chunk-7LLPRPR5.js → chunk-R2I3M5B4.js} +2 -2
- package/dist/{chunk-7RLE5EWE.js → chunk-R56FJU3E.js} +34 -13
- package/dist/{chunk-H2MDONBU.js → chunk-RFMT7UAZ.js} +3 -3
- package/dist/{chunk-SEFSL2GF.js → chunk-TOIEB3LG.js} +2 -2
- package/dist/chunk-VO4QI3LS.js +84 -0
- package/dist/{chunk-ZK6GXM3J.js → chunk-WVK7AASK.js} +3 -3
- package/dist/{chunk-HMLMH7VZ.js → chunk-Y3M323OX.js} +2 -2
- package/dist/{chunk-DCKMSTJ4.js → chunk-Y4JFVQ7C.js} +2 -2
- package/dist/{chunk-7UCKSQRS.js → chunk-YAFWL3RA.js} +3 -3
- package/dist/{chunk-FGXRVW7G.js → chunk-YZ6L7GFO.js} +2 -2
- package/dist/cli.js +1355 -671
- package/dist/{db-BNVVZSfP.d.ts → db-BHYam4BK.d.ts} +6 -18
- package/dist/index.d.ts +15 -15
- package/dist/index.js +260 -231
- package/dist/postinstall.js +5 -76
- package/dist/queries/affected.d.ts +1 -1
- package/dist/queries/affected.js +3 -3
- package/dist/queries/bottlenecks.d.ts +1 -1
- package/dist/queries/bottlenecks.js +2 -2
- package/dist/queries/by-kind.d.ts +1 -1
- package/dist/queries/by-kind.js +2 -2
- package/dist/queries/call-graph.d.ts +1 -1
- package/dist/queries/call-graph.js +3 -3
- package/dist/queries/change-surface.d.ts +2 -2
- package/dist/queries/change-surface.js +2 -3
- package/dist/queries/code.d.ts +1 -1
- package/dist/queries/code.js +3 -3
- package/dist/queries/complexity-hotspots.d.ts +1 -1
- package/dist/queries/complexity-hotspots.js +3 -3
- package/dist/queries/complexity.d.ts +1 -1
- package/dist/queries/complexity.js +3 -3
- package/dist/queries/convergence.d.ts +1 -1
- package/dist/queries/convergence.js +3 -3
- package/dist/queries/coupling.d.ts +1 -1
- package/dist/queries/cycles.d.ts +1 -1
- package/dist/queries/cycles.js +3 -2
- package/dist/queries/dataflow.d.ts +1 -1
- package/dist/queries/dataflow.js +3 -3
- package/dist/queries/dead.d.ts +1 -1
- package/dist/queries/dead.js +4 -3
- package/dist/queries/deep-chains.d.ts +1 -1
- package/dist/queries/deep-chains.js +3 -2
- package/dist/queries/deps.d.ts +1 -1
- package/dist/queries/diff-impact.d.ts +2 -2
- package/dist/queries/diff-impact.js +2 -3
- package/dist/queries/doc-coverage.d.ts +1 -1
- package/dist/queries/doc-coverage.js +2 -2
- package/dist/queries/drift.d.ts +1 -1
- package/dist/queries/drift.js +3 -2
- package/dist/queries/extract-candidates.d.ts +1 -1
- package/dist/queries/extract-candidates.js +3 -3
- package/dist/queries/fan.d.ts +1 -1
- package/dist/queries/fan.js +2 -2
- package/dist/queries/files.d.ts +1 -1
- package/dist/queries/health.d.ts +1 -1
- package/dist/queries/health.js +14 -14
- package/dist/queries/hierarchy.d.ts +1 -1
- package/dist/queries/hierarchy.js +3 -2
- package/dist/queries/hotspots.d.ts +1 -1
- package/dist/queries/hotspots.js +2 -2
- package/dist/queries/imports.d.ts +1 -1
- package/dist/queries/imports.js +3 -2
- package/dist/queries/index.d.ts +1 -2
- package/dist/queries/index.js +43 -48
- package/dist/queries/isolated.d.ts +1 -1
- package/dist/queries/isolated.js +4 -3
- package/dist/queries/members.d.ts +2 -2
- package/dist/queries/members.js +3 -2
- package/dist/queries/methods.d.ts +1 -1
- package/dist/queries/methods.js +2 -2
- package/dist/queries/outline.d.ts +1 -1
- package/dist/queries/outline.js +2 -2
- package/dist/queries/passthrough-candidates.d.ts +1 -1
- package/dist/queries/passthrough-candidates.js +3 -3
- package/dist/queries/redundant-reexports.d.ts +1 -1
- package/dist/queries/redundant-reexports.js +4 -2
- package/dist/queries/refs.d.ts +1 -1
- package/dist/queries/similar-chains.d.ts +1 -1
- package/dist/queries/similar-chains.js +3 -2
- package/dist/queries/similar-files.d.ts +1 -1
- package/dist/queries/similar-files.js +3 -2
- package/dist/queries/similar-signatures.d.ts +1 -1
- package/dist/queries/similar-signatures.js +2 -2
- package/dist/queries/similar.d.ts +1 -1
- package/dist/queries/similar.js +3 -3
- package/dist/queries/slice.d.ts +1 -1
- package/dist/queries/slice.js +3 -3
- package/dist/queries/stale-abstractions.d.ts +1 -1
- package/dist/queries/stale-abstractions.js +3 -3
- package/dist/queries/stats.d.ts +1 -1
- package/dist/queries/surface.d.ts +1 -1
- package/dist/queries/surface.js +2 -2
- package/dist/queries/symbols.d.ts +1 -1
- package/dist/queries/symbols.js +2 -2
- package/dist/queries/system.d.ts +1 -1
- package/dist/queries/system.js +2 -2
- package/dist/queries/trace.d.ts +1 -1
- package/dist/queries/trace.js +3 -1
- package/dist/queries/wrapper-candidates.d.ts +1 -1
- package/dist/queries/wrapper-candidates.js +3 -3
- package/dist/reindex-worker.js +24 -12
- package/package.json +6 -1
- package/IMPROVEMENTS.md +0 -143
- package/PLAN.md +0 -320
- package/dist/chunk-2CKGIR6G.js.map +0 -1
- package/dist/chunk-3UOUTZQT.js +0 -45
- package/dist/chunk-3UOUTZQT.js.map +0 -1
- package/dist/chunk-4EXL2CUA.js.map +0 -1
- package/dist/chunk-4PDAL6IL.js.map +0 -1
- package/dist/chunk-4TYLS5XX.js.map +0 -1
- package/dist/chunk-4XHWPRAX.js.map +0 -1
- package/dist/chunk-5RMYT5WH.js.map +0 -1
- package/dist/chunk-63G7IQTD.js.map +0 -1
- package/dist/chunk-6SXADWLW.js.map +0 -1
- package/dist/chunk-74RFWB5T.js.map +0 -1
- package/dist/chunk-7LLPRPR5.js.map +0 -1
- package/dist/chunk-7PBOG4YE.js.map +0 -1
- package/dist/chunk-7RLE5EWE.js.map +0 -1
- package/dist/chunk-7UCKSQRS.js.map +0 -1
- package/dist/chunk-BNN2RKD2.js.map +0 -1
- package/dist/chunk-BOVXCR46.js.map +0 -1
- package/dist/chunk-D567NFIF.js.map +0 -1
- package/dist/chunk-DCKMSTJ4.js.map +0 -1
- package/dist/chunk-DEZKCZXD.js +0 -40
- package/dist/chunk-DEZKCZXD.js.map +0 -1
- package/dist/chunk-DGUPQSOR.js.map +0 -1
- package/dist/chunk-DVWGWHFW.js +0 -99
- package/dist/chunk-DVWGWHFW.js.map +0 -1
- package/dist/chunk-EQYLEQCW.js.map +0 -1
- package/dist/chunk-FGXRVW7G.js.map +0 -1
- package/dist/chunk-H2MDONBU.js.map +0 -1
- package/dist/chunk-HB7MRLLL.js +0 -76
- package/dist/chunk-HB7MRLLL.js.map +0 -1
- package/dist/chunk-HDSRORNV.js.map +0 -1
- package/dist/chunk-HMLMH7VZ.js.map +0 -1
- package/dist/chunk-HPFZLISB.js.map +0 -1
- package/dist/chunk-HZBC7PPD.js +0 -88
- package/dist/chunk-HZBC7PPD.js.map +0 -1
- package/dist/chunk-ITZ3DDOG.js.map +0 -1
- package/dist/chunk-JJP7KQND.js +0 -1
- package/dist/chunk-JJP7KQND.js.map +0 -1
- package/dist/chunk-KCBMVQL5.js.map +0 -1
- package/dist/chunk-KPPHZCZJ.js.map +0 -1
- package/dist/chunk-LAWMH22O.js.map +0 -1
- package/dist/chunk-MCUX5LA7.js.map +0 -1
- package/dist/chunk-MGNMHKX3.js.map +0 -1
- package/dist/chunk-N5KEREIA.js.map +0 -1
- package/dist/chunk-NHBZIL2J.js.map +0 -1
- package/dist/chunk-NUZ4OMU3.js.map +0 -1
- package/dist/chunk-NWCE4CIC.js.map +0 -1
- package/dist/chunk-OVPLOMPY.js.map +0 -1
- package/dist/chunk-QOV2R2WT.js.map +0 -1
- package/dist/chunk-SEFSL2GF.js.map +0 -1
- package/dist/chunk-UJQN5N3I.js.map +0 -1
- package/dist/chunk-W4ALF422.js.map +0 -1
- package/dist/chunk-Z4GHE2HD.js.map +0 -1
- package/dist/chunk-Z6YZJ36C.js.map +0 -1
- package/dist/chunk-ZK6GXM3J.js.map +0 -1
- package/dist/chunk-ZOGY2V3N.js.map +0 -1
- package/dist/chunk-ZQIIPFD7.js.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/postinstall.js.map +0 -1
- package/dist/queries/affected.js.map +0 -1
- package/dist/queries/bottlenecks.js.map +0 -1
- package/dist/queries/by-kind.js.map +0 -1
- package/dist/queries/call-graph.js.map +0 -1
- package/dist/queries/change-surface.js.map +0 -1
- package/dist/queries/clean-signature.js.map +0 -1
- package/dist/queries/code.js.map +0 -1
- package/dist/queries/complexity-hotspots.js.map +0 -1
- package/dist/queries/complexity.js.map +0 -1
- package/dist/queries/convergence.js.map +0 -1
- package/dist/queries/coupling.js.map +0 -1
- package/dist/queries/cycles.js.map +0 -1
- package/dist/queries/dataflow.js.map +0 -1
- package/dist/queries/dead.js.map +0 -1
- package/dist/queries/deep-chains.js.map +0 -1
- package/dist/queries/deps.js.map +0 -1
- package/dist/queries/diff-impact.js.map +0 -1
- package/dist/queries/doc-coverage.js.map +0 -1
- package/dist/queries/drift.js.map +0 -1
- package/dist/queries/extract-candidates.js.map +0 -1
- package/dist/queries/fan.js.map +0 -1
- package/dist/queries/files.js.map +0 -1
- package/dist/queries/health.js.map +0 -1
- package/dist/queries/hierarchy.js.map +0 -1
- package/dist/queries/hotspots.js.map +0 -1
- package/dist/queries/imports.js.map +0 -1
- package/dist/queries/index.js.map +0 -1
- package/dist/queries/isolated.js.map +0 -1
- package/dist/queries/members.js.map +0 -1
- package/dist/queries/methods.js.map +0 -1
- package/dist/queries/outline.js.map +0 -1
- package/dist/queries/passthrough-candidates.js.map +0 -1
- package/dist/queries/redundant-reexports.js.map +0 -1
- package/dist/queries/refs.js.map +0 -1
- package/dist/queries/similar-chains.js.map +0 -1
- package/dist/queries/similar-files.js.map +0 -1
- package/dist/queries/similar-signatures.js.map +0 -1
- package/dist/queries/similar.js.map +0 -1
- package/dist/queries/slice.js.map +0 -1
- package/dist/queries/stale-abstractions.js.map +0 -1
- package/dist/queries/stats.js.map +0 -1
- package/dist/queries/surface.js.map +0 -1
- package/dist/queries/symbols.js.map +0 -1
- package/dist/queries/system.js.map +0 -1
- package/dist/queries/test-coverage.d.ts +0 -22
- package/dist/queries/test-coverage.js +0 -11
- package/dist/queries/test-coverage.js.map +0 -1
- package/dist/queries/trace.js.map +0 -1
- package/dist/queries/wrapper-candidates.js.map +0 -1
- package/dist/reindex-worker.js.map +0 -1
- package/docs/AGENT_GUIDE.md +0 -359
- package/reports/debloat/2026-04-10-scip-query-self-audit.md +0 -161
- package/src/cli.ts +0 -1480
- package/src/config.ts +0 -117
- package/src/db.ts +0 -127
- package/src/gitignore-filter.ts +0 -143
- package/src/index.ts +0 -11
- package/src/postinstall.ts +0 -8
- package/src/queries/affected.ts +0 -86
- package/src/queries/bottlenecks.ts +0 -67
- package/src/queries/by-kind.ts +0 -204
- package/src/queries/call-graph.ts +0 -66
- package/src/queries/change-surface.ts +0 -110
- package/src/queries/clean-signature.ts +0 -22
- package/src/queries/code.ts +0 -101
- package/src/queries/complexity-hotspots.ts +0 -119
- package/src/queries/complexity.ts +0 -152
- package/src/queries/convergence.ts +0 -82
- package/src/queries/coupling.ts +0 -99
- package/src/queries/cycles.ts +0 -78
- package/src/queries/dataflow.ts +0 -128
- package/src/queries/dead.ts +0 -122
- package/src/queries/deep-chains.ts +0 -59
- package/src/queries/deps.ts +0 -46
- package/src/queries/diff-impact.ts +0 -204
- package/src/queries/doc-coverage.ts +0 -86
- package/src/queries/drift.ts +0 -224
- package/src/queries/extract-candidates.ts +0 -167
- package/src/queries/fan.ts +0 -148
- package/src/queries/files.ts +0 -16
- package/src/queries/health.ts +0 -324
- package/src/queries/hierarchy.ts +0 -49
- package/src/queries/hotspots.ts +0 -53
- package/src/queries/imports.ts +0 -95
- package/src/queries/index.ts +0 -45
- package/src/queries/isolated.ts +0 -67
- package/src/queries/members.ts +0 -54
- package/src/queries/methods.ts +0 -27
- package/src/queries/outline.ts +0 -52
- package/src/queries/passthrough-candidates.ts +0 -94
- package/src/queries/redundant-reexports.ts +0 -170
- package/src/queries/refs.ts +0 -27
- package/src/queries/similar-chains.ts +0 -314
- package/src/queries/similar-files.ts +0 -140
- package/src/queries/similar-signatures.ts +0 -151
- package/src/queries/similar.ts +0 -305
- package/src/queries/slice.ts +0 -154
- package/src/queries/stale-abstractions.ts +0 -82
- package/src/queries/stats.ts +0 -22
- package/src/queries/surface.ts +0 -34
- package/src/queries/symbols.ts +0 -39
- package/src/queries/system.ts +0 -86
- package/src/queries/test-coverage.ts +0 -106
- package/src/queries/trace.ts +0 -55
- package/src/queries/wrapper-candidates.ts +0 -112
- package/src/query-support.ts +0 -226
- package/src/reindex/detect.ts +0 -58
- package/src/reindex/index.ts +0 -153
- package/src/reindex/indexers.ts +0 -220
- package/src/reindex/install.ts +0 -125
- package/src/reindex-worker.ts +0 -35
- package/src/setup.ts +0 -202
- package/src/symbol-parser.ts +0 -278
- package/src/types.ts +0 -654
- package/src/watch.ts +0 -274
- package/tests/gitignore-filter.test.ts +0 -48
- package/tests/queries.test.ts +0 -300
- package/tests/symbol-parser.test.ts +0 -157
- package/tsconfig.json +0 -20
- package/tsup.config.ts +0 -40
- package/vitest.config.ts +0 -7
|
@@ -0,0 +1,601 @@
|
|
|
1
|
+
import {
|
|
2
|
+
findFirstSymbolMatch
|
|
3
|
+
} from "./chunk-LLMPAG56.js";
|
|
4
|
+
import {
|
|
5
|
+
isModuleLikeSymbol,
|
|
6
|
+
leafName,
|
|
7
|
+
shortenSymbol
|
|
8
|
+
} from "./chunk-QIXNAB5K.js";
|
|
9
|
+
|
|
10
|
+
// src/source-analysis.ts
|
|
11
|
+
import {
|
|
12
|
+
existsSync,
|
|
13
|
+
readFileSync
|
|
14
|
+
} from "fs";
|
|
15
|
+
import {
|
|
16
|
+
dirname,
|
|
17
|
+
extname,
|
|
18
|
+
join,
|
|
19
|
+
relative,
|
|
20
|
+
resolve
|
|
21
|
+
} from "path";
|
|
22
|
+
var SOURCE_IMPORT_CACHE = /* @__PURE__ */ new WeakMap();
|
|
23
|
+
var INDEXED_PATH_CACHE = /* @__PURE__ */ new WeakMap();
|
|
24
|
+
var SOURCE_EXTENSIONS = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
|
|
25
|
+
var PYTHON_SOURCE_EXTENSIONS = [".py", ".pyi"];
|
|
26
|
+
function getSourceImports(db, relativePath) {
|
|
27
|
+
const cache = getCachedMap(SOURCE_IMPORT_CACHE, db);
|
|
28
|
+
const normalized = normalizePath(relativePath);
|
|
29
|
+
const cached = cache.get(normalized);
|
|
30
|
+
if (cached) {
|
|
31
|
+
return cached;
|
|
32
|
+
}
|
|
33
|
+
const fullPath = join(db.config.projectRoot, normalized);
|
|
34
|
+
if (!existsSync(fullPath)) {
|
|
35
|
+
cache.set(normalized, []);
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
const source = readFileSync(fullPath, "utf-8");
|
|
39
|
+
const parsed = isPythonSourcePath(normalized) ? parsePythonImports(db, normalized, source) : parseJavaScriptImports(db, normalized, source);
|
|
40
|
+
cache.set(normalized, parsed);
|
|
41
|
+
return parsed;
|
|
42
|
+
}
|
|
43
|
+
function parseJavaScriptImports(db, importerPath, source) {
|
|
44
|
+
return parseJavaScriptImportStatements(source).flatMap((statement) => parseJavaScriptImportStatement(
|
|
45
|
+
db,
|
|
46
|
+
importerPath,
|
|
47
|
+
statement.clause,
|
|
48
|
+
statement.specifier,
|
|
49
|
+
statement.start,
|
|
50
|
+
statement.end,
|
|
51
|
+
source
|
|
52
|
+
));
|
|
53
|
+
}
|
|
54
|
+
function parseJavaScriptImportStatements(source) {
|
|
55
|
+
const statements = [];
|
|
56
|
+
const importFromRegex = /^[ \t]*import\s+([\s\S]*?)\s+from\s+['"]([^'"]+)['"]\s*;?/gm;
|
|
57
|
+
for (const match of source.matchAll(importFromRegex)) {
|
|
58
|
+
const full = match[0];
|
|
59
|
+
const clause = match[1];
|
|
60
|
+
const specifier = match[2];
|
|
61
|
+
if (!full || !specifier || typeof match.index !== "number") continue;
|
|
62
|
+
statements.push({
|
|
63
|
+
clause,
|
|
64
|
+
specifier,
|
|
65
|
+
start: match.index,
|
|
66
|
+
end: match.index + full.length
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
const sideEffectRegex = /^[ \t]*import\s+['"]([^'"]+)['"]\s*;?/gm;
|
|
70
|
+
for (const match of source.matchAll(sideEffectRegex)) {
|
|
71
|
+
const full = match[0];
|
|
72
|
+
const specifier = match[1];
|
|
73
|
+
if (!full || !specifier || typeof match.index !== "number") continue;
|
|
74
|
+
statements.push({
|
|
75
|
+
clause: null,
|
|
76
|
+
specifier,
|
|
77
|
+
start: match.index,
|
|
78
|
+
end: match.index + full.length
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
return statements.sort((a, b) => a.start - b.start);
|
|
82
|
+
}
|
|
83
|
+
function parseJavaScriptImportStatement(db, importerPath, clause, specifier, start, end, source) {
|
|
84
|
+
const resolvedSource = resolveImportPath(db, importerPath, specifier);
|
|
85
|
+
const body = buildUsageBody(source, start, end);
|
|
86
|
+
if (!clause) {
|
|
87
|
+
return [{
|
|
88
|
+
importedName: "*",
|
|
89
|
+
localName: null,
|
|
90
|
+
sourcePath: resolvedSource,
|
|
91
|
+
kind: "side-effect",
|
|
92
|
+
used: true,
|
|
93
|
+
usedMembers: []
|
|
94
|
+
}];
|
|
95
|
+
}
|
|
96
|
+
const bindings = parseImportClause(clause).map((binding) => ({
|
|
97
|
+
...binding,
|
|
98
|
+
sourcePath: resolvedSource
|
|
99
|
+
}));
|
|
100
|
+
return bindings.map((binding) => {
|
|
101
|
+
if (binding.kind === "namespace") {
|
|
102
|
+
const usedMembers = collectNamespaceMembers(body, binding.localName);
|
|
103
|
+
return {
|
|
104
|
+
...binding,
|
|
105
|
+
used: usedMembers.length > 0 || hasIdentifierUsage(body, binding.localName),
|
|
106
|
+
usedMembers
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
if (binding.kind === "side-effect") {
|
|
110
|
+
return { ...binding, used: true, usedMembers: [] };
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
...binding,
|
|
114
|
+
used: binding.localName ? hasIdentifierUsage(body, binding.localName) : false,
|
|
115
|
+
usedMembers: []
|
|
116
|
+
};
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
function parsePythonImports(db, importerPath, source) {
|
|
120
|
+
return collectPythonImportStatements(source).flatMap(
|
|
121
|
+
(statement) => parsePythonImportStatement(db, importerPath, statement, source)
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
function collectPythonImportStatements(source) {
|
|
125
|
+
const lines = source.split("\n");
|
|
126
|
+
const statements = [];
|
|
127
|
+
let offset = 0;
|
|
128
|
+
for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
|
|
129
|
+
const line = lines[lineIndex];
|
|
130
|
+
const trimmed = line.trimStart();
|
|
131
|
+
const lineStart = offset;
|
|
132
|
+
offset += line.length + 1;
|
|
133
|
+
if (!trimmed.startsWith("import ") && !trimmed.startsWith("from ")) {
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
let statement = line;
|
|
137
|
+
let statementEnd = lineStart + line.length;
|
|
138
|
+
let balance = pythonParenBalance(line);
|
|
139
|
+
while (lineIndex + 1 < lines.length && (balance > 0 || statement.trimEnd().endsWith("\\"))) {
|
|
140
|
+
lineIndex++;
|
|
141
|
+
const nextLine = lines[lineIndex];
|
|
142
|
+
statement += `
|
|
143
|
+
${nextLine}`;
|
|
144
|
+
statementEnd += 1 + nextLine.length;
|
|
145
|
+
balance += pythonParenBalance(nextLine);
|
|
146
|
+
offset += nextLine.length + 1;
|
|
147
|
+
}
|
|
148
|
+
const parsed = parsePythonStatementHeader(statement);
|
|
149
|
+
if (parsed) {
|
|
150
|
+
statements.push({
|
|
151
|
+
...parsed,
|
|
152
|
+
start: lineStart,
|
|
153
|
+
end: statementEnd
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return statements;
|
|
158
|
+
}
|
|
159
|
+
function parsePythonStatementHeader(statement) {
|
|
160
|
+
const normalized = statement.replace(/\\\s*\n/g, " ").trim();
|
|
161
|
+
if (normalized.startsWith("import ")) {
|
|
162
|
+
return {
|
|
163
|
+
kind: "import",
|
|
164
|
+
module: null,
|
|
165
|
+
clause: normalized.slice("import ".length).trim()
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
const fromMatch = normalized.match(/^from\s+([.\w]+)\s+import\s+([\s\S]+)$/);
|
|
169
|
+
if (!fromMatch) {
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
let clause = fromMatch[2].trim();
|
|
173
|
+
if (clause.startsWith("(") && clause.endsWith(")")) {
|
|
174
|
+
clause = clause.slice(1, -1).trim();
|
|
175
|
+
}
|
|
176
|
+
return {
|
|
177
|
+
kind: "from",
|
|
178
|
+
module: fromMatch[1],
|
|
179
|
+
clause
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
function parsePythonImportStatement(db, importerPath, statement, source) {
|
|
183
|
+
const body = buildUsageBody(source, statement.start, statement.end);
|
|
184
|
+
const normalizedClause = statement.clause.replace(/\n/g, " ").trim();
|
|
185
|
+
if (statement.kind === "import") {
|
|
186
|
+
return splitTopLevel(normalizedClause).flatMap((entry) => {
|
|
187
|
+
const cleaned = entry.trim().replace(/,$/, "");
|
|
188
|
+
if (!cleaned) return [];
|
|
189
|
+
const [moduleName, alias] = cleaned.split(/\s+as\s+/);
|
|
190
|
+
const importedName = moduleName.trim();
|
|
191
|
+
const localName = (alias ?? importedName.split(".")[0] ?? importedName).trim();
|
|
192
|
+
const sourcePath2 = resolvePythonImportPath(db, importerPath, importedName);
|
|
193
|
+
const usedMembers = collectNamespaceMembers(body, localName);
|
|
194
|
+
return [{
|
|
195
|
+
importedName,
|
|
196
|
+
localName,
|
|
197
|
+
sourcePath: sourcePath2,
|
|
198
|
+
kind: "namespace",
|
|
199
|
+
used: hasIdentifierUsage(body, localName) || usedMembers.length > 0,
|
|
200
|
+
usedMembers
|
|
201
|
+
}];
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
const sourcePath = statement.module ? resolvePythonImportPath(db, importerPath, statement.module) : null;
|
|
205
|
+
const results = [];
|
|
206
|
+
for (const entry of splitTopLevel(normalizedClause)) {
|
|
207
|
+
const cleaned = entry.trim().replace(/,$/, "");
|
|
208
|
+
if (!cleaned) continue;
|
|
209
|
+
if (cleaned === "*") {
|
|
210
|
+
results.push({
|
|
211
|
+
importedName: "*",
|
|
212
|
+
localName: null,
|
|
213
|
+
sourcePath,
|
|
214
|
+
kind: "side-effect",
|
|
215
|
+
used: true,
|
|
216
|
+
usedMembers: []
|
|
217
|
+
});
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
const [importedName, alias] = cleaned.split(/\s+as\s+/);
|
|
221
|
+
const localName = (alias ?? importedName).trim();
|
|
222
|
+
results.push({
|
|
223
|
+
importedName: importedName.trim(),
|
|
224
|
+
localName,
|
|
225
|
+
sourcePath,
|
|
226
|
+
kind: "named",
|
|
227
|
+
used: hasIdentifierUsage(body, localName),
|
|
228
|
+
usedMembers: []
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
return results;
|
|
232
|
+
}
|
|
233
|
+
function parseImportClause(clause) {
|
|
234
|
+
const trimmed = clause.trim().replace(/^type\s+/, "");
|
|
235
|
+
const [first, second] = splitImportClause(trimmed);
|
|
236
|
+
const entries = [];
|
|
237
|
+
if (first) {
|
|
238
|
+
entries.push(...parseImportBinding(first));
|
|
239
|
+
}
|
|
240
|
+
if (second) {
|
|
241
|
+
entries.push(...parseImportBinding(second));
|
|
242
|
+
}
|
|
243
|
+
return entries;
|
|
244
|
+
}
|
|
245
|
+
function parseImportBinding(binding) {
|
|
246
|
+
const trimmed = binding.trim();
|
|
247
|
+
if (!trimmed) return [];
|
|
248
|
+
if (trimmed.startsWith("{")) {
|
|
249
|
+
const inner = trimmed.slice(1, -1).trim();
|
|
250
|
+
if (!inner) return [];
|
|
251
|
+
return splitTopLevel(inner).map((entry) => {
|
|
252
|
+
const cleaned = entry.trim().replace(/^type\s+/, "");
|
|
253
|
+
const [importedName, alias] = cleaned.split(/\s+as\s+/);
|
|
254
|
+
return {
|
|
255
|
+
importedName: importedName.trim(),
|
|
256
|
+
localName: (alias ?? importedName).trim(),
|
|
257
|
+
kind: "named"
|
|
258
|
+
};
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
if (trimmed.startsWith("* as ")) {
|
|
262
|
+
return [{
|
|
263
|
+
importedName: "*",
|
|
264
|
+
localName: trimmed.slice(5).trim(),
|
|
265
|
+
kind: "namespace"
|
|
266
|
+
}];
|
|
267
|
+
}
|
|
268
|
+
return [{
|
|
269
|
+
importedName: "default",
|
|
270
|
+
localName: trimmed,
|
|
271
|
+
kind: "default"
|
|
272
|
+
}];
|
|
273
|
+
}
|
|
274
|
+
function splitImportClause(clause) {
|
|
275
|
+
let depth = 0;
|
|
276
|
+
for (let i = 0; i < clause.length; i++) {
|
|
277
|
+
const char = clause[i];
|
|
278
|
+
if (char === "{") depth++;
|
|
279
|
+
if (char === "}") depth--;
|
|
280
|
+
if (char === "," && depth === 0) {
|
|
281
|
+
return [clause.slice(0, i).trim(), clause.slice(i + 1).trim()];
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
return [clause.trim(), null];
|
|
285
|
+
}
|
|
286
|
+
function splitTopLevel(input) {
|
|
287
|
+
const parts = [];
|
|
288
|
+
let depth = 0;
|
|
289
|
+
let start = 0;
|
|
290
|
+
for (let i = 0; i < input.length; i++) {
|
|
291
|
+
const char = input[i];
|
|
292
|
+
if (char === "{" || char === "[" || char === "(") depth++;
|
|
293
|
+
if (char === "}" || char === "]" || char === ")") depth--;
|
|
294
|
+
if (char === "," && depth === 0) {
|
|
295
|
+
parts.push(input.slice(start, i));
|
|
296
|
+
start = i + 1;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
parts.push(input.slice(start));
|
|
300
|
+
return parts;
|
|
301
|
+
}
|
|
302
|
+
function buildUsageBody(source, start, end) {
|
|
303
|
+
const masked = `${source.slice(0, start)}${" ".repeat(end - start)}${source.slice(end)}`;
|
|
304
|
+
return stripCommentsAndStrings(masked);
|
|
305
|
+
}
|
|
306
|
+
function stripCommentsAndStrings(source) {
|
|
307
|
+
return source.replace(/'''[\s\S]*?'''/g, " ").replace(/"""[\s\S]*?"""/g, " ").replace(/#.*$/gm, " ").replace(/\/\/.*$/gm, " ").replace(/\/\*[\s\S]*?\*\//g, " ").replace(/`(?:\\[\s\S]|[^`])*`/g, " ").replace(/'(?:\\.|[^'\\\r\n])*'/g, " ").replace(/"(?:\\.|[^"\\\r\n])*"/g, " ");
|
|
308
|
+
}
|
|
309
|
+
function hasIdentifierUsage(body, identifier) {
|
|
310
|
+
return new RegExp(`\\b${escapeRegex(identifier)}\\b`, "m").test(body);
|
|
311
|
+
}
|
|
312
|
+
function collectNamespaceMembers(body, namespaceName) {
|
|
313
|
+
const members = /* @__PURE__ */ new Set();
|
|
314
|
+
const regex = new RegExp(`\\b${escapeRegex(namespaceName)}\\s*\\.\\s*([A-Za-z_$][\\w$]*)`, "g");
|
|
315
|
+
for (const match of body.matchAll(regex)) {
|
|
316
|
+
const member = match[1];
|
|
317
|
+
if (member) {
|
|
318
|
+
members.add(member);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
return [...members];
|
|
322
|
+
}
|
|
323
|
+
function resolveImportPath(db, importerPath, specifier) {
|
|
324
|
+
if (isPythonSourcePath(importerPath)) {
|
|
325
|
+
return resolvePythonImportPath(db, importerPath, specifier);
|
|
326
|
+
}
|
|
327
|
+
return resolveJavaScriptImportPath(db, importerPath, specifier);
|
|
328
|
+
}
|
|
329
|
+
function resolveJavaScriptImportPath(db, importerPath, specifier) {
|
|
330
|
+
if (!specifier.startsWith(".") && !specifier.startsWith("/")) {
|
|
331
|
+
return null;
|
|
332
|
+
}
|
|
333
|
+
const importerDir = dirname(join(db.config.projectRoot, importerPath));
|
|
334
|
+
const absolute = resolve(importerDir, specifier);
|
|
335
|
+
const indexedPaths = getIndexedPaths(db);
|
|
336
|
+
for (const candidate of candidateImportPaths(absolute)) {
|
|
337
|
+
const relativeCandidate = normalizePath(relative(db.config.projectRoot, candidate));
|
|
338
|
+
if (indexedPaths.has(relativeCandidate) || existsSync(candidate)) {
|
|
339
|
+
return relativeCandidate;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
return normalizePath(relative(db.config.projectRoot, absolute));
|
|
343
|
+
}
|
|
344
|
+
function resolvePythonImportPath(db, importerPath, specifier) {
|
|
345
|
+
const indexedPaths = getIndexedPaths(db);
|
|
346
|
+
let basePath;
|
|
347
|
+
if (specifier.startsWith(".")) {
|
|
348
|
+
const match = specifier.match(/^(\.+)(.*)$/);
|
|
349
|
+
if (!match) return null;
|
|
350
|
+
const dots = match[1].length;
|
|
351
|
+
const remainder = match[2].replace(/^\./, "");
|
|
352
|
+
let baseDir = dirname(join(db.config.projectRoot, importerPath));
|
|
353
|
+
for (let i = 1; i < dots; i++) {
|
|
354
|
+
baseDir = dirname(baseDir);
|
|
355
|
+
}
|
|
356
|
+
basePath = remainder ? resolve(baseDir, remainder.replace(/\./g, "/")) : baseDir;
|
|
357
|
+
} else {
|
|
358
|
+
basePath = resolve(db.config.projectRoot, specifier.replace(/\./g, "/"));
|
|
359
|
+
}
|
|
360
|
+
for (const candidate of pythonCandidateImportPaths(basePath)) {
|
|
361
|
+
const relativeCandidate = normalizePath(relative(db.config.projectRoot, candidate));
|
|
362
|
+
if (indexedPaths.has(relativeCandidate) || existsSync(candidate)) {
|
|
363
|
+
return relativeCandidate;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
return null;
|
|
367
|
+
}
|
|
368
|
+
function pythonCandidateImportPaths(basePath) {
|
|
369
|
+
const ext = extname(basePath);
|
|
370
|
+
if (PYTHON_SOURCE_EXTENSIONS.includes(ext)) {
|
|
371
|
+
return [basePath];
|
|
372
|
+
}
|
|
373
|
+
return [
|
|
374
|
+
`${basePath}.py`,
|
|
375
|
+
`${basePath}.pyi`,
|
|
376
|
+
join(basePath, "__init__.py"),
|
|
377
|
+
join(basePath, "__init__.pyi")
|
|
378
|
+
];
|
|
379
|
+
}
|
|
380
|
+
function candidateImportPaths(absolute) {
|
|
381
|
+
const ext = extname(absolute);
|
|
382
|
+
const candidates = /* @__PURE__ */ new Set();
|
|
383
|
+
if (ext) {
|
|
384
|
+
candidates.add(absolute);
|
|
385
|
+
for (const sourceExt of SOURCE_EXTENSIONS) {
|
|
386
|
+
candidates.add(absolute.slice(0, -ext.length) + sourceExt);
|
|
387
|
+
}
|
|
388
|
+
} else {
|
|
389
|
+
for (const sourceExt of SOURCE_EXTENSIONS) {
|
|
390
|
+
candidates.add(`${absolute}${sourceExt}`);
|
|
391
|
+
candidates.add(join(absolute, `index${sourceExt}`));
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
return [...candidates];
|
|
395
|
+
}
|
|
396
|
+
function getIndexedPaths(db) {
|
|
397
|
+
const cached = INDEXED_PATH_CACHE.get(db);
|
|
398
|
+
if (cached) {
|
|
399
|
+
return cached;
|
|
400
|
+
}
|
|
401
|
+
const paths = new Set(
|
|
402
|
+
db.all(
|
|
403
|
+
`SELECT relative_path
|
|
404
|
+
FROM documents
|
|
405
|
+
WHERE 1 = 1
|
|
406
|
+
${db.pathExclusionsFor("documents")}`
|
|
407
|
+
).map((row) => normalizePath(row.relative_path)).filter((relativePath) => !db.isIgnored(relativePath))
|
|
408
|
+
);
|
|
409
|
+
INDEXED_PATH_CACHE.set(db, paths);
|
|
410
|
+
return paths;
|
|
411
|
+
}
|
|
412
|
+
function getCachedMap(cache, db) {
|
|
413
|
+
let map = cache.get(db);
|
|
414
|
+
if (!map) {
|
|
415
|
+
map = /* @__PURE__ */ new Map();
|
|
416
|
+
cache.set(db, map);
|
|
417
|
+
}
|
|
418
|
+
return map;
|
|
419
|
+
}
|
|
420
|
+
function normalizePath(path) {
|
|
421
|
+
return path.replace(/\\/g, "/");
|
|
422
|
+
}
|
|
423
|
+
function isPythonSourcePath(relativePath) {
|
|
424
|
+
return PYTHON_SOURCE_EXTENSIONS.includes(extname(relativePath).toLowerCase());
|
|
425
|
+
}
|
|
426
|
+
function pythonParenBalance(value) {
|
|
427
|
+
let balance = 0;
|
|
428
|
+
for (const char of value) {
|
|
429
|
+
if (char === "(") balance++;
|
|
430
|
+
if (char === ")") balance--;
|
|
431
|
+
}
|
|
432
|
+
return balance;
|
|
433
|
+
}
|
|
434
|
+
function escapeRegex(value) {
|
|
435
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// src/queries/imports.ts
|
|
439
|
+
function imports(db, filePattern) {
|
|
440
|
+
const rows = db.all(
|
|
441
|
+
`SELECT DISTINCT gs.symbol, def_d.relative_path AS from_file, imp_d.relative_path AS importer
|
|
442
|
+
FROM mentions m
|
|
443
|
+
JOIN chunks c ON m.chunk_id = c.id
|
|
444
|
+
JOIN documents imp_d ON c.document_id = imp_d.id
|
|
445
|
+
JOIN global_symbols gs ON m.symbol_id = gs.id
|
|
446
|
+
LEFT JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id
|
|
447
|
+
LEFT JOIN documents def_d ON der.document_id = def_d.id
|
|
448
|
+
WHERE imp_d.relative_path LIKE ?
|
|
449
|
+
AND m.role = 2
|
|
450
|
+
ORDER BY def_d.relative_path, gs.symbol`,
|
|
451
|
+
`%${filePattern}%`
|
|
452
|
+
);
|
|
453
|
+
const indexedResults = rows.filter((row) => !db.isIgnored(row.importer)).map((r) => ({
|
|
454
|
+
symbol: r.symbol,
|
|
455
|
+
shortName: shortenSymbol(r.symbol),
|
|
456
|
+
fromFile: r.from_file ?? "(external)"
|
|
457
|
+
}));
|
|
458
|
+
if (indexedResults.length > 0) {
|
|
459
|
+
return indexedResults;
|
|
460
|
+
}
|
|
461
|
+
const importer = findIndexedFile(db, filePattern);
|
|
462
|
+
if (!importer) return [];
|
|
463
|
+
return getSourceImports(db, importer).map((entry) => ({
|
|
464
|
+
symbol: renderImportSymbol(entry.importedName, entry.localName, entry.kind),
|
|
465
|
+
shortName: renderImportSymbol(entry.importedName, entry.localName, entry.kind),
|
|
466
|
+
fromFile: entry.sourcePath ?? "(external)"
|
|
467
|
+
}));
|
|
468
|
+
}
|
|
469
|
+
function importedBy(db, symbolPattern) {
|
|
470
|
+
const rows = db.all(
|
|
471
|
+
`SELECT DISTINCT gs.symbol, d.relative_path AS importer
|
|
472
|
+
FROM mentions m
|
|
473
|
+
JOIN chunks c ON m.chunk_id = c.id
|
|
474
|
+
JOIN documents d ON c.document_id = d.id
|
|
475
|
+
JOIN global_symbols gs ON m.symbol_id = gs.id
|
|
476
|
+
WHERE gs.symbol LIKE ?
|
|
477
|
+
AND m.role = 2
|
|
478
|
+
ORDER BY d.relative_path`,
|
|
479
|
+
`%${symbolPattern}%`
|
|
480
|
+
);
|
|
481
|
+
const indexedResults = rows.filter((r) => !db.isIgnored(r.importer)).map((r) => ({
|
|
482
|
+
symbol: r.symbol,
|
|
483
|
+
shortName: shortenSymbol(r.symbol),
|
|
484
|
+
fromFile: r.importer
|
|
485
|
+
}));
|
|
486
|
+
if (indexedResults.length > 0) {
|
|
487
|
+
return indexedResults;
|
|
488
|
+
}
|
|
489
|
+
const target = findFirstSymbolMatch(db, symbolPattern);
|
|
490
|
+
const targetFile = target?.relativePath ?? null;
|
|
491
|
+
const targetLeaf = target ? leafName(target.symbol) : symbolPattern.replace(/\(\)$/, "");
|
|
492
|
+
const targetIsModule = target ? isModuleLikeSymbol(target.symbol) : false;
|
|
493
|
+
const files = db.all(
|
|
494
|
+
`SELECT relative_path
|
|
495
|
+
FROM documents
|
|
496
|
+
WHERE 1 = 1
|
|
497
|
+
${db.pathExclusionsFor("documents")}
|
|
498
|
+
ORDER BY relative_path`
|
|
499
|
+
);
|
|
500
|
+
const importers = /* @__PURE__ */ new Set();
|
|
501
|
+
for (const row of files) {
|
|
502
|
+
if (db.isIgnored(row.relative_path)) continue;
|
|
503
|
+
for (const entry of getSourceImports(db, row.relative_path)) {
|
|
504
|
+
if (!entry.sourcePath) continue;
|
|
505
|
+
if (targetFile && normalizePath2(entry.sourcePath) !== normalizePath2(targetFile)) {
|
|
506
|
+
continue;
|
|
507
|
+
}
|
|
508
|
+
if (targetIsModule) {
|
|
509
|
+
importers.add(row.relative_path);
|
|
510
|
+
continue;
|
|
511
|
+
}
|
|
512
|
+
if (entry.kind === "named" && entry.importedName === targetLeaf) {
|
|
513
|
+
importers.add(row.relative_path);
|
|
514
|
+
continue;
|
|
515
|
+
}
|
|
516
|
+
if (entry.kind === "namespace" && entry.usedMembers.includes(targetLeaf)) {
|
|
517
|
+
importers.add(row.relative_path);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
return [...importers].sort().map((importer) => ({
|
|
522
|
+
symbol: target?.symbol ?? targetLeaf,
|
|
523
|
+
shortName: target ? shortenSymbol(target.symbol) : targetLeaf,
|
|
524
|
+
fromFile: importer
|
|
525
|
+
}));
|
|
526
|
+
}
|
|
527
|
+
function unusedImports(db, filePattern) {
|
|
528
|
+
const rows = db.all(
|
|
529
|
+
`SELECT gs.symbol, d.relative_path AS imported_in, d.relative_path AS importer
|
|
530
|
+
FROM mentions m
|
|
531
|
+
JOIN chunks c ON m.chunk_id = c.id
|
|
532
|
+
JOIN documents d ON c.document_id = d.id
|
|
533
|
+
JOIN global_symbols gs ON m.symbol_id = gs.id
|
|
534
|
+
WHERE d.relative_path LIKE ?
|
|
535
|
+
AND m.role = 2
|
|
536
|
+
AND NOT EXISTS (
|
|
537
|
+
SELECT 1
|
|
538
|
+
FROM mentions ref_m
|
|
539
|
+
JOIN chunks ref_c ON ref_m.chunk_id = ref_c.id
|
|
540
|
+
WHERE ref_m.symbol_id = gs.id
|
|
541
|
+
AND ref_m.role != 1
|
|
542
|
+
AND ref_c.document_id = d.id
|
|
543
|
+
)
|
|
544
|
+
ORDER BY d.relative_path, gs.symbol`,
|
|
545
|
+
`%${filePattern}%`
|
|
546
|
+
);
|
|
547
|
+
const indexedResults = rows.filter((row) => !db.isIgnored(row.importer)).map((r) => ({
|
|
548
|
+
symbol: r.symbol,
|
|
549
|
+
shortName: shortenSymbol(r.symbol),
|
|
550
|
+
importedIn: r.imported_in
|
|
551
|
+
}));
|
|
552
|
+
if (indexedResults.length > 0) {
|
|
553
|
+
return indexedResults;
|
|
554
|
+
}
|
|
555
|
+
const importer = findIndexedFile(db, filePattern);
|
|
556
|
+
if (!importer) return [];
|
|
557
|
+
return getSourceImports(db, importer).filter((entry) => entry.kind !== "side-effect" && !entry.used).map((entry) => ({
|
|
558
|
+
symbol: renderImportSymbol(entry.importedName, entry.localName, entry.kind),
|
|
559
|
+
shortName: renderImportSymbol(entry.importedName, entry.localName, entry.kind),
|
|
560
|
+
importedIn: importer
|
|
561
|
+
}));
|
|
562
|
+
}
|
|
563
|
+
function findIndexedFile(db, filePattern) {
|
|
564
|
+
const doc = db.get(
|
|
565
|
+
`SELECT relative_path
|
|
566
|
+
FROM documents
|
|
567
|
+
WHERE relative_path LIKE ?
|
|
568
|
+
${db.pathExclusionsFor("documents")}
|
|
569
|
+
LIMIT 1`,
|
|
570
|
+
`%${filePattern}%`
|
|
571
|
+
);
|
|
572
|
+
if (!doc || db.isIgnored(doc.relative_path)) {
|
|
573
|
+
return null;
|
|
574
|
+
}
|
|
575
|
+
return doc.relative_path;
|
|
576
|
+
}
|
|
577
|
+
function renderImportSymbol(importedName, localName, kind) {
|
|
578
|
+
if (kind === "namespace" && importedName === "*" && localName) {
|
|
579
|
+
return `* as ${localName}`;
|
|
580
|
+
}
|
|
581
|
+
if (kind === "default" && localName) {
|
|
582
|
+
return `default as ${localName}`;
|
|
583
|
+
}
|
|
584
|
+
if (kind === "side-effect") {
|
|
585
|
+
return "(side effect import)";
|
|
586
|
+
}
|
|
587
|
+
if (localName && localName !== importedName) {
|
|
588
|
+
return `${importedName} as ${localName}`;
|
|
589
|
+
}
|
|
590
|
+
return importedName;
|
|
591
|
+
}
|
|
592
|
+
function normalizePath2(path) {
|
|
593
|
+
return path.replace(/\\/g, "/");
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
export {
|
|
597
|
+
imports,
|
|
598
|
+
importedBy,
|
|
599
|
+
unusedImports
|
|
600
|
+
};
|
|
601
|
+
//# sourceMappingURL=chunk-34JPTNRN.js.map
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getCalleeRowsForSymbol,
|
|
3
3
|
testFileExclusionSql
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-LLMPAG56.js";
|
|
5
5
|
import {
|
|
6
6
|
shortenSymbol
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-QIXNAB5K.js";
|
|
8
8
|
|
|
9
9
|
// src/queries/passthrough-candidates.ts
|
|
10
10
|
function passthroughCandidates(db, opts) {
|
|
@@ -68,4 +68,4 @@ function passthroughCandidates(db, opts) {
|
|
|
68
68
|
export {
|
|
69
69
|
passthroughCandidates
|
|
70
70
|
};
|
|
71
|
-
//# sourceMappingURL=chunk-
|
|
71
|
+
//# sourceMappingURL=chunk-3566TKJ5.js.map
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
findFirstSymbolMatch,
|
|
3
3
|
getCalleeRowsForSymbol
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-LLMPAG56.js";
|
|
5
5
|
import {
|
|
6
6
|
shortenSymbol
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-QIXNAB5K.js";
|
|
8
8
|
|
|
9
9
|
// src/queries/convergence.ts
|
|
10
10
|
function convergence(db, symbolPatternA, symbolPatternB) {
|
|
@@ -32,7 +32,11 @@ function convergence(db, symbolPatternA, symbolPatternB) {
|
|
|
32
32
|
const union = /* @__PURE__ */ new Set([...calleesA, ...calleesB]);
|
|
33
33
|
const similarity = union.size > 0 ? shared.length / union.size : 0;
|
|
34
34
|
let strategy;
|
|
35
|
-
if (
|
|
35
|
+
if (union.size === 0) {
|
|
36
|
+
strategy = "Neither function calls other tracked symbols. There is no callee-pattern evidence for consolidation; inspect the source bodies directly.";
|
|
37
|
+
} else if (shared.length === 0) {
|
|
38
|
+
strategy = "These functions do not share any callees. They are not a callee-based consolidation candidate.";
|
|
39
|
+
} else if (uniqueA.length === 0 && uniqueB.length === 0) {
|
|
36
40
|
strategy = "These functions have identical callee sets. One can replace the other directly.";
|
|
37
41
|
} else if (uniqueA.length === 0) {
|
|
38
42
|
strategy = `A is a subset of B. A can be replaced by calling B (B does everything A does plus more).`;
|
|
@@ -69,4 +73,4 @@ function convergence(db, symbolPatternA, symbolPatternB) {
|
|
|
69
73
|
export {
|
|
70
74
|
convergence
|
|
71
75
|
};
|
|
72
|
-
//# sourceMappingURL=chunk-
|
|
76
|
+
//# sourceMappingURL=chunk-4ACRRQC4.js.map
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isLiveBarrel
|
|
3
|
+
} from "./chunk-VO4QI3LS.js";
|
|
1
4
|
import {
|
|
2
5
|
shortenSymbol
|
|
3
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-QIXNAB5K.js";
|
|
4
7
|
|
|
5
8
|
// src/queries/redundant-reexports.ts
|
|
6
9
|
function redundantReexports(db, opts = {}) {
|
|
@@ -36,6 +39,7 @@ function redundantReexports(db, opts = {}) {
|
|
|
36
39
|
const results = [];
|
|
37
40
|
for (const row of reexportRows) {
|
|
38
41
|
if (db.isIgnored(row.barrel_path) || db.isIgnored(row.original_path)) continue;
|
|
42
|
+
if (isLiveBarrel(db, row.barrel_path)) continue;
|
|
39
43
|
const consumerCounts = db.get(
|
|
40
44
|
`SELECT
|
|
41
45
|
SUM(CASE WHEN uses_barrel = 1 THEN 1 ELSE 0 END) AS barrel_consumers,
|
|
@@ -98,4 +102,4 @@ function redundantReexports(db, opts = {}) {
|
|
|
98
102
|
export {
|
|
99
103
|
redundantReexports
|
|
100
104
|
};
|
|
101
|
-
//# sourceMappingURL=chunk-
|
|
105
|
+
//# sourceMappingURL=chunk-4BQFSNFI.js.map
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
findFirstSymbolMatch,
|
|
3
3
|
getCalleeRowsForSymbol
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-LLMPAG56.js";
|
|
5
5
|
import {
|
|
6
6
|
shortenSymbol
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-QIXNAB5K.js";
|
|
8
8
|
|
|
9
9
|
// src/queries/complexity.ts
|
|
10
10
|
import { readFileSync } from "fs";
|
|
@@ -107,4 +107,4 @@ function stripCommentsAndStrings(source) {
|
|
|
107
107
|
export {
|
|
108
108
|
complexity
|
|
109
109
|
};
|
|
110
|
-
//# sourceMappingURL=chunk-
|
|
110
|
+
//# sourceMappingURL=chunk-6QSHLFSL.js.map
|