scip-query 0.3.5 → 0.4.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.
Files changed (149) hide show
  1. package/README.md +1 -0
  2. package/dist/{chunk-6FKIA6EI.js → chunk-2F2WH5WQ.js} +12 -12
  3. package/dist/{chunk-C7H5WBTJ.js → chunk-2UISVZGQ.js} +2 -2
  4. package/dist/{chunk-EN2Z2CLO.js → chunk-4ZT7UGWW.js} +16 -19
  5. package/dist/chunk-5AJJGPZE.js +60 -0
  6. package/dist/chunk-5RKYZSQ6.js +75 -0
  7. package/dist/chunk-7YBLWIXY.js +115 -0
  8. package/dist/{chunk-O7Q7FDUJ.js → chunk-A4GWYETB.js} +2 -2
  9. package/dist/{chunk-CHDJXYBG.js → chunk-A5BGEBM7.js} +2 -2
  10. package/dist/{chunk-KKCHYLVI.js → chunk-A7YY7IDA.js} +2 -2
  11. package/dist/chunk-AS7N27JK.js +115 -0
  12. package/dist/{chunk-F7XU27LU.js → chunk-CQRYLK33.js} +26 -2
  13. package/dist/{chunk-NFS5W3PP.js → chunk-CQUNEJYM.js} +2 -2
  14. package/dist/chunk-D4I3ZMN5.js +38 -0
  15. package/dist/{chunk-J3JSOSUO.js → chunk-E7J7Q7UW.js} +2 -2
  16. package/dist/{chunk-GEXE2T6I.js → chunk-EOHPASDV.js} +22 -14
  17. package/dist/chunk-GIBETK3W.js +37 -0
  18. package/dist/{chunk-SMDCNPMK.js → chunk-H3FPW5YN.js} +2 -2
  19. package/dist/{chunk-VMM4SYV4.js → chunk-HNURMDF4.js} +16 -3
  20. package/dist/{chunk-7KIMF5PV.js → chunk-HRDPUTIQ.js} +2 -2
  21. package/dist/{chunk-OIDHN6GD.js → chunk-I2JM34UV.js} +146 -5
  22. package/dist/{chunk-EPWLXXBL.js → chunk-IV6NZ426.js} +27 -29
  23. package/dist/{chunk-VT4JBH6L.js → chunk-KDCQJTYW.js} +2 -2
  24. package/dist/{chunk-5OMVSV6E.js → chunk-LOVDB4C6.js} +2 -2
  25. package/dist/chunk-MA3B3IUT.js +75 -0
  26. package/dist/{chunk-26DOJ63W.js → chunk-N2LH3M2P.js} +13 -2
  27. package/dist/chunk-NWCJWA36.js +162 -0
  28. package/dist/{chunk-NG5F43OU.js → chunk-P3VCDYMJ.js} +70 -1
  29. package/dist/{chunk-P3E6L7KW.js → chunk-P42KQKJZ.js} +83 -3
  30. package/dist/{chunk-YDBXNPYU.js → chunk-PGHN5UTM.js} +2 -2
  31. package/dist/{chunk-UGQKAVCD.js → chunk-QCYR4S6T.js} +2 -2
  32. package/dist/chunk-QGCEAVJD.js +2529 -0
  33. package/dist/{chunk-KBOQX573.js → chunk-RIEA5DOB.js} +19 -2
  34. package/dist/{chunk-VIYSWZCO.js → chunk-SL674KAW.js} +31 -3
  35. package/dist/chunk-SRELHCMG.js +110 -0
  36. package/dist/chunk-UTRKBUCB.js +87 -0
  37. package/dist/{chunk-TRESG7OB.js → chunk-VCOJRQPP.js} +2 -2
  38. package/dist/chunk-VISMEWYP.js +34 -0
  39. package/dist/{chunk-LFJQVJYJ.js → chunk-VU7FDTWV.js} +2 -2
  40. package/dist/{chunk-HLUS2HEB.js → chunk-VUBLUTMU.js} +5 -4
  41. package/dist/{chunk-WGAD3GNR.js → chunk-WNPF2I25.js} +5 -5
  42. package/dist/{chunk-YY4QGUQ5.js → chunk-X3J4VPWM.js} +2 -2
  43. package/dist/{chunk-GSH2FPKV.js → chunk-XH56HXLC.js} +2 -2
  44. package/dist/{chunk-DH7G3DDV.js → chunk-ZU2AQQB5.js} +2 -2
  45. package/dist/cli.js +2607 -805
  46. package/dist/{db-viWlyVtv.d.ts → db-C4rPbKkI.d.ts} +6 -1
  47. package/dist/index.d.ts +4 -4
  48. package/dist/index.js +371 -138
  49. package/dist/postinstall.js +9 -3
  50. package/dist/queries/affected.d.ts +1 -1
  51. package/dist/queries/affected.js +2 -2
  52. package/dist/queries/bottlenecks.d.ts +1 -1
  53. package/dist/queries/bottlenecks.js +2 -1
  54. package/dist/queries/by-kind.d.ts +1 -1
  55. package/dist/queries/by-kind.js +2 -1
  56. package/dist/queries/call-graph.d.ts +1 -1
  57. package/dist/queries/call-graph.js +2 -2
  58. package/dist/queries/change-surface.d.ts +1 -1
  59. package/dist/queries/change-surface.js +2 -2
  60. package/dist/queries/code.d.ts +1 -1
  61. package/dist/queries/code.js +2 -2
  62. package/dist/queries/complexity-hotspots.d.ts +1 -1
  63. package/dist/queries/complexity-hotspots.js +2 -2
  64. package/dist/queries/complexity.d.ts +1 -1
  65. package/dist/queries/complexity.js +2 -2
  66. package/dist/queries/convergence.d.ts +1 -1
  67. package/dist/queries/convergence.js +2 -2
  68. package/dist/queries/coupling.d.ts +1 -1
  69. package/dist/queries/coupling.js +2 -2
  70. package/dist/queries/cycles.d.ts +1 -1
  71. package/dist/queries/cycles.js +2 -2
  72. package/dist/queries/dataflow.d.ts +1 -1
  73. package/dist/queries/dataflow.js +2 -2
  74. package/dist/queries/dead.d.ts +1 -1
  75. package/dist/queries/dead.js +3 -3
  76. package/dist/queries/deep-chains.d.ts +1 -1
  77. package/dist/queries/deep-chains.js +2 -2
  78. package/dist/queries/deps.d.ts +1 -1
  79. package/dist/queries/deps.js +2 -2
  80. package/dist/queries/diff-impact.d.ts +1 -1
  81. package/dist/queries/drift.d.ts +1 -1
  82. package/dist/queries/drift.js +2 -2
  83. package/dist/queries/extract-candidates.d.ts +1 -1
  84. package/dist/queries/extract-candidates.js +2 -2
  85. package/dist/queries/fan.d.ts +1 -1
  86. package/dist/queries/fan.js +2 -2
  87. package/dist/queries/files.d.ts +1 -1
  88. package/dist/queries/health.d.ts +1 -1
  89. package/dist/queries/health.js +13 -13
  90. package/dist/queries/hierarchy.d.ts +1 -1
  91. package/dist/queries/hierarchy.js +2 -2
  92. package/dist/queries/hotspots.d.ts +1 -1
  93. package/dist/queries/hotspots.js +2 -1
  94. package/dist/queries/imports.d.ts +1 -1
  95. package/dist/queries/imports.js +2 -2
  96. package/dist/queries/index.d.ts +1 -1
  97. package/dist/queries/index.js +42 -42
  98. package/dist/queries/isolated.d.ts +3 -4
  99. package/dist/queries/isolated.js +3 -3
  100. package/dist/queries/members.d.ts +1 -1
  101. package/dist/queries/members.js +2 -2
  102. package/dist/queries/methods.d.ts +1 -1
  103. package/dist/queries/methods.js +2 -1
  104. package/dist/queries/outline.d.ts +1 -1
  105. package/dist/queries/outline.js +2 -2
  106. package/dist/queries/passthrough-candidates.d.ts +1 -1
  107. package/dist/queries/passthrough-candidates.js +2 -2
  108. package/dist/queries/redundant-reexports.d.ts +1 -1
  109. package/dist/queries/redundant-reexports.js +3 -3
  110. package/dist/queries/refs.d.ts +1 -1
  111. package/dist/queries/refs.js +2 -2
  112. package/dist/queries/similar-chains.d.ts +1 -1
  113. package/dist/queries/similar-chains.js +2 -2
  114. package/dist/queries/similar-files.d.ts +1 -1
  115. package/dist/queries/similar-files.js +2 -2
  116. package/dist/queries/similar-signatures.d.ts +5 -3
  117. package/dist/queries/similar-signatures.js +2 -1
  118. package/dist/queries/similar.d.ts +1 -1
  119. package/dist/queries/similar.js +2 -2
  120. package/dist/queries/slice.d.ts +1 -1
  121. package/dist/queries/slice.js +2 -2
  122. package/dist/queries/stale-abstractions.d.ts +1 -1
  123. package/dist/queries/stale-abstractions.js +2 -2
  124. package/dist/queries/stats.d.ts +1 -1
  125. package/dist/queries/surface.d.ts +1 -1
  126. package/dist/queries/surface.js +2 -2
  127. package/dist/queries/symbols.d.ts +1 -1
  128. package/dist/queries/symbols.js +2 -2
  129. package/dist/queries/system.d.ts +1 -1
  130. package/dist/queries/system.js +2 -2
  131. package/dist/queries/trace.d.ts +1 -1
  132. package/dist/queries/trace.js +2 -2
  133. package/dist/queries/wrapper-candidates.d.ts +1 -1
  134. package/dist/queries/wrapper-candidates.js +2 -2
  135. package/dist/reindex-worker.js +213 -62
  136. package/package.json +1 -1
  137. package/skills/scip-language-playbook/SKILL.md +371 -0
  138. package/dist/chunk-4JCSOF2O.js +0 -97
  139. package/dist/chunk-AXQKUYKF.js +0 -1442
  140. package/dist/chunk-CPVAQJEC.js +0 -46
  141. package/dist/chunk-EOROMIFO.js +0 -41
  142. package/dist/chunk-GU2H5QRN.js +0 -28
  143. package/dist/chunk-LQJUPXQY.js +0 -109
  144. package/dist/chunk-MPGIHELS.js +0 -39
  145. package/dist/chunk-TOIEB3LG.js +0 -78
  146. package/dist/chunk-UQEQ6AHX.js +0 -60
  147. package/dist/chunk-VJJKSGIX.js +0 -121
  148. package/dist/chunk-YGGFLMTM.js +0 -83
  149. package/dist/chunk-ZEUCXQBN.js +0 -71
@@ -3,8 +3,9 @@ import {
3
3
  } from "./chunk-4TYLS5XX.js";
4
4
  import {
5
5
  findFirstSymbolMatch,
6
- getSourceReferenceSites
7
- } from "./chunk-AXQKUYKF.js";
6
+ getSourceReferenceSites,
7
+ getSourceText
8
+ } from "./chunk-QGCEAVJD.js";
8
9
  import {
9
10
  isFunctionLikeSymbol,
10
11
  shortenSymbol
@@ -16,24 +17,22 @@ function trace(db, symbolPattern) {
16
17
  if (!match) {
17
18
  return { definitions: [], referencedBy: [] };
18
19
  }
19
- const defRows = db.all(
20
- `SELECT d.relative_path, der.start_line, der.end_line,
20
+ const definitionMeta = db.get(
21
+ `SELECT
21
22
  gs.display_name,
22
23
  REPLACE(SUBSTR(gs.documentation, INSTR(gs.documentation, '|') + 1), char(10), ' ') AS sig
23
24
  FROM global_symbols gs
24
- JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id
25
- JOIN documents d ON der.document_id = d.id
26
25
  WHERE gs.id = ?
27
- ORDER BY d.relative_path, der.start_line
28
26
  LIMIT 10`,
29
27
  match.symbolId
30
28
  );
31
- const definitions = defRows.filter((r) => !db.isIgnored(r.relative_path)).map((r) => ({
32
- relativePath: r.relative_path,
33
- startLine: r.start_line,
34
- endLine: r.end_line,
35
- signature: buildTraceSignature(r.sig, r.display_name, match.symbol)
36
- }));
29
+ const definitions = db.isIgnored(match.relativePath) ? [] : [{
30
+ relativePath: match.relativePath,
31
+ startLine: match.startLine,
32
+ endLine: match.endLine,
33
+ signature: buildTraceSignature(definitionMeta?.sig ?? null, definitionMeta?.display_name ?? null, match.symbol),
34
+ source: definitionSource(db, match.relativePath, match.startLine, match.endLine)
35
+ }];
37
36
  const sourceSites = getSourceReferenceSites(db, match);
38
37
  const referencedBy = sourceSites.length > 0 ? sourceSites.filter((site) => !db.isIgnored(site.file)).map((site) => ({
39
38
  relativePath: site.file,
@@ -66,6 +65,15 @@ function trace(db, symbolPattern) {
66
65
  }));
67
66
  return { definitions, referencedBy };
68
67
  }
68
+ function definitionSource(db, relativePath, startLine, endLine) {
69
+ const source = getSourceText(db, relativePath);
70
+ if (!source) {
71
+ return null;
72
+ }
73
+ const lines = source.split("\n");
74
+ const slice = lines.slice(startLine, endLine + 1).join("\n").trimEnd();
75
+ return slice.length > 0 ? slice : null;
76
+ }
69
77
  function buildTraceSignature(signature, displayName, rawSymbol) {
70
78
  const cleaned = cleanSignature(signature);
71
79
  if (cleaned && !looksBogusSignature(cleaned)) {
@@ -84,4 +92,4 @@ function looksBogusSignature(signature) {
84
92
  export {
85
93
  trace
86
94
  };
87
- //# sourceMappingURL=chunk-GEXE2T6I.js.map
95
+ //# sourceMappingURL=chunk-EOHPASDV.js.map
@@ -0,0 +1,37 @@
1
+ import {
2
+ findFirstSymbolMatch,
3
+ getDefinitionsForFile
4
+ } from "./chunk-QGCEAVJD.js";
5
+ import {
6
+ leafName,
7
+ leafSuffix
8
+ } from "./chunk-QIXNAB5K.js";
9
+
10
+ // src/queries/methods.ts
11
+ import { basename } from "path";
12
+ function methods(db, className) {
13
+ const classMatch = findFirstSymbolMatch(db, className);
14
+ if (!classMatch) {
15
+ return [];
16
+ }
17
+ const ownerName = leafName(classMatch.symbol);
18
+ const definitions = getDefinitionsForFile(db, classMatch.relativePath).filter((definition) => isCallableSymbol(definition.symbol));
19
+ const directMethods = definitions.filter((definition) => definition.parentTypeName === ownerName || definition.symbol.includes(ownerName));
20
+ const fileScopedMethods = directMethods.length > 0 ? directMethods : stripExtension(basename(classMatch.relativePath)) === ownerName ? definitions.filter((definition) => definition.symbol.includes("<invalid-global-code>")) : [];
21
+ return fileScopedMethods.map((definition) => ({
22
+ startLine: definition.startLine,
23
+ endLine: definition.endLine,
24
+ name: leafName(definition.symbol)
25
+ }));
26
+ }
27
+ function isCallableSymbol(rawSymbol) {
28
+ return rawSymbol.endsWith("().") || leafSuffix(rawSymbol) === "method";
29
+ }
30
+ function stripExtension(relativePath) {
31
+ return relativePath.replace(/\.[^.]+$/, "");
32
+ }
33
+
34
+ export {
35
+ methods
36
+ };
37
+ //# sourceMappingURL=chunk-GIBETK3W.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  resolveIndexedFile
3
- } from "./chunk-AXQKUYKF.js";
3
+ } from "./chunk-QGCEAVJD.js";
4
4
  import {
5
5
  shortenSymbol
6
6
  } from "./chunk-QIXNAB5K.js";
@@ -68,4 +68,4 @@ function changeSurface(db, filePattern) {
68
68
  export {
69
69
  changeSurface
70
70
  };
71
- //# sourceMappingURL=chunk-SMDCNPMK.js.map
71
+ //# sourceMappingURL=chunk-H3FPW5YN.js.map
@@ -1,7 +1,8 @@
1
1
  import {
2
+ buildFileDepGraph,
2
3
  findFirstSymbolMatch,
3
4
  resolveIndexedFile
4
- } from "./chunk-AXQKUYKF.js";
5
+ } from "./chunk-QGCEAVJD.js";
5
6
  import {
6
7
  shortenSymbol
7
8
  } from "./chunk-QIXNAB5K.js";
@@ -45,10 +46,22 @@ function fanOut(db, filePattern) {
45
46
  ORDER BY symbol_count DESC`,
46
47
  resolvedFile
47
48
  );
48
- return rows.filter((r) => !db.isIgnored(r.relative_path)).map((r) => ({
49
+ const indexedResults = rows.filter((r) => !db.isIgnored(r.relative_path)).map((r) => ({
49
50
  name: r.relative_path,
50
51
  count: r.symbol_count
51
52
  }));
53
+ if (indexedResults.length > 0) {
54
+ return indexedResults;
55
+ }
56
+ const graph = buildFileDepGraph(db);
57
+ const deps = graph.get(resolvedFile);
58
+ if (!deps || deps.size === 0) {
59
+ return [];
60
+ }
61
+ return [{
62
+ name: resolvedFile,
63
+ count: deps.size
64
+ }];
52
65
  }
53
66
  function topFanIn(db, opts = {}) {
54
67
  const { limit = 30, scope } = opts;
@@ -108,4 +121,4 @@ export {
108
121
  topFanIn,
109
122
  topFanOut
110
123
  };
111
- //# sourceMappingURL=chunk-VMM4SYV4.js.map
124
+ //# sourceMappingURL=chunk-HNURMDF4.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  buildFileDepGraph
3
- } from "./chunk-AXQKUYKF.js";
3
+ } from "./chunk-QGCEAVJD.js";
4
4
 
5
5
  // src/queries/drift.ts
6
6
  import path from "path";
@@ -162,4 +162,4 @@ function isTestLikePath(filePath) {
162
162
  export {
163
163
  drift
164
164
  };
165
- //# sourceMappingURL=chunk-7KIMF5PV.js.map
165
+ //# sourceMappingURL=chunk-HRDPUTIQ.js.map
@@ -1,9 +1,12 @@
1
1
  import {
2
2
  findFirstSymbolMatch,
3
- getCalleeRowsForSymbol
4
- } from "./chunk-AXQKUYKF.js";
3
+ getAllDefinitions,
4
+ getCalleeRowsForSymbol,
5
+ getSourceText
6
+ } from "./chunk-QGCEAVJD.js";
5
7
  import {
6
8
  isFunctionLikeSymbol,
9
+ leafName,
7
10
  shortenSymbol
8
11
  } from "./chunk-QIXNAB5K.js";
9
12
 
@@ -11,7 +14,7 @@ import {
11
14
  function similar(db, symbolPattern, opts = {}) {
12
15
  const { minSimilarity = 0.4, limit = 20 } = opts;
13
16
  const target = findCallees(db, symbolPattern);
14
- if (!target || target.callees.size === 0) return [];
17
+ if (!target) return [];
15
18
  if (!isFunctionLikeSymbol(target.symbol)) return [];
16
19
  const candidates = getAllCalleeFingerprints(db, {
17
20
  minCallees: 3,
@@ -43,7 +46,10 @@ function similar(db, symbolPattern, opts = {}) {
43
46
  });
44
47
  }
45
48
  results.sort((a, b) => b.similarity - a.similarity);
46
- return results.slice(0, limit);
49
+ if (results.length > 0) {
50
+ return results.slice(0, limit);
51
+ }
52
+ return similarBySourceShape(db, symbolPattern, { minSimilarity, limit });
47
53
  }
48
54
  function similarAll(db, opts = {}) {
49
55
  const { minSimilarity = 0.5, limit = 20, scope, minCallees = 4 } = opts;
@@ -190,9 +196,144 @@ function difference(a, b) {
190
196
  }
191
197
  return result;
192
198
  }
199
+ function similarBySourceShape(db, symbolPattern, opts) {
200
+ const target = findSourceFingerprint(db, symbolPattern);
201
+ if (!target || target.tokens.size < 3) {
202
+ return [];
203
+ }
204
+ const minSimilarity = opts.minSimilarity >= 0.5 ? opts.minSimilarity : 0.3;
205
+ const results = [];
206
+ for (const candidate of getAllSourceFingerprints(db)) {
207
+ if (candidate.symbol === target.symbol || candidate.tokens.size < 3) continue;
208
+ const shared = intersection(target.tokens, candidate.tokens);
209
+ if (shared.size < 2) continue;
210
+ const union = /* @__PURE__ */ new Set([...target.tokens, ...candidate.tokens]);
211
+ const similarity = union.size > 0 ? shared.size / union.size : 0;
212
+ if (similarity < minSimilarity) continue;
213
+ results.push({
214
+ symbolA: target.symbol,
215
+ shortNameA: shortenSymbol(target.symbol),
216
+ fileA: target.file,
217
+ symbolB: candidate.symbol,
218
+ shortNameB: shortenSymbol(candidate.symbol),
219
+ fileB: candidate.file,
220
+ similarity,
221
+ sharedCallees: [...shared].sort(),
222
+ uniqueToA: [...difference(target.tokens, candidate.tokens)].sort(),
223
+ uniqueToB: [...difference(candidate.tokens, target.tokens)].sort()
224
+ });
225
+ }
226
+ results.sort((a, b) => b.similarity - a.similarity || a.shortNameB.localeCompare(b.shortNameB));
227
+ return results.slice(0, opts.limit);
228
+ }
229
+ function findSourceFingerprint(db, symbolPattern) {
230
+ const match = findFirstSymbolMatch(db, symbolPattern);
231
+ if (!match || !isFunctionLikeSymbol(match.symbol)) {
232
+ return null;
233
+ }
234
+ const snippet = definitionSnippet(db, match.relativePath, match.startLine, match.endLine, leafName(match.symbol));
235
+ const tokens = sourceTokens(snippet, leafName(match.symbol));
236
+ if (tokens.size === 0) {
237
+ return null;
238
+ }
239
+ return {
240
+ symbol: match.symbol,
241
+ file: match.relativePath,
242
+ tokens
243
+ };
244
+ }
245
+ function getAllSourceFingerprints(db) {
246
+ return getAllDefinitions(db).filter((definition) => definition.isFunctionLike).map((definition) => ({
247
+ symbol: definition.symbol,
248
+ file: definition.relativePath,
249
+ tokens: sourceTokens(
250
+ definitionSnippet(db, definition.relativePath, definition.startLine, definition.endLine, definition.leaf),
251
+ definition.leaf
252
+ )
253
+ })).filter((fingerprint) => fingerprint.tokens.size > 0);
254
+ }
255
+ function definitionSnippet(db, relativePath, startLine, endLine, leaf) {
256
+ const source = getSourceText(db, relativePath);
257
+ if (!source) {
258
+ return "";
259
+ }
260
+ const lines = source.split("\n");
261
+ if (endLine >= startLine && endLine - startLine <= 12) {
262
+ return lines.slice(startLine, endLine + 1).join("\n");
263
+ }
264
+ const markerPatterns = [
265
+ new RegExp(`\\bdef\\s+${escapeRegex(leaf)}\\b`),
266
+ new RegExp(`\\bfun\\s+${escapeRegex(leaf)}\\b`),
267
+ new RegExp(`\\bfn\\s+${escapeRegex(leaf)}\\b`),
268
+ new RegExp(`\\bfunction\\s+${escapeRegex(leaf)}\\b`),
269
+ new RegExp(`\\b${escapeRegex(leaf)}\\s*\\(`)
270
+ ];
271
+ const definitionStart = lines.findIndex((line) => markerPatterns.some((pattern) => pattern.test(line)));
272
+ if (definitionStart >= 0) {
273
+ let definitionEnd = definitionStart;
274
+ for (let index = definitionStart + 1; index < lines.length && index <= definitionStart + 8; index++) {
275
+ const line = lines[index] ?? "";
276
+ if (index > definitionStart && looksLikeDefinitionBoundary(line)) {
277
+ break;
278
+ }
279
+ definitionEnd = index;
280
+ if (line.trim() === "" && index > definitionStart + 1) {
281
+ break;
282
+ }
283
+ }
284
+ return lines.slice(definitionStart, definitionEnd + 1).join("\n");
285
+ }
286
+ return lines.slice(startLine, Math.min(lines.length, startLine + 8)).join("\n");
287
+ }
288
+ function sourceTokens(snippet, leaf) {
289
+ if (!snippet) {
290
+ return /* @__PURE__ */ new Set();
291
+ }
292
+ const stopWords = /* @__PURE__ */ new Set([
293
+ "public",
294
+ "private",
295
+ "protected",
296
+ "final",
297
+ "static",
298
+ "class",
299
+ "def",
300
+ "fun",
301
+ "fn",
302
+ "function",
303
+ "return",
304
+ "string",
305
+ "bool",
306
+ "boolean",
307
+ "void",
308
+ "unit",
309
+ "self",
310
+ "this",
311
+ "new",
312
+ "const",
313
+ "let",
314
+ "var",
315
+ "end",
316
+ "pub"
317
+ ]);
318
+ const normalizedLeafParts = splitIdentifier(leaf);
319
+ const normalized = snippet.replace(/["'`]/g, " ").replace(/\b\d+\b/g, " NUM ").replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[^A-Za-z0-9_]+/g, " ").replace(/_/g, " ").toLowerCase();
320
+ const tokens = normalized.split(/\s+/).map((token) => token.trim()).filter((token) => token.length > 1).filter((token) => !stopWords.has(token)).filter((token) => !normalizedLeafParts.has(token));
321
+ return new Set(tokens);
322
+ }
323
+ function splitIdentifier(value) {
324
+ return new Set(
325
+ value.replace(/([a-z0-9])([A-Z])/g, "$1 $2").split(/[^A-Za-z0-9_]+|_/).map((part) => part.toLowerCase()).filter((part) => part.length > 1)
326
+ );
327
+ }
328
+ function looksLikeDefinitionBoundary(line) {
329
+ return /^\s*(?:def|fun|fn|function|class|trait|module|object|enum|interface|public|private|protected)\b/.test(line);
330
+ }
331
+ function escapeRegex(value) {
332
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
333
+ }
193
334
 
194
335
  export {
195
336
  similar,
196
337
  similarAll
197
338
  };
198
- //# sourceMappingURL=chunk-OIDHN6GD.js.map
339
+ //# sourceMappingURL=chunk-I2JM34UV.js.map
@@ -1,38 +1,22 @@
1
1
  import {
2
- getCalleeRowsForSymbol
3
- } from "./chunk-AXQKUYKF.js";
2
+ getCalleeRowsForSymbol,
3
+ getDefinitionsForFile
4
+ } from "./chunk-QGCEAVJD.js";
4
5
  import {
6
+ isFunctionLikeSymbol,
5
7
  shortenSymbol
6
8
  } from "./chunk-QIXNAB5K.js";
7
9
 
8
10
  // src/queries/extract-candidates.ts
9
11
  function extractCandidates(db, opts = {}) {
10
12
  const { scope, minLoc = 10, minCallees = 6, limit = 20 } = opts;
11
- const scopeFilter = scope ? `AND d.relative_path LIKE '%${scope}%'` : "";
12
- const symbols = db.all(
13
- `SELECT gs.id, gs.symbol, der.document_id, der.start_line, der.end_line, d.relative_path
14
- FROM global_symbols gs
15
- JOIN defn_enclosing_ranges der ON gs.id = der.symbol_id
16
- JOIN documents d ON der.document_id = d.id
17
- WHERE 1 = 1
18
- ${db.pathExclusionsFor("d")}
19
- ${db.symbolNoiseFor("gs")}
20
- AND (der.end_line - der.start_line + 1) >= ?
21
- ${scopeFilter}
22
- ORDER BY (der.end_line - der.start_line + 1) DESC`,
23
- minLoc
24
- );
13
+ const symbols = getScopedDefinitions(db, scope).filter((definition) => definitionLoc(definition) >= minLoc && isFunctionLikeSymbol(definition.symbol)).sort((left, right) => definitionLoc(right) - definitionLoc(left));
25
14
  const results = [];
26
15
  for (const sym of symbols) {
27
- if (db.isIgnored(sym.relative_path)) continue;
28
- const basename = sym.relative_path.split("/").pop() ?? "";
16
+ if (db.isIgnored(sym.relativePath)) continue;
17
+ const basename = sym.relativePath.split("/").pop() ?? "";
29
18
  if (basename.includes("types")) continue;
30
- const calleeChunks = getCalleeRowsForSymbol(db, {
31
- documentId: sym.document_id,
32
- startLine: sym.start_line,
33
- endLine: sym.end_line,
34
- symbolId: sym.id
35
- });
19
+ const calleeChunks = getCalleeRowsForSymbol(db, sym);
36
20
  const calleeSet = new Set(calleeChunks.map((c) => c.symbol));
37
21
  if (calleeSet.size < minCallees) continue;
38
22
  const cooccurrence = /* @__PURE__ */ new Map();
@@ -95,10 +79,10 @@ function extractCandidates(db, opts = {}) {
95
79
  results.push({
96
80
  symbol: sym.symbol,
97
81
  shortName: shortenSymbol(sym.symbol),
98
- relativePath: sym.relative_path,
99
- startLine: sym.start_line,
100
- endLine: sym.end_line,
101
- loc: sym.end_line - sym.start_line + 1,
82
+ relativePath: sym.relativePath,
83
+ startLine: sym.startLine,
84
+ endLine: sym.endLine,
85
+ loc: definitionLoc(sym),
102
86
  totalCallees: calleeSet.size,
103
87
  clusters: scoredClusters
104
88
  });
@@ -107,8 +91,22 @@ function extractCandidates(db, opts = {}) {
107
91
  results.sort((a, b) => b.clusters.length - a.clusters.length || b.loc - a.loc);
108
92
  return results.slice(0, limit);
109
93
  }
94
+ function getScopedDefinitions(db, scope) {
95
+ const scopeFilter = scope ? `AND relative_path LIKE '%${scope}%'` : "";
96
+ return db.all(
97
+ `SELECT relative_path
98
+ FROM documents
99
+ WHERE 1 = 1
100
+ ${db.pathExclusionsFor("documents")}
101
+ ${scopeFilter}
102
+ ORDER BY relative_path`
103
+ ).flatMap((row) => getDefinitionsForFile(db, row.relative_path)).filter((row) => !db.isIgnored(row.relativePath));
104
+ }
105
+ function definitionLoc(definition) {
106
+ return definition.endLine - definition.startLine + 1;
107
+ }
110
108
 
111
109
  export {
112
110
  extractCandidates
113
111
  };
114
- //# sourceMappingURL=chunk-EPWLXXBL.js.map
112
+ //# sourceMappingURL=chunk-IV6NZ426.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  resolveIndexedFile
3
- } from "./chunk-AXQKUYKF.js";
3
+ } from "./chunk-QGCEAVJD.js";
4
4
 
5
5
  // src/queries/deps.ts
6
6
  function deps(db, filePattern) {
@@ -50,4 +50,4 @@ export {
50
50
  deps,
51
51
  rdeps
52
52
  };
53
- //# sourceMappingURL=chunk-VT4JBH6L.js.map
53
+ //# sourceMappingURL=chunk-KDCQJTYW.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  resolveIndexedPaths
3
- } from "./chunk-AXQKUYKF.js";
3
+ } from "./chunk-QGCEAVJD.js";
4
4
  import {
5
5
  shortenSymbol
6
6
  } from "./chunk-QIXNAB5K.js";
@@ -48,4 +48,4 @@ function outline(db, filePattern) {
48
48
  export {
49
49
  outline
50
50
  };
51
- //# sourceMappingURL=chunk-5OMVSV6E.js.map
51
+ //# sourceMappingURL=chunk-LOVDB4C6.js.map
@@ -0,0 +1,75 @@
1
+ import {
2
+ getDefinitionsForFile,
3
+ resolveIndexedPaths
4
+ } from "./chunk-QGCEAVJD.js";
5
+ import {
6
+ leafSuffix,
7
+ shortenSymbol
8
+ } from "./chunk-QIXNAB5K.js";
9
+
10
+ // src/queries/surface.ts
11
+ function surface(db, modulePattern) {
12
+ const matchedPaths = resolveIndexedPaths(db, modulePattern);
13
+ if (matchedPaths.length === 0) {
14
+ return [];
15
+ }
16
+ const placeholders = matchedPaths.map(() => "?").join(", ");
17
+ const rows = db.all(
18
+ `SELECT DISTINCT d1.relative_path, gs.symbol
19
+ FROM mentions m
20
+ JOIN chunks c ON m.chunk_id = c.id
21
+ JOIN documents d1 ON c.document_id = d1.id
22
+ JOIN global_symbols gs ON m.symbol_id = gs.id
23
+ WHERE d1.relative_path NOT IN (${placeholders})
24
+ AND (
25
+ EXISTS (
26
+ SELECT 1
27
+ FROM defn_enclosing_ranges der
28
+ JOIN documents d2 ON der.document_id = d2.id
29
+ WHERE der.symbol_id = gs.id
30
+ AND d2.relative_path IN (${placeholders})
31
+ )
32
+ OR EXISTS (
33
+ SELECT 1
34
+ FROM mentions def_m
35
+ JOIN chunks def_c ON def_m.chunk_id = def_c.id
36
+ JOIN documents d2 ON def_c.document_id = d2.id
37
+ WHERE def_m.symbol_id = gs.id
38
+ AND def_m.role = 1
39
+ AND d2.relative_path IN (${placeholders})
40
+ )
41
+ )
42
+ AND m.role != 1
43
+ AND ${db.localSymbolPredicate}
44
+ ${db.pathExclusionsFor("d1")}
45
+ ORDER BY d1.relative_path`,
46
+ ...matchedPaths,
47
+ ...matchedPaths,
48
+ ...matchedPaths
49
+ );
50
+ const exposedDefinitions = matchedPaths.flatMap(
51
+ (relativePath) => getDefinitionsForFile(db, relativePath).filter((definition) => isCallableSymbol(definition.symbol)).map((definition) => ({
52
+ relative_path: relativePath,
53
+ symbol: definition.symbol
54
+ }))
55
+ );
56
+ const seen = /* @__PURE__ */ new Set();
57
+ return [...rows, ...exposedDefinitions].filter((r) => !db.isIgnored(r.relative_path)).filter((r) => {
58
+ const key = `${r.relative_path}|${r.symbol}`;
59
+ if (seen.has(key)) return false;
60
+ seen.add(key);
61
+ return true;
62
+ }).map((r) => ({
63
+ consumer: r.relative_path,
64
+ symbol: r.symbol,
65
+ shortName: shortenSymbol(r.symbol)
66
+ }));
67
+ }
68
+ function isCallableSymbol(rawSymbol) {
69
+ return rawSymbol.endsWith("().") || leafSuffix(rawSymbol) === "method";
70
+ }
71
+
72
+ export {
73
+ surface
74
+ };
75
+ //# sourceMappingURL=chunk-MA3B3IUT.js.map
@@ -2,7 +2,7 @@ import {
2
2
  findFirstSymbolMatch,
3
3
  getSourceImports,
4
4
  resolveIndexedFile
5
- } from "./chunk-AXQKUYKF.js";
5
+ } from "./chunk-QGCEAVJD.js";
6
6
  import {
7
7
  isModuleLikeSymbol,
8
8
  leafName,
@@ -79,6 +79,14 @@ function importedBy(db, symbolPattern) {
79
79
  if (targetFile && normalizePath(entry.sourcePath) !== normalizePath(targetFile)) {
80
80
  continue;
81
81
  }
82
+ if (entry.kind === "side-effect") {
83
+ importers.add(row.relative_path);
84
+ continue;
85
+ }
86
+ if (targetFile && isCLikeImporter(row.relative_path)) {
87
+ importers.add(row.relative_path);
88
+ continue;
89
+ }
82
90
  if (targetIsModule) {
83
91
  importers.add(row.relative_path);
84
92
  continue;
@@ -152,10 +160,13 @@ function renderImportSymbol(importedName, localName, kind) {
152
160
  function normalizePath(path) {
153
161
  return path.replace(/\\/g, "/");
154
162
  }
163
+ function isCLikeImporter(relativePath) {
164
+ return /\.(?:c|h|cc|cpp|cxx|hpp|hh|hxx)$/i.test(relativePath);
165
+ }
155
166
 
156
167
  export {
157
168
  imports,
158
169
  importedBy,
159
170
  unusedImports
160
171
  };
161
- //# sourceMappingURL=chunk-26DOJ63W.js.map
172
+ //# sourceMappingURL=chunk-N2LH3M2P.js.map