scip-query 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-CM454WL3.js → chunk-2CKGIR6G.js} +2 -2
- package/dist/{chunk-5FGUEU7N.js → chunk-4EXL2CUA.js} +4 -4
- package/dist/chunk-4EXL2CUA.js.map +1 -0
- package/dist/{chunk-TDNNOR6D.js → chunk-4PDAL6IL.js} +6 -6
- package/dist/chunk-4PDAL6IL.js.map +1 -0
- package/dist/{chunk-BP2ATLK2.js → chunk-4XHWPRAX.js} +3 -3
- package/dist/chunk-4XHWPRAX.js.map +1 -0
- package/dist/{chunk-2QZ23IBN.js → chunk-5RMYT5WH.js} +3 -3
- package/dist/chunk-5RMYT5WH.js.map +1 -0
- package/dist/{chunk-7OZPA5OO.js → chunk-63G7IQTD.js} +13 -13
- package/dist/{chunk-XFXDXEUN.js → chunk-74RFWB5T.js} +2 -2
- package/dist/{chunk-XFXDXEUN.js.map → chunk-74RFWB5T.js.map} +1 -1
- package/dist/{chunk-JKP5GH6T.js → chunk-7LLPRPR5.js} +2 -2
- package/dist/{chunk-BFSCMC22.js → chunk-7PBOG4YE.js} +2 -2
- package/dist/{chunk-BFSCMC22.js.map → chunk-7PBOG4YE.js.map} +1 -1
- package/dist/{chunk-36OMT7ZJ.js → chunk-7RLE5EWE.js} +3 -3
- package/dist/{chunk-36OMT7ZJ.js.map → chunk-7RLE5EWE.js.map} +1 -1
- package/dist/{chunk-UNTPVD36.js → chunk-7UCKSQRS.js} +3 -3
- package/dist/{chunk-UNTPVD36.js.map → chunk-7UCKSQRS.js.map} +1 -1
- package/dist/{chunk-GJFURBEW.js → chunk-BNN2RKD2.js} +3 -3
- package/dist/chunk-BNN2RKD2.js.map +1 -0
- package/dist/{chunk-FFSWWE5O.js → chunk-BOVXCR46.js} +2 -2
- package/dist/{chunk-FFSWWE5O.js.map → chunk-BOVXCR46.js.map} +1 -1
- package/dist/{chunk-6VJ6Q7IE.js → chunk-D567NFIF.js} +3 -3
- package/dist/{chunk-6VJ6Q7IE.js.map → chunk-D567NFIF.js.map} +1 -1
- package/dist/{chunk-GTILYBH6.js → chunk-DGUPQSOR.js} +5 -5
- package/dist/chunk-DGUPQSOR.js.map +1 -0
- package/dist/{chunk-TBP6BICL.js → chunk-EQYLEQCW.js} +2 -2
- package/dist/{chunk-TBP6BICL.js.map → chunk-EQYLEQCW.js.map} +1 -1
- package/dist/{chunk-VZ7AMAFL.js → chunk-H2MDONBU.js} +2 -2
- package/dist/{chunk-BEPIEVLR.js → chunk-HB7MRLLL.js} +2 -2
- package/dist/{chunk-BEPIEVLR.js.map → chunk-HB7MRLLL.js.map} +1 -1
- package/dist/{chunk-KVSW5KYP.js → chunk-HDSRORNV.js} +4 -4
- package/dist/chunk-HDSRORNV.js.map +1 -0
- package/dist/{chunk-5WTJAXY2.js → chunk-HMLMH7VZ.js} +2 -2
- package/dist/{chunk-Z73NYSBZ.js → chunk-HPFZLISB.js} +2 -2
- package/dist/{chunk-3ZZJVBIO.js → chunk-HZBC7PPD.js} +4 -4
- package/dist/chunk-HZBC7PPD.js.map +1 -0
- package/dist/{chunk-6NBLIDF4.js → chunk-ITZ3DDOG.js} +2 -2
- package/dist/chunk-ITZ3DDOG.js.map +1 -0
- package/dist/{chunk-YZAA4LYG.js → chunk-KPPHZCZJ.js} +5 -5
- package/dist/chunk-KPPHZCZJ.js.map +1 -0
- package/dist/{chunk-T6ARFSBZ.js → chunk-MCUX5LA7.js} +6 -6
- package/dist/chunk-MCUX5LA7.js.map +1 -0
- package/dist/{chunk-ZJRYBOEE.js → chunk-NHBZIL2J.js} +4 -4
- package/dist/{chunk-ZJRYBOEE.js.map → chunk-NHBZIL2J.js.map} +1 -1
- package/dist/{chunk-VRUJH4BO.js → chunk-NWCE4CIC.js} +4 -4
- package/dist/chunk-NWCE4CIC.js.map +1 -0
- package/dist/{chunk-LUSIFBXO.js → chunk-OVPLOMPY.js} +4 -4
- package/dist/{chunk-LUSIFBXO.js.map → chunk-OVPLOMPY.js.map} +1 -1
- package/dist/{chunk-TSPZOMHC.js → chunk-UJQN5N3I.js} +2 -2
- package/dist/{chunk-NDSQYIWT.js → chunk-W4ALF422.js} +2 -2
- package/dist/{chunk-3E2X7RIE.js → chunk-Z4GHE2HD.js} +5 -5
- package/dist/chunk-Z4GHE2HD.js.map +1 -0
- package/dist/{chunk-LB7OS35Q.js → chunk-Z6YZJ36C.js} +2 -2
- package/dist/{chunk-EMDQWNYR.js → chunk-ZK6GXM3J.js} +7 -7
- package/dist/chunk-ZK6GXM3J.js.map +1 -0
- package/dist/{chunk-FUHJCHS4.js → chunk-ZOGY2V3N.js} +3 -3
- package/dist/chunk-ZOGY2V3N.js.map +1 -0
- package/dist/{chunk-MBVNHJVN.js → chunk-ZQIIPFD7.js} +2 -2
- package/dist/cli.js +52 -52
- package/dist/cli.js.map +1 -1
- package/dist/{db-BxaevAyc.d.ts → db-BNVVZSfP.d.ts} +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +35 -35
- package/dist/queries/affected.d.ts +1 -1
- package/dist/queries/affected.js +2 -2
- package/dist/queries/bottlenecks.d.ts +1 -1
- package/dist/queries/bottlenecks.js +1 -1
- package/dist/queries/by-kind.d.ts +1 -1
- package/dist/queries/call-graph.d.ts +1 -1
- package/dist/queries/call-graph.js +2 -2
- package/dist/queries/change-surface.d.ts +1 -1
- package/dist/queries/change-surface.js +2 -2
- package/dist/queries/code.d.ts +1 -1
- package/dist/queries/code.js +2 -2
- package/dist/queries/complexity-hotspots.d.ts +1 -1
- package/dist/queries/complexity-hotspots.js +2 -2
- package/dist/queries/complexity.d.ts +1 -1
- package/dist/queries/complexity.js +2 -2
- package/dist/queries/convergence.d.ts +1 -1
- package/dist/queries/convergence.js +2 -2
- package/dist/queries/coupling.d.ts +1 -1
- package/dist/queries/coupling.js +1 -1
- package/dist/queries/cycles.d.ts +1 -1
- package/dist/queries/cycles.js +2 -2
- package/dist/queries/dataflow.d.ts +1 -1
- package/dist/queries/dataflow.js +2 -2
- package/dist/queries/dead.d.ts +1 -1
- package/dist/queries/dead.js +2 -2
- package/dist/queries/deep-chains.d.ts +1 -1
- package/dist/queries/deep-chains.js +2 -2
- package/dist/queries/deps.d.ts +1 -1
- package/dist/queries/diff-impact.d.ts +1 -1
- package/dist/queries/diff-impact.js +2 -2
- package/dist/queries/doc-coverage.d.ts +1 -1
- package/dist/queries/drift.d.ts +1 -1
- package/dist/queries/drift.js +2 -2
- package/dist/queries/extract-candidates.d.ts +1 -1
- package/dist/queries/extract-candidates.js +2 -2
- package/dist/queries/fan.d.ts +1 -1
- package/dist/queries/fan.js +1 -1
- 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/hotspots.d.ts +1 -1
- package/dist/queries/hotspots.js +1 -1
- package/dist/queries/imports.d.ts +1 -1
- package/dist/queries/imports.js +1 -1
- package/dist/queries/index.d.ts +1 -1
- package/dist/queries/index.js +35 -35
- package/dist/queries/isolated.d.ts +1 -1
- package/dist/queries/isolated.js +2 -2
- package/dist/queries/members.d.ts +1 -1
- package/dist/queries/methods.d.ts +1 -1
- package/dist/queries/outline.d.ts +1 -1
- package/dist/queries/passthrough-candidates.d.ts +1 -1
- package/dist/queries/passthrough-candidates.js +2 -2
- package/dist/queries/redundant-reexports.d.ts +1 -1
- package/dist/queries/redundant-reexports.js +1 -1
- package/dist/queries/refs.d.ts +1 -1
- package/dist/queries/refs.js +1 -1
- package/dist/queries/similar-chains.d.ts +1 -1
- package/dist/queries/similar-chains.js +2 -2
- package/dist/queries/similar-files.d.ts +1 -1
- package/dist/queries/similar-files.js +2 -2
- package/dist/queries/similar-signatures.d.ts +1 -1
- package/dist/queries/similar.d.ts +1 -1
- package/dist/queries/similar.js +2 -2
- package/dist/queries/slice.d.ts +1 -1
- package/dist/queries/slice.js +2 -2
- package/dist/queries/stale-abstractions.d.ts +1 -1
- package/dist/queries/stale-abstractions.js +2 -2
- package/dist/queries/stats.d.ts +1 -1
- package/dist/queries/stats.js +1 -1
- package/dist/queries/surface.d.ts +1 -1
- package/dist/queries/surface.js +1 -1
- package/dist/queries/symbols.d.ts +1 -1
- package/dist/queries/system.d.ts +1 -1
- package/dist/queries/test-coverage.d.ts +1 -1
- package/dist/queries/test-coverage.js +2 -2
- package/dist/queries/trace.d.ts +1 -1
- package/dist/queries/trace.js +1 -1
- package/dist/queries/wrapper-candidates.d.ts +1 -1
- package/dist/queries/wrapper-candidates.js +2 -2
- package/package.json +1 -1
- package/src/queries/affected.ts +1 -1
- package/src/queries/bottlenecks.ts +2 -2
- package/src/queries/call-graph.ts +1 -1
- package/src/queries/change-surface.ts +2 -2
- package/src/queries/complexity-hotspots.ts +5 -5
- package/src/queries/complexity.ts +1 -1
- package/src/queries/coupling.ts +3 -3
- package/src/queries/dataflow.ts +4 -4
- package/src/queries/dead.ts +2 -2
- package/src/queries/diff-impact.ts +3 -3
- package/src/queries/drift.ts +1 -1
- package/src/queries/fan.ts +4 -4
- package/src/queries/hotspots.ts +1 -1
- package/src/queries/imports.ts +1 -1
- package/src/queries/isolated.ts +2 -2
- package/src/queries/redundant-reexports.ts +4 -4
- package/src/queries/refs.ts +1 -1
- package/src/queries/slice.ts +2 -2
- package/src/queries/stale-abstractions.ts +1 -1
- package/src/queries/stats.ts +1 -1
- package/src/queries/surface.ts +1 -1
- package/src/queries/test-coverage.ts +2 -2
- package/src/queries/trace.ts +1 -1
- package/src/queries/wrapper-candidates.ts +4 -4
- package/src/query-support.ts +2 -2
- package/src/types.ts +1 -1
- package/dist/chunk-2QZ23IBN.js.map +0 -1
- package/dist/chunk-3E2X7RIE.js.map +0 -1
- package/dist/chunk-3ZZJVBIO.js.map +0 -1
- package/dist/chunk-5FGUEU7N.js.map +0 -1
- package/dist/chunk-6NBLIDF4.js.map +0 -1
- package/dist/chunk-BP2ATLK2.js.map +0 -1
- package/dist/chunk-EMDQWNYR.js.map +0 -1
- package/dist/chunk-FUHJCHS4.js.map +0 -1
- package/dist/chunk-GJFURBEW.js.map +0 -1
- package/dist/chunk-GTILYBH6.js.map +0 -1
- package/dist/chunk-KVSW5KYP.js.map +0 -1
- package/dist/chunk-T6ARFSBZ.js.map +0 -1
- package/dist/chunk-TDNNOR6D.js.map +0 -1
- package/dist/chunk-VRUJH4BO.js.map +0 -1
- package/dist/chunk-YZAA4LYG.js.map +0 -1
- /package/dist/{chunk-CM454WL3.js.map → chunk-2CKGIR6G.js.map} +0 -0
- /package/dist/{chunk-7OZPA5OO.js.map → chunk-63G7IQTD.js.map} +0 -0
- /package/dist/{chunk-JKP5GH6T.js.map → chunk-7LLPRPR5.js.map} +0 -0
- /package/dist/{chunk-VZ7AMAFL.js.map → chunk-H2MDONBU.js.map} +0 -0
- /package/dist/{chunk-5WTJAXY2.js.map → chunk-HMLMH7VZ.js.map} +0 -0
- /package/dist/{chunk-Z73NYSBZ.js.map → chunk-HPFZLISB.js.map} +0 -0
- /package/dist/{chunk-TSPZOMHC.js.map → chunk-UJQN5N3I.js.map} +0 -0
- /package/dist/{chunk-NDSQYIWT.js.map → chunk-W4ALF422.js.map} +0 -0
- /package/dist/{chunk-LB7OS35Q.js.map → chunk-Z6YZJ36C.js.map} +0 -0
- /package/dist/{chunk-MBVNHJVN.js.map → chunk-ZQIIPFD7.js.map} +0 -0
|
@@ -32,7 +32,7 @@ function trace(db, symbolPattern) {
|
|
|
32
32
|
WHERE gs.symbol LIKE ?
|
|
33
33
|
AND ${db.localSymbolPredicate}
|
|
34
34
|
${db.symbolNoise}
|
|
35
|
-
AND m.role
|
|
35
|
+
AND m.role != 1
|
|
36
36
|
ORDER BY d.relative_path`,
|
|
37
37
|
`%${symbolPattern}%`
|
|
38
38
|
);
|
|
@@ -43,4 +43,4 @@ function trace(db, symbolPattern) {
|
|
|
43
43
|
export {
|
|
44
44
|
trace
|
|
45
45
|
};
|
|
46
|
-
//# sourceMappingURL=chunk-
|
|
46
|
+
//# sourceMappingURL=chunk-EQYLEQCW.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/queries/trace.ts"],"sourcesContent":["import type { ScipDatabase } from '../db.js';\nimport type { TraceResult } from '../types.js';\nimport { cleanSignature } from './clean-signature.js';\n\nexport function trace(db: ScipDatabase, symbolPattern: string): TraceResult {\n // Definitions\n const defRows = db.all<{\n relative_path: string;\n start_line: number;\n end_line: number;\n sig: string | null;\n }>(\n `SELECT d.relative_path, der.start_line, der.end_line,\n REPLACE(SUBSTR(gs.documentation, INSTR(gs.documentation, '|') + 1), char(10), ' ') AS sig\n FROM global_symbols gs\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents d ON der.document_id = d.id\n WHERE gs.symbol LIKE ?\n AND ${db.localSymbolPredicate}\n ${db.symbolNoise}\n ORDER BY d.relative_path, der.start_line\n LIMIT 10`,\n `%${symbolPattern}%`,\n );\n\n const definitions = defRows\n .filter((r) => !db.isIgnored(r.relative_path))\n .map((r) => ({\n relativePath: r.relative_path,\n startLine: r.start_line,\n endLine: r.end_line,\n signature: cleanSignature(r.sig),\n }));\n\n // References\n const refRows = db.all<{ relative_path: string }>(\n `SELECT DISTINCT d.relative_path\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents d ON c.document_id = d.id\n JOIN global_symbols gs ON m.symbol_id = gs.id\n WHERE gs.symbol LIKE ?\n AND ${db.localSymbolPredicate}\n ${db.symbolNoise}\n AND m.role
|
|
1
|
+
{"version":3,"sources":["../src/queries/trace.ts"],"sourcesContent":["import type { ScipDatabase } from '../db.js';\nimport type { TraceResult } from '../types.js';\nimport { cleanSignature } from './clean-signature.js';\n\nexport function trace(db: ScipDatabase, symbolPattern: string): TraceResult {\n // Definitions\n const defRows = db.all<{\n relative_path: string;\n start_line: number;\n end_line: number;\n sig: string | null;\n }>(\n `SELECT d.relative_path, der.start_line, der.end_line,\n REPLACE(SUBSTR(gs.documentation, INSTR(gs.documentation, '|') + 1), char(10), ' ') AS sig\n FROM global_symbols gs\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents d ON der.document_id = d.id\n WHERE gs.symbol LIKE ?\n AND ${db.localSymbolPredicate}\n ${db.symbolNoise}\n ORDER BY d.relative_path, der.start_line\n LIMIT 10`,\n `%${symbolPattern}%`,\n );\n\n const definitions = defRows\n .filter((r) => !db.isIgnored(r.relative_path))\n .map((r) => ({\n relativePath: r.relative_path,\n startLine: r.start_line,\n endLine: r.end_line,\n signature: cleanSignature(r.sig),\n }));\n\n // References\n const refRows = db.all<{ relative_path: string }>(\n `SELECT DISTINCT d.relative_path\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents d ON c.document_id = d.id\n JOIN global_symbols gs ON m.symbol_id = gs.id\n WHERE gs.symbol LIKE ?\n AND ${db.localSymbolPredicate}\n ${db.symbolNoise}\n AND m.role != 1\n ORDER BY d.relative_path`,\n `%${symbolPattern}%`,\n );\n\n const referencedBy = refRows\n .map((r) => r.relative_path)\n .filter((p) => !db.isIgnored(p));\n\n return { definitions, referencedBy };\n}\n"],"mappings":";;;;;AAIO,SAAS,MAAM,IAAkB,eAAoC;AAE1E,QAAM,UAAU,GAAG;AAAA,IAMjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAMQ,GAAG,oBAAoB;AAAA,QAC3B,GAAG,WAAW;AAAA;AAAA;AAAA,IAGlB,IAAI,aAAa;AAAA,EACnB;AAEA,QAAM,cAAc,QACjB,OAAO,CAAC,MAAM,CAAC,GAAG,UAAU,EAAE,aAAa,CAAC,EAC5C,IAAI,CAAC,OAAO;AAAA,IACX,cAAc,EAAE;AAAA,IAChB,WAAW,EAAE;AAAA,IACb,SAAS,EAAE;AAAA,IACX,WAAW,eAAe,EAAE,GAAG;AAAA,EACjC,EAAE;AAGJ,QAAM,UAAU,GAAG;AAAA,IACjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAMQ,GAAG,oBAAoB;AAAA,QAC3B,GAAG,WAAW;AAAA;AAAA;AAAA,IAGlB,IAAI,aAAa;AAAA,EACnB;AAEA,QAAM,eAAe,QAClB,IAAI,CAAC,MAAM,EAAE,aAAa,EAC1B,OAAO,CAAC,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC;AAEjC,SAAO,EAAE,aAAa,aAAa;AACrC;","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
findFirstSymbolMatch
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-ZOGY2V3N.js";
|
|
4
4
|
import {
|
|
5
5
|
shortenSymbol
|
|
6
6
|
} from "./chunk-QOV2R2WT.js";
|
|
@@ -73,4 +73,4 @@ function readFileRange(db, filePath, startLine, endLine, context) {
|
|
|
73
73
|
export {
|
|
74
74
|
code
|
|
75
75
|
};
|
|
76
|
-
//# sourceMappingURL=chunk-
|
|
76
|
+
//# sourceMappingURL=chunk-H2MDONBU.js.map
|
|
@@ -55,7 +55,7 @@ function unusedImports(db, filePattern) {
|
|
|
55
55
|
FROM mentions ref_m
|
|
56
56
|
JOIN chunks ref_c ON ref_m.chunk_id = ref_c.id
|
|
57
57
|
WHERE ref_m.symbol_id = gs.id
|
|
58
|
-
AND ref_m.role
|
|
58
|
+
AND ref_m.role != 1
|
|
59
59
|
AND ref_c.document_id = d.id
|
|
60
60
|
)
|
|
61
61
|
ORDER BY d.relative_path, gs.symbol`,
|
|
@@ -73,4 +73,4 @@ export {
|
|
|
73
73
|
importedBy,
|
|
74
74
|
unusedImports
|
|
75
75
|
};
|
|
76
|
-
//# sourceMappingURL=chunk-
|
|
76
|
+
//# sourceMappingURL=chunk-HB7MRLLL.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/queries/imports.ts"],"sourcesContent":["import type { ScipDatabase } from '../db.js';\nimport type { ImportResult, UnusedImportResult } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * What symbols does this file import?\n * Uses role=2 (import) from the SCIP mentions table.\n */\nexport function imports(db: ScipDatabase, filePattern: string): ImportResult[] {\n const rows = db.all<{\n symbol: string;\n from_file: string;\n }>(\n `SELECT DISTINCT gs.symbol, def_d.relative_path AS from_file\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents imp_d ON c.document_id = imp_d.id\n JOIN global_symbols gs ON m.symbol_id = gs.id\n LEFT JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n LEFT JOIN documents def_d ON der.document_id = def_d.id\n WHERE imp_d.relative_path LIKE ?\n AND m.role = 2\n ORDER BY def_d.relative_path, gs.symbol`,\n `%${filePattern}%`,\n );\n\n return rows.map((r) => ({\n symbol: r.symbol,\n shortName: shortenSymbol(r.symbol),\n fromFile: r.from_file ?? '(external)',\n }));\n}\n\n/**\n * Which files import this symbol?\n */\nexport function importedBy(db: ScipDatabase, symbolPattern: string): ImportResult[] {\n const rows = db.all<{\n symbol: string;\n importer: string;\n }>(\n `SELECT DISTINCT gs.symbol, d.relative_path AS importer\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents d ON c.document_id = d.id\n JOIN global_symbols gs ON m.symbol_id = gs.id\n WHERE gs.symbol LIKE ?\n AND m.role = 2\n ORDER BY d.relative_path`,\n `%${symbolPattern}%`,\n );\n\n return rows\n .filter((r) => !db.isIgnored(r.importer))\n .map((r) => ({\n symbol: r.symbol,\n shortName: shortenSymbol(r.symbol),\n fromFile: r.importer,\n }));\n}\n\n/**\n * Find imports in a file that are never referenced (role=0) in the same file.\n * These are likely unused imports.\n */\nexport function unusedImports(db: ScipDatabase, filePattern: string): UnusedImportResult[] {\n const rows = db.all<{\n symbol: string;\n imported_in: string;\n }>(\n `SELECT gs.symbol, d.relative_path AS imported_in\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents d ON c.document_id = d.id\n JOIN global_symbols gs ON m.symbol_id = gs.id\n WHERE d.relative_path LIKE ?\n AND m.role = 2\n AND NOT EXISTS (\n SELECT 1\n FROM mentions ref_m\n JOIN chunks ref_c ON ref_m.chunk_id = ref_c.id\n WHERE ref_m.symbol_id = gs.id\n AND ref_m.role
|
|
1
|
+
{"version":3,"sources":["../src/queries/imports.ts"],"sourcesContent":["import type { ScipDatabase } from '../db.js';\nimport type { ImportResult, UnusedImportResult } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * What symbols does this file import?\n * Uses role=2 (import) from the SCIP mentions table.\n */\nexport function imports(db: ScipDatabase, filePattern: string): ImportResult[] {\n const rows = db.all<{\n symbol: string;\n from_file: string;\n }>(\n `SELECT DISTINCT gs.symbol, def_d.relative_path AS from_file\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents imp_d ON c.document_id = imp_d.id\n JOIN global_symbols gs ON m.symbol_id = gs.id\n LEFT JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n LEFT JOIN documents def_d ON der.document_id = def_d.id\n WHERE imp_d.relative_path LIKE ?\n AND m.role = 2\n ORDER BY def_d.relative_path, gs.symbol`,\n `%${filePattern}%`,\n );\n\n return rows.map((r) => ({\n symbol: r.symbol,\n shortName: shortenSymbol(r.symbol),\n fromFile: r.from_file ?? '(external)',\n }));\n}\n\n/**\n * Which files import this symbol?\n */\nexport function importedBy(db: ScipDatabase, symbolPattern: string): ImportResult[] {\n const rows = db.all<{\n symbol: string;\n importer: string;\n }>(\n `SELECT DISTINCT gs.symbol, d.relative_path AS importer\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents d ON c.document_id = d.id\n JOIN global_symbols gs ON m.symbol_id = gs.id\n WHERE gs.symbol LIKE ?\n AND m.role = 2\n ORDER BY d.relative_path`,\n `%${symbolPattern}%`,\n );\n\n return rows\n .filter((r) => !db.isIgnored(r.importer))\n .map((r) => ({\n symbol: r.symbol,\n shortName: shortenSymbol(r.symbol),\n fromFile: r.importer,\n }));\n}\n\n/**\n * Find imports in a file that are never referenced (role=0) in the same file.\n * These are likely unused imports.\n */\nexport function unusedImports(db: ScipDatabase, filePattern: string): UnusedImportResult[] {\n const rows = db.all<{\n symbol: string;\n imported_in: string;\n }>(\n `SELECT gs.symbol, d.relative_path AS imported_in\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents d ON c.document_id = d.id\n JOIN global_symbols gs ON m.symbol_id = gs.id\n WHERE d.relative_path LIKE ?\n AND m.role = 2\n AND NOT EXISTS (\n SELECT 1\n FROM mentions ref_m\n JOIN chunks ref_c ON ref_m.chunk_id = ref_c.id\n WHERE ref_m.symbol_id = gs.id\n AND ref_m.role != 1\n AND ref_c.document_id = d.id\n )\n ORDER BY d.relative_path, gs.symbol`,\n `%${filePattern}%`,\n );\n\n return rows.map((r) => ({\n symbol: r.symbol,\n shortName: shortenSymbol(r.symbol),\n importedIn: r.imported_in,\n }));\n}\n"],"mappings":";;;;;AAQO,SAAS,QAAQ,IAAkB,aAAqC;AAC7E,QAAM,OAAO,GAAG;AAAA,IAId;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAUA,IAAI,WAAW;AAAA,EACjB;AAEA,SAAO,KAAK,IAAI,CAAC,OAAO;AAAA,IACtB,QAAQ,EAAE;AAAA,IACV,WAAW,cAAc,EAAE,MAAM;AAAA,IACjC,UAAU,EAAE,aAAa;AAAA,EAC3B,EAAE;AACJ;AAKO,SAAS,WAAW,IAAkB,eAAuC;AAClF,QAAM,OAAO,GAAG;AAAA,IAId;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQA,IAAI,aAAa;AAAA,EACnB;AAEA,SAAO,KACJ,OAAO,CAAC,MAAM,CAAC,GAAG,UAAU,EAAE,QAAQ,CAAC,EACvC,IAAI,CAAC,OAAO;AAAA,IACX,QAAQ,EAAE;AAAA,IACV,WAAW,cAAc,EAAE,MAAM;AAAA,IACjC,UAAU,EAAE;AAAA,EACd,EAAE;AACN;AAMO,SAAS,cAAc,IAAkB,aAA2C;AACzF,QAAM,OAAO,GAAG;AAAA,IAId;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAgBA,IAAI,WAAW;AAAA,EACjB;AAEA,SAAO,KAAK,IAAI,CAAC,OAAO;AAAA,IACtB,QAAQ,EAAE;AAAA,IACV,WAAW,cAAc,EAAE,MAAM;AAAA,IACjC,YAAY,EAAE;AAAA,EAChB,EAAE;AACJ;","names":[]}
|
|
@@ -14,7 +14,7 @@ function coupling(db, file1, file2) {
|
|
|
14
14
|
SELECT 1 FROM mentions m
|
|
15
15
|
JOIN chunks c ON m.chunk_id = c.id
|
|
16
16
|
JOIN documents d ON c.document_id = d.id
|
|
17
|
-
WHERE m.symbol_id = gs.id AND m.role
|
|
17
|
+
WHERE m.symbol_id = gs.id AND m.role != 1 AND d.relative_path LIKE ?
|
|
18
18
|
)
|
|
19
19
|
) OR (
|
|
20
20
|
-- Defined in file2, referenced in file1
|
|
@@ -27,7 +27,7 @@ function coupling(db, file1, file2) {
|
|
|
27
27
|
SELECT 1 FROM mentions m
|
|
28
28
|
JOIN chunks c ON m.chunk_id = c.id
|
|
29
29
|
JOIN documents d ON c.document_id = d.id
|
|
30
|
-
WHERE m.symbol_id = gs.id AND m.role
|
|
30
|
+
WHERE m.symbol_id = gs.id AND m.role != 1 AND d.relative_path LIKE ?
|
|
31
31
|
)
|
|
32
32
|
)`,
|
|
33
33
|
`%${file1}%`,
|
|
@@ -55,7 +55,7 @@ function topCoupling(db, opts = {}) {
|
|
|
55
55
|
JOIN global_symbols gs ON m.symbol_id = gs.id
|
|
56
56
|
JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id
|
|
57
57
|
JOIN documents def_d ON der.document_id = def_d.id
|
|
58
|
-
WHERE m.role
|
|
58
|
+
WHERE m.role != 1
|
|
59
59
|
AND def_d.id != ref_d.id
|
|
60
60
|
${db.pathExclusionsFor("def_d", "ref_d")}
|
|
61
61
|
${scopeFilter}
|
|
@@ -75,4 +75,4 @@ export {
|
|
|
75
75
|
coupling,
|
|
76
76
|
topCoupling
|
|
77
77
|
};
|
|
78
|
-
//# sourceMappingURL=chunk-
|
|
78
|
+
//# sourceMappingURL=chunk-HDSRORNV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/queries/coupling.ts"],"sourcesContent":["import type { ScipDatabase } from '../db.js';\nimport type { CouplingResult } from '../types.js';\n\n/**\n * Measure coupling between two files: how many symbols do they share\n * (symbols defined in one and referenced in the other, or vice versa).\n */\nexport function coupling(\n db: ScipDatabase,\n file1: string,\n file2: string,\n): CouplingResult {\n const row = db.get<{ shared: number }>(\n `SELECT COUNT(DISTINCT gs.id) AS shared\n FROM global_symbols gs\n WHERE (\n -- Defined in file1, referenced in file2\n EXISTS (\n SELECT 1 FROM defn_enclosing_ranges der\n JOIN documents d ON der.document_id = d.id\n WHERE der.symbol_id = gs.id AND d.relative_path LIKE ?\n )\n AND EXISTS (\n SELECT 1 FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents d ON c.document_id = d.id\n WHERE m.symbol_id = gs.id AND m.role != 1 AND d.relative_path LIKE ?\n )\n ) OR (\n -- Defined in file2, referenced in file1\n EXISTS (\n SELECT 1 FROM defn_enclosing_ranges der\n JOIN documents d ON der.document_id = d.id\n WHERE der.symbol_id = gs.id AND d.relative_path LIKE ?\n )\n AND EXISTS (\n SELECT 1 FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents d ON c.document_id = d.id\n WHERE m.symbol_id = gs.id AND m.role != 1 AND d.relative_path LIKE ?\n )\n )`,\n `%${file1}%`, `%${file2}%`,\n `%${file2}%`, `%${file1}%`,\n );\n\n return {\n file1,\n file2,\n sharedSymbols: row?.shared ?? 0,\n };\n}\n\n/**\n * Find the most coupled file pairs in the codebase.\n */\nexport function topCoupling(\n db: ScipDatabase,\n opts: { limit?: number; scope?: string } = {},\n): CouplingResult[] {\n const { limit = 20, scope } = opts;\n const scopeFilter = scope\n ? `AND d1.relative_path LIKE '%${scope}%' AND d2.relative_path LIKE '%${scope}%'`\n : '';\n\n // Find file pairs that share the most symbols (one defines, other references)\n const rows = db.all<{\n file1: string;\n file2: string;\n shared: number;\n }>(\n `SELECT\n def_d.relative_path AS file1,\n ref_d.relative_path AS file2,\n COUNT(DISTINCT gs.id) AS shared\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents ref_d ON c.document_id = ref_d.id\n JOIN global_symbols gs ON m.symbol_id = gs.id\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents def_d ON der.document_id = def_d.id\n WHERE m.role != 1\n AND def_d.id != ref_d.id\n ${db.pathExclusionsFor('def_d', 'ref_d')}\n ${scopeFilter}\n GROUP BY def_d.id, ref_d.id\n ORDER BY shared DESC\n LIMIT ?`,\n limit,\n );\n\n return rows\n .filter((r) => !db.isIgnored(r.file1) && !db.isIgnored(r.file2))\n .map((r) => ({\n file1: r.file1,\n file2: r.file2,\n sharedSymbols: r.shared,\n }));\n}\n"],"mappings":";AAOO,SAAS,SACd,IACA,OACA,OACgB;AAChB,QAAM,MAAM,GAAG;AAAA,IACb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IA6BA,IAAI,KAAK;AAAA,IAAK,IAAI,KAAK;AAAA,IACvB,IAAI,KAAK;AAAA,IAAK,IAAI,KAAK;AAAA,EACzB;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,eAAe,KAAK,UAAU;AAAA,EAChC;AACF;AAKO,SAAS,YACd,IACA,OAA2C,CAAC,GAC1B;AAClB,QAAM,EAAE,QAAQ,IAAI,MAAM,IAAI;AAC9B,QAAM,cAAc,QAChB,+BAA+B,KAAK,kCAAkC,KAAK,OAC3E;AAGJ,QAAM,OAAO,GAAG;AAAA,IAKd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAYI,GAAG,kBAAkB,SAAS,OAAO,CAAC;AAAA,QACtC,WAAW;AAAA;AAAA;AAAA;AAAA,IAIf;AAAA,EACF;AAEA,SAAO,KACJ,OAAO,CAAC,MAAM,CAAC,GAAG,UAAU,EAAE,KAAK,KAAK,CAAC,GAAG,UAAU,EAAE,KAAK,CAAC,EAC9D,IAAI,CAAC,OAAO;AAAA,IACX,OAAO,EAAE;AAAA,IACT,OAAO,EAAE;AAAA,IACT,eAAe,EAAE;AAAA,EACnB,EAAE;AACN;","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
buildFileDepGraph
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-ZOGY2V3N.js";
|
|
4
4
|
|
|
5
5
|
// src/queries/cycles.ts
|
|
6
6
|
function cycles(db, opts = {}) {
|
|
@@ -58,4 +58,4 @@ function cycles(db, opts = {}) {
|
|
|
58
58
|
export {
|
|
59
59
|
cycles
|
|
60
60
|
};
|
|
61
|
-
//# sourceMappingURL=chunk-
|
|
61
|
+
//# sourceMappingURL=chunk-HMLMH7VZ.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
buildFileDepGraph
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-ZOGY2V3N.js";
|
|
4
4
|
|
|
5
5
|
// src/queries/similar-files.ts
|
|
6
6
|
function similarFiles(db, opts = {}) {
|
|
@@ -89,4 +89,4 @@ function compareProfiles(a, b, minSimilarity) {
|
|
|
89
89
|
export {
|
|
90
90
|
similarFiles
|
|
91
91
|
};
|
|
92
|
-
//# sourceMappingURL=chunk-
|
|
92
|
+
//# sourceMappingURL=chunk-HPFZLISB.js.map
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
TEST_FILE_PATTERNS,
|
|
3
3
|
testFileExclusionSql,
|
|
4
4
|
testFileMatchSql
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-ZOGY2V3N.js";
|
|
6
6
|
import {
|
|
7
7
|
shortenSymbol
|
|
8
8
|
} from "./chunk-QOV2R2WT.js";
|
|
@@ -28,7 +28,7 @@ function testCoverage(db, symbolPattern) {
|
|
|
28
28
|
JOIN chunks c ON m.chunk_id = c.id
|
|
29
29
|
JOIN documents ref_d ON c.document_id = ref_d.id
|
|
30
30
|
WHERE m.symbol_id = ?
|
|
31
|
-
AND m.role
|
|
31
|
+
AND m.role != 1
|
|
32
32
|
AND (${testPatternSql})
|
|
33
33
|
ORDER BY ref_d.relative_path`,
|
|
34
34
|
s.id
|
|
@@ -67,7 +67,7 @@ function testCoverageSummary(db, opts = {}) {
|
|
|
67
67
|
`SELECT COUNT(*) AS c FROM mentions m
|
|
68
68
|
JOIN chunks c ON m.chunk_id = c.id
|
|
69
69
|
JOIN documents ref_d ON c.document_id = ref_d.id
|
|
70
|
-
WHERE m.symbol_id = ? AND m.role
|
|
70
|
+
WHERE m.symbol_id = ? AND m.role != 1 AND (${testRefSql})`,
|
|
71
71
|
s.id
|
|
72
72
|
);
|
|
73
73
|
if (hasTest && hasTest.c > 0) covered++;
|
|
@@ -85,4 +85,4 @@ export {
|
|
|
85
85
|
testCoverage,
|
|
86
86
|
testCoverageSummary
|
|
87
87
|
};
|
|
88
|
-
//# sourceMappingURL=chunk-
|
|
88
|
+
//# sourceMappingURL=chunk-HZBC7PPD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/queries/test-coverage.ts"],"sourcesContent":["import type { ScipDatabase } from '../db.js';\nimport { TEST_FILE_PATTERNS, testFileExclusionSql, testFileMatchSql } from '../query-support.js';\nimport type { TestCoverageResult } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * Check if a symbol is referenced by any test file.\n * Reports which test files cover (reference) each matching symbol.\n */\nexport function testCoverage(\n db: ScipDatabase,\n symbolPattern: string,\n): TestCoverageResult[] {\n // Find matching symbols\n const syms = db.all<{\n id: number;\n symbol: string;\n relative_path: string;\n }>(\n `SELECT gs.id, gs.symbol, d.relative_path\n FROM global_symbols gs\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents d ON der.document_id = d.id\n WHERE gs.symbol LIKE ?\n ${db.pathExclusionsFor('d')}\n ${db.symbolNoiseFor('gs')}\n ORDER BY d.relative_path`,\n `%${symbolPattern}%`,\n );\n\n const testPatternSql = testFileMatchSql('ref_d', TEST_FILE_PATTERNS);\n\n return syms\n .filter((s) => !db.isIgnored(s.relative_path))\n .map((s) => {\n // Find test files that reference this symbol\n const testFiles = db.all<{ relative_path: string }>(\n `SELECT DISTINCT ref_d.relative_path\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents ref_d ON c.document_id = ref_d.id\n WHERE m.symbol_id = ?\n AND m.role != 1\n AND (${testPatternSql})\n ORDER BY ref_d.relative_path`,\n s.id,\n ).map((r) => r.relative_path);\n\n return {\n symbol: s.symbol,\n shortName: shortenSymbol(s.symbol),\n definedIn: s.relative_path,\n testFiles,\n covered: testFiles.length > 0,\n };\n });\n}\n\n/**\n * Summary: what percentage of symbols in scope are referenced by test files?\n */\nexport function testCoverageSummary(\n db: ScipDatabase,\n opts: { scope?: string; minLoc?: number } = {},\n): { total: number; covered: number; uncovered: number; percent: number } {\n const { scope, minLoc = 3 } = opts;\n const scopeFilter = scope ? `AND d.relative_path LIKE '%${scope}%'` : '';\n const testPatternSql = testFileExclusionSql('d');\n\n const symbols = db.all<{ id: number }>(\n `SELECT gs.id\n FROM global_symbols gs\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents d ON der.document_id = d.id\n WHERE 1 = 1\n ${db.pathExclusionsFor('d')}\n AND ${testPatternSql}\n ${db.symbolNoiseFor('gs')}\n AND gs.symbol NOT LIKE '%#%'\n AND (der.end_line - der.start_line + 1) >= ?\n ${scopeFilter}`,\n minLoc,\n );\n\n const testRefSql = testFileMatchSql('ref_d', TEST_FILE_PATTERNS);\n\n let covered = 0;\n for (const s of symbols) {\n const hasTest = db.get<{ c: number }>(\n `SELECT COUNT(*) AS c FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents ref_d ON c.document_id = ref_d.id\n WHERE m.symbol_id = ? AND m.role != 1 AND (${testRefSql})`,\n s.id,\n );\n if (hasTest && hasTest.c > 0) covered++;\n }\n\n const total = symbols.length;\n return {\n total,\n covered,\n uncovered: total - covered,\n percent: total > 0 ? Math.round((covered / total) * 100) : 0,\n };\n}\n"],"mappings":";;;;;;;;;;AASO,SAAS,aACd,IACA,eACsB;AAEtB,QAAM,OAAO,GAAG;AAAA,IAKd;AAAA;AAAA;AAAA;AAAA;AAAA,QAKI,GAAG,kBAAkB,GAAG,CAAC;AAAA,QACzB,GAAG,eAAe,IAAI,CAAC;AAAA;AAAA,IAE3B,IAAI,aAAa;AAAA,EACnB;AAEA,QAAM,iBAAiB,iBAAiB,SAAS,kBAAkB;AAEnE,SAAO,KACJ,OAAO,CAAC,MAAM,CAAC,GAAG,UAAU,EAAE,aAAa,CAAC,EAC5C,IAAI,CAAC,MAAM;AAEV,UAAM,YAAY,GAAG;AAAA,MACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAMS,cAAc;AAAA;AAAA,MAEvB,EAAE;AAAA,IACJ,EAAE,IAAI,CAAC,MAAM,EAAE,aAAa;AAE5B,WAAO;AAAA,MACL,QAAQ,EAAE;AAAA,MACV,WAAW,cAAc,EAAE,MAAM;AAAA,MACjC,WAAW,EAAE;AAAA,MACb;AAAA,MACA,SAAS,UAAU,SAAS;AAAA,IAC9B;AAAA,EACF,CAAC;AACL;AAKO,SAAS,oBACd,IACA,OAA4C,CAAC,GAC2B;AACxE,QAAM,EAAE,OAAO,SAAS,EAAE,IAAI;AAC9B,QAAM,cAAc,QAAQ,8BAA8B,KAAK,OAAO;AACtE,QAAM,iBAAiB,qBAAqB,GAAG;AAE/C,QAAM,UAAU,GAAG;AAAA,IACjB;AAAA;AAAA;AAAA;AAAA;AAAA,QAKI,GAAG,kBAAkB,GAAG,CAAC;AAAA,YACrB,cAAc;AAAA,QAClB,GAAG,eAAe,IAAI,CAAC;AAAA;AAAA;AAAA,QAGvB,WAAW;AAAA,IACf;AAAA,EACF;AAEA,QAAM,aAAa,iBAAiB,SAAS,kBAAkB;AAE/D,MAAI,UAAU;AACd,aAAW,KAAK,SAAS;AACvB,UAAM,UAAU,GAAG;AAAA,MACjB;AAAA;AAAA;AAAA,oDAG8C,UAAU;AAAA,MACxD,EAAE;AAAA,IACJ;AACA,QAAI,WAAW,QAAQ,IAAI,EAAG;AAAA,EAChC;AAEA,QAAM,QAAQ,QAAQ;AACtB,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,WAAW,QAAQ;AAAA,IACnB,SAAS,QAAQ,IAAI,KAAK,MAAO,UAAU,QAAS,GAAG,IAAI;AAAA,EAC7D;AACF;","names":[]}
|
|
@@ -8,7 +8,7 @@ function refs(db, symbolPattern) {
|
|
|
8
8
|
JOIN global_symbols gs ON m.symbol_id = gs.id
|
|
9
9
|
WHERE gs.symbol LIKE ?
|
|
10
10
|
AND ${db.localSymbolPredicate}
|
|
11
|
-
AND m.role
|
|
11
|
+
AND m.role != 1
|
|
12
12
|
ORDER BY d.relative_path, c.start_line`,
|
|
13
13
|
`%${symbolPattern}%`
|
|
14
14
|
);
|
|
@@ -21,4 +21,4 @@ function refs(db, symbolPattern) {
|
|
|
21
21
|
export {
|
|
22
22
|
refs
|
|
23
23
|
};
|
|
24
|
-
//# sourceMappingURL=chunk-
|
|
24
|
+
//# sourceMappingURL=chunk-ITZ3DDOG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/queries/refs.ts"],"sourcesContent":["import type { ScipDatabase } from '../db.js';\nimport type { RefResult } from '../types.js';\n\nexport function refs(db: ScipDatabase, symbolPattern: string): RefResult[] {\n const rows = db.all<{\n relative_path: string;\n start_line: number;\n }>(\n `SELECT DISTINCT d.relative_path, c.start_line\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents d ON c.document_id = d.id\n JOIN global_symbols gs ON m.symbol_id = gs.id\n WHERE gs.symbol LIKE ?\n AND ${db.localSymbolPredicate}\n AND m.role != 1\n ORDER BY d.relative_path, c.start_line`,\n `%${symbolPattern}%`,\n );\n\n return rows\n .filter((r) => !db.isIgnored(r.relative_path))\n .map((r) => ({\n relativePath: r.relative_path,\n line: r.start_line,\n }));\n}\n"],"mappings":";AAGO,SAAS,KAAK,IAAkB,eAAoC;AACzE,QAAM,OAAO,GAAG;AAAA,IAId;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAMQ,GAAG,oBAAoB;AAAA;AAAA;AAAA,IAG/B,IAAI,aAAa;AAAA,EACnB;AAEA,SAAO,KACJ,OAAO,CAAC,MAAM,CAAC,GAAG,UAAU,EAAE,aAAa,CAAC,EAC5C,IAAI,CAAC,OAAO;AAAA,IACX,cAAc,EAAE;AAAA,IAChB,MAAM,EAAE;AAAA,EACV,EAAE;AACN;","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
TEST_FILE_PATTERNS,
|
|
3
3
|
testFileMatchSql
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ZOGY2V3N.js";
|
|
5
5
|
import {
|
|
6
6
|
shortenSymbol
|
|
7
7
|
} from "./chunk-QOV2R2WT.js";
|
|
@@ -96,7 +96,7 @@ function diffImpact(db, opts = {}) {
|
|
|
96
96
|
FROM mentions m
|
|
97
97
|
JOIN chunks c ON m.chunk_id = c.id
|
|
98
98
|
WHERE m.symbol_id = ?
|
|
99
|
-
AND m.role
|
|
99
|
+
AND m.role != 1`,
|
|
100
100
|
sym.symbol_id
|
|
101
101
|
);
|
|
102
102
|
const fanIn = fanInRow?.fan_in ?? 0;
|
|
@@ -113,7 +113,7 @@ function diffImpact(db, opts = {}) {
|
|
|
113
113
|
JOIN chunks c ON m.chunk_id = c.id
|
|
114
114
|
JOIN documents ref_d ON c.document_id = ref_d.id
|
|
115
115
|
WHERE m.symbol_id = ?
|
|
116
|
-
AND m.role
|
|
116
|
+
AND m.role != 1
|
|
117
117
|
AND ref_d.relative_path NOT IN (${changedFiles.map(() => "?").join(",")})
|
|
118
118
|
${db.pathExclusionsFor("ref_d")}`,
|
|
119
119
|
sym.symbol_id,
|
|
@@ -132,7 +132,7 @@ function diffImpact(db, opts = {}) {
|
|
|
132
132
|
JOIN chunks c ON m.chunk_id = c.id
|
|
133
133
|
JOIN documents ref_d ON c.document_id = ref_d.id
|
|
134
134
|
WHERE m.symbol_id = ?
|
|
135
|
-
AND m.role
|
|
135
|
+
AND m.role != 1
|
|
136
136
|
AND (${testPatternSql})`,
|
|
137
137
|
sym.symbol_id
|
|
138
138
|
);
|
|
@@ -166,4 +166,4 @@ function diffImpact(db, opts = {}) {
|
|
|
166
166
|
export {
|
|
167
167
|
diffImpact
|
|
168
168
|
};
|
|
169
|
-
//# sourceMappingURL=chunk-
|
|
169
|
+
//# sourceMappingURL=chunk-KPPHZCZJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/queries/diff-impact.ts"],"sourcesContent":["import { execFileSync } from 'node:child_process';\nimport type { ScipDatabase } from '../db.js';\nimport { TEST_FILE_PATTERNS, testFileMatchSql } from '../query-support.js';\nimport type { DiffImpactResult } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * Given a git diff, compute the affected symbol set.\n * Finds all symbols defined in changed files, their fan-in,\n * the files that consume them, and test coverage gaps.\n */\nexport function diffImpact(\n db: ScipDatabase,\n opts: { base?: string } = {},\n): DiffImpactResult {\n const { base = 'HEAD' } = opts;\n\n // Get changed files from git\n let changedFileLines: string[];\n try {\n const stdout = execFileSync('git', ['diff', '--name-only', base], {\n encoding: 'utf-8',\n cwd: db.config.projectRoot,\n timeout: 10_000,\n });\n changedFileLines = stdout\n .split('\\n')\n .map((l) => l.trim())\n .filter((l) => l.length > 0);\n } catch {\n // Not in a git repo or git not available — return empty result\n return {\n changedFiles: [],\n changedSymbols: [],\n affectedConsumers: [],\n uncoveredSymbols: [],\n summary: {\n totalChangedFiles: 0,\n totalChangedSymbols: 0,\n totalAffectedFiles: 0,\n testCoveragePercent: 0,\n },\n };\n }\n\n if (changedFileLines.length === 0) {\n return {\n changedFiles: [],\n changedSymbols: [],\n affectedConsumers: [],\n uncoveredSymbols: [],\n summary: {\n totalChangedFiles: 0,\n totalChangedSymbols: 0,\n totalAffectedFiles: 0,\n testCoveragePercent: 0,\n },\n };\n }\n\n // Match changed files against the index\n const changedFiles: string[] = [];\n const changedDocIds: number[] = [];\n\n for (const file of changedFileLines) {\n const doc = db.get<{ id: number; relative_path: string }>(\n `SELECT id, relative_path FROM documents\n WHERE relative_path LIKE ?\n LIMIT 1`,\n `%${file}`,\n );\n if (doc && !db.isIgnored(doc.relative_path)) {\n changedFiles.push(doc.relative_path);\n changedDocIds.push(doc.id);\n }\n }\n\n if (changedDocIds.length === 0) {\n return {\n changedFiles: changedFileLines,\n changedSymbols: [],\n affectedConsumers: [],\n uncoveredSymbols: [],\n summary: {\n totalChangedFiles: changedFileLines.length,\n totalChangedSymbols: 0,\n totalAffectedFiles: 0,\n testCoveragePercent: 0,\n },\n };\n }\n\n // Get all symbols defined in changed files\n const docPlaceholders = changedDocIds.map(() => '?').join(',');\n const syms = db.all<{\n symbol_id: number;\n symbol: string;\n relative_path: string;\n }>(\n `SELECT DISTINCT gs.id AS symbol_id, gs.symbol, d.relative_path\n FROM defn_enclosing_ranges der\n JOIN global_symbols gs ON der.symbol_id = gs.id\n JOIN documents d ON der.document_id = d.id\n WHERE der.document_id IN (${docPlaceholders})\n ${db.symbolNoiseFor('gs')}\n ORDER BY d.relative_path`,\n ...changedDocIds,\n );\n\n // For each symbol, compute fan-in (distinct referencing documents)\n const testPatternSql = testFileMatchSql('ref_d', TEST_FILE_PATTERNS);\n const changedSymbols: DiffImpactResult['changedSymbols'] = [];\n const consumerMap = new Map<string, Set<string>>(); // file -> set of consumed symbol shortNames\n const uncoveredSymbols: DiffImpactResult['uncoveredSymbols'] = [];\n let coveredCount = 0;\n\n for (const sym of syms) {\n // Fan-in: distinct files that reference this symbol\n const fanInRow = db.get<{ fan_in: number }>(\n `SELECT COUNT(DISTINCT c.document_id) AS fan_in\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n WHERE m.symbol_id = ?\n AND m.role != 1`,\n sym.symbol_id,\n );\n\n const fanIn = fanInRow?.fan_in ?? 0;\n const shortName = shortenSymbol(sym.symbol);\n\n changedSymbols.push({\n symbol: sym.symbol,\n shortName,\n file: sym.relative_path,\n fanIn,\n });\n\n // Collect consumer files (excluding the changed files themselves)\n const consumers = db.all<{ relative_path: string }>(\n `SELECT DISTINCT ref_d.relative_path\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents ref_d ON c.document_id = ref_d.id\n WHERE m.symbol_id = ?\n AND m.role != 1\n AND ref_d.relative_path NOT IN (${changedFiles.map(() => '?').join(',')})\n ${db.pathExclusionsFor('ref_d')}`,\n sym.symbol_id,\n ...changedFiles,\n );\n\n for (const consumer of consumers) {\n if (db.isIgnored(consumer.relative_path)) continue;\n if (!consumerMap.has(consumer.relative_path)) {\n consumerMap.set(consumer.relative_path, new Set());\n }\n consumerMap.get(consumer.relative_path)!.add(shortName);\n }\n\n // Check test coverage\n const hasTest = db.get<{ c: number }>(\n `SELECT COUNT(*) AS c\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents ref_d ON c.document_id = ref_d.id\n WHERE m.symbol_id = ?\n AND m.role != 1\n AND (${testPatternSql})`,\n sym.symbol_id,\n );\n\n if (hasTest && hasTest.c > 0) {\n coveredCount++;\n } else {\n uncoveredSymbols.push({\n symbol: sym.symbol,\n shortName,\n file: sym.relative_path,\n });\n }\n }\n\n // Build affected consumers list\n const affectedConsumers = [...consumerMap.entries()]\n .map(([file, symbols]) => ({ file, consumedSymbols: symbols.size }))\n .sort((a, b) => b.consumedSymbols - a.consumedSymbols);\n\n const totalSymbols = changedSymbols.length;\n const testCoveragePercent =\n totalSymbols > 0 ? Math.round((coveredCount / totalSymbols) * 100) : 0;\n\n return {\n changedFiles,\n changedSymbols,\n affectedConsumers,\n uncoveredSymbols,\n summary: {\n totalChangedFiles: changedFiles.length,\n totalChangedSymbols: totalSymbols,\n totalAffectedFiles: affectedConsumers.length,\n testCoveragePercent,\n },\n };\n}\n"],"mappings":";;;;;;;;;AAAA,SAAS,oBAAoB;AAWtB,SAAS,WACd,IACA,OAA0B,CAAC,GACT;AAClB,QAAM,EAAE,OAAO,OAAO,IAAI;AAG1B,MAAI;AACJ,MAAI;AACF,UAAM,SAAS,aAAa,OAAO,CAAC,QAAQ,eAAe,IAAI,GAAG;AAAA,MAChE,UAAU;AAAA,MACV,KAAK,GAAG,OAAO;AAAA,MACf,SAAS;AAAA,IACX,CAAC;AACD,uBAAmB,OAChB,MAAM,IAAI,EACV,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC;AAAA,EAC/B,QAAQ;AAEN,WAAO;AAAA,MACL,cAAc,CAAC;AAAA,MACf,gBAAgB,CAAC;AAAA,MACjB,mBAAmB,CAAC;AAAA,MACpB,kBAAkB,CAAC;AAAA,MACnB,SAAS;AAAA,QACP,mBAAmB;AAAA,QACnB,qBAAqB;AAAA,QACrB,oBAAoB;AAAA,QACpB,qBAAqB;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AAEA,MAAI,iBAAiB,WAAW,GAAG;AACjC,WAAO;AAAA,MACL,cAAc,CAAC;AAAA,MACf,gBAAgB,CAAC;AAAA,MACjB,mBAAmB,CAAC;AAAA,MACpB,kBAAkB,CAAC;AAAA,MACnB,SAAS;AAAA,QACP,mBAAmB;AAAA,QACnB,qBAAqB;AAAA,QACrB,oBAAoB;AAAA,QACpB,qBAAqB;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AAGA,QAAM,eAAyB,CAAC;AAChC,QAAM,gBAA0B,CAAC;AAEjC,aAAW,QAAQ,kBAAkB;AACnC,UAAM,MAAM,GAAG;AAAA,MACb;AAAA;AAAA;AAAA,MAGA,IAAI,IAAI;AAAA,IACV;AACA,QAAI,OAAO,CAAC,GAAG,UAAU,IAAI,aAAa,GAAG;AAC3C,mBAAa,KAAK,IAAI,aAAa;AACnC,oBAAc,KAAK,IAAI,EAAE;AAAA,IAC3B;AAAA,EACF;AAEA,MAAI,cAAc,WAAW,GAAG;AAC9B,WAAO;AAAA,MACL,cAAc;AAAA,MACd,gBAAgB,CAAC;AAAA,MACjB,mBAAmB,CAAC;AAAA,MACpB,kBAAkB,CAAC;AAAA,MACnB,SAAS;AAAA,QACP,mBAAmB,iBAAiB;AAAA,QACpC,qBAAqB;AAAA,QACrB,oBAAoB;AAAA,QACpB,qBAAqB;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AAGA,QAAM,kBAAkB,cAAc,IAAI,MAAM,GAAG,EAAE,KAAK,GAAG;AAC7D,QAAM,OAAO,GAAG;AAAA,IAKd;AAAA;AAAA;AAAA;AAAA,gCAI4B,eAAe;AAAA,QACvC,GAAG,eAAe,IAAI,CAAC;AAAA;AAAA,IAE3B,GAAG;AAAA,EACL;AAGA,QAAM,iBAAiB,iBAAiB,SAAS,kBAAkB;AACnE,QAAM,iBAAqD,CAAC;AAC5D,QAAM,cAAc,oBAAI,IAAyB;AACjD,QAAM,mBAAyD,CAAC;AAChE,MAAI,eAAe;AAEnB,aAAW,OAAO,MAAM;AAEtB,UAAM,WAAW,GAAG;AAAA,MAClB;AAAA;AAAA;AAAA;AAAA;AAAA,MAKA,IAAI;AAAA,IACN;AAEA,UAAM,QAAQ,UAAU,UAAU;AAClC,UAAM,YAAY,cAAc,IAAI,MAAM;AAE1C,mBAAe,KAAK;AAAA,MAClB,QAAQ,IAAI;AAAA,MACZ;AAAA,MACA,MAAM,IAAI;AAAA,MACV;AAAA,IACF,CAAC;AAGD,UAAM,YAAY,GAAG;AAAA,MACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0CAMoC,aAAa,IAAI,MAAM,GAAG,EAAE,KAAK,GAAG,CAAC;AAAA,UACrE,GAAG,kBAAkB,OAAO,CAAC;AAAA,MACjC,IAAI;AAAA,MACJ,GAAG;AAAA,IACL;AAEA,eAAW,YAAY,WAAW;AAChC,UAAI,GAAG,UAAU,SAAS,aAAa,EAAG;AAC1C,UAAI,CAAC,YAAY,IAAI,SAAS,aAAa,GAAG;AAC5C,oBAAY,IAAI,SAAS,eAAe,oBAAI,IAAI,CAAC;AAAA,MACnD;AACA,kBAAY,IAAI,SAAS,aAAa,EAAG,IAAI,SAAS;AAAA,IACxD;AAGA,UAAM,UAAU,GAAG;AAAA,MACjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,eAMS,cAAc;AAAA,MACvB,IAAI;AAAA,IACN;AAEA,QAAI,WAAW,QAAQ,IAAI,GAAG;AAC5B;AAAA,IACF,OAAO;AACL,uBAAiB,KAAK;AAAA,QACpB,QAAQ,IAAI;AAAA,QACZ;AAAA,QACA,MAAM,IAAI;AAAA,MACZ,CAAC;AAAA,IACH;AAAA,EACF;AAGA,QAAM,oBAAoB,CAAC,GAAG,YAAY,QAAQ,CAAC,EAChD,IAAI,CAAC,CAAC,MAAM,OAAO,OAAO,EAAE,MAAM,iBAAiB,QAAQ,KAAK,EAAE,EAClE,KAAK,CAAC,GAAG,MAAM,EAAE,kBAAkB,EAAE,eAAe;AAEvD,QAAM,eAAe,eAAe;AACpC,QAAM,sBACJ,eAAe,IAAI,KAAK,MAAO,eAAe,eAAgB,GAAG,IAAI;AAEvE,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS;AAAA,MACP,mBAAmB,aAAa;AAAA,MAChC,qBAAqB;AAAA,MACrB,oBAAoB,kBAAkB;AAAA,MACtC;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
findFirstSymbolMatch
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-ZOGY2V3N.js";
|
|
4
4
|
import {
|
|
5
5
|
shortenSymbol
|
|
6
6
|
} from "./chunk-QOV2R2WT.js";
|
|
@@ -32,7 +32,7 @@ function dataflow(db, symbolPattern) {
|
|
|
32
32
|
FROM mentions m
|
|
33
33
|
JOIN chunks c ON m.chunk_id = c.id
|
|
34
34
|
JOIN documents d ON c.document_id = d.id
|
|
35
|
-
WHERE m.symbol_id = ? AND m.role
|
|
35
|
+
WHERE m.symbol_id = ? AND m.role != 1
|
|
36
36
|
${db.pathExclusionsFor("d")}
|
|
37
37
|
ORDER BY d.relative_path, c.start_line`,
|
|
38
38
|
match.symbolId
|
|
@@ -46,7 +46,7 @@ function dataflow(db, symbolPattern) {
|
|
|
46
46
|
JOIN documents other_d ON other_der.document_id = other_d.id
|
|
47
47
|
WHERE other_c.document_id = ?
|
|
48
48
|
AND other_c.start_line >= ? AND other_c.end_line <= ?
|
|
49
|
-
AND other_m.role
|
|
49
|
+
AND other_m.role != 1
|
|
50
50
|
AND other_gs.id != ?
|
|
51
51
|
${db.symbolNoiseFor("other_gs")}
|
|
52
52
|
${db.pathExclusionsFor("other_d")}
|
|
@@ -69,11 +69,11 @@ function dataflow(db, symbolPattern) {
|
|
|
69
69
|
AND enc_der.end_line >= ref_c.end_line
|
|
70
70
|
JOIN global_symbols enc_gs ON enc_der.symbol_id = enc_gs.id
|
|
71
71
|
-- Find other symbols defined by that enclosing function's file
|
|
72
|
-
JOIN mentions consumer_m ON consumer_m.symbol_id = enc_gs.id AND consumer_m.role
|
|
72
|
+
JOIN mentions consumer_m ON consumer_m.symbol_id = enc_gs.id AND consumer_m.role != 1
|
|
73
73
|
JOIN chunks consumer_c ON consumer_m.chunk_id = consumer_c.id
|
|
74
74
|
JOIN documents consumer_d ON consumer_c.document_id = consumer_d.id
|
|
75
75
|
JOIN global_symbols consumer_gs ON consumer_m.symbol_id = consumer_gs.id
|
|
76
|
-
WHERE ref_m.symbol_id = ? AND ref_m.role
|
|
76
|
+
WHERE ref_m.symbol_id = ? AND ref_m.role != 1
|
|
77
77
|
AND consumer_d.id != ref_d.id
|
|
78
78
|
${db.symbolNoiseFor("consumer_gs")}
|
|
79
79
|
${db.pathExclusionsFor("consumer_d")}
|
|
@@ -100,4 +100,4 @@ function dataflow(db, symbolPattern) {
|
|
|
100
100
|
export {
|
|
101
101
|
dataflow
|
|
102
102
|
};
|
|
103
|
-
//# sourceMappingURL=chunk-
|
|
103
|
+
//# sourceMappingURL=chunk-MCUX5LA7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/queries/dataflow.ts"],"sourcesContent":["import type { ScipDatabase } from '../db.js';\nimport { findFirstSymbolMatch } from '../query-support.js';\nimport type { DataflowResult } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * Reference-level dataflow analysis: where does data around this symbol\n * come from and where does it go?\n *\n * This is not value-level dataflow (we can't trace x = foo(); bar(x);\n * as a chain). Instead it shows:\n * - Where the symbol is defined and used\n * - What other symbols appear in the same enclosing scope (co-occurring data)\n * - What feeds into the function that defines it (producers)\n * - What consumes the function that uses it (consumers)\n *\n * Language-agnostic: works with any SCIP index.\n */\nexport function dataflow(\n db: ScipDatabase,\n symbolPattern: string,\n): DataflowResult | null {\n const match = findFirstSymbolMatch(db, symbolPattern);\n if (!match) return null;\n\n // Definition sites (role=1)\n const defSites = db.all<{ file: string; line: number }>(\n `SELECT d.relative_path AS file, c.start_line AS line\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents d ON c.document_id = d.id\n WHERE m.symbol_id = ? AND m.role = 1\n ORDER BY d.relative_path, c.start_line`,\n match.symbolId,\n );\n\n // Usage sites (role=0) with enclosing symbol\n const usageSites = db.all<{\n file: string;\n line: number;\n enclosing_symbol: string | null;\n }>(\n `SELECT d.relative_path AS file, c.start_line AS line,\n (SELECT enc_gs.symbol\n FROM defn_enclosing_ranges enc_der\n JOIN global_symbols enc_gs ON enc_der.symbol_id = enc_gs.id\n WHERE enc_der.document_id = d.id\n AND enc_der.start_line <= c.start_line\n AND enc_der.end_line >= c.end_line\n ORDER BY (enc_der.end_line - enc_der.start_line) ASC\n LIMIT 1\n ) AS enclosing_symbol\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents d ON c.document_id = d.id\n WHERE m.symbol_id = ? AND m.role != 1\n ${db.pathExclusionsFor('d')}\n ORDER BY d.relative_path, c.start_line`,\n match.symbolId,\n );\n\n // Producers: other symbols referenced within the same function that defines our target\n const producers = db.all<{ symbol: string; file: string }>(\n `SELECT DISTINCT other_gs.symbol, other_d.relative_path AS file\n FROM mentions other_m\n JOIN chunks other_c ON other_m.chunk_id = other_c.id\n JOIN global_symbols other_gs ON other_m.symbol_id = other_gs.id\n JOIN defn_enclosing_ranges other_der ON other_gs.id = other_der.symbol_id\n JOIN documents other_d ON other_der.document_id = other_d.id\n WHERE other_c.document_id = ?\n AND other_c.start_line >= ? AND other_c.end_line <= ?\n AND other_m.role != 1\n AND other_gs.id != ?\n ${db.symbolNoiseFor('other_gs')}\n ${db.pathExclusionsFor('other_d')}\n ORDER BY other_d.relative_path\n LIMIT 30`,\n match.documentId, match.startLine, match.endLine, match.symbolId,\n );\n\n // Consumers: symbols exported/defined by functions that reference our target\n // (what does the data flow into after being used)\n const consumers = db.all<{ symbol: string; file: string }>(\n `SELECT DISTINCT consumer_gs.symbol, consumer_d.relative_path AS file\n FROM mentions ref_m\n JOIN chunks ref_c ON ref_m.chunk_id = ref_c.id\n JOIN documents ref_d ON ref_c.document_id = ref_d.id\n -- Find the enclosing function at each usage site\n JOIN defn_enclosing_ranges enc_der\n ON enc_der.document_id = ref_d.id\n AND enc_der.start_line <= ref_c.start_line\n AND enc_der.end_line >= ref_c.end_line\n JOIN global_symbols enc_gs ON enc_der.symbol_id = enc_gs.id\n -- Find other symbols defined by that enclosing function's file\n JOIN mentions consumer_m ON consumer_m.symbol_id = enc_gs.id AND consumer_m.role != 1\n JOIN chunks consumer_c ON consumer_m.chunk_id = consumer_c.id\n JOIN documents consumer_d ON consumer_c.document_id = consumer_d.id\n JOIN global_symbols consumer_gs ON consumer_m.symbol_id = consumer_gs.id\n WHERE ref_m.symbol_id = ? AND ref_m.role != 1\n AND consumer_d.id != ref_d.id\n ${db.symbolNoiseFor('consumer_gs')}\n ${db.pathExclusionsFor('consumer_d')}\n ORDER BY consumer_d.relative_path\n LIMIT 30`,\n match.symbolId,\n );\n\n return {\n symbol: match.symbol,\n shortName: shortenSymbol(match.symbol),\n relativePath: match.relativePath,\n definitionSites: defSites.filter((s) => !db.isIgnored(s.file)),\n usageSites: usageSites\n .filter((s) => !db.isIgnored(s.file))\n .map((s) => ({\n file: s.file,\n line: s.line,\n enclosingSymbol: s.enclosing_symbol ?? '(top-level)',\n enclosingShort: s.enclosing_symbol ? shortenSymbol(s.enclosing_symbol) : '(top-level)',\n })),\n producers: producers\n .filter((p) => !db.isIgnored(p.file))\n .map((p) => ({ symbol: p.symbol, shortName: shortenSymbol(p.symbol), file: p.file })),\n consumers: consumers\n .filter((c) => !db.isIgnored(c.file))\n .map((c) => ({ symbol: c.symbol, shortName: shortenSymbol(c.symbol), file: c.file })),\n };\n}\n"],"mappings":";;;;;;;;AAkBO,SAAS,SACd,IACA,eACuB;AACvB,QAAM,QAAQ,qBAAqB,IAAI,aAAa;AACpD,MAAI,CAAC,MAAO,QAAO;AAGnB,QAAM,WAAW,GAAG;AAAA,IAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,MAAM;AAAA,EACR;AAGA,QAAM,aAAa,GAAG;AAAA,IAKpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAcI,GAAG,kBAAkB,GAAG,CAAC;AAAA;AAAA,IAE7B,MAAM;AAAA,EACR;AAGA,QAAM,YAAY,GAAG;AAAA,IACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAUI,GAAG,eAAe,UAAU,CAAC;AAAA,QAC7B,GAAG,kBAAkB,SAAS,CAAC;AAAA;AAAA;AAAA,IAGnC,MAAM;AAAA,IAAY,MAAM;AAAA,IAAW,MAAM;AAAA,IAAS,MAAM;AAAA,EAC1D;AAIA,QAAM,YAAY,GAAG;AAAA,IACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAiBI,GAAG,eAAe,aAAa,CAAC;AAAA,QAChC,GAAG,kBAAkB,YAAY,CAAC;AAAA;AAAA;AAAA,IAGtC,MAAM;AAAA,EACR;AAEA,SAAO;AAAA,IACL,QAAQ,MAAM;AAAA,IACd,WAAW,cAAc,MAAM,MAAM;AAAA,IACrC,cAAc,MAAM;AAAA,IACpB,iBAAiB,SAAS,OAAO,CAAC,MAAM,CAAC,GAAG,UAAU,EAAE,IAAI,CAAC;AAAA,IAC7D,YAAY,WACT,OAAO,CAAC,MAAM,CAAC,GAAG,UAAU,EAAE,IAAI,CAAC,EACnC,IAAI,CAAC,OAAO;AAAA,MACX,MAAM,EAAE;AAAA,MACR,MAAM,EAAE;AAAA,MACR,iBAAiB,EAAE,oBAAoB;AAAA,MACvC,gBAAgB,EAAE,mBAAmB,cAAc,EAAE,gBAAgB,IAAI;AAAA,IAC3E,EAAE;AAAA,IACJ,WAAW,UACR,OAAO,CAAC,MAAM,CAAC,GAAG,UAAU,EAAE,IAAI,CAAC,EACnC,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,WAAW,cAAc,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,EAAE;AAAA,IACtF,WAAW,UACR,OAAO,CAAC,MAAM,CAAC,GAAG,UAAU,EAAE,IAAI,CAAC,EACnC,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,WAAW,cAAc,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,EAAE;AAAA,EACxF;AACF;","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
findFirstSymbolMatch,
|
|
3
3
|
getCalleeRowsForSymbol
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ZOGY2V3N.js";
|
|
5
5
|
import {
|
|
6
6
|
shortenSymbol
|
|
7
7
|
} from "./chunk-QOV2R2WT.js";
|
|
@@ -81,7 +81,7 @@ function forwardSlice(db, match) {
|
|
|
81
81
|
JOIN global_symbols enc_gs ON enc_der.symbol_id = enc_gs.id
|
|
82
82
|
JOIN documents enc_d ON enc_der.document_id = enc_d.id
|
|
83
83
|
-- Find other symbols referenced within that enclosing function
|
|
84
|
-
JOIN mentions out_m ON out_m.role
|
|
84
|
+
JOIN mentions out_m ON out_m.role != 1
|
|
85
85
|
JOIN chunks out_c ON out_m.chunk_id = out_c.id
|
|
86
86
|
AND out_c.document_id = enc_der.document_id
|
|
87
87
|
AND out_c.start_line >= enc_der.start_line
|
|
@@ -89,7 +89,7 @@ function forwardSlice(db, match) {
|
|
|
89
89
|
JOIN global_symbols out_gs ON out_m.symbol_id = out_gs.id
|
|
90
90
|
JOIN defn_enclosing_ranges out_der ON out_gs.id = out_der.symbol_id
|
|
91
91
|
JOIN documents out_d ON out_der.document_id = out_d.id
|
|
92
|
-
WHERE ref_m.symbol_id = ? AND ref_m.role
|
|
92
|
+
WHERE ref_m.symbol_id = ? AND ref_m.role != 1
|
|
93
93
|
AND out_gs.id != ? AND out_gs.id != enc_gs.id
|
|
94
94
|
AND out_d.id != ref_d.id
|
|
95
95
|
${db.symbolNoiseFor("out_gs")}
|
|
@@ -122,4 +122,4 @@ function forwardSlice(db, match) {
|
|
|
122
122
|
export {
|
|
123
123
|
slice
|
|
124
124
|
};
|
|
125
|
-
//# sourceMappingURL=chunk-
|
|
125
|
+
//# sourceMappingURL=chunk-NHBZIL2J.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/queries/slice.ts"],"sourcesContent":["import type { ScipDatabase } from '../db.js';\nimport { findFirstSymbolMatch, getCalleeRowsForSymbol, type SymbolMatch } from '../query-support.js';\nimport type { SliceResult } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * Reference-level program slicing: track what affects a symbol (backward)\n * or what a symbol affects (forward).\n *\n * Backward slice: \"What feeds into this?\" — symbols referenced in the same\n * function that defines the target. These are the inputs/dependencies.\n *\n * Forward slice: \"What does this feed into?\" — at each site where the target\n * is referenced, find the enclosing function, then find what that function\n * exports/defines. These are the outputs/consumers.\n *\n * Language-agnostic: works with any SCIP index.\n */\nexport function slice(\n db: ScipDatabase,\n symbolPattern: string,\n opts: { direction?: 'backward' | 'forward' } = {},\n): SliceResult | null {\n const { direction = 'backward' } = opts;\n\n const match = findFirstSymbolMatch(db, symbolPattern);\n if (!match) return null;\n\n if (direction === 'backward') {\n return backwardSlice(db, match);\n } else {\n return forwardSlice(db, match);\n }\n}\n\n\nfunction backwardSlice(db: ScipDatabase, match: SymbolMatch): SliceResult {\n // Find all symbols referenced within the definition range of the target.\n // These are what \"feeds into\" the target — the inputs.\n const callees = getCalleeRowsForSymbol(db, match);\n\n // Also find symbols whose definitions are in the same file and whose\n // ranges overlap or precede the target — local variables, parameters, etc.\n const localPredecessors = db.all<{ symbol: string; file: string }>(\n `SELECT DISTINCT gs.symbol, d.relative_path AS file\n FROM defn_enclosing_ranges der\n JOIN global_symbols gs ON der.symbol_id = gs.id\n JOIN documents d ON der.document_id = d.id\n WHERE der.document_id = ?\n AND der.end_line < ?\n AND gs.id != ?\n ${db.symbolNoiseFor('gs')}\n ORDER BY der.start_line DESC\n LIMIT 15`,\n match.documentId, match.startLine, match.symbolId,\n );\n\n const seen = new Set<string>();\n const connected: SliceResult['connectedSymbols'] = [];\n\n for (const c of callees) {\n if (seen.has(c.symbol)) continue;\n seen.add(c.symbol);\n connected.push({\n symbol: c.symbol,\n shortName: shortenSymbol(c.symbol),\n file: c.file,\n relationship: 'referenced within definition (callee)',\n });\n }\n\n for (const p of localPredecessors) {\n if (seen.has(p.symbol) || db.isIgnored(p.file)) continue;\n seen.add(p.symbol);\n connected.push({\n symbol: p.symbol,\n shortName: shortenSymbol(p.symbol),\n file: p.file,\n relationship: 'defined before target in same file (local predecessor)',\n });\n }\n\n return {\n symbol: match.symbol,\n shortName: shortenSymbol(match.symbol),\n direction: 'backward',\n connectedSymbols: connected,\n };\n}\n\nfunction forwardSlice(db: ScipDatabase, match: SymbolMatch): SliceResult {\n // Find where the target is referenced, then at each reference site,\n // find what else the enclosing function defines/exports.\n const rows = db.all<{\n enclosing_symbol: string;\n enclosing_file: string;\n output_symbol: string;\n output_file: string;\n }>(\n `SELECT DISTINCT\n enc_gs.symbol AS enclosing_symbol,\n enc_d.relative_path AS enclosing_file,\n out_gs.symbol AS output_symbol,\n out_d.relative_path AS output_file\n FROM mentions ref_m\n JOIN chunks ref_c ON ref_m.chunk_id = ref_c.id\n JOIN documents ref_d ON ref_c.document_id = ref_d.id\n -- Find enclosing function at each reference site\n JOIN defn_enclosing_ranges enc_der\n ON enc_der.document_id = ref_d.id\n AND enc_der.start_line <= ref_c.start_line\n AND enc_der.end_line >= ref_c.end_line\n JOIN global_symbols enc_gs ON enc_der.symbol_id = enc_gs.id\n JOIN documents enc_d ON enc_der.document_id = enc_d.id\n -- Find other symbols referenced within that enclosing function\n JOIN mentions out_m ON out_m.role
|
|
1
|
+
{"version":3,"sources":["../src/queries/slice.ts"],"sourcesContent":["import type { ScipDatabase } from '../db.js';\nimport { findFirstSymbolMatch, getCalleeRowsForSymbol, type SymbolMatch } from '../query-support.js';\nimport type { SliceResult } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * Reference-level program slicing: track what affects a symbol (backward)\n * or what a symbol affects (forward).\n *\n * Backward slice: \"What feeds into this?\" — symbols referenced in the same\n * function that defines the target. These are the inputs/dependencies.\n *\n * Forward slice: \"What does this feed into?\" — at each site where the target\n * is referenced, find the enclosing function, then find what that function\n * exports/defines. These are the outputs/consumers.\n *\n * Language-agnostic: works with any SCIP index.\n */\nexport function slice(\n db: ScipDatabase,\n symbolPattern: string,\n opts: { direction?: 'backward' | 'forward' } = {},\n): SliceResult | null {\n const { direction = 'backward' } = opts;\n\n const match = findFirstSymbolMatch(db, symbolPattern);\n if (!match) return null;\n\n if (direction === 'backward') {\n return backwardSlice(db, match);\n } else {\n return forwardSlice(db, match);\n }\n}\n\n\nfunction backwardSlice(db: ScipDatabase, match: SymbolMatch): SliceResult {\n // Find all symbols referenced within the definition range of the target.\n // These are what \"feeds into\" the target — the inputs.\n const callees = getCalleeRowsForSymbol(db, match);\n\n // Also find symbols whose definitions are in the same file and whose\n // ranges overlap or precede the target — local variables, parameters, etc.\n const localPredecessors = db.all<{ symbol: string; file: string }>(\n `SELECT DISTINCT gs.symbol, d.relative_path AS file\n FROM defn_enclosing_ranges der\n JOIN global_symbols gs ON der.symbol_id = gs.id\n JOIN documents d ON der.document_id = d.id\n WHERE der.document_id = ?\n AND der.end_line < ?\n AND gs.id != ?\n ${db.symbolNoiseFor('gs')}\n ORDER BY der.start_line DESC\n LIMIT 15`,\n match.documentId, match.startLine, match.symbolId,\n );\n\n const seen = new Set<string>();\n const connected: SliceResult['connectedSymbols'] = [];\n\n for (const c of callees) {\n if (seen.has(c.symbol)) continue;\n seen.add(c.symbol);\n connected.push({\n symbol: c.symbol,\n shortName: shortenSymbol(c.symbol),\n file: c.file,\n relationship: 'referenced within definition (callee)',\n });\n }\n\n for (const p of localPredecessors) {\n if (seen.has(p.symbol) || db.isIgnored(p.file)) continue;\n seen.add(p.symbol);\n connected.push({\n symbol: p.symbol,\n shortName: shortenSymbol(p.symbol),\n file: p.file,\n relationship: 'defined before target in same file (local predecessor)',\n });\n }\n\n return {\n symbol: match.symbol,\n shortName: shortenSymbol(match.symbol),\n direction: 'backward',\n connectedSymbols: connected,\n };\n}\n\nfunction forwardSlice(db: ScipDatabase, match: SymbolMatch): SliceResult {\n // Find where the target is referenced, then at each reference site,\n // find what else the enclosing function defines/exports.\n const rows = db.all<{\n enclosing_symbol: string;\n enclosing_file: string;\n output_symbol: string;\n output_file: string;\n }>(\n `SELECT DISTINCT\n enc_gs.symbol AS enclosing_symbol,\n enc_d.relative_path AS enclosing_file,\n out_gs.symbol AS output_symbol,\n out_d.relative_path AS output_file\n FROM mentions ref_m\n JOIN chunks ref_c ON ref_m.chunk_id = ref_c.id\n JOIN documents ref_d ON ref_c.document_id = ref_d.id\n -- Find enclosing function at each reference site\n JOIN defn_enclosing_ranges enc_der\n ON enc_der.document_id = ref_d.id\n AND enc_der.start_line <= ref_c.start_line\n AND enc_der.end_line >= ref_c.end_line\n JOIN global_symbols enc_gs ON enc_der.symbol_id = enc_gs.id\n JOIN documents enc_d ON enc_der.document_id = enc_d.id\n -- Find other symbols referenced within that enclosing function\n JOIN mentions out_m ON out_m.role != 1\n JOIN chunks out_c ON out_m.chunk_id = out_c.id\n AND out_c.document_id = enc_der.document_id\n AND out_c.start_line >= enc_der.start_line\n AND out_c.end_line <= enc_der.end_line\n JOIN global_symbols out_gs ON out_m.symbol_id = out_gs.id\n JOIN defn_enclosing_ranges out_der ON out_gs.id = out_der.symbol_id\n JOIN documents out_d ON out_der.document_id = out_d.id\n WHERE ref_m.symbol_id = ? AND ref_m.role != 1\n AND out_gs.id != ? AND out_gs.id != enc_gs.id\n AND out_d.id != ref_d.id\n ${db.symbolNoiseFor('out_gs')}\n ${db.pathExclusionsFor('out_d')}\n ORDER BY out_d.relative_path\n LIMIT 30`,\n match.symbolId, match.symbolId,\n );\n\n const seen = new Set<string>();\n const connected: SliceResult['connectedSymbols'] = [];\n\n for (const r of rows) {\n if (seen.has(r.output_symbol) || db.isIgnored(r.output_file)) continue;\n seen.add(r.output_symbol);\n connected.push({\n symbol: r.output_symbol,\n shortName: shortenSymbol(r.output_symbol),\n file: r.output_file,\n relationship: `used alongside target in ${shortenSymbol(r.enclosing_symbol)}`,\n });\n }\n\n return {\n symbol: match.symbol,\n shortName: shortenSymbol(match.symbol),\n direction: 'forward',\n connectedSymbols: connected,\n };\n}\n"],"mappings":";;;;;;;;;AAkBO,SAAS,MACd,IACA,eACA,OAA+C,CAAC,GAC5B;AACpB,QAAM,EAAE,YAAY,WAAW,IAAI;AAEnC,QAAM,QAAQ,qBAAqB,IAAI,aAAa;AACpD,MAAI,CAAC,MAAO,QAAO;AAEnB,MAAI,cAAc,YAAY;AAC5B,WAAO,cAAc,IAAI,KAAK;AAAA,EAChC,OAAO;AACL,WAAO,aAAa,IAAI,KAAK;AAAA,EAC/B;AACF;AAGA,SAAS,cAAc,IAAkB,OAAiC;AAGxE,QAAM,UAAU,uBAAuB,IAAI,KAAK;AAIhD,QAAM,oBAAoB,GAAG;AAAA,IAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAOI,GAAG,eAAe,IAAI,CAAC;AAAA;AAAA;AAAA,IAG3B,MAAM;AAAA,IAAY,MAAM;AAAA,IAAW,MAAM;AAAA,EAC3C;AAEA,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,YAA6C,CAAC;AAEpD,aAAW,KAAK,SAAS;AACvB,QAAI,KAAK,IAAI,EAAE,MAAM,EAAG;AACxB,SAAK,IAAI,EAAE,MAAM;AACjB,cAAU,KAAK;AAAA,MACb,QAAQ,EAAE;AAAA,MACV,WAAW,cAAc,EAAE,MAAM;AAAA,MACjC,MAAM,EAAE;AAAA,MACR,cAAc;AAAA,IAChB,CAAC;AAAA,EACH;AAEA,aAAW,KAAK,mBAAmB;AACjC,QAAI,KAAK,IAAI,EAAE,MAAM,KAAK,GAAG,UAAU,EAAE,IAAI,EAAG;AAChD,SAAK,IAAI,EAAE,MAAM;AACjB,cAAU,KAAK;AAAA,MACb,QAAQ,EAAE;AAAA,MACV,WAAW,cAAc,EAAE,MAAM;AAAA,MACjC,MAAM,EAAE;AAAA,MACR,cAAc;AAAA,IAChB,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,QAAQ,MAAM;AAAA,IACd,WAAW,cAAc,MAAM,MAAM;AAAA,IACrC,WAAW;AAAA,IACX,kBAAkB;AAAA,EACpB;AACF;AAEA,SAAS,aAAa,IAAkB,OAAiC;AAGvE,QAAM,OAAO,GAAG;AAAA,IAMd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QA2BI,GAAG,eAAe,QAAQ,CAAC;AAAA,QAC3B,GAAG,kBAAkB,OAAO,CAAC;AAAA;AAAA;AAAA,IAGjC,MAAM;AAAA,IAAU,MAAM;AAAA,EACxB;AAEA,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,YAA6C,CAAC;AAEpD,aAAW,KAAK,MAAM;AACpB,QAAI,KAAK,IAAI,EAAE,aAAa,KAAK,GAAG,UAAU,EAAE,WAAW,EAAG;AAC9D,SAAK,IAAI,EAAE,aAAa;AACxB,cAAU,KAAK;AAAA,MACb,QAAQ,EAAE;AAAA,MACV,WAAW,cAAc,EAAE,aAAa;AAAA,MACxC,MAAM,EAAE;AAAA,MACR,cAAc,4BAA4B,cAAc,EAAE,gBAAgB,CAAC;AAAA,IAC7E,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,QAAQ,MAAM;AAAA,IACd,WAAW,cAAc,MAAM,MAAM;AAAA,IACrC,WAAW;AAAA,IACX,kBAAkB;AAAA,EACpB;AACF;","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
TEST_FILE_PATTERNS,
|
|
3
3
|
testFileMatchSql
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ZOGY2V3N.js";
|
|
5
5
|
import {
|
|
6
6
|
shortenSymbol
|
|
7
7
|
} from "./chunk-QOV2R2WT.js";
|
|
@@ -35,7 +35,7 @@ function changeSurface(db, filePattern) {
|
|
|
35
35
|
FROM mentions m
|
|
36
36
|
JOIN chunks c ON m.chunk_id = c.id
|
|
37
37
|
WHERE m.symbol_id = ?
|
|
38
|
-
AND m.role
|
|
38
|
+
AND m.role != 1
|
|
39
39
|
AND c.document_id != ?`,
|
|
40
40
|
sym.symbol_id,
|
|
41
41
|
doc.id
|
|
@@ -47,7 +47,7 @@ function changeSurface(db, filePattern) {
|
|
|
47
47
|
JOIN chunks c ON m.chunk_id = c.id
|
|
48
48
|
JOIN documents ref_d ON c.document_id = ref_d.id
|
|
49
49
|
WHERE m.symbol_id = ?
|
|
50
|
-
AND m.role
|
|
50
|
+
AND m.role != 1
|
|
51
51
|
AND (${testPatternSql})
|
|
52
52
|
ORDER BY ref_d.relative_path`,
|
|
53
53
|
sym.symbol_id
|
|
@@ -85,4 +85,4 @@ function changeSurface(db, filePattern) {
|
|
|
85
85
|
export {
|
|
86
86
|
changeSurface
|
|
87
87
|
};
|
|
88
|
-
//# sourceMappingURL=chunk-
|
|
88
|
+
//# sourceMappingURL=chunk-NWCE4CIC.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/queries/change-surface.ts"],"sourcesContent":["import type { ScipDatabase } from '../db.js';\nimport { TEST_FILE_PATTERNS, testFileMatchSql } from '../query-support.js';\nimport type { ChangeSurfaceEntry, ChangeSurfaceResult } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * Pre-change briefing for a file. For each symbol defined in the file,\n * reports external consumer count, test coverage, and risk level.\n */\nexport function changeSurface(\n db: ScipDatabase,\n filePattern: string,\n): ChangeSurfaceResult | null {\n // Find the file\n const doc = db.get<{ id: number; relative_path: string }>(\n `SELECT id, relative_path FROM documents\n WHERE relative_path LIKE ?\n ${db.pathExclusionsFor('documents')}\n LIMIT 1`,\n `%${filePattern}%`,\n );\n\n if (!doc || db.isIgnored(doc.relative_path)) return null;\n\n // Get all symbols defined in this file, excluding typeLiterals\n const syms = db.all<{\n symbol_id: number;\n symbol: string;\n start_line: number;\n end_line: number;\n }>(\n `SELECT DISTINCT gs.id AS symbol_id, gs.symbol, der.start_line, der.end_line\n FROM defn_enclosing_ranges der\n JOIN global_symbols gs ON der.symbol_id = gs.id\n WHERE der.document_id = ?\n ${db.symbolNoiseFor('gs')}\n ORDER BY der.start_line`,\n doc.id,\n );\n\n const testPatternSql = testFileMatchSql('ref_d', TEST_FILE_PATTERNS);\n\n const symbols: ChangeSurfaceEntry[] = [];\n let totalExternalConsumers = 0;\n let coveredCount = 0;\n\n for (const sym of syms) {\n // Count external consumers: mentions with role=0 from different documents\n const consumerRow = db.get<{ consumer_count: number }>(\n `SELECT COUNT(DISTINCT c.document_id) AS consumer_count\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n WHERE m.symbol_id = ?\n AND m.role != 1\n AND c.document_id != ?`,\n sym.symbol_id,\n doc.id,\n );\n\n const externalConsumers = consumerRow?.consumer_count ?? 0;\n\n // Find test files that reference this symbol\n const testFiles = db.all<{ relative_path: string }>(\n `SELECT DISTINCT ref_d.relative_path\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents ref_d ON c.document_id = ref_d.id\n WHERE m.symbol_id = ?\n AND m.role != 1\n AND (${testPatternSql})\n ORDER BY ref_d.relative_path`,\n sym.symbol_id,\n ).map((r) => r.relative_path);\n\n const hasTests = testFiles.length > 0;\n if (hasTests) coveredCount++;\n\n // Risk level determination\n let riskLevel: 'low' | 'medium' | 'high';\n if (externalConsumers > 10 && !hasTests) {\n riskLevel = 'high';\n } else if (externalConsumers > 5 || !hasTests) {\n riskLevel = 'medium';\n } else {\n riskLevel = 'low';\n }\n\n totalExternalConsumers += externalConsumers;\n\n symbols.push({\n symbol: sym.symbol,\n shortName: shortenSymbol(sym.symbol),\n startLine: sym.start_line,\n endLine: sym.end_line,\n externalConsumers,\n testFiles,\n riskLevel,\n });\n }\n\n const testCoveragePercent =\n symbols.length > 0 ? Math.round((coveredCount / symbols.length) * 100) : 0;\n\n return {\n file: doc.relative_path,\n symbols,\n totalExternalConsumers,\n testCoveragePercent,\n };\n}\n"],"mappings":";;;;;;;;;AASO,SAAS,cACd,IACA,aAC4B;AAE5B,QAAM,MAAM,GAAG;AAAA,IACb;AAAA;AAAA,SAEK,GAAG,kBAAkB,WAAW,CAAC;AAAA;AAAA,IAEtC,IAAI,WAAW;AAAA,EACjB;AAEA,MAAI,CAAC,OAAO,GAAG,UAAU,IAAI,aAAa,EAAG,QAAO;AAGpD,QAAM,OAAO,GAAG;AAAA,IAMd;AAAA;AAAA;AAAA;AAAA,QAII,GAAG,eAAe,IAAI,CAAC;AAAA;AAAA,IAE3B,IAAI;AAAA,EACN;AAEA,QAAM,iBAAiB,iBAAiB,SAAS,kBAAkB;AAEnE,QAAM,UAAgC,CAAC;AACvC,MAAI,yBAAyB;AAC7B,MAAI,eAAe;AAEnB,aAAW,OAAO,MAAM;AAEtB,UAAM,cAAc,GAAG;AAAA,MACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAEA,UAAM,oBAAoB,aAAa,kBAAkB;AAGzD,UAAM,YAAY,GAAG;AAAA,MACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,eAMS,cAAc;AAAA;AAAA,MAEvB,IAAI;AAAA,IACN,EAAE,IAAI,CAAC,MAAM,EAAE,aAAa;AAE5B,UAAM,WAAW,UAAU,SAAS;AACpC,QAAI,SAAU;AAGd,QAAI;AACJ,QAAI,oBAAoB,MAAM,CAAC,UAAU;AACvC,kBAAY;AAAA,IACd,WAAW,oBAAoB,KAAK,CAAC,UAAU;AAC7C,kBAAY;AAAA,IACd,OAAO;AACL,kBAAY;AAAA,IACd;AAEA,8BAA0B;AAE1B,YAAQ,KAAK;AAAA,MACX,QAAQ,IAAI;AAAA,MACZ,WAAW,cAAc,IAAI,MAAM;AAAA,MACnC,WAAW,IAAI;AAAA,MACf,SAAS,IAAI;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,sBACJ,QAAQ,SAAS,IAAI,KAAK,MAAO,eAAe,QAAQ,SAAU,GAAG,IAAI;AAE3E,SAAO;AAAA,IACL,MAAM,IAAI;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
testFileExclusionSql
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-ZOGY2V3N.js";
|
|
4
4
|
import {
|
|
5
5
|
shortenSymbol
|
|
6
6
|
} from "./chunk-QOV2R2WT.js";
|
|
@@ -30,13 +30,13 @@ function isolated(db, opts = {}) {
|
|
|
30
30
|
AND NOT EXISTS (
|
|
31
31
|
SELECT 1 FROM mentions m
|
|
32
32
|
JOIN chunks c ON m.chunk_id = c.id
|
|
33
|
-
WHERE m.symbol_id = gs.id AND m.role
|
|
33
|
+
WHERE m.symbol_id = gs.id AND m.role != 1 AND c.document_id != d.id
|
|
34
34
|
)
|
|
35
35
|
-- No same-file references either
|
|
36
36
|
AND NOT EXISTS (
|
|
37
37
|
SELECT 1 FROM mentions m
|
|
38
38
|
JOIN chunks c ON m.chunk_id = c.id
|
|
39
|
-
WHERE m.symbol_id = gs.id AND m.role
|
|
39
|
+
WHERE m.symbol_id = gs.id AND m.role != 1 AND c.document_id = d.id
|
|
40
40
|
)
|
|
41
41
|
ORDER BY loc DESC, d.relative_path`,
|
|
42
42
|
minLoc
|
|
@@ -54,4 +54,4 @@ function isolated(db, opts = {}) {
|
|
|
54
54
|
export {
|
|
55
55
|
isolated
|
|
56
56
|
};
|
|
57
|
-
//# sourceMappingURL=chunk-
|
|
57
|
+
//# sourceMappingURL=chunk-OVPLOMPY.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/queries/isolated.ts"],"sourcesContent":["import type { ScipDatabase } from '../db.js';\nimport { testFileExclusionSql } from '../query-support.js';\nimport type { IsolatedResult } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * Find isolated symbols: defined locally, referenced by nothing,\n * and referencing nothing external. These are truly orphaned code —\n * not just unused exports, but completely disconnected from the graph.\n */\nexport function isolated(\n db: ScipDatabase,\n opts: { scope?: string; minLoc?: number } = {},\n): IsolatedResult[] {\n const { scope, minLoc = 3 } = opts;\n const scopeFilter = scope ? `AND d.relative_path LIKE '%${scope}%'` : '';\n\n const rows = db.all<{\n symbol: string;\n relative_path: string;\n start_line: number;\n end_line: number;\n loc: number;\n }>(\n `SELECT\n gs.symbol,\n d.relative_path,\n der.start_line,\n der.end_line,\n (der.end_line - der.start_line + 1) AS loc\n FROM global_symbols gs\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents d ON der.document_id = d.id\n WHERE 1 = 1\n ${db.pathExclusionsFor('d')}\n AND ${testFileExclusionSql('d')}\n ${db.symbolNoiseFor('gs')}\n AND gs.symbol NOT LIKE '%#%'\n AND (der.end_line - der.start_line + 1) >= ?\n ${scopeFilter}\n -- No cross-file references TO this symbol\n AND NOT EXISTS (\n SELECT 1 FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n WHERE m.symbol_id = gs.id AND m.role
|
|
1
|
+
{"version":3,"sources":["../src/queries/isolated.ts"],"sourcesContent":["import type { ScipDatabase } from '../db.js';\nimport { testFileExclusionSql } from '../query-support.js';\nimport type { IsolatedResult } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * Find isolated symbols: defined locally, referenced by nothing,\n * and referencing nothing external. These are truly orphaned code —\n * not just unused exports, but completely disconnected from the graph.\n */\nexport function isolated(\n db: ScipDatabase,\n opts: { scope?: string; minLoc?: number } = {},\n): IsolatedResult[] {\n const { scope, minLoc = 3 } = opts;\n const scopeFilter = scope ? `AND d.relative_path LIKE '%${scope}%'` : '';\n\n const rows = db.all<{\n symbol: string;\n relative_path: string;\n start_line: number;\n end_line: number;\n loc: number;\n }>(\n `SELECT\n gs.symbol,\n d.relative_path,\n der.start_line,\n der.end_line,\n (der.end_line - der.start_line + 1) AS loc\n FROM global_symbols gs\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents d ON der.document_id = d.id\n WHERE 1 = 1\n ${db.pathExclusionsFor('d')}\n AND ${testFileExclusionSql('d')}\n ${db.symbolNoiseFor('gs')}\n AND gs.symbol NOT LIKE '%#%'\n AND (der.end_line - der.start_line + 1) >= ?\n ${scopeFilter}\n -- No cross-file references TO this symbol\n AND NOT EXISTS (\n SELECT 1 FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n WHERE m.symbol_id = gs.id AND m.role != 1 AND c.document_id != d.id\n )\n -- No same-file references either\n AND NOT EXISTS (\n SELECT 1 FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n WHERE m.symbol_id = gs.id AND m.role != 1 AND c.document_id = d.id\n )\n ORDER BY loc DESC, d.relative_path`,\n minLoc,\n );\n\n return rows\n .filter((r) => !db.isIgnored(r.relative_path))\n .map((r) => ({\n symbol: r.symbol,\n shortName: shortenSymbol(r.symbol),\n relativePath: r.relative_path,\n startLine: r.start_line,\n endLine: r.end_line,\n loc: r.loc,\n }));\n}\n"],"mappings":";;;;;;;;AAUO,SAAS,SACd,IACA,OAA4C,CAAC,GAC3B;AAClB,QAAM,EAAE,OAAO,SAAS,EAAE,IAAI;AAC9B,QAAM,cAAc,QAAQ,8BAA8B,KAAK,OAAO;AAEtE,QAAM,OAAO,GAAG;AAAA,IAOd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAUI,GAAG,kBAAkB,GAAG,CAAC;AAAA,YACrB,qBAAqB,GAAG,CAAC;AAAA,QAC7B,GAAG,eAAe,IAAI,CAAC;AAAA;AAAA;AAAA,QAGvB,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAcf;AAAA,EACF;AAEA,SAAO,KACJ,OAAO,CAAC,MAAM,CAAC,GAAG,UAAU,EAAE,aAAa,CAAC,EAC5C,IAAI,CAAC,OAAO;AAAA,IACX,QAAQ,EAAE;AAAA,IACV,WAAW,cAAc,EAAE,MAAM;AAAA,IACjC,cAAc,EAAE;AAAA,IAChB,WAAW,EAAE;AAAA,IACb,SAAS,EAAE;AAAA,IACX,KAAK,EAAE;AAAA,EACT,EAAE;AACN;","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
findFirstSymbolMatch,
|
|
3
3
|
getCalleeRowsForSymbol
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ZOGY2V3N.js";
|
|
5
5
|
import {
|
|
6
6
|
shortenSymbol
|
|
7
7
|
} from "./chunk-QOV2R2WT.js";
|
|
@@ -192,4 +192,4 @@ export {
|
|
|
192
192
|
similar,
|
|
193
193
|
similarAll
|
|
194
194
|
};
|
|
195
|
-
//# sourceMappingURL=chunk-
|
|
195
|
+
//# sourceMappingURL=chunk-UJQN5N3I.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getCalleeRowsForSymbol,
|
|
3
3
|
testFileExclusionSql
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ZOGY2V3N.js";
|
|
5
5
|
import {
|
|
6
6
|
shortenSymbol
|
|
7
7
|
} from "./chunk-QOV2R2WT.js";
|
|
@@ -68,4 +68,4 @@ function passthroughCandidates(db, opts) {
|
|
|
68
68
|
export {
|
|
69
69
|
passthroughCandidates
|
|
70
70
|
};
|
|
71
|
-
//# sourceMappingURL=chunk-
|
|
71
|
+
//# sourceMappingURL=chunk-W4ALF422.js.map
|
|
@@ -20,7 +20,7 @@ function redundantReexports(db, opts = {}) {
|
|
|
20
20
|
JOIN global_symbols gs ON m.symbol_id = gs.id
|
|
21
21
|
JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id
|
|
22
22
|
JOIN documents orig_d ON der.document_id = orig_d.id
|
|
23
|
-
WHERE m.role
|
|
23
|
+
WHERE m.role != 1
|
|
24
24
|
AND (barrel_d.relative_path LIKE '%/index.ts'
|
|
25
25
|
OR barrel_d.relative_path LIKE '%/index.js'
|
|
26
26
|
OR barrel_d.relative_path = 'index.ts'
|
|
@@ -48,20 +48,20 @@ function redundantReexports(db, opts = {}) {
|
|
|
48
48
|
FROM mentions barrel_m
|
|
49
49
|
JOIN chunks barrel_c ON barrel_m.chunk_id = barrel_c.id
|
|
50
50
|
WHERE barrel_c.document_id = consumer_d.id
|
|
51
|
-
AND barrel_m.role
|
|
51
|
+
AND barrel_m.role != 1
|
|
52
52
|
AND barrel_m.symbol_id IN (
|
|
53
53
|
SELECT m2.symbol_id
|
|
54
54
|
FROM mentions m2
|
|
55
55
|
JOIN chunks c2 ON m2.chunk_id = c2.id
|
|
56
56
|
WHERE c2.document_id = ?
|
|
57
|
-
AND m2.role
|
|
57
|
+
AND m2.role != 1
|
|
58
58
|
)
|
|
59
59
|
) THEN 1 ELSE 0 END) AS uses_barrel
|
|
60
60
|
FROM mentions ref_m
|
|
61
61
|
JOIN chunks ref_c ON ref_m.chunk_id = ref_c.id
|
|
62
62
|
JOIN documents consumer_d ON ref_c.document_id = consumer_d.id
|
|
63
63
|
WHERE ref_m.symbol_id = ?
|
|
64
|
-
AND ref_m.role
|
|
64
|
+
AND ref_m.role != 1
|
|
65
65
|
AND consumer_d.id != ?
|
|
66
66
|
AND consumer_d.id != ?
|
|
67
67
|
${db.pathExclusionsFor("consumer_d")}
|
|
@@ -98,4 +98,4 @@ function redundantReexports(db, opts = {}) {
|
|
|
98
98
|
export {
|
|
99
99
|
redundantReexports
|
|
100
100
|
};
|
|
101
|
-
//# sourceMappingURL=chunk-
|
|
101
|
+
//# sourceMappingURL=chunk-Z4GHE2HD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/queries/redundant-reexports.ts"],"sourcesContent":["import type { ScipDatabase } from '../db.js';\nimport type { RedundantReexport } from '../types.js';\nimport { shortenSymbol } from '../symbol-parser.js';\n\n/**\n * Find barrel re-exports that no consumer actually imports through.\n *\n * If `queries/index.ts` re-exports `byKind` from `by-kind.ts`, but every\n * consumer of `byKind` imports it directly from `by-kind.ts` (not through\n * `index.ts`), the re-export in the barrel is dead weight.\n *\n * Algorithm:\n * 1. Find all barrel files (index.ts / index.js)\n * 2. For each barrel, find symbols it re-exports (defined elsewhere, referenced in barrel with role=0)\n * 3. For each re-exported symbol, count consumers through the barrel vs direct from the source\n * 4. If zero consumers go through the barrel, the re-export is redundant\n */\nexport function redundantReexports(\n db: ScipDatabase,\n opts: { scope?: string; limit?: number } = {},\n): RedundantReexport[] {\n const { scope, limit } = opts;\n\n const scopeFilter = scope ? `AND barrel_d.relative_path LIKE '%${scope}%'` : '';\n\n // Step 1 + 2: Find all barrel files and symbols they re-export.\n // A re-export is a symbol that:\n // - is mentioned in a barrel file with role=0 (reference/import)\n // - has its definition (defn_enclosing_ranges) in a DIFFERENT file\n const reexportRows = db.all<{\n barrel_doc_id: number;\n barrel_path: string;\n symbol_id: number;\n symbol: string;\n original_doc_id: number;\n original_path: string;\n }>(\n `SELECT DISTINCT\n barrel_d.id AS barrel_doc_id,\n barrel_d.relative_path AS barrel_path,\n gs.id AS symbol_id,\n gs.symbol AS symbol,\n orig_d.id AS original_doc_id,\n orig_d.relative_path AS original_path\n FROM mentions m\n JOIN chunks c ON m.chunk_id = c.id\n JOIN documents barrel_d ON c.document_id = barrel_d.id\n JOIN global_symbols gs ON m.symbol_id = gs.id\n JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id\n JOIN documents orig_d ON der.document_id = orig_d.id\n WHERE m.role != 1\n AND (barrel_d.relative_path LIKE '%/index.ts'\n OR barrel_d.relative_path LIKE '%/index.js'\n OR barrel_d.relative_path = 'index.ts'\n OR barrel_d.relative_path = 'index.js')\n AND orig_d.id != barrel_d.id\n ${db.pathExclusionsFor('barrel_d', 'orig_d')}\n ${db.symbolNoiseFor('gs')}\n -- Only function-level symbols (ending with ().), not module-level\n AND gs.symbol LIKE '%().'\n ${scopeFilter}\n ORDER BY barrel_d.relative_path, gs.symbol`,\n );\n\n const results: RedundantReexport[] = [];\n\n for (const row of reexportRows) {\n if (db.isIgnored(row.barrel_path) || db.isIgnored(row.original_path)) continue;\n\n // Step 3: Count consumers that reference this symbol through the barrel\n // A \"barrel consumer\" is a file (other than the barrel itself and the original file)\n // that mentions this symbol AND also mentions something from the barrel document.\n // More precisely: count distinct files that reference this symbol AND whose\n // chunk is in a document that also has a role=0 mention pointing to the barrel file's symbols.\n //\n // Simpler approach: count distinct documents that reference this symbol (role=0)\n // grouped by whether the reference chunk is in a file that imports from the barrel\n // or from the original.\n //\n // Actually, the most reliable approach with SCIP data: count how many distinct\n // consumer documents reference this symbol_id with role=0, excluding the barrel\n // and the original file themselves. Then check if those consumers also reference\n // ANY symbol through a mention in the barrel doc vs the original doc.\n //\n // Simplest correct approach: In SCIP, when file A does `import { foo } from './bar/index'`,\n // the mention of `foo` in file A points to the same global symbol regardless of import path.\n // SCIP doesn't track import provenance. BUT the barrel file itself contains mentions\n // (role=0 references) of the re-exported symbols. So we can check:\n // - barrelConsumers: files that mention both this symbol AND any symbol whose definition\n // is in the barrel (i.e., they import the barrel)\n // - directConsumers: files that mention this symbol but don't import the barrel\n //\n // Even simpler: check if the barrel document is in the deps of the consumer.\n // A consumer \"goes through the barrel\" if it has ANY role=0 mention pointing to a\n // chunk in the barrel file. Otherwise it goes direct.\n\n const consumerCounts = db.get<{\n barrel_consumers: number;\n direct_consumers: number;\n }>(\n `SELECT\n SUM(CASE WHEN uses_barrel = 1 THEN 1 ELSE 0 END) AS barrel_consumers,\n SUM(CASE WHEN uses_barrel = 0 THEN 1 ELSE 0 END) AS direct_consumers\n FROM (\n SELECT\n consumer_d.id AS consumer_doc_id,\n MAX(CASE WHEN EXISTS (\n SELECT 1\n FROM mentions barrel_m\n JOIN chunks barrel_c ON barrel_m.chunk_id = barrel_c.id\n WHERE barrel_c.document_id = consumer_d.id\n AND barrel_m.role != 1\n AND barrel_m.symbol_id IN (\n SELECT m2.symbol_id\n FROM mentions m2\n JOIN chunks c2 ON m2.chunk_id = c2.id\n WHERE c2.document_id = ?\n AND m2.role != 1\n )\n ) THEN 1 ELSE 0 END) AS uses_barrel\n FROM mentions ref_m\n JOIN chunks ref_c ON ref_m.chunk_id = ref_c.id\n JOIN documents consumer_d ON ref_c.document_id = consumer_d.id\n WHERE ref_m.symbol_id = ?\n AND ref_m.role != 1\n AND consumer_d.id != ?\n AND consumer_d.id != ?\n ${db.pathExclusionsFor('consumer_d')}\n GROUP BY consumer_d.id\n )`,\n row.barrel_doc_id, // for the inner subquery checking barrel mentions\n row.symbol_id, // the re-exported symbol\n row.barrel_doc_id, // exclude the barrel itself\n row.original_doc_id, // exclude the original file\n );\n\n const barrelConsumers = consumerCounts?.barrel_consumers ?? 0;\n const directConsumers = consumerCounts?.direct_consumers ?? 0;\n\n // In TypeScript, `import * as X from './barrel'` resolves all references\n // directly to the source file — the barrel is transparent to SCIP.\n // This means barrelConsumers is always 0 for namespace imports.\n //\n // We can only confidently report symbols with 0 consumers EVERYWHERE\n // (both barrel and direct). These are truly dead re-exports.\n //\n // Symbols with directConsumers > 0 but barrelConsumers === 0 might be\n // consumed through a namespace import — we can't tell, so we skip them.\n if (barrelConsumers === 0 && directConsumers === 0) {\n results.push({\n barrelFile: row.barrel_path,\n symbol: row.symbol,\n shortName: shortenSymbol(row.symbol),\n originalFile: row.original_path,\n barrelConsumers,\n directConsumers,\n });\n }\n }\n\n // Sort: symbols with the most direct consumers first (biggest cleanup wins),\n // then by barrel file path for stable output\n results.sort((a, b) =>\n b.directConsumers - a.directConsumers\n || a.barrelFile.localeCompare(b.barrelFile)\n || a.shortName.localeCompare(b.shortName),\n );\n\n return limit ? results.slice(0, limit) : results;\n}\n"],"mappings":";;;;;AAiBO,SAAS,mBACd,IACA,OAA2C,CAAC,GACvB;AACrB,QAAM,EAAE,OAAO,MAAM,IAAI;AAEzB,QAAM,cAAc,QAAQ,qCAAqC,KAAK,OAAO;AAM7E,QAAM,eAAe,GAAG;AAAA,IAQtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAmBI,GAAG,kBAAkB,YAAY,QAAQ,CAAC;AAAA,QAC1C,GAAG,eAAe,IAAI,CAAC;AAAA;AAAA;AAAA,QAGvB,WAAW;AAAA;AAAA,EAEjB;AAEA,QAAM,UAA+B,CAAC;AAEtC,aAAW,OAAO,cAAc;AAC9B,QAAI,GAAG,UAAU,IAAI,WAAW,KAAK,GAAG,UAAU,IAAI,aAAa,EAAG;AA6BtE,UAAM,iBAAiB,GAAG;AAAA,MAIxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YA2BM,GAAG,kBAAkB,YAAY,CAAC;AAAA;AAAA;AAAA,MAGxC,IAAI;AAAA;AAAA,MACJ,IAAI;AAAA;AAAA,MACJ,IAAI;AAAA;AAAA,MACJ,IAAI;AAAA;AAAA,IACN;AAEA,UAAM,kBAAkB,gBAAgB,oBAAoB;AAC5D,UAAM,kBAAkB,gBAAgB,oBAAoB;AAW5D,QAAI,oBAAoB,KAAK,oBAAoB,GAAG;AAClD,cAAQ,KAAK;AAAA,QACX,YAAY,IAAI;AAAA,QAChB,QAAQ,IAAI;AAAA,QACZ,WAAW,cAAc,IAAI,MAAM;AAAA,QACnC,cAAc,IAAI;AAAA,QAClB;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAIA,UAAQ;AAAA,IAAK,CAAC,GAAG,MACf,EAAE,kBAAkB,EAAE,mBACnB,EAAE,WAAW,cAAc,EAAE,UAAU,KACvC,EAAE,UAAU,cAAc,EAAE,SAAS;AAAA,EAC1C;AAEA,SAAO,QAAQ,QAAQ,MAAM,GAAG,KAAK,IAAI;AAC3C;","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
findFirstSymbolMatch,
|
|
3
3
|
getCalleeRowsForSymbol
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ZOGY2V3N.js";
|
|
5
5
|
import {
|
|
6
6
|
shortenSymbol
|
|
7
7
|
} from "./chunk-QOV2R2WT.js";
|
|
@@ -69,4 +69,4 @@ function convergence(db, symbolPatternA, symbolPatternB) {
|
|
|
69
69
|
export {
|
|
70
70
|
convergence
|
|
71
71
|
};
|
|
72
|
-
//# sourceMappingURL=chunk-
|
|
72
|
+
//# sourceMappingURL=chunk-Z6YZJ36C.js.map
|