token-goat 2.9.29 → 2.9.30

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 (131) hide show
  1. package/README.md +34 -40
  2. package/SECURITY.md +28 -10
  3. package/THIRD_PARTY_NOTICES.md +40 -3
  4. package/dist/native/linux-arm64/tg-hook +0 -0
  5. package/dist/native/linux-x64/tg-hook +0 -0
  6. package/dist/ort-wasm-simd-threaded.mjs +59 -0
  7. package/dist/token-goat-chunk-3CHUNJ2O.mjs +53 -0
  8. package/dist/token-goat-chunk-3Z5S4KGM.mjs +918 -0
  9. package/dist/token-goat-chunk-4FVIAHSI.mjs +211 -0
  10. package/dist/{token-goat-chunk-PGTH2U4C.mjs → token-goat-chunk-4JJS54TR.mjs} +4 -3
  11. package/dist/token-goat-chunk-4LCCNRTG.mjs +313 -0
  12. package/dist/{token-goat-chunk-L7H3U27L.mjs → token-goat-chunk-54K3EUV3.mjs} +1 -1
  13. package/dist/token-goat-chunk-56EIMS3E.mjs +159 -0
  14. package/dist/token-goat-chunk-5BCIJXMO.mjs +609 -0
  15. package/dist/token-goat-chunk-5KDMCMF2.mjs +362 -0
  16. package/dist/token-goat-chunk-5RG5SBL6.mjs +221 -0
  17. package/dist/{token-goat-chunk-RRNZMM3A.mjs → token-goat-chunk-5Y6ZYL6U.mjs} +21 -2
  18. package/dist/{token-goat-chunk-GLXRTTLE.mjs → token-goat-chunk-64FBPDTK.mjs} +12 -8
  19. package/dist/{token-goat-chunk-G23DWHV4.mjs → token-goat-chunk-664RTTUV.mjs} +28 -15
  20. package/dist/token-goat-chunk-67TQJ76B.mjs +57 -0
  21. package/dist/token-goat-chunk-6QMAS7AB.mjs +42 -0
  22. package/dist/token-goat-chunk-7BXSNBY5.mjs +253 -0
  23. package/dist/{token-goat-chunk-IVWI2OCK.mjs → token-goat-chunk-7F2UBPD3.mjs} +40 -11
  24. package/dist/{token-goat-chunk-TGOXNAHW.mjs → token-goat-chunk-7IN2MKDS.mjs} +682 -501
  25. package/dist/token-goat-chunk-7NADEDKJ.mjs +124 -0
  26. package/dist/{token-goat-chunk-KOPIR3KZ.mjs → token-goat-chunk-A3CK6N5Z.mjs} +618 -72
  27. package/dist/{token-goat-chunk-O6I2XU4P.mjs → token-goat-chunk-AFLYLHDH.mjs} +44 -31
  28. package/dist/{token-goat-chunk-TCQANXYC.mjs → token-goat-chunk-AM5V6GSX.mjs} +18 -2
  29. package/dist/{token-goat-chunk-E4ZOJIZK.mjs → token-goat-chunk-APGZXSPS.mjs} +39 -146
  30. package/dist/{token-goat-chunk-D4ETHJD6.mjs → token-goat-chunk-ARDNEC2U.mjs} +9 -7
  31. package/dist/token-goat-chunk-ATCPY7EQ.mjs +134 -0
  32. package/dist/token-goat-chunk-B2RZZCSS.mjs +354 -0
  33. package/dist/{token-goat-chunk-BGYOZ6DO.mjs → token-goat-chunk-B45VMIIH.mjs} +6 -7
  34. package/dist/token-goat-chunk-BPGCUMR7.mjs +30 -0
  35. package/dist/{token-goat-chunk-TDUT2CL6.mjs → token-goat-chunk-C63JQV5K.mjs} +45 -6
  36. package/dist/{token-goat-chunk-ZER6EAXZ.mjs → token-goat-chunk-COBQGL5S.mjs} +2661 -2440
  37. package/dist/token-goat-chunk-COTXZHTS.mjs +39 -0
  38. package/dist/{token-goat-chunk-RQGGMPCR.mjs → token-goat-chunk-CYCEYAEO.mjs} +76 -16
  39. package/dist/token-goat-chunk-CZ3LUXYZ.mjs +4115 -0
  40. package/dist/{token-goat-chunk-ASLWOQ3I.mjs → token-goat-chunk-DZX2YDPT.mjs} +2 -1
  41. package/dist/token-goat-chunk-E3OQX2XT.mjs +824 -0
  42. package/dist/token-goat-chunk-EFHMMIGP.mjs +68 -0
  43. package/dist/token-goat-chunk-ETBHVDB6.mjs +328 -0
  44. package/dist/token-goat-chunk-EVMZJ27Z.mjs +147 -0
  45. package/dist/token-goat-chunk-EXKGNHEG.mjs +2096 -0
  46. package/dist/{token-goat-chunk-RTMVLHWX.mjs → token-goat-chunk-FBNQNSJK.mjs} +2555 -5127
  47. package/dist/{token-goat-chunk-NMTKNYGF.mjs → token-goat-chunk-FNFBKLRD.mjs} +74 -9
  48. package/dist/{token-goat-chunk-RLP6J7WR.mjs → token-goat-chunk-FZ3NEW5O.mjs} +33 -19
  49. package/dist/token-goat-chunk-G5PJ7AGM.mjs +36 -0
  50. package/dist/{token-goat-chunk-DNRPXHYH.mjs → token-goat-chunk-GFBSN7BD.mjs} +29 -401
  51. package/dist/{token-goat-chunk-XYWPOSCN.mjs → token-goat-chunk-GOLEOXZP.mjs} +763 -211
  52. package/dist/token-goat-chunk-H2K3QP6H.mjs +24 -0
  53. package/dist/token-goat-chunk-H2PHHGM5.mjs +188 -0
  54. package/dist/token-goat-chunk-HAVAOB3S.mjs +87 -0
  55. package/dist/token-goat-chunk-HG45AF2B.mjs +2228 -0
  56. package/dist/{token-goat-chunk-HUYUHODZ.mjs → token-goat-chunk-HOJLCGDP.mjs} +12965 -11748
  57. package/dist/{token-goat-chunk-435UQTKD.mjs → token-goat-chunk-HYBFA5X3.mjs} +118 -19
  58. package/dist/token-goat-chunk-IVALLT3S.mjs +48 -0
  59. package/dist/{token-goat-chunk-UXSXQQIY.mjs → token-goat-chunk-IVKIZWAB.mjs} +3 -3
  60. package/dist/{token-goat-chunk-52NSDWYY.mjs → token-goat-chunk-JB6QN6VF.mjs} +6 -4
  61. package/dist/{token-goat-chunk-HNFZZHFW.mjs → token-goat-chunk-JDHE26RP.mjs} +10 -3
  62. package/dist/{token-goat-chunk-FTP4U4QA.mjs → token-goat-chunk-JDU3EXSU.mjs} +12 -11
  63. package/dist/token-goat-chunk-JDWCRD6M.mjs +253 -0
  64. package/dist/{token-goat-chunk-6AK46ZT7.mjs → token-goat-chunk-JN4XMLSD.mjs} +5 -1
  65. package/dist/token-goat-chunk-JTQQGXZH.mjs +733 -0
  66. package/dist/token-goat-chunk-KKUFXAPD.mjs +25 -0
  67. package/dist/token-goat-chunk-KQNZDCBD.mjs +47 -0
  68. package/dist/{token-goat-chunk-2WOUYWLM.mjs → token-goat-chunk-KWPNJBDH.mjs} +27 -3
  69. package/dist/{token-goat-chunk-DPNLUJWB.mjs → token-goat-chunk-LOBGHXPB.mjs} +30 -8
  70. package/dist/token-goat-chunk-MKPF4CL5.mjs +37 -0
  71. package/dist/token-goat-chunk-MNWKPRAL.mjs +13 -0
  72. package/dist/{token-goat-chunk-DNSPXQXQ.mjs → token-goat-chunk-N2NMER56.mjs} +25 -15
  73. package/dist/token-goat-chunk-NYKZLXMK.mjs +218 -0
  74. package/dist/token-goat-chunk-OJBNYTJP.mjs +3087 -0
  75. package/dist/token-goat-chunk-P4QMM4WK.mjs +295 -0
  76. package/dist/token-goat-chunk-PD5VKH46.mjs +184 -0
  77. package/dist/token-goat-chunk-PEPTHRFF.mjs +129 -0
  78. package/dist/{token-goat-chunk-NMBWLRHW.mjs → token-goat-chunk-PU7V3FD6.mjs} +8721 -11104
  79. package/dist/token-goat-chunk-PY533T7F.mjs +46 -0
  80. package/dist/token-goat-chunk-Q5VTGRH7.mjs +761 -0
  81. package/dist/{token-goat-chunk-67BNIKKO.mjs → token-goat-chunk-QCLDAQTS.mjs} +31 -20
  82. package/dist/{token-goat-chunk-SE6E4BKJ.mjs → token-goat-chunk-QSBRTGM2.mjs} +9 -2
  83. package/dist/{token-goat-chunk-VZQEWRVH.mjs → token-goat-chunk-RC35RBUL.mjs} +4 -4
  84. package/dist/{token-goat-chunk-VMFWNHGR.mjs → token-goat-chunk-RHXKCZX3.mjs} +873 -504
  85. package/dist/{token-goat-chunk-PYSUADX4.mjs → token-goat-chunk-RZRTDST7.mjs} +17 -7
  86. package/dist/{token-goat-chunk-ONXH6NZ5.mjs → token-goat-chunk-SJHWVNDQ.mjs} +15 -21
  87. package/dist/token-goat-chunk-SMVRN2HU.mjs +188 -0
  88. package/dist/{token-goat-chunk-QO3LXVVR.mjs → token-goat-chunk-SQSSNQPE.mjs} +2295 -1718
  89. package/dist/{token-goat-chunk-2AWQ2R5X.mjs → token-goat-chunk-T4FK7VOV.mjs} +2 -2
  90. package/dist/token-goat-chunk-U4N3BN2W.mjs +92 -0
  91. package/dist/token-goat-chunk-UA5V6P3P.mjs +122 -0
  92. package/dist/{token-goat-chunk-UA5BKWWQ.mjs → token-goat-chunk-UQ5UK2T7.mjs} +15 -4
  93. package/dist/token-goat-chunk-USILZ3T3.mjs +53 -0
  94. package/dist/{token-goat-chunk-MELOKFDJ.mjs → token-goat-chunk-VES7EL7O.mjs} +7 -1
  95. package/dist/{token-goat-chunk-7CPMDFGB.mjs → token-goat-chunk-VL3YIFHZ.mjs} +389 -14
  96. package/dist/{token-goat-chunk-E5TK5DNO.mjs → token-goat-chunk-VPBBTSJR.mjs} +356 -129
  97. package/dist/{token-goat-chunk-YOOVFPTP.mjs → token-goat-chunk-W3QCJS6G.mjs} +10 -2
  98. package/dist/{token-goat-chunk-LZNBQTDK.mjs → token-goat-chunk-WY3L4DVT.mjs} +11 -7
  99. package/dist/token-goat-chunk-XKI4SEMX.mjs +66 -0
  100. package/dist/token-goat-chunk-XU4P6Z24.mjs +133 -0
  101. package/dist/{token-goat-chunk-H5J3C56Q.mjs → token-goat-chunk-Y776AENC.mjs} +112 -26
  102. package/dist/token-goat-chunk-YARZFCZS.mjs +359 -0
  103. package/dist/{token-goat-chunk-S4VSXURL.mjs → token-goat-chunk-Z44YO3QZ.mjs} +4 -0
  104. package/dist/token-goat-chunk-Z57YODA2.mjs +35 -0
  105. package/dist/{token-goat-chunk-PQ53BSCF.mjs → token-goat-chunk-ZCDTCVIS.mjs} +48 -29
  106. package/dist/token-goat-chunk-ZEJVMUQH.mjs +48 -0
  107. package/dist/{token-goat-chunk-BGHSSJUA.mjs → token-goat-chunk-ZFOBKUWH.mjs} +1 -1
  108. package/dist/token-goat-chunk-ZMBL6UVV.mjs +110 -0
  109. package/dist/{token-goat-chunk-PKRWMHVP.mjs → token-goat-chunk-ZQSJMO2R.mjs} +338 -170
  110. package/dist/token-goat-hook-client.cjs +87 -23
  111. package/dist/token-goat-hook-client.mjs +3 -3
  112. package/dist/token-goat-hook.mjs +46 -30
  113. package/dist/token-goat.core.mjs +6 -6
  114. package/docs/C4_RUNTIME_ARCHITECTURE.md +1 -1
  115. package/docs/cli.md +80 -46
  116. package/docs/install.md +47 -14
  117. package/docs/security.md +7 -7
  118. package/package.json +17 -7
  119. package/scripts/verify-native-dist.mjs +386 -0
  120. package/dist/token-goat-chunk-2NNUA2LR.mjs +0 -143
  121. package/dist/token-goat-chunk-44BM7DDQ.mjs +0 -294
  122. package/dist/token-goat-chunk-C5YPNZKQ.mjs +0 -318
  123. package/dist/token-goat-chunk-CIQ2FTY3.mjs +0 -1990
  124. package/dist/token-goat-chunk-EUSDXRXU.mjs +0 -1429
  125. package/dist/token-goat-chunk-G7IWXCFF.mjs +0 -456
  126. package/dist/token-goat-chunk-JTKCQMQA.mjs +0 -418
  127. package/dist/token-goat-chunk-ORNFMIER.mjs +0 -295
  128. package/dist/token-goat-chunk-VQ6F6T7X.mjs +0 -36
  129. package/dist/token-goat-chunk-YAGLESS3.mjs +0 -23
  130. package/dist/token-goat-chunk-YKSRAWUU.mjs +0 -33
  131. package/dist/token-goat-chunk-Z6KBMOBI.mjs +0 -53
@@ -25,11 +25,12 @@ import {
25
25
  extractSwift,
26
26
  extractThrift,
27
27
  extractWgsl
28
- } from "./token-goat-chunk-PGTH2U4C.mjs";
28
+ } from "./token-goat-chunk-4JJS54TR.mjs";
29
29
  import {
30
30
  extractShellBannerHeading
31
- } from "./token-goat-chunk-VMFWNHGR.mjs";
32
- import "./token-goat-chunk-435UQTKD.mjs";
31
+ } from "./token-goat-chunk-RHXKCZX3.mjs";
32
+ import "./token-goat-chunk-EVMZJ27Z.mjs";
33
+ import "./token-goat-chunk-HYBFA5X3.mjs";
33
34
  import {
34
35
  GENERIC_CLAUSE,
35
36
  assignBraceBlockSpans,
@@ -59,21 +60,21 @@ import {
59
60
  stripMultilineStringSpan,
60
61
  stripStringLiterals,
61
62
  stripXmlComments
62
- } from "./token-goat-chunk-7CPMDFGB.mjs";
63
- import "./token-goat-chunk-TGOXNAHW.mjs";
63
+ } from "./token-goat-chunk-VL3YIFHZ.mjs";
64
64
  import "./token-goat-chunk-XB5KKOCG.mjs";
65
+ import "./token-goat-chunk-7IN2MKDS.mjs";
66
+ import "./token-goat-chunk-U4N3BN2W.mjs";
65
67
  import "./token-goat-chunk-YZAAZU2S.mjs";
66
68
  import "./token-goat-chunk-IVE6U7KV.mjs";
69
+ import "./token-goat-chunk-Y4AFKTHK.mjs";
67
70
  import {
68
71
  countContentLines,
69
72
  escapeRegExp,
70
73
  pushAll
71
- } from "./token-goat-chunk-XYWPOSCN.mjs";
72
- import "./token-goat-chunk-TCQANXYC.mjs";
73
- import "./token-goat-chunk-NMTKNYGF.mjs";
74
- import "./token-goat-chunk-MELOKFDJ.mjs";
75
- import "./token-goat-chunk-Y4AFKTHK.mjs";
76
- import "./token-goat-chunk-JTKCQMQA.mjs";
74
+ } from "./token-goat-chunk-GOLEOXZP.mjs";
75
+ import "./token-goat-chunk-AM5V6GSX.mjs";
76
+ import "./token-goat-chunk-FNFBKLRD.mjs";
77
+ import "./token-goat-chunk-VES7EL7O.mjs";
77
78
  import {
78
79
  init_define_import_meta_env
79
80
  } from "./token-goat-chunk-A37V4PBF.mjs";
@@ -144,6 +145,13 @@ var PROPERTY_ARROW_RE = new RegExp(
144
145
  var CONSTRUCTOR_RE = new RegExp(
145
146
  `${MEMBER_INDENT}(?:(?:public|protected|private|internal|static)\\s+)*(${IDENT})\\s*\\(`
146
147
  );
148
+ var FINALIZER_RE = new RegExp(`${MEMBER_INDENT}(?:(?:extern|unsafe)\\s+)*~\\s*(${IDENT})\\s*\\(`);
149
+ var OPERATOR_RE = /\b(?:implicit|explicit)\s+operator\s([^(]+)\(|\boperator(\s+checked)?\s*([-+!~*/%&|^<>=]+|true|false)\s*\(/;
150
+ var INDEXER_RE = /\bthis\s*\[/;
151
+ var DECLARATION_PREFIX_RE = /^[\w@.<>,?[\]()\s]*$/;
152
+ function isDeclarationPrefix(prefix) {
153
+ return DECLARATION_PREFIX_RE.test(prefix) && /\w/.test(prefix);
154
+ }
147
155
  var CLASS_HEADER_RE = new RegExp(
148
156
  `^(?:(?:public|protected|private|internal|abstract|sealed|static|partial|readonly|ref|unsafe|file|new)\\s+)*(class|struct|interface|enum|record)(?:\\s+(?:class|struct))?\\s+(${IDENT})`
149
157
  );
@@ -159,9 +167,102 @@ function nextCodeLines(lines, from, count) {
159
167
  }
160
168
  return out;
161
169
  }
170
+ var CS_REF_NOISE = /* @__PURE__ */ new Set([
171
+ "if",
172
+ "else",
173
+ "while",
174
+ "for",
175
+ "foreach",
176
+ "switch",
177
+ "case",
178
+ "catch",
179
+ "finally",
180
+ "using",
181
+ "lock",
182
+ "fixed",
183
+ "sizeof",
184
+ "typeof",
185
+ "nameof",
186
+ "default",
187
+ "checked",
188
+ "unchecked",
189
+ "delegate",
190
+ "return",
191
+ "throw",
192
+ "yield",
193
+ "base",
194
+ "this",
195
+ "new",
196
+ "var",
197
+ "async",
198
+ "await",
199
+ "get",
200
+ "set",
201
+ "init",
202
+ "add",
203
+ "remove",
204
+ "where",
205
+ "when",
206
+ "select",
207
+ "from",
208
+ "join",
209
+ "into",
210
+ "let",
211
+ "orderby",
212
+ "group",
213
+ "by",
214
+ "equals",
215
+ "on",
216
+ "ascending",
217
+ "descending",
218
+ "true",
219
+ "false",
220
+ "null",
221
+ "void",
222
+ "bool",
223
+ "byte",
224
+ "sbyte",
225
+ "short",
226
+ "ushort",
227
+ "int",
228
+ "uint",
229
+ "long",
230
+ "ulong",
231
+ "float",
232
+ "double",
233
+ "decimal",
234
+ "char",
235
+ "string",
236
+ "object",
237
+ "dynamic",
238
+ "public",
239
+ "private",
240
+ "protected",
241
+ "internal",
242
+ "static",
243
+ "readonly",
244
+ "volatile",
245
+ "virtual",
246
+ "override",
247
+ "abstract",
248
+ "sealed",
249
+ "extern",
250
+ "unsafe",
251
+ "partial",
252
+ "class",
253
+ "struct",
254
+ "interface",
255
+ "enum",
256
+ "record"
257
+ ]);
258
+ var CS_NEW_CALL_RE = /\bnew\s+([A-Za-z_][A-Za-z0-9_.]*)(?:<[^>()]+>)?\s*(?:\(|(?=\{))/g;
259
+ var CS_INVOCATION_RE = /(?:\b([A-Za-z_][A-Za-z0-9_]*)\s*(?:\.|\?\.)\s*|(?:\.|\?\.)\s*)?\b([A-Za-z_][A-Za-z0-9_]*)(?:\s*<[^>()\n]+>)?\s*\(/g;
260
+ var CS_MULTILINE_INVOCATION_RE = /(?:\b([A-Za-z_][A-Za-z0-9_]*)\s*(?:\.|\?\.)\s*|(?:\.|\?\.)\s*)?\b([A-Za-z_][A-Za-z0-9_]*)(?:\s*<[^>()\n]+>)?\s*$/;
162
261
  function extractCsharp(content, filePath) {
163
262
  const symbols = [];
263
+ const refs = [];
164
264
  const imports = [];
265
+ const seenRefs = /* @__PURE__ */ new Set();
165
266
  const lines = content.split(/\r?\n/);
166
267
  const classStack = [];
167
268
  let braceDepth = 0;
@@ -169,6 +270,8 @@ function extractCsharp(content, filePath) {
169
270
  let mlState = null;
170
271
  let inFalseBlock = false;
171
272
  let falseNesting = 0;
273
+ let currentMember;
274
+ let memberBodyEntered = false;
172
275
  for (let i = 0; i < lines.length; i++) {
173
276
  const rawLine = lines[i] ?? "";
174
277
  const lineNum = i + 1;
@@ -219,16 +322,24 @@ function extractCsharp(content, filePath) {
219
322
  symbols.push(makeLineSymbol(filePath, cname, kind, lineNum, stripped.slice(0, 200), parent, lines, "c"));
220
323
  classStack.push({ name: cname, startDepth: braceDepth, bodyEntered: false });
221
324
  }
325
+ let ctorM = null;
326
+ let finM = null;
327
+ let methM = null;
328
+ let propM = null;
329
+ let headerM = null;
330
+ let arrowM = null;
222
331
  const frame = classStack.length > 0 ? classStack[classStack.length - 1] : null;
223
332
  if (frame !== null) {
224
333
  const depthInClass = braceDepth - frame.startDepth;
225
334
  if (depthInClass === 1) {
226
335
  const lineNoAttr = stripLeadingAttributes(line);
227
- const ctorM = CONSTRUCTOR_RE.exec(lineNoAttr);
336
+ ctorM = CONSTRUCTOR_RE.exec(lineNoAttr);
228
337
  if (ctorM && stripVerbatim(ctorM[1] ?? "") === frame.name) {
229
338
  const sigEnd = line.indexOf("{");
230
339
  const sig = sigEnd >= 0 ? line.slice(0, sigEnd).trimEnd() : line.trimEnd();
231
340
  symbols.push(makeLineSymbol(filePath, frame.name, "method", lineNum, sig.slice(0, 200), frame.name, lines, "c"));
341
+ currentMember = frame.name;
342
+ memberBodyEntered = line.includes("{");
232
343
  }
233
344
  let isPropertyLine = false;
234
345
  const eventM = EVENT_RE.exec(lineNoAttr);
@@ -240,41 +351,191 @@ function extractCsharp(content, filePath) {
240
351
  if (declM) symbols.push(makeLineSymbol(filePath, stripVerbatim(declM[1] ?? ""), "var", lineNum, stripped.slice(0, 200), frame.name, lines, "c"));
241
352
  }
242
353
  }
243
- const propM = isPropertyLine ? null : PROPERTY_RE.exec(lineNoAttr);
354
+ propM = isPropertyLine ? null : PROPERTY_RE.exec(lineNoAttr);
244
355
  if (propM) {
245
356
  isPropertyLine = true;
246
- symbols.push(makeLineSymbol(filePath, stripVerbatim(propM[1] ?? ""), "var", lineNum, stripped.slice(0, 200), frame.name, lines, "c"));
357
+ const propName = stripVerbatim(propM[1] ?? "");
358
+ symbols.push(makeLineSymbol(filePath, propName, "var", lineNum, stripped.slice(0, 200), frame.name, lines, "c"));
359
+ currentMember = propName;
360
+ memberBodyEntered = line.includes("{");
247
361
  } else {
248
- const headerM = PROPERTY_HEADER_RE.exec(lineNoAttr);
362
+ headerM = PROPERTY_HEADER_RE.exec(lineNoAttr);
249
363
  if (headerM) {
250
364
  const [braceLineNext = "", accessorLine = ""] = nextCodeLines(lines, i, 2);
251
365
  if (braceLineNext === "{" && (ALLMAN_ACCESSOR_RE.test(accessorLine) || ALLMAN_ACCESSOR_BODY_RE.test(accessorLine))) {
252
366
  isPropertyLine = true;
253
- symbols.push(makeLineSymbol(filePath, stripVerbatim(headerM[1] ?? ""), "var", lineNum, stripped.slice(0, 200), frame.name, lines, "c"));
367
+ const propName = stripVerbatim(headerM[1] ?? "");
368
+ symbols.push(makeLineSymbol(filePath, propName, "var", lineNum, stripped.slice(0, 200), frame.name, lines, "c"));
369
+ currentMember = propName;
370
+ memberBodyEntered = false;
254
371
  }
255
372
  } else {
256
- const arrowM = PROPERTY_ARROW_RE.exec(lineNoAttr);
373
+ arrowM = PROPERTY_ARROW_RE.exec(lineNoAttr);
257
374
  if (arrowM) {
258
375
  isPropertyLine = true;
259
- symbols.push(makeLineSymbol(filePath, stripVerbatim(arrowM[1] ?? ""), "var", lineNum, stripped.slice(0, 200), frame.name, lines, "c"));
376
+ const propName = stripVerbatim(arrowM[1] ?? "");
377
+ symbols.push(makeLineSymbol(filePath, propName, "var", lineNum, stripped.slice(0, 200), frame.name, lines, "c"));
378
+ currentMember = propName;
379
+ memberBodyEntered = false;
260
380
  }
261
381
  }
262
382
  }
263
- const methM = isPropertyLine ? null : METHOD_RE.exec(lineNoAttr);
383
+ let specialName = null;
384
+ let specialKind = "method";
385
+ finM = FINALIZER_RE.exec(lineNoAttr);
386
+ if (finM && stripVerbatim(finM[1] ?? "") === frame.name) specialName = `~${frame.name}`;
387
+ else finM = null;
388
+ const opM = specialName === null && !isPropertyLine ? OPERATOR_RE.exec(lineNoAttr) : null;
389
+ if (opM && isDeclarationPrefix(lineNoAttr.slice(0, opM.index))) specialName = opM[1] !== void 0 ? `operator ${opM[1].replace(/\s+/g, " ").trim()}` : `operator${opM[2] !== void 0 ? " checked " : ""}${opM[3] ?? ""}`;
390
+ const ixM = specialName === null && !isPropertyLine ? INDEXER_RE.exec(lineNoAttr) : null;
391
+ if (ixM && isDeclarationPrefix(lineNoAttr.slice(0, ixM.index))) {
392
+ specialName = "this[]";
393
+ specialKind = "var";
394
+ }
395
+ if (specialName !== null) {
396
+ isPropertyLine = true;
397
+ const sigEnd = line.indexOf("{");
398
+ const sig = sigEnd >= 0 ? line.slice(0, sigEnd).trimEnd() : line.trimEnd();
399
+ symbols.push(makeLineSymbol(filePath, specialName, specialKind, lineNum, sig.slice(0, 200), frame.name, lines, "c"));
400
+ currentMember = specialName;
401
+ memberBodyEntered = line.includes("{");
402
+ }
403
+ methM = isPropertyLine ? null : METHOD_RE.exec(lineNoAttr);
264
404
  if (methM) {
265
405
  const mname = stripVerbatim(methM[1] ?? "");
266
406
  if (mname && mname !== frame.name) {
267
407
  const sigEnd = line.indexOf("{");
268
408
  const sig = sigEnd >= 0 ? line.slice(0, sigEnd).trimEnd() : line.trimEnd();
269
409
  symbols.push(makeLineSymbol(filePath, mname, "method", lineNum, sig.slice(0, 200), frame.name, lines, "c"));
410
+ currentMember = mname;
411
+ memberBodyEntered = line.includes("{");
412
+ }
413
+ }
414
+ }
415
+ }
416
+ const isInterpolatedLine = rawLine.includes('$"') || rawLine.includes('$@"') || rawLine.includes('@$"');
417
+ const baseLine = isInterpolatedLine ? stripLineComment(rawLine) : stripLineComment(line);
418
+ const braceLine = stripStringLiterals(baseLine, { tripleQuotes: true });
419
+ if (!inFalseBlock && !stripped.startsWith("#")) {
420
+ const declSpans = [];
421
+ if (cm) {
422
+ const name = stripVerbatim(cm[2] ?? "");
423
+ declSpans.push({ name, col: line.indexOf(name) });
424
+ }
425
+ if (ctorM) {
426
+ const name = stripVerbatim(ctorM[1] ?? "");
427
+ declSpans.push({ name, col: line.indexOf(name) });
428
+ }
429
+ if (methM) {
430
+ const name = stripVerbatim(methM[1] ?? "");
431
+ declSpans.push({ name, col: line.indexOf(name) });
432
+ }
433
+ if (delM) {
434
+ const name = stripVerbatim(delM[1] ?? "");
435
+ declSpans.push({ name, col: line.indexOf(name) });
436
+ }
437
+ if (propM) {
438
+ const name = stripVerbatim(propM[1] ?? "");
439
+ declSpans.push({ name, col: line.indexOf(name) });
440
+ }
441
+ if (headerM) {
442
+ const name = stripVerbatim(headerM[1] ?? "");
443
+ declSpans.push({ name, col: line.indexOf(name) });
444
+ }
445
+ if (finM) declSpans.push({ name: stripVerbatim(finM[1] ?? ""), col: line.indexOf("~") + 1 });
446
+ if (arrowM) {
447
+ const name = stripVerbatim(arrowM[1] ?? "");
448
+ declSpans.push({ name, col: line.indexOf(name) });
449
+ }
450
+ const isDeclaration = (name, col) => declSpans.some((d) => d.name === name && Math.abs(d.col - col) <= 2);
451
+ const context = currentMember ?? (frame !== null ? frame.name : "");
452
+ for (const m of braceLine.matchAll(CS_NEW_CALL_RE)) {
453
+ const rawName = stripVerbatim(m[1] ?? "");
454
+ const name = rawName.includes(".") ? rawName.slice(rawName.lastIndexOf(".") + 1) : rawName;
455
+ if (name.length < 1 || CS_REF_NOISE.has(name)) continue;
456
+ const nameOffset = m[0].lastIndexOf(name);
457
+ const col = m.index !== void 0 ? m.index + (nameOffset >= 0 ? nameOffset : 0) : 0;
458
+ if (isDeclaration(name, col)) continue;
459
+ const key = `${name}\0${lineNum}`;
460
+ if (!seenRefs.has(key)) {
461
+ seenRefs.add(key);
462
+ refs.push({ filePath, name, line: lineNum, col, context });
463
+ }
464
+ }
465
+ for (const m of braceLine.matchAll(CS_INVOCATION_RE)) {
466
+ const callee = stripVerbatim(m[2] ?? "");
467
+ if (callee.length >= 1 && !CS_REF_NOISE.has(callee)) {
468
+ const dotIdx = m[0].indexOf(".");
469
+ const searchStart = dotIdx >= 0 ? m[0].lastIndexOf(".") + 1 : 0;
470
+ const calleeOffset = m[0].indexOf(callee, searchStart);
471
+ const col = m.index !== void 0 ? m.index + (calleeOffset >= 0 ? calleeOffset : 0) : 0;
472
+ if (!isDeclaration(callee, col)) {
473
+ const key = `${callee}\0${lineNum}`;
474
+ if (!seenRefs.has(key)) {
475
+ seenRefs.add(key);
476
+ refs.push({ filePath, name: callee, line: lineNum, col, context });
477
+ }
478
+ }
479
+ }
480
+ const receiver = m[1] !== void 0 ? stripVerbatim(m[1]) : "";
481
+ if (receiver.length > 1 && !CS_REF_NOISE.has(receiver)) {
482
+ const col = m.index !== void 0 ? m.index + m[0].indexOf(receiver) : 0;
483
+ if (!isDeclaration(receiver, col)) {
484
+ const key = `${receiver}\0${lineNum}`;
485
+ if (!seenRefs.has(key)) {
486
+ seenRefs.add(key);
487
+ refs.push({ filePath, name: receiver, line: lineNum, col, context });
488
+ }
489
+ }
490
+ }
491
+ }
492
+ const nextCode = nextCodeLines(lines, i, 1)[0];
493
+ if (nextCode?.startsWith("(")) {
494
+ const mlMatch = CS_MULTILINE_INVOCATION_RE.exec(braceLine);
495
+ if (mlMatch) {
496
+ const callee = stripVerbatim(mlMatch[2] ?? "");
497
+ if (callee.length >= 1 && !CS_REF_NOISE.has(callee)) {
498
+ const dotIdx = mlMatch[0].indexOf(".");
499
+ const searchStart = dotIdx >= 0 ? mlMatch[0].lastIndexOf(".") + 1 : 0;
500
+ const calleeOffset = mlMatch[0].indexOf(callee, searchStart);
501
+ const col = mlMatch.index !== void 0 ? mlMatch.index + (calleeOffset >= 0 ? calleeOffset : 0) : 0;
502
+ if (!isDeclaration(callee, col)) {
503
+ const key = `${callee}\0${lineNum}`;
504
+ if (!seenRefs.has(key)) {
505
+ seenRefs.add(key);
506
+ refs.push({ filePath, name: callee, line: lineNum, col, context });
507
+ }
508
+ }
509
+ }
510
+ const receiver = mlMatch[1] !== void 0 ? stripVerbatim(mlMatch[1]) : "";
511
+ if (receiver.length > 1 && !CS_REF_NOISE.has(receiver)) {
512
+ const col = mlMatch.index !== void 0 ? mlMatch.index + mlMatch[0].indexOf(receiver) : 0;
513
+ if (!isDeclaration(receiver, col)) {
514
+ const key = `${receiver}\0${lineNum}`;
515
+ if (!seenRefs.has(key)) {
516
+ seenRefs.add(key);
517
+ refs.push({ filePath, name: receiver, line: lineNum, col, context });
518
+ }
519
+ }
270
520
  }
271
521
  }
272
522
  }
273
523
  }
274
- const braceLine = stripStringLiterals(stripLineComment(line));
275
524
  const openBraces = (braceLine.match(/\{/g) ?? []).length;
276
525
  const closeBraces = (braceLine.match(/\}/g) ?? []).length;
277
526
  braceDepth += openBraces - closeBraces;
527
+ if (currentMember !== void 0) {
528
+ if (!memberBodyEntered) {
529
+ if (openBraces > 0 && braceDepth > (frame?.startDepth ?? 0) + 1) {
530
+ memberBodyEntered = true;
531
+ } else if (stripped.endsWith(";")) {
532
+ currentMember = void 0;
533
+ }
534
+ } else if (frame === null || braceDepth <= frame.startDepth + 1) {
535
+ currentMember = void 0;
536
+ memberBodyEntered = false;
537
+ }
538
+ }
278
539
  const bracelessTop = classStack.length > 0 ? classStack[classStack.length - 1] : null;
279
540
  if (bracelessTop !== null && !bracelessTop.bodyEntered && braceDepth === bracelessTop.startDepth && (openBraces > 0 && openBraces === closeBraces || openBraces === 0 && closeBraces === 0 && stripped.endsWith(";"))) {
280
541
  classStack.pop();
@@ -293,7 +554,7 @@ function extractCsharp(content, filePath) {
293
554
  }
294
555
  }
295
556
  }
296
- return { symbols, imports };
557
+ return { symbols, refs, imports };
297
558
  }
298
559
 
299
560
  // src/languages/php.ts
@@ -881,7 +1142,23 @@ function extractKotlin(content, filePath) {
881
1142
 
882
1143
  // src/languages/scala.ts
883
1144
  init_define_import_meta_env();
884
- var SCALA_STRIP = { symbolLiterals: true };
1145
+ var SCALA_STRIP = { symbolLiterals: true, interpolatorPrefix: true };
1146
+ var MEMBER_KINDS = /* @__PURE__ */ new Set(["function", "val", "var"]);
1147
+ function withSpanEnd(sym, endLine, lines) {
1148
+ if (endLine <= sym.lineStart) return sym;
1149
+ return { ...sym, lineEnd: endLine, body: lines.slice(sym.lineStart - 1, endLine).join("\n") };
1150
+ }
1151
+ function indentedBodyEnd(lines, startLine, declIndent) {
1152
+ let end = startLine;
1153
+ for (let j = startLine; j < lines.length; j++) {
1154
+ const text = lines[j] ?? "";
1155
+ const trimmed = text.trim();
1156
+ if (trimmed === "" || trimmed.startsWith("//")) continue;
1157
+ if (indentOf(text) <= declIndent) break;
1158
+ end = j + 1;
1159
+ }
1160
+ return end;
1161
+ }
885
1162
  function indentOf(line) {
886
1163
  return line.length - line.trimStart().length;
887
1164
  }
@@ -911,6 +1188,11 @@ function extractScala(content, filePath) {
911
1188
  let braceDepth = 0;
912
1189
  let inComment = false;
913
1190
  let mlState = null;
1191
+ let lastCodeLine = 0;
1192
+ const closeColonFrame = (frame, endLine) => {
1193
+ const open = symbols[frame.symbolIndex];
1194
+ if (open !== void 0) symbols[frame.symbolIndex] = withSpanEnd(open, endLine, lines);
1195
+ };
914
1196
  for (let i = 0; i < lines.length; i++) {
915
1197
  const rawLine = lines[i] ?? "";
916
1198
  const lineNum = i + 1;
@@ -933,9 +1215,13 @@ function extractScala(content, filePath) {
933
1215
  const indent = indentOf(line);
934
1216
  while (typeStack.length > 0) {
935
1217
  const top = typeStack[typeStack.length - 1];
936
- if (top.colonBody && indent <= top.declIndent) typeStack.pop();
937
- else break;
1218
+ if (!top.colonBody || indent > top.declIndent) break;
1219
+ typeStack.pop();
1220
+ const closesWithMarker = indent === top.declIndent && stripped === `end ${top.name}`;
1221
+ closeColonFrame(top, closesWithMarker ? lineNum : lastCodeLine);
1222
+ if (closesWithMarker) lastCodeLine = lineNum;
938
1223
  }
1224
+ lastCodeLine = lineNum;
939
1225
  const colonTop = typeStack.length > 0 && typeStack[typeStack.length - 1].colonBody ? typeStack[typeStack.length - 1] : null;
940
1226
  if (colonTop !== null && colonTop.bodyIndent === null) {
941
1227
  colonTop.bodyIndent = indent;
@@ -974,7 +1260,7 @@ function extractScala(content, filePath) {
974
1260
  const cname = unquoteName2(cm[1] ?? "");
975
1261
  const parent = typeStack.length > 0 ? typeStack[typeStack.length - 1].name : void 0;
976
1262
  symbols.push(makeLineSymbol(filePath, cname, "class", lineNum, stripped.slice(0, 200), parent, lines, "c"));
977
- typeStack.push({ name: cname, startDepth: braceDepth, bodyEntered: false, openParens: 0, declIndent: indent, colonBody: opensColonBody, bodyIndent: null });
1263
+ typeStack.push({ name: cname, startDepth: braceDepth, bodyEntered: false, openParens: 0, declIndent: indent, colonBody: opensColonBody, bodyIndent: null, symbolIndex: symbols.length - 1 });
978
1264
  matched = true;
979
1265
  }
980
1266
  const om = !matched && typeDetectionGateOk && (!isIndented || typeStack.length > 0) ? OBJECT_RE.exec(stripped) : null;
@@ -982,7 +1268,7 @@ function extractScala(content, filePath) {
982
1268
  const oname = unquoteName2(om[1] ?? "");
983
1269
  const parent = typeStack.length > 0 ? typeStack[typeStack.length - 1].name : void 0;
984
1270
  symbols.push(makeLineSymbol(filePath, oname, "object", lineNum, stripped.slice(0, 200), parent, lines, "c"));
985
- typeStack.push({ name: oname, startDepth: braceDepth, bodyEntered: false, openParens: 0, declIndent: indent, colonBody: opensColonBody, bodyIndent: null });
1271
+ typeStack.push({ name: oname, startDepth: braceDepth, bodyEntered: false, openParens: 0, declIndent: indent, colonBody: opensColonBody, bodyIndent: null, symbolIndex: symbols.length - 1 });
986
1272
  matched = true;
987
1273
  }
988
1274
  const tm = !matched && typeDetectionGateOk && (!isIndented || typeStack.length > 0) ? TRAIT_RE.exec(stripped) : null;
@@ -990,7 +1276,7 @@ function extractScala(content, filePath) {
990
1276
  const tname = unquoteName2(tm[1] ?? "");
991
1277
  const parent = typeStack.length > 0 ? typeStack[typeStack.length - 1].name : void 0;
992
1278
  symbols.push(makeLineSymbol(filePath, tname, "trait", lineNum, stripped.slice(0, 200), parent, lines, "c"));
993
- typeStack.push({ name: tname, startDepth: braceDepth, bodyEntered: false, openParens: 0, declIndent: indent, colonBody: opensColonBody, bodyIndent: null });
1279
+ typeStack.push({ name: tname, startDepth: braceDepth, bodyEntered: false, openParens: 0, declIndent: indent, colonBody: opensColonBody, bodyIndent: null, symbolIndex: symbols.length - 1 });
994
1280
  matched = true;
995
1281
  }
996
1282
  const enm = !matched && typeDetectionGateOk && (!isIndented || typeStack.length > 0) ? ENUM_RE.exec(stripped) : null;
@@ -998,7 +1284,7 @@ function extractScala(content, filePath) {
998
1284
  const enname = unquoteName2(enm[1] ?? "");
999
1285
  const parent = typeStack.length > 0 ? typeStack[typeStack.length - 1].name : void 0;
1000
1286
  symbols.push(makeLineSymbol(filePath, enname, "enum", lineNum, stripped.slice(0, 200), parent, lines, "c"));
1001
- typeStack.push({ name: enname, startDepth: braceDepth, bodyEntered: false, openParens: 0, declIndent: indent, colonBody: opensColonBody, bodyIndent: null });
1287
+ typeStack.push({ name: enname, startDepth: braceDepth, bodyEntered: false, openParens: 0, declIndent: indent, colonBody: opensColonBody, bodyIndent: null, symbolIndex: symbols.length - 1 });
1002
1288
  matched = true;
1003
1289
  }
1004
1290
  const frame = typeStack.length > 0 ? typeStack[typeStack.length - 1] : null;
@@ -1040,6 +1326,10 @@ function extractScala(content, filePath) {
1040
1326
  }
1041
1327
  }
1042
1328
  }
1329
+ const lastSymbol = symbols[symbols.length - 1];
1330
+ if (lastSymbol !== void 0 && lastSymbol.lineStart === lineNum && MEMBER_KINDS.has(lastSymbol.kind) && stripped.endsWith("=") && !stripped.includes("{")) {
1331
+ symbols[symbols.length - 1] = withSpanEnd(lastSymbol, indentedBodyEnd(lines, lineNum, indent), lines);
1332
+ }
1043
1333
  const braceLine = stripStringLiterals(line, SCALA_STRIP);
1044
1334
  if (frame !== null && !frame.bodyEntered) {
1045
1335
  const parenDelta2 = (braceLine.match(/\(/g) ?? []).length - (braceLine.match(/\)/g) ?? []).length;
@@ -1064,11 +1354,19 @@ function extractScala(content, filePath) {
1064
1354
  }
1065
1355
  }
1066
1356
  }
1357
+ while (typeStack.length > 0) {
1358
+ const top = typeStack.pop();
1359
+ if (top.colonBody) closeColonFrame(top, lastCodeLine);
1360
+ }
1067
1361
  return { symbols, imports };
1068
1362
  }
1069
1363
 
1070
1364
  // src/languages/lua.ts
1071
1365
  init_define_import_meta_env();
1366
+ function receiverName(fname) {
1367
+ const parts = fname.split(/[.:]/);
1368
+ return parts.length > 1 ? parts[parts.length - 2] : void 0;
1369
+ }
1072
1370
  function nearestFunctionName(stack) {
1073
1371
  for (let i = stack.length - 1; i >= 0; i--) {
1074
1372
  const frame = stack[i];
@@ -1160,7 +1458,7 @@ function extractLua(content, filePath) {
1160
1458
  if (fm) {
1161
1459
  const fname = fm[1] ?? "";
1162
1460
  const baseName = fname.split(/[.:]/).pop() ?? fname;
1163
- const parent = nearestFunctionName(funcStack);
1461
+ const parent = receiverName(fname) ?? nearestFunctionName(funcStack);
1164
1462
  if (parent !== void 0) {
1165
1463
  symbols.push(makeLineSymbol(filePath, baseName, "function", lineNum, stripped.slice(0, 200), parent));
1166
1464
  } else {
@@ -1189,7 +1487,7 @@ function extractLua(content, filePath) {
1189
1487
  if (afm) {
1190
1488
  const fname = afm[1] ?? "";
1191
1489
  const baseName = fname.split(/[.:]/).pop() ?? fname;
1192
- const parent = nearestFunctionName(funcStack);
1490
+ const parent = receiverName(fname) ?? nearestFunctionName(funcStack);
1193
1491
  if (parent !== void 0) {
1194
1492
  symbols.push(makeLineSymbol(filePath, baseName, "function", lineNum, stripped.slice(0, 200), parent));
1195
1493
  } else {
@@ -1249,7 +1547,7 @@ var DECLARE_RE = new RegExp(String.raw`^Declare\s+(?:(?:Ansi|Unicode|Auto|PtrSaf
1249
1547
  var VB6_PROPERTY_RE = new RegExp(String.raw`^Property\s+(?:Get|Let|Set)\s+(${ID})`, "i");
1250
1548
  var PROPERTY_RE2 = new RegExp(String.raw`^Property\s+(${ID})`, "i");
1251
1549
  var PROCEDURE_RE = new RegExp(String.raw`^(Sub|Function)\s+(${ID})`, "i");
1252
- var OPERATOR_RE = /^Operator\s+([^\s(]+)\s*\(/i;
1550
+ var OPERATOR_RE2 = /^Operator\s+([^\s(]+)\s*\(/i;
1253
1551
  var EVENT_RE2 = new RegExp(String.raw`^Event\s+(${ID})`, "i");
1254
1552
  var CONST_RE3 = /^Const\s+(\S.*)$/i;
1255
1553
  var DIM_RE = /^Dim\s+(\S.*)$/i;
@@ -1578,7 +1876,7 @@ function extractVb(content, filePath) {
1578
1876
  else open(keyword, name, procedureKind(), stmt);
1579
1877
  continue;
1580
1878
  }
1581
- if ((m = OPERATOR_RE.exec(rest)) !== null) {
1879
+ if ((m = OPERATOR_RE2.exec(rest)) !== null) {
1582
1880
  open("operator", m[1], "method", stmt);
1583
1881
  continue;
1584
1882
  }
@@ -1803,6 +2101,16 @@ function extractVhdl(content, filePath) {
1803
2101
 
1804
2102
  // src/languages/elixir.ts
1805
2103
  init_define_import_meta_env();
2104
+ function bracketDelta(line) {
2105
+ const code = line.replace(/"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'/g, "");
2106
+ return (code.match(/[([{]/g)?.length ?? 0) - (code.match(/[)\]}]/g)?.length ?? 0);
2107
+ }
2108
+ var DANGLING_RE = /(?:,|\bwhen|\band|\bor|\bin|&&|\|\||[+\-*/<>=!|&])\s*$/;
2109
+ var DO_KEYWORD_RE = /(?:^|[\s,)])do:/;
2110
+ var DO_KEYWORD_AT_EOL_RE = /(?:^|[\s,)])do:$/;
2111
+ function indentOf2(line) {
2112
+ return line.length - line.trimStart().length;
2113
+ }
1806
2114
  function nearestDefName(stack) {
1807
2115
  for (let i = stack.length - 1; i >= 0; i--) {
1808
2116
  const frame = stack[i];
@@ -1822,6 +2130,30 @@ function extractElixir(content, filePath) {
1822
2130
  const lines = content.split(/\r?\n/);
1823
2131
  const moduleStack = [];
1824
2132
  let mlState = null;
2133
+ let pending;
2134
+ let keywordBody;
2135
+ const extendDefSpan = (symbolIndex, lineEnd) => {
2136
+ const open = symbols[symbolIndex];
2137
+ if (open !== void 0 && lineEnd > open.lineStart) {
2138
+ symbols[symbolIndex] = { ...open, lineEnd, body: lines.slice(open.lineStart - 1, lineEnd).join("\n") };
2139
+ }
2140
+ };
2141
+ const trackKeywordBody = (symbolIndex, stripped) => {
2142
+ const open = symbols[symbolIndex];
2143
+ if (open !== void 0 && DO_KEYWORD_AT_EOL_RE.test(stripped)) {
2144
+ keywordBody = { symbolIndex, headIndent: indentOf2(lines[open.lineStart - 1] ?? "") };
2145
+ }
2146
+ };
2147
+ const settleDefHead = (name, stripped) => {
2148
+ const symbolIndex = symbols.length - 1;
2149
+ if (/\bdo\s*$/.test(stripped)) {
2150
+ moduleStack.push({ name, endKeywordNeeded: true, isBlock: false, symbolIndex });
2151
+ } else if (!DO_KEYWORD_RE.test(stripped)) {
2152
+ pending = { name, symbolIndex, depth: bracketDelta(stripped), dangling: DANGLING_RE.test(stripped) };
2153
+ } else {
2154
+ trackKeywordBody(symbolIndex, stripped);
2155
+ }
2156
+ };
1825
2157
  for (let i = 0; i < lines.length; i++) {
1826
2158
  const rawLine = lines[i] ?? "";
1827
2159
  const lineNum = i + 1;
@@ -1829,9 +2161,37 @@ function extractElixir(content, filePath) {
1829
2161
  mlState = nextMlState;
1830
2162
  const line = stripLineComment(masked, ["#"]).trimEnd();
1831
2163
  const stripped = line.trim();
2164
+ if (keywordBody !== void 0) {
2165
+ if (rawLine.trim() === "") {
2166
+ keywordBody = void 0;
2167
+ } else if (stripped && indentOf2(masked) <= keywordBody.headIndent) {
2168
+ keywordBody = void 0;
2169
+ } else {
2170
+ if (stripped) extendDefSpan(keywordBody.symbolIndex, lineNum);
2171
+ continue;
2172
+ }
2173
+ }
1832
2174
  if (!stripped) {
1833
2175
  continue;
1834
2176
  }
2177
+ if (pending !== void 0) {
2178
+ const startsContinuation = /^(?:when\b|do\b|,|\|)/.test(stripped);
2179
+ if (pending.depth <= 0 && !pending.dangling && !startsContinuation) {
2180
+ pending = void 0;
2181
+ } else {
2182
+ pending.depth += bracketDelta(stripped);
2183
+ pending.dangling = DANGLING_RE.test(stripped);
2184
+ if (pending.depth <= 0 && /\bdo\s*$/.test(stripped)) {
2185
+ moduleStack.push({ name: pending.name, endKeywordNeeded: true, isBlock: false, symbolIndex: pending.symbolIndex });
2186
+ pending = void 0;
2187
+ } else if (pending.depth <= 0 && DO_KEYWORD_RE.test(stripped)) {
2188
+ extendDefSpan(pending.symbolIndex, lineNum);
2189
+ trackKeywordBody(pending.symbolIndex, stripped);
2190
+ pending = void 0;
2191
+ }
2192
+ continue;
2193
+ }
2194
+ }
1835
2195
  const opensDoBlock = /\bdo\s*$/.test(stripped);
1836
2196
  const opensFnBlock = /\bfn\b/.test(stripped) && !/\bend\b/.test(stripped) && /(?:fn|->)\s*$/.test(stripped);
1837
2197
  const modM = MODULE_RE.exec(stripped);
@@ -1868,9 +2228,7 @@ function extractElixir(content, filePath) {
1868
2228
  } else {
1869
2229
  symbols.push(makeLineSymbol(filePath, fname, "function", lineNum, stripped.slice(0, 200), void 0, lines, "hash"));
1870
2230
  }
1871
- if (opensDoBlock) {
1872
- moduleStack.push({ name: fname, endKeywordNeeded: true, isBlock: false, symbolIndex: symbols.length - 1 });
1873
- }
2231
+ settleDefHead(fname, stripped);
1874
2232
  continue;
1875
2233
  }
1876
2234
  const pfm = PRIVATE_FUNC_RE.exec(stripped);
@@ -1882,9 +2240,7 @@ function extractElixir(content, filePath) {
1882
2240
  } else {
1883
2241
  symbols.push(makeLineSymbol(filePath, fname, "function", lineNum, stripped.slice(0, 200), void 0, lines, "hash"));
1884
2242
  }
1885
- if (opensDoBlock) {
1886
- moduleStack.push({ name: fname, endKeywordNeeded: true, isBlock: false, symbolIndex: symbols.length - 1 });
1887
- }
2243
+ settleDefHead(fname, stripped);
1888
2244
  continue;
1889
2245
  }
1890
2246
  if (STRUCT_RE.test(stripped)) {
@@ -1915,12 +2271,14 @@ function extractElixir(content, filePath) {
1915
2271
 
1916
2272
  // src/languages/dart.ts
1917
2273
  init_define_import_meta_env();
2274
+ var DART_STRIP = { tripleQuotes: true, singleQuoteHoles: true };
1918
2275
  var CLASS_RE4 = /^(?:(?:abstract|base|interface|final|sealed|mixin)\s+)*class\s+([A-Za-z_][A-Za-z0-9_]*)/;
1919
2276
  var ENUM_RE2 = /^enum\s+([A-Za-z_][A-Za-z0-9_]*)/;
1920
2277
  var MIXIN_RE = /^(?:base\s+)?mixin\s+([A-Za-z_][A-Za-z0-9_]*)/;
1921
2278
  var EXTENSION_RE = new RegExp("^extension\\s+(?:([A-Za-z_][A-Za-z0-9_]*)\\s*(?:" + GENERIC_CLAUSE + ")?\\s+)?on\\s+");
1922
2279
  var EXTENSION_TYPE_RE = /^extension\s+type\s+([A-Za-z_][A-Za-z0-9_]*)/;
1923
2280
  var FUNC_RE5 = new RegExp("(?:^|\\s)(?:static\\s+)?(?:(?:void|Future|Stream|async|external)\\s+|[A-Za-z_][A-Za-z0-9_<>?]*(?:\\s*\\?)?\\s+)([A-Za-z_][A-Za-z0-9_]*)\\s*(?:" + GENERIC_CLAUSE + ")?\\s*\\(");
2281
+ var OPERATOR_RE3 = /(?:^|\s)(?:(?:external|abstract)\s+)*(?:[A-Za-z_][A-Za-z0-9_<>?,]*(?:\s*\?)?\s+)?operator\s*(\[\]=|\[\]|>>>|<<|>>|<=|>=|==|~\/|[-+*/%<>&|^~])\s*\(/;
1924
2282
  var GETTER_RE = /^(?:(?:static|external|abstract|covariant)\s+)*(?:[A-Za-z_][A-Za-z0-9_<>,?\s]*(?:\s*\?)?\s+)?get\s+([A-Za-z_][A-Za-z0-9_]*)/;
1925
2283
  var NAMED_CTOR_RE = /^(?:(?:const|factory|external)\s+)*([A-Za-z_][A-Za-z0-9_]*)\.([A-Za-z_][A-Za-z0-9_]*)\s*\(/;
1926
2284
  var UNNAMED_CTOR_RE = /^(?:(?:const|factory|external)\s+)*([A-Za-z_][A-Za-z0-9_]*)\s*\(/;
@@ -1950,11 +2308,11 @@ function extractDart(content, filePath) {
1950
2308
  const line = stripLineComment(blockStripped).trimEnd();
1951
2309
  const stripped = line.trim();
1952
2310
  if (!stripped) {
1953
- const braceLine2 = stripStringLiterals(line, { tripleQuotes: true });
2311
+ const braceLine2 = stripStringLiterals(line, DART_STRIP);
1954
2312
  braceDepth += (braceLine2.match(/\{/g) ?? []).length - (braceLine2.match(/\}/g) ?? []).length;
1955
2313
  continue;
1956
2314
  }
1957
- const structural = stripStringLiterals(stripped, { tripleQuotes: true });
2315
+ const structural = stripStringLiterals(stripped, DART_STRIP);
1958
2316
  const isIndented = line[0] === " " || line[0] === " ";
1959
2317
  const outerFrame = typeStack.length > 0 ? typeStack[typeStack.length - 1] : null;
1960
2318
  const outerDepthInType = outerFrame !== null ? braceDepth - outerFrame.startDepth : 0;
@@ -2029,6 +2387,11 @@ function extractDart(content, filePath) {
2029
2387
  if (!member && FIELD_START_RE.test(stripped)) {
2030
2388
  member = true;
2031
2389
  }
2390
+ const om = !member ? OPERATOR_RE3.exec(structural) : null;
2391
+ if (om) {
2392
+ symbols.push(makeLineSymbol(filePath, om[1] ?? "", "function", lineNum, stripped.slice(0, 200), frame.name, lines, "c"));
2393
+ member = true;
2394
+ }
2032
2395
  const gm = !member ? GETTER_RE.exec(stripped) : null;
2033
2396
  if (gm) {
2034
2397
  symbols.push(makeLineSymbol(filePath, gm[1] ?? "", "function", lineNum, stripped.slice(0, 200), frame.name, lines, "c"));
@@ -2053,7 +2416,7 @@ function extractDart(content, filePath) {
2053
2416
  symbols.push(makeLineSymbol(filePath, fname, "function", lineNum, stripped.slice(0, 200), void 0, lines, "c"));
2054
2417
  }
2055
2418
  }
2056
- const braceLine = stripStringLiterals(line, { tripleQuotes: true });
2419
+ const braceLine = stripStringLiterals(line, DART_STRIP);
2057
2420
  for (const ch of braceLine) {
2058
2421
  if (ch === "{") {
2059
2422
  braceDepth++;
@@ -2470,7 +2833,7 @@ var DOMAIN_RE = makeCreateRe("DOMAIN");
2470
2833
  var AGGREGATE_RE = makeCreateRe("AGGREGATE", OR_REPLACE);
2471
2834
  var POLICY_RE = makeCreateRe("POLICY");
2472
2835
  var RULE_RE = makeCreateRe("RULE", OR_REPLACE);
2473
- var OPERATOR_RE2 = makeCreateRe("OPERATOR(?!\\s+(?:CLASS|FAMILY)\\b)", OR_REPLACE);
2836
+ var OPERATOR_RE4 = makeCreateRe("OPERATOR(?!\\s+(?:CLASS|FAMILY)\\b)", OR_REPLACE);
2474
2837
  var SYNONYM_RE = makeCreateRe("SYNONYM", `${OR_REPLACE}(?:PUBLIC\\s+)?`);
2475
2838
  var DATABASE_LINK_RE = makeCreateRe("DATABASE\\s+LINK", "(?:PUBLIC\\s+)?");
2476
2839
  var CLUSTER_RE = makeCreateRe("CLUSTER");
@@ -2496,7 +2859,7 @@ var PATTERNS = [
2496
2859
  [AGGREGATE_RE, "sql_aggregate"],
2497
2860
  [POLICY_RE, "sql_policy"],
2498
2861
  [RULE_RE, "sql_rule"],
2499
- [OPERATOR_RE2, "sql_operator"],
2862
+ [OPERATOR_RE4, "sql_operator"],
2500
2863
  [SYNONYM_RE, "sql_synonym"],
2501
2864
  [DATABASE_LINK_RE, "sql_database_link"],
2502
2865
  [CLUSTER_RE, "sql_cluster"],
@@ -2788,6 +3151,26 @@ function plsqlStructure(noStrings, lineIndex, units, createStarts, filePath, roo
2788
3151
  }
2789
3152
  return { ends, children };
2790
3153
  }
3154
+ var BODY_KINDS = /* @__PURE__ */ new Set([
3155
+ "sql_function",
3156
+ "sql_procedure",
3157
+ "sql_trigger",
3158
+ "sql_type",
3159
+ "sql_type_body",
3160
+ "sql_package",
3161
+ "sql_package_body",
3162
+ "sql_rule"
3163
+ ]);
3164
+ var BODY_OPENER_RE = /\b(?:BEGIN|DECLARE)\b|\$\w*\$|\bRETURN\s+[\w$#.%]+(?:\s+[\w$#.%=]+|\s*\([^()]*\)){0,16}?\s+(?:IS|AS)\b(?!\s+(?:NOT|NULL|TRUE|FALSE|DISTINCT|UNKNOWN)\b)/i;
3165
+ var QUOTED_IDENTIFIER_RE = /"[^"]*"|`[^`]*`|\[[^\]]*\]/g;
3166
+ function isBodylessFunction(kind, header) {
3167
+ return kind === "sql_function" && !BODY_OPENER_RE.test(header.replace(QUOTED_IDENTIFIER_RE, " "));
3168
+ }
3169
+ function trimBlankTail(lines, start, end) {
3170
+ let e = end;
3171
+ while (e > start && (lines[e - 1] ?? "").trim() === "") e--;
3172
+ return e;
3173
+ }
2791
3174
  function extractSql(content, filePath) {
2792
3175
  const symbols = [];
2793
3176
  const sections = [];
@@ -2809,8 +3192,8 @@ function extractSql(content, filePath) {
2809
3192
  const line = offsetToLine(lineIndex, m.index ?? 0);
2810
3193
  createStarts.push(m.index ?? 0);
2811
3194
  const semiIdx = findStatementTerminator(noStrings, m.index ?? 0);
2812
- if (semiIdx !== -1 && offsetToLine(lineIndex, semiIdx) === line) {
2813
- singleLineEndLines.set(`${name}\0${kind}\0${line}`, line);
3195
+ if (semiIdx !== -1 && (offsetToLine(lineIndex, semiIdx) === line || !BODY_KINDS.has(kind) || isBodylessFunction(kind, noStrings.slice(m.index ?? 0, semiIdx)))) {
3196
+ singleLineEndLines.set(`${name}\0${kind}\0${line}`, offsetToLine(lineIndex, semiIdx));
2814
3197
  } else if (PLSQL_UNIT_KINDS.has(kind)) {
2815
3198
  units.push({ name, kind, index: m.index ?? 0, matchEnd: (m.index ?? 0) + m[0].length, line });
2816
3199
  }
@@ -2824,10 +3207,13 @@ function extractSql(content, filePath) {
2824
3207
  sections.sort((a, b) => a.line - b.line);
2825
3208
  symbols.sort((a, b) => a.lineStart - b.lineStart);
2826
3209
  assignFlatEndLines(sections, totalLines);
3210
+ const noLines = noStrings.split("\n");
2827
3211
  const pinned = propagateEndLinesToSymbols(symbols, sections).map((sym) => {
2828
3212
  const key = `${sym.name}\0${sym.kind}\0${sym.lineStart}`;
2829
- const pinnedEndLine = singleLineEndLines.get(key) ?? plsql.ends.get(key);
2830
- return pinnedEndLine !== void 0 && pinnedEndLine !== sym.lineEnd ? { ...sym, lineEnd: pinnedEndLine } : sym;
3213
+ const semiEnd = singleLineEndLines.get(key);
3214
+ const pinnedEndLine = semiEnd !== void 0 ? Math.min(semiEnd, sym.lineEnd) : plsql.ends.get(key);
3215
+ const end = pinnedEndLine ?? trimBlankTail(noLines, sym.lineStart, sym.lineEnd);
3216
+ return end !== sym.lineEnd ? { ...sym, lineEnd: end } : sym;
2831
3217
  });
2832
3218
  if (plsql.children.length === 0) return pinned;
2833
3219
  return [...pinned, ...plsql.children].sort((a, b) => a.lineStart - b.lineStart);
@@ -3055,6 +3441,103 @@ var FUNC_NAME = "[A-Za-z_][A-Za-z0-9_.+:-]*";
3055
3441
  var FUNC_KEYWORD_RE = new RegExp(`^function\\s+(${FUNC_NAME})\\s*(?:\\(\\s*\\))?`);
3056
3442
  var FUNC_POSIX_RE = new RegExp(`^(${FUNC_NAME})\\s*\\(\\s*\\)`);
3057
3443
  var VAR_RE3 = /^(?:(?:export|declare|readonly)\s+(?:-\w+\s+)*)?([A-Za-z_]\w*)=/;
3444
+ var COMPOUND_OPENERS = /* @__PURE__ */ new Set(["if", "for", "while", "until", "select", "case"]);
3445
+ var COMPOUND_CLOSERS = /* @__PURE__ */ new Set(["fi", "done", "esac"]);
3446
+ var COMPOUND_PREFIX_WORDS = /* @__PURE__ */ new Set(["then", "do", "else", "!", "time"]);
3447
+ var COMPOUND_BODY_START_RE = /^(?:if|for|while|until|select|case)\b/;
3448
+ var COMPOUND_SEGMENT_SPLIT_RE = /;|&&|\|\||\||&|\(|\{|\)|\}/;
3449
+ function cleanForScan(line) {
3450
+ return stripStringLiterals(stripBashComment(line)).trim();
3451
+ }
3452
+ function compoundDelta(text) {
3453
+ let delta = 0;
3454
+ for (const segment of text.split(COMPOUND_SEGMENT_SPLIT_RE)) {
3455
+ const words = segment.trim().split(/\s+/);
3456
+ let w = 0;
3457
+ while (w < words.length && COMPOUND_PREFIX_WORDS.has(words[w] ?? "")) w++;
3458
+ const first = words[w] ?? "";
3459
+ if (COMPOUND_OPENERS.has(first)) delta++;
3460
+ else if (COMPOUND_CLOSERS.has(first)) delta--;
3461
+ }
3462
+ return delta;
3463
+ }
3464
+ var SUBSHELL_TOKEN_RE = /;;&|;;|;&|\|\||&&|[()]|[;&|]|[^\s()&;|]+/g;
3465
+ var CASE_ARM_ENDS = /* @__PURE__ */ new Set([";;", ";&", ";;&"]);
3466
+ var COMMAND_POSITION_WORDS = /* @__PURE__ */ new Set(["then", "do", "else", "elif", "!", "time", "{"]);
3467
+ var SubshellParenScanner = class {
3468
+ depth = 0;
3469
+ // One entry per open `case`: 'subject' until `in`, 'pattern' while reading an arm's pattern, 'body' inside an arm.
3470
+ cases = [];
3471
+ commandPosition = true;
3472
+ // Feeds one cleaned line; true once the body's opening `(` has been closed.
3473
+ closes(text) {
3474
+ for (const tok of text.match(SUBSHELL_TOKEN_RE) ?? []) {
3475
+ const top = this.cases.length - 1;
3476
+ const state = this.cases[top];
3477
+ if (state === "subject") {
3478
+ if (tok === "in") this.cases[top] = "pattern";
3479
+ continue;
3480
+ }
3481
+ if (state === "pattern") {
3482
+ if (tok === "esac") {
3483
+ this.cases.pop();
3484
+ this.commandPosition = false;
3485
+ } else if (tok === ")") {
3486
+ this.cases[top] = "body";
3487
+ this.commandPosition = true;
3488
+ }
3489
+ continue;
3490
+ }
3491
+ if (state === "body" && CASE_ARM_ENDS.has(tok)) {
3492
+ this.cases[top] = "pattern";
3493
+ continue;
3494
+ }
3495
+ if (tok === "(") {
3496
+ this.depth++;
3497
+ this.commandPosition = true;
3498
+ continue;
3499
+ }
3500
+ if (tok === ")") {
3501
+ this.depth--;
3502
+ if (this.depth <= 0) return true;
3503
+ this.commandPosition = false;
3504
+ continue;
3505
+ }
3506
+ if (this.commandPosition && tok === "case") this.cases.push("subject");
3507
+ else if (this.commandPosition && tok === "esac" && state === "body") this.cases.pop();
3508
+ this.commandPosition = /^[;&|]/.test(tok) || COMMAND_POSITION_WORDS.has(tok);
3509
+ }
3510
+ this.commandPosition = true;
3511
+ return false;
3512
+ }
3513
+ };
3514
+ function findCompoundBodyEnd(lines, headerIdx, rest) {
3515
+ let startIdx = headerIdx;
3516
+ let text = rest;
3517
+ if (text === "") {
3518
+ let j = headerIdx + 1;
3519
+ while (j < lines.length && cleanForScan(lines[j] ?? "") === "") j++;
3520
+ if (j >= lines.length) return null;
3521
+ startIdx = j;
3522
+ text = cleanForScan(lines[j] ?? "");
3523
+ }
3524
+ const kind = text.startsWith("(") ? "paren" : text.startsWith("[[") ? "test" : COMPOUND_BODY_START_RE.test(text) ? "keyword" : null;
3525
+ if (kind === null) return null;
3526
+ let depth = 0;
3527
+ const parens = kind === "paren" ? new SubshellParenScanner() : null;
3528
+ for (let k = startIdx; k < lines.length; k++) {
3529
+ const cur = k === startIdx ? text : cleanForScan(lines[k] ?? "");
3530
+ if (parens !== null) {
3531
+ if (parens.closes(cur)) return k + 1;
3532
+ } else if (kind === "test") {
3533
+ if (cur.includes("]]")) return k + 1;
3534
+ } else {
3535
+ depth += compoundDelta(cur);
3536
+ if (depth <= 0) return k + 1;
3537
+ }
3538
+ }
3539
+ return null;
3540
+ }
3058
3541
  function stripBashComment(line) {
3059
3542
  for (let i = 0; i < line.length; i++) {
3060
3543
  if (line[i] !== "#") continue;
@@ -3113,6 +3596,7 @@ function extractBash(content, filePath) {
3113
3596
  let awaitingFunctionBrace = false;
3114
3597
  let openFunctionIndex = null;
3115
3598
  let openHeadingIndex = null;
3599
+ let skipUntil = 0;
3116
3600
  for (let i = 0; i < lines.length; i++) {
3117
3601
  const rawLine = lines[i] ?? "";
3118
3602
  const lineNum = i + 1;
@@ -3120,7 +3604,7 @@ function extractBash(content, filePath) {
3120
3604
  if (rawLine.trim() === heredocs[0]) heredocs.shift();
3121
3605
  continue;
3122
3606
  }
3123
- if (!inFunction && braceDepth === 0) {
3607
+ if (!inFunction && braceDepth === 0 && lineNum > skipUntil) {
3124
3608
  const banner = extractShellBannerHeading(rawLine);
3125
3609
  if (banner !== null) {
3126
3610
  if (openHeadingIndex !== null) {
@@ -3155,6 +3639,7 @@ function extractBash(content, filePath) {
3155
3639
  const opened = findHeredocOpeners(noComment, arithmeticDepth);
3156
3640
  arithmeticDepth = opened.depth;
3157
3641
  heredocs.push(...opened.terminators);
3642
+ if (lineNum <= skipUntil) continue;
3158
3643
  if (!stripped) continue;
3159
3644
  if (!inFunction && !awaitingFunctionBrace && braceDepth === 0) {
3160
3645
  const kwMatch = FUNC_KEYWORD_RE.exec(stripped);
@@ -3178,7 +3663,18 @@ function extractBash(content, filePath) {
3178
3663
  pushedIndex = symbols.length;
3179
3664
  symbols.push(makeLineSymbol(filePath, fname, "function", lineNum, stripped.slice(0, 200), void 0, lines, "hash"));
3180
3665
  }
3181
- if (fname) {
3666
+ const rest = stripped.slice(funcMatch[0].length).trim();
3667
+ const compoundEnd = fname && !rest.startsWith("{") ? findCompoundBodyEnd(lines, i, rest) : null;
3668
+ if (compoundEnd !== null) {
3669
+ if (pushedIndex !== null) {
3670
+ const open = symbols[pushedIndex];
3671
+ if (open !== void 0 && compoundEnd > lineNum) {
3672
+ symbols[pushedIndex] = { ...open, lineEnd: compoundEnd, body: lines.slice(lineNum - 1, compoundEnd).join("\n") };
3673
+ }
3674
+ }
3675
+ skipUntil = compoundEnd;
3676
+ continue;
3677
+ } else if (fname) {
3182
3678
  if (stripped.includes("{")) {
3183
3679
  const braceLine2 = stripStringLiterals(stripped);
3184
3680
  const openCount = (braceLine2.match(/\{/g) ?? []).length;
@@ -3292,7 +3788,7 @@ function maskContinuationAndDefines(text) {
3292
3788
  }
3293
3789
  return { noContinuation: contLines.join("\n"), forTargets: targetLines.join("\n") };
3294
3790
  }
3295
- var TARGET_RE = /^((?:[^\t\n#:=]|:(?=[\\/])|\\#)(?:[^:\n#=]|:(?=[\\/])|\\#)*):{1,2}(?![:=])\s*(?:[^=\n]|$)/gm;
3791
+ var TARGET_RE = /^((?:[^\t\n#:=]|:(?=[\\/])|\\#)(?:[^:\n#=]|:(?=[\\/])|\\#)*):{1,2}(?![:=])(?![ \t]*(?:(?:override|export|private)[ \t]+)*[^\s:=#]+[ \t]*(?:[?+!]|:{0,3})=)\s*(?:[^=\n]|$)/gm;
3296
3792
  var DEFINE_RE2 = /^ *(?:(?:override|export|private)\s+)*define\s+([\w./%$()-]+)/gm;
3297
3793
  var SPECIAL_TARGETS = /* @__PURE__ */ new Set([
3298
3794
  ".PHONY",
@@ -4447,10 +4943,30 @@ function blankJsStringLiterals(content) {
4447
4943
  var FUNC_DECL_RE = /^(?:export\s+)?(?:default\s+)?(?:async\s+)?function\s*\*?\s+([A-Za-z_$][\w$]*)/;
4448
4944
  var CONST_DECL_RE = /^(?:export\s+)?const\s+([A-Za-z_$][\w$]*)\s*[:=]/;
4449
4945
  var CLASS_DECL_RE = /^(?:export\s+)?(?:default\s+)?(?:abstract\s+)?class\s+([A-Za-z_$][\w$]*)/;
4946
+ function declarationEndIdx(blanked, startIdx) {
4947
+ let depth = 0;
4948
+ for (let j = startIdx; j < blanked.length; j++) {
4949
+ const line = blanked[j] ?? "";
4950
+ for (const ch of line) {
4951
+ if (ch === "(" || ch === "[" || ch === "{") depth++;
4952
+ else if (ch === ")" || ch === "]" || ch === "}") depth--;
4953
+ }
4954
+ if (depth > 0) continue;
4955
+ let k = j + 1;
4956
+ while (k < blanked.length && (blanked[k] ?? "").trim() === "") k++;
4957
+ if (j === startIdx && (blanked[k] ?? "").trimStart().startsWith("{")) {
4958
+ j = k - 1;
4959
+ continue;
4960
+ }
4961
+ return j;
4962
+ }
4963
+ return startIdx;
4964
+ }
4450
4965
  function extractTopLevelDeclarations(scriptContent, filePath, startLine) {
4451
4966
  const symbols = [];
4452
4967
  const commentFree = stripJsComments(scriptContent);
4453
4968
  const lines = blankJsStringLiterals(commentFree).split("\n");
4969
+ const rawLines = scriptContent.split("\n");
4454
4970
  let depth = 0;
4455
4971
  for (let i = 0; i < lines.length; i++) {
4456
4972
  const rawLine = lines[i] ?? "";
@@ -4458,16 +4974,14 @@ function extractTopLevelDeclarations(scriptContent, filePath, startLine) {
4458
4974
  if (depth === 0 && trimmed) {
4459
4975
  const line = startLine + i;
4460
4976
  const fm = FUNC_DECL_RE.exec(trimmed);
4461
- if (fm?.[1]) {
4462
- symbols.push(makeLineSymbol(filePath, fm[1], "sfc_script_function", line));
4463
- } else {
4464
- const cm = CONST_DECL_RE.exec(trimmed);
4465
- if (cm?.[1]) {
4466
- symbols.push(makeLineSymbol(filePath, cm[1], "sfc_script_const", line));
4467
- } else {
4468
- const clm = CLASS_DECL_RE.exec(trimmed);
4469
- if (clm?.[1]) symbols.push(makeLineSymbol(filePath, clm[1], "sfc_script_class", line));
4470
- }
4977
+ const cm = fm ? null : CONST_DECL_RE.exec(trimmed);
4978
+ const clm = fm || cm ? null : CLASS_DECL_RE.exec(trimmed);
4979
+ const name = fm?.[1] ?? cm?.[1] ?? clm?.[1];
4980
+ if (name) {
4981
+ const kind = fm ? "sfc_script_function" : cm ? "sfc_script_const" : "sfc_script_class";
4982
+ const sym = makeLineSymbol(filePath, name, kind, line);
4983
+ const endIdx = declarationEndIdx(lines, i);
4984
+ symbols.push(endIdx > i ? { ...sym, lineEnd: startLine + endIdx, body: rawLines.slice(i, endIdx + 1).join("\n") } : sym);
4471
4985
  }
4472
4986
  }
4473
4987
  depth += (rawLine.match(/\{/g) ?? []).length - (rawLine.match(/\}/g) ?? []).length;
@@ -5401,6 +5915,16 @@ function readToken4(masked, i) {
5401
5915
  if (p === start) return void 0;
5402
5916
  return { word: masked.slice(start, p), start, end: p };
5403
5917
  }
5918
+ function readNameToken(masked, i) {
5919
+ let p = i;
5920
+ for (; ; ) {
5921
+ while (isSpace4(masked[p])) p++;
5922
+ if (masked[p] === "#" && masked[p + 1] === "^") p++;
5923
+ if (masked[p] !== "^") break;
5924
+ p = datumEnd2(masked, p + 1);
5925
+ }
5926
+ return readToken4(masked, p);
5927
+ }
5404
5928
  function extractClojure(content, filePath) {
5405
5929
  if (content.includes("\0")) return { symbols: [], imports: [] };
5406
5930
  const rawLines = content.split(/\r?\n/);
@@ -5421,7 +5945,7 @@ function extractClojure(content, filePath) {
5421
5945
  if (tok !== void 0) {
5422
5946
  const kind = DEFINERS4.get(tok.word.toLowerCase());
5423
5947
  if (kind !== void 0) {
5424
- const nameTok = readToken4(masked, tok.end);
5948
+ const nameTok = readNameToken(masked, tok.end);
5425
5949
  const name = nameTok?.word.replace(/^:+/, "") ?? "";
5426
5950
  const idx = spans.open(name, kind, lineOf(i), owner());
5427
5951
  stack.push({ index: idx, depth });
@@ -5728,7 +6252,7 @@ function afterContext(rest) {
5728
6252
  const arrow = rest.indexOf("=>");
5729
6253
  return (arrow >= 0 ? rest.slice(arrow + 2) : rest).trimStart();
5730
6254
  }
5731
- function classify(line) {
6255
+ function classify(line, continued = false) {
5732
6256
  let m;
5733
6257
  if (m = /^module\s+([A-Za-z_][A-Za-z0-9_.']*)/.exec(line)) return [{ kind: "module", name: m[1] }];
5734
6258
  if (m = /^(?:data|newtype)\s+(?:instance\s+)?([A-Z][A-Za-z0-9_']*)/.exec(line)) return [{ kind: "type", name: m[1] }];
@@ -5748,11 +6272,11 @@ function classify(line) {
5748
6272
  if (m = /^\(([^()]+)\)\s*::/.exec(line)) return [{ kind: "function", name: m[1].trim() }];
5749
6273
  if (m = /^([a-z_][A-Za-z0-9_']*)\b/.exec(line)) {
5750
6274
  const name = m[1];
5751
- if (!RESERVED_TOP.has(name) && hasTopLevelEquals(line)) return [{ kind: "function", name }];
6275
+ if (!RESERVED_TOP.has(name) && (continued || hasTopLevelEquals(line))) return [{ kind: "function", name }];
5752
6276
  return void 0;
5753
6277
  }
5754
6278
  if (m = /^\(([^()]+)\)/.exec(line)) {
5755
- if (hasTopLevelEquals(line)) return [{ kind: "function", name: m[1].trim() }];
6279
+ if (continued || hasTopLevelEquals(line)) return [{ kind: "function", name: m[1].trim() }];
5756
6280
  }
5757
6281
  return void 0;
5758
6282
  }
@@ -5761,7 +6285,15 @@ function extractHaskell(content, filePath) {
5761
6285
  const rawLines = content.split(/\r?\n/);
5762
6286
  const masked = maskHaskell(content);
5763
6287
  const maskedLines = masked.split(/\r?\n/);
5764
- const n = rawLines.length;
6288
+ const n = rawLines.length > 1 && rawLines[rawLines.length - 1] === "" ? rawLines.length - 1 : rawLines.length;
6289
+ const headContinues = (idx) => {
6290
+ for (let j = idx + 1; j < n; j++) {
6291
+ if ((maskedLines[j] ?? "").trim() === "") continue;
6292
+ if (!/^\s/.test(rawLines[j] ?? "")) return false;
6293
+ return /^(?:\|(?!\|)|=(?![=>])|::)/.test((maskedLines[j] ?? "").trim());
6294
+ }
6295
+ return false;
6296
+ };
5765
6297
  const boundaries = [];
5766
6298
  for (let idx = 0; idx < n; idx++) {
5767
6299
  const raw = rawLines[idx] ?? "";
@@ -5769,7 +6301,7 @@ function extractHaskell(content, filePath) {
5769
6301
  const maskedLine = maskedLines[idx] ?? "";
5770
6302
  const trimmed = maskedLine.trim();
5771
6303
  if (trimmed === "") continue;
5772
- const defs = classify(trimmed);
6304
+ const defs = classify(trimmed) ?? classify(trimmed, headContinues(idx));
5773
6305
  if (defs === void 0) {
5774
6306
  boundaries.push({ num: idx + 1, consumed: false });
5775
6307
  continue;
@@ -5786,6 +6318,17 @@ function extractHaskell(content, filePath) {
5786
6318
  boundaries[endIdx + 1].consumed = true;
5787
6319
  endIdx++;
5788
6320
  }
6321
+ if (boundaries.some((o, k) => k !== i && o.num === b.num && o.def?.kind === "function")) {
6322
+ let k = endIdx + 1;
6323
+ while (k < boundaries.length && boundaries[k].def?.kind === "function" && boundaries[k].def?.name !== b.def.name) k++;
6324
+ if (k < boundaries.length && boundaries[k].def?.kind === "function" && !boundaries[k].consumed) {
6325
+ while (k < boundaries.length && boundaries[k].def?.kind === "function" && boundaries[k].def?.name === b.def.name) {
6326
+ boundaries[k].consumed = true;
6327
+ endIdx = k;
6328
+ k++;
6329
+ }
6330
+ }
6331
+ }
5789
6332
  }
5790
6333
  const next = boundaries[endIdx + 1];
5791
6334
  const lineEnd = Math.max(b.num, next !== void 0 ? next.num - 1 : n);
@@ -5935,7 +6478,7 @@ function extractOcaml(content, filePath) {
5935
6478
  const rawLines = content.split(/\r?\n/);
5936
6479
  const masked = maskOcaml(content);
5937
6480
  const maskedLines = masked.split(/\r?\n/);
5938
- const n = rawLines.length;
6481
+ const n = rawLines.length > 1 && rawLines[rawLines.length - 1] === "" ? rawLines.length - 1 : rawLines.length;
5939
6482
  const boundaries = [];
5940
6483
  for (let idx = 0; idx < n; idx++) {
5941
6484
  const raw = rawLines[idx] ?? "";
@@ -5943,6 +6486,7 @@ function extractOcaml(content, filePath) {
5943
6486
  const maskedLine = maskedLines[idx] ?? "";
5944
6487
  const trimmed = maskedLine.trim();
5945
6488
  if (trimmed === "") continue;
6489
+ if (/^end\b/.test(trimmed)) continue;
5946
6490
  const def = classify2(trimmed);
5947
6491
  boundaries.push(def === void 0 ? { num: idx + 1 } : { num: idx + 1, def });
5948
6492
  }
@@ -6297,7 +6841,7 @@ function sectionsToHeadingSymbols(sections, filePath) {
6297
6841
  }));
6298
6842
  }
6299
6843
  var ADAPTER_EXTRACTORS = {
6300
- csharp: (content, filePath) => assignBraceBlockSpans(extractCsharp(content, filePath).symbols, content, { lineComment: "//", stringEscapes: "csharp", rawStringQuotes: true }),
6844
+ csharp: (content, filePath) => assignBraceBlockSpans(extractCsharp(content, filePath).symbols, content, { lineComment: "//", stringEscapes: "csharp", rawStringQuotes: true, expressionBodies: true, interpolation: "csharp" }),
6301
6845
  // Both halves walk the SAME masked text: the brace pass used to span raw file content, so it nested on braces in the inline HTML the extractor is no longer reading.
6302
6846
  php: (content, filePath) => {
6303
6847
  const code = maskPhpInlineHtml(content);
@@ -6338,13 +6882,13 @@ var ADAPTER_EXTRACTORS = {
6338
6882
  const r = extractTwig(content, filePath);
6339
6883
  return [...r.symbols, ...sectionsToHeadingSymbols(r.sections, filePath)];
6340
6884
  },
6341
- kotlin: (content, filePath) => assignBraceBlockSpans(extractKotlin(content, filePath).symbols, content, { lineComment: "//", nestedBlockComments: true, tripleQuote: true, tripleQuoteRunClose: "last" }),
6342
- swift: (content, filePath) => assignBraceBlockSpans(extractSwift(content, filePath).symbols, content, { lineComment: "//", nestedBlockComments: true, tripleQuote: true, tripleQuoteRunClose: "last", multilineLang: "swift" }),
6343
- scala: (content, filePath) => assignBraceBlockSpans(extractScala(content, filePath).symbols, content, { lineComment: "//", nestedBlockComments: true, tripleQuote: true, tripleQuoteRunClose: "last" }),
6885
+ kotlin: (content, filePath) => assignBraceBlockSpans(extractKotlin(content, filePath).symbols, content, { lineComment: "//", nestedBlockComments: true, tripleQuote: true, tripleQuoteRunClose: "last", expressionBodies: "kotlin", interpolation: "kotlin" }),
6886
+ swift: (content, filePath) => assignBraceBlockSpans(extractSwift(content, filePath).symbols, content, { lineComment: "//", nestedBlockComments: true, tripleQuote: true, tripleQuoteRunClose: "last", multilineLang: "swift", interpolation: "swift" }),
6887
+ scala: (content, filePath) => assignBraceBlockSpans(extractScala(content, filePath).symbols, content, { lineComment: "//", nestedBlockComments: true, tripleQuote: true, tripleQuoteRunClose: "last", interpolation: "scala" }),
6344
6888
  lua: (content, filePath) => extractLua(content, filePath).symbols,
6345
6889
  vb: (content, filePath) => extractVb(content, filePath).symbols,
6346
6890
  elixir: (content, filePath) => extractElixir(content, filePath).symbols,
6347
- dart: (content, filePath) => assignBraceBlockSpans(extractDart(content, filePath).symbols, content, { lineComment: "//", nestedBlockComments: true, tripleQuote: true, tripleSingleQuote: true, tripleQuoteRunClose: "first" }),
6891
+ dart: (content, filePath) => assignBraceBlockSpans(extractDart(content, filePath).symbols, content, { lineComment: "//", nestedBlockComments: true, tripleQuote: true, tripleSingleQuote: true, tripleQuoteRunClose: "first", interpolation: "dart" }),
6348
6892
  zig: (content, filePath) => assignBraceBlockSpans(extractZig(content, filePath).symbols, content, { lineComment: "//", blockComment: null, lineStringPrefix: "\\\\" }),
6349
6893
  r: (content, filePath) => extractR(content, filePath).symbols,
6350
6894
  graphql: (content, filePath) => extractGraphql(content, filePath).symbols,
@@ -6396,8 +6940,10 @@ var ADAPTER_EXTRACTORS = {
6396
6940
  };
6397
6941
  export {
6398
6942
  ADAPTER_EXTRACTORS,
6943
+ assignBraceBlockSpans,
6399
6944
  extractAstro,
6400
6945
  extractCobol,
6946
+ extractCsharp,
6401
6947
  extractNatural,
6402
6948
  extractSalesforceMetadata,
6403
6949
  extractSvelte,