token-goat 2.9.28 → 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 (134) hide show
  1. package/README.md +36 -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-66LODAUT.mjs → token-goat-chunk-4JJS54TR.mjs} +4 -3
  11. package/dist/token-goat-chunk-4LCCNRTG.mjs +313 -0
  12. package/dist/token-goat-chunk-54K3EUV3.mjs +35 -0
  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-NILVK7XM.mjs → token-goat-chunk-64FBPDTK.mjs} +12 -6
  19. package/dist/{token-goat-chunk-LEG3JNJ6.mjs → token-goat-chunk-664RTTUV.mjs} +31 -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-F7QZRIWM.mjs → token-goat-chunk-7F2UBPD3.mjs} +42 -35
  24. package/dist/{token-goat-chunk-CC2PYJM7.mjs → token-goat-chunk-7IN2MKDS.mjs} +718 -595
  25. package/dist/token-goat-chunk-7NADEDKJ.mjs +124 -0
  26. package/dist/{token-goat-chunk-6SGLIPQB.mjs → token-goat-chunk-A3CK6N5Z.mjs} +621 -72
  27. package/dist/{token-goat-chunk-HXNAC4ZF.mjs → token-goat-chunk-AFLYLHDH.mjs} +48 -33
  28. package/dist/token-goat-chunk-AM5V6GSX.mjs +367 -0
  29. package/dist/{token-goat-chunk-I7CB3X4K.mjs → token-goat-chunk-APGZXSPS.mjs} +44 -148
  30. package/dist/{token-goat-chunk-BJBRGPBX.mjs → token-goat-chunk-ARDNEC2U.mjs} +11 -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-QM76S6YS.mjs → token-goat-chunk-B45VMIIH.mjs} +6 -5
  34. package/dist/token-goat-chunk-BPGCUMR7.mjs +30 -0
  35. package/dist/{token-goat-chunk-GGLEE35R.mjs → token-goat-chunk-C63JQV5K.mjs} +49 -10
  36. package/dist/{token-goat-chunk-RJH64KQH.mjs → token-goat-chunk-COBQGL5S.mjs} +2661 -2440
  37. package/dist/token-goat-chunk-COTXZHTS.mjs +39 -0
  38. package/dist/token-goat-chunk-CYCEYAEO.mjs +265 -0
  39. package/dist/token-goat-chunk-CZ3LUXYZ.mjs +4115 -0
  40. package/dist/token-goat-chunk-DZX2YDPT.mjs +15 -0
  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-6Z5ULNE5.mjs → token-goat-chunk-FBNQNSJK.mjs} +2490 -4957
  47. package/dist/{token-goat-chunk-NMTKNYGF.mjs → token-goat-chunk-FNFBKLRD.mjs} +74 -9
  48. package/dist/{token-goat-chunk-XI2VFAV6.mjs → token-goat-chunk-FZ3NEW5O.mjs} +33 -19
  49. package/dist/token-goat-chunk-G5PJ7AGM.mjs +36 -0
  50. package/dist/{token-goat-chunk-VE27HPIF.mjs → token-goat-chunk-GFBSN7BD.mjs} +30 -398
  51. package/dist/{token-goat-chunk-L45ZQRT7.mjs → token-goat-chunk-GOLEOXZP.mjs} +780 -786
  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-CBMY2FGI.mjs → token-goat-chunk-HOJLCGDP.mjs} +17113 -15554
  57. package/dist/{token-goat-chunk-HUDC5GS5.mjs → token-goat-chunk-HYBFA5X3.mjs} +120 -19
  58. package/dist/token-goat-chunk-IVALLT3S.mjs +48 -0
  59. package/dist/token-goat-chunk-IVE6U7KV.mjs +53 -0
  60. package/dist/{token-goat-chunk-UBUKHVYW.mjs → token-goat-chunk-IVKIZWAB.mjs} +3 -3
  61. package/dist/{token-goat-chunk-4JMWPWCS.mjs → token-goat-chunk-JB6QN6VF.mjs} +6 -4
  62. package/dist/{token-goat-chunk-Q4S3UQGO.mjs → token-goat-chunk-JDHE26RP.mjs} +10 -3
  63. package/dist/{token-goat-chunk-7R2XYKC5.mjs → token-goat-chunk-JDU3EXSU.mjs} +14 -10
  64. package/dist/token-goat-chunk-JDWCRD6M.mjs +253 -0
  65. package/dist/{token-goat-chunk-XBESNWEX.mjs → token-goat-chunk-JN4XMLSD.mjs} +7 -4
  66. package/dist/token-goat-chunk-JTQQGXZH.mjs +733 -0
  67. package/dist/token-goat-chunk-KKUFXAPD.mjs +25 -0
  68. package/dist/token-goat-chunk-KQNZDCBD.mjs +47 -0
  69. package/dist/{token-goat-chunk-4RN64ZND.mjs → token-goat-chunk-KWPNJBDH.mjs} +28 -3
  70. package/dist/token-goat-chunk-LOBGHXPB.mjs +242 -0
  71. package/dist/token-goat-chunk-MKPF4CL5.mjs +37 -0
  72. package/dist/token-goat-chunk-MNWKPRAL.mjs +13 -0
  73. package/dist/{token-goat-chunk-YWSP6IU7.mjs → token-goat-chunk-N2NMER56.mjs} +25 -15
  74. package/dist/token-goat-chunk-NYKZLXMK.mjs +218 -0
  75. package/dist/token-goat-chunk-OJBNYTJP.mjs +3087 -0
  76. package/dist/token-goat-chunk-P4QMM4WK.mjs +295 -0
  77. package/dist/token-goat-chunk-PD5VKH46.mjs +184 -0
  78. package/dist/token-goat-chunk-PEPTHRFF.mjs +129 -0
  79. package/dist/{token-goat-chunk-VWZKZPSR.mjs → token-goat-chunk-PU7V3FD6.mjs} +8752 -11098
  80. package/dist/token-goat-chunk-PY533T7F.mjs +46 -0
  81. package/dist/token-goat-chunk-Q5VTGRH7.mjs +761 -0
  82. package/dist/{token-goat-chunk-IHKZ3QNA.mjs → token-goat-chunk-QCLDAQTS.mjs} +33 -19
  83. package/dist/{token-goat-chunk-LKSXAMJB.mjs → token-goat-chunk-QSBRTGM2.mjs} +9 -2
  84. package/dist/{token-goat-chunk-4STDIGYC.mjs → token-goat-chunk-RC35RBUL.mjs} +7 -5
  85. package/dist/{token-goat-chunk-D5ICEPSB.mjs → token-goat-chunk-RHXKCZX3.mjs} +887 -507
  86. package/dist/{token-goat-chunk-RSS3TLXU.mjs → token-goat-chunk-RZRTDST7.mjs} +17 -7
  87. package/dist/{token-goat-chunk-MAMQPC43.mjs → token-goat-chunk-SJHWVNDQ.mjs} +15 -21
  88. package/dist/token-goat-chunk-SMVRN2HU.mjs +188 -0
  89. package/dist/{token-goat-chunk-EL7M26WP.mjs → token-goat-chunk-SQSSNQPE.mjs} +2100 -1442
  90. package/dist/{token-goat-chunk-OZRSREKR.mjs → token-goat-chunk-T4FK7VOV.mjs} +3 -3
  91. package/dist/token-goat-chunk-U4N3BN2W.mjs +92 -0
  92. package/dist/token-goat-chunk-UA5V6P3P.mjs +122 -0
  93. package/dist/{token-goat-chunk-XKY4VKJ4.mjs → token-goat-chunk-UQ5UK2T7.mjs} +15 -4
  94. package/dist/token-goat-chunk-USILZ3T3.mjs +53 -0
  95. package/dist/token-goat-chunk-VES7EL7O.mjs +205 -0
  96. package/dist/{token-goat-chunk-M56BWPBN.mjs → token-goat-chunk-VL3YIFHZ.mjs} +550 -49
  97. package/dist/{token-goat-chunk-IZXKVT4A.mjs → token-goat-chunk-VPBBTSJR.mjs} +362 -128
  98. package/dist/{token-goat-chunk-F2ARFHLJ.mjs → token-goat-chunk-W3QCJS6G.mjs} +10 -2
  99. package/dist/{token-goat-chunk-FSTWAOW6.mjs → token-goat-chunk-WY3L4DVT.mjs} +11 -5
  100. package/dist/{token-goat-chunk-OSUFN2FV.mjs → token-goat-chunk-XB5KKOCG.mjs} +5 -25
  101. package/dist/token-goat-chunk-XKI4SEMX.mjs +66 -0
  102. package/dist/token-goat-chunk-XU4P6Z24.mjs +133 -0
  103. package/dist/{token-goat-chunk-6CCQDAYY.mjs → token-goat-chunk-Y776AENC.mjs} +138 -33
  104. package/dist/token-goat-chunk-YARZFCZS.mjs +359 -0
  105. package/dist/{token-goat-chunk-EEIDFMEM.mjs → token-goat-chunk-YZAAZU2S.mjs} +12 -3
  106. package/dist/{token-goat-chunk-E3K3BTEQ.mjs → token-goat-chunk-Z44YO3QZ.mjs} +12 -6
  107. package/dist/token-goat-chunk-Z57YODA2.mjs +35 -0
  108. package/dist/{token-goat-chunk-DA43OE7L.mjs → token-goat-chunk-ZCDTCVIS.mjs} +49 -30
  109. package/dist/token-goat-chunk-ZEJVMUQH.mjs +48 -0
  110. package/dist/{token-goat-chunk-BGHSSJUA.mjs → token-goat-chunk-ZFOBKUWH.mjs} +1 -1
  111. package/dist/token-goat-chunk-ZMBL6UVV.mjs +110 -0
  112. package/dist/{token-goat-chunk-SJEKA7Y2.mjs → token-goat-chunk-ZQSJMO2R.mjs} +381 -201
  113. package/dist/token-goat-hook-client.cjs +539 -0
  114. package/dist/token-goat-hook-client.mjs +26 -0
  115. package/dist/token-goat-hook.mjs +48 -28
  116. package/dist/token-goat.core.mjs +10 -45
  117. package/docs/C4_RUNTIME_ARCHITECTURE.md +3 -3
  118. package/docs/cli.md +82 -47
  119. package/docs/install.md +58 -23
  120. package/docs/security.md +7 -7
  121. package/package.json +17 -7
  122. package/scripts/verify-native-dist.mjs +386 -0
  123. package/dist/token-goat-chunk-4JJBFT7V.mjs +0 -20
  124. package/dist/token-goat-chunk-5NNYIUGV.mjs +0 -143
  125. package/dist/token-goat-chunk-6DQNNFJ6.mjs +0 -294
  126. package/dist/token-goat-chunk-7MAFDRVR.mjs +0 -47
  127. package/dist/token-goat-chunk-BCN2YQC6.mjs +0 -32
  128. package/dist/token-goat-chunk-D7GHQKQD.mjs +0 -30
  129. package/dist/token-goat-chunk-GMOUBOX4.mjs +0 -386
  130. package/dist/token-goat-chunk-IFORDBGC.mjs +0 -192
  131. package/dist/token-goat-chunk-JXK2HQXS.mjs +0 -318
  132. package/dist/token-goat-chunk-L7SDVGBT.mjs +0 -430
  133. package/dist/token-goat-chunk-MMLMALWK.mjs +0 -1381
  134. package/dist/token-goat-chunk-MVSWBNMD.mjs +0 -1985
@@ -25,11 +25,12 @@ import {
25
25
  extractSwift,
26
26
  extractThrift,
27
27
  extractWgsl
28
- } from "./token-goat-chunk-66LODAUT.mjs";
28
+ } from "./token-goat-chunk-4JJS54TR.mjs";
29
29
  import {
30
30
  extractShellBannerHeading
31
- } from "./token-goat-chunk-D5ICEPSB.mjs";
32
- import "./token-goat-chunk-HUDC5GS5.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,18 +60,21 @@ import {
59
60
  stripMultilineStringSpan,
60
61
  stripStringLiterals,
61
62
  stripXmlComments
62
- } from "./token-goat-chunk-M56BWPBN.mjs";
63
- import "./token-goat-chunk-CC2PYJM7.mjs";
64
- import "./token-goat-chunk-EEIDFMEM.mjs";
65
- import "./token-goat-chunk-OSUFN2FV.mjs";
63
+ } from "./token-goat-chunk-VL3YIFHZ.mjs";
64
+ import "./token-goat-chunk-XB5KKOCG.mjs";
65
+ import "./token-goat-chunk-7IN2MKDS.mjs";
66
+ import "./token-goat-chunk-U4N3BN2W.mjs";
67
+ import "./token-goat-chunk-YZAAZU2S.mjs";
68
+ import "./token-goat-chunk-IVE6U7KV.mjs";
69
+ import "./token-goat-chunk-Y4AFKTHK.mjs";
66
70
  import {
67
71
  countContentLines,
68
72
  escapeRegExp,
69
73
  pushAll
70
- } from "./token-goat-chunk-L45ZQRT7.mjs";
71
- import "./token-goat-chunk-NMTKNYGF.mjs";
72
- import "./token-goat-chunk-Y4AFKTHK.mjs";
73
- import "./token-goat-chunk-GMOUBOX4.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";
74
78
  import {
75
79
  init_define_import_meta_env
76
80
  } from "./token-goat-chunk-A37V4PBF.mjs";
@@ -141,6 +145,13 @@ var PROPERTY_ARROW_RE = new RegExp(
141
145
  var CONSTRUCTOR_RE = new RegExp(
142
146
  `${MEMBER_INDENT}(?:(?:public|protected|private|internal|static)\\s+)*(${IDENT})\\s*\\(`
143
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
+ }
144
155
  var CLASS_HEADER_RE = new RegExp(
145
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})`
146
157
  );
@@ -156,9 +167,102 @@ function nextCodeLines(lines, from, count) {
156
167
  }
157
168
  return out;
158
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*$/;
159
261
  function extractCsharp(content, filePath) {
160
262
  const symbols = [];
263
+ const refs = [];
161
264
  const imports = [];
265
+ const seenRefs = /* @__PURE__ */ new Set();
162
266
  const lines = content.split(/\r?\n/);
163
267
  const classStack = [];
164
268
  let braceDepth = 0;
@@ -166,6 +270,8 @@ function extractCsharp(content, filePath) {
166
270
  let mlState = null;
167
271
  let inFalseBlock = false;
168
272
  let falseNesting = 0;
273
+ let currentMember;
274
+ let memberBodyEntered = false;
169
275
  for (let i = 0; i < lines.length; i++) {
170
276
  const rawLine = lines[i] ?? "";
171
277
  const lineNum = i + 1;
@@ -216,16 +322,24 @@ function extractCsharp(content, filePath) {
216
322
  symbols.push(makeLineSymbol(filePath, cname, kind, lineNum, stripped.slice(0, 200), parent, lines, "c"));
217
323
  classStack.push({ name: cname, startDepth: braceDepth, bodyEntered: false });
218
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;
219
331
  const frame = classStack.length > 0 ? classStack[classStack.length - 1] : null;
220
332
  if (frame !== null) {
221
333
  const depthInClass = braceDepth - frame.startDepth;
222
334
  if (depthInClass === 1) {
223
335
  const lineNoAttr = stripLeadingAttributes(line);
224
- const ctorM = CONSTRUCTOR_RE.exec(lineNoAttr);
336
+ ctorM = CONSTRUCTOR_RE.exec(lineNoAttr);
225
337
  if (ctorM && stripVerbatim(ctorM[1] ?? "") === frame.name) {
226
338
  const sigEnd = line.indexOf("{");
227
339
  const sig = sigEnd >= 0 ? line.slice(0, sigEnd).trimEnd() : line.trimEnd();
228
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("{");
229
343
  }
230
344
  let isPropertyLine = false;
231
345
  const eventM = EVENT_RE.exec(lineNoAttr);
@@ -237,41 +351,191 @@ function extractCsharp(content, filePath) {
237
351
  if (declM) symbols.push(makeLineSymbol(filePath, stripVerbatim(declM[1] ?? ""), "var", lineNum, stripped.slice(0, 200), frame.name, lines, "c"));
238
352
  }
239
353
  }
240
- const propM = isPropertyLine ? null : PROPERTY_RE.exec(lineNoAttr);
354
+ propM = isPropertyLine ? null : PROPERTY_RE.exec(lineNoAttr);
241
355
  if (propM) {
242
356
  isPropertyLine = true;
243
- 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("{");
244
361
  } else {
245
- const headerM = PROPERTY_HEADER_RE.exec(lineNoAttr);
362
+ headerM = PROPERTY_HEADER_RE.exec(lineNoAttr);
246
363
  if (headerM) {
247
364
  const [braceLineNext = "", accessorLine = ""] = nextCodeLines(lines, i, 2);
248
365
  if (braceLineNext === "{" && (ALLMAN_ACCESSOR_RE.test(accessorLine) || ALLMAN_ACCESSOR_BODY_RE.test(accessorLine))) {
249
366
  isPropertyLine = true;
250
- 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;
251
371
  }
252
372
  } else {
253
- const arrowM = PROPERTY_ARROW_RE.exec(lineNoAttr);
373
+ arrowM = PROPERTY_ARROW_RE.exec(lineNoAttr);
254
374
  if (arrowM) {
255
375
  isPropertyLine = true;
256
- 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;
257
380
  }
258
381
  }
259
382
  }
260
- 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);
261
404
  if (methM) {
262
405
  const mname = stripVerbatim(methM[1] ?? "");
263
406
  if (mname && mname !== frame.name) {
264
407
  const sigEnd = line.indexOf("{");
265
408
  const sig = sigEnd >= 0 ? line.slice(0, sigEnd).trimEnd() : line.trimEnd();
266
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
+ }
267
520
  }
268
521
  }
269
522
  }
270
523
  }
271
- const braceLine = stripStringLiterals(stripLineComment(line));
272
524
  const openBraces = (braceLine.match(/\{/g) ?? []).length;
273
525
  const closeBraces = (braceLine.match(/\}/g) ?? []).length;
274
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
+ }
275
539
  const bracelessTop = classStack.length > 0 ? classStack[classStack.length - 1] : null;
276
540
  if (bracelessTop !== null && !bracelessTop.bodyEntered && braceDepth === bracelessTop.startDepth && (openBraces > 0 && openBraces === closeBraces || openBraces === 0 && closeBraces === 0 && stripped.endsWith(";"))) {
277
541
  classStack.pop();
@@ -290,7 +554,7 @@ function extractCsharp(content, filePath) {
290
554
  }
291
555
  }
292
556
  }
293
- return { symbols, imports };
557
+ return { symbols, refs, imports };
294
558
  }
295
559
 
296
560
  // src/languages/php.ts
@@ -878,7 +1142,23 @@ function extractKotlin(content, filePath) {
878
1142
 
879
1143
  // src/languages/scala.ts
880
1144
  init_define_import_meta_env();
881
- 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
+ }
882
1162
  function indentOf(line) {
883
1163
  return line.length - line.trimStart().length;
884
1164
  }
@@ -908,6 +1188,11 @@ function extractScala(content, filePath) {
908
1188
  let braceDepth = 0;
909
1189
  let inComment = false;
910
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
+ };
911
1196
  for (let i = 0; i < lines.length; i++) {
912
1197
  const rawLine = lines[i] ?? "";
913
1198
  const lineNum = i + 1;
@@ -930,9 +1215,13 @@ function extractScala(content, filePath) {
930
1215
  const indent = indentOf(line);
931
1216
  while (typeStack.length > 0) {
932
1217
  const top = typeStack[typeStack.length - 1];
933
- if (top.colonBody && indent <= top.declIndent) typeStack.pop();
934
- 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;
935
1223
  }
1224
+ lastCodeLine = lineNum;
936
1225
  const colonTop = typeStack.length > 0 && typeStack[typeStack.length - 1].colonBody ? typeStack[typeStack.length - 1] : null;
937
1226
  if (colonTop !== null && colonTop.bodyIndent === null) {
938
1227
  colonTop.bodyIndent = indent;
@@ -971,7 +1260,7 @@ function extractScala(content, filePath) {
971
1260
  const cname = unquoteName2(cm[1] ?? "");
972
1261
  const parent = typeStack.length > 0 ? typeStack[typeStack.length - 1].name : void 0;
973
1262
  symbols.push(makeLineSymbol(filePath, cname, "class", lineNum, stripped.slice(0, 200), parent, lines, "c"));
974
- 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 });
975
1264
  matched = true;
976
1265
  }
977
1266
  const om = !matched && typeDetectionGateOk && (!isIndented || typeStack.length > 0) ? OBJECT_RE.exec(stripped) : null;
@@ -979,7 +1268,7 @@ function extractScala(content, filePath) {
979
1268
  const oname = unquoteName2(om[1] ?? "");
980
1269
  const parent = typeStack.length > 0 ? typeStack[typeStack.length - 1].name : void 0;
981
1270
  symbols.push(makeLineSymbol(filePath, oname, "object", lineNum, stripped.slice(0, 200), parent, lines, "c"));
982
- 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 });
983
1272
  matched = true;
984
1273
  }
985
1274
  const tm = !matched && typeDetectionGateOk && (!isIndented || typeStack.length > 0) ? TRAIT_RE.exec(stripped) : null;
@@ -987,7 +1276,7 @@ function extractScala(content, filePath) {
987
1276
  const tname = unquoteName2(tm[1] ?? "");
988
1277
  const parent = typeStack.length > 0 ? typeStack[typeStack.length - 1].name : void 0;
989
1278
  symbols.push(makeLineSymbol(filePath, tname, "trait", lineNum, stripped.slice(0, 200), parent, lines, "c"));
990
- 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 });
991
1280
  matched = true;
992
1281
  }
993
1282
  const enm = !matched && typeDetectionGateOk && (!isIndented || typeStack.length > 0) ? ENUM_RE.exec(stripped) : null;
@@ -995,7 +1284,7 @@ function extractScala(content, filePath) {
995
1284
  const enname = unquoteName2(enm[1] ?? "");
996
1285
  const parent = typeStack.length > 0 ? typeStack[typeStack.length - 1].name : void 0;
997
1286
  symbols.push(makeLineSymbol(filePath, enname, "enum", lineNum, stripped.slice(0, 200), parent, lines, "c"));
998
- 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 });
999
1288
  matched = true;
1000
1289
  }
1001
1290
  const frame = typeStack.length > 0 ? typeStack[typeStack.length - 1] : null;
@@ -1037,6 +1326,10 @@ function extractScala(content, filePath) {
1037
1326
  }
1038
1327
  }
1039
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
+ }
1040
1333
  const braceLine = stripStringLiterals(line, SCALA_STRIP);
1041
1334
  if (frame !== null && !frame.bodyEntered) {
1042
1335
  const parenDelta2 = (braceLine.match(/\(/g) ?? []).length - (braceLine.match(/\)/g) ?? []).length;
@@ -1061,11 +1354,19 @@ function extractScala(content, filePath) {
1061
1354
  }
1062
1355
  }
1063
1356
  }
1357
+ while (typeStack.length > 0) {
1358
+ const top = typeStack.pop();
1359
+ if (top.colonBody) closeColonFrame(top, lastCodeLine);
1360
+ }
1064
1361
  return { symbols, imports };
1065
1362
  }
1066
1363
 
1067
1364
  // src/languages/lua.ts
1068
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
+ }
1069
1370
  function nearestFunctionName(stack) {
1070
1371
  for (let i = stack.length - 1; i >= 0; i--) {
1071
1372
  const frame = stack[i];
@@ -1157,7 +1458,7 @@ function extractLua(content, filePath) {
1157
1458
  if (fm) {
1158
1459
  const fname = fm[1] ?? "";
1159
1460
  const baseName = fname.split(/[.:]/).pop() ?? fname;
1160
- const parent = nearestFunctionName(funcStack);
1461
+ const parent = receiverName(fname) ?? nearestFunctionName(funcStack);
1161
1462
  if (parent !== void 0) {
1162
1463
  symbols.push(makeLineSymbol(filePath, baseName, "function", lineNum, stripped.slice(0, 200), parent));
1163
1464
  } else {
@@ -1186,7 +1487,7 @@ function extractLua(content, filePath) {
1186
1487
  if (afm) {
1187
1488
  const fname = afm[1] ?? "";
1188
1489
  const baseName = fname.split(/[.:]/).pop() ?? fname;
1189
- const parent = nearestFunctionName(funcStack);
1490
+ const parent = receiverName(fname) ?? nearestFunctionName(funcStack);
1190
1491
  if (parent !== void 0) {
1191
1492
  symbols.push(makeLineSymbol(filePath, baseName, "function", lineNum, stripped.slice(0, 200), parent));
1192
1493
  } else {
@@ -1246,7 +1547,7 @@ var DECLARE_RE = new RegExp(String.raw`^Declare\s+(?:(?:Ansi|Unicode|Auto|PtrSaf
1246
1547
  var VB6_PROPERTY_RE = new RegExp(String.raw`^Property\s+(?:Get|Let|Set)\s+(${ID})`, "i");
1247
1548
  var PROPERTY_RE2 = new RegExp(String.raw`^Property\s+(${ID})`, "i");
1248
1549
  var PROCEDURE_RE = new RegExp(String.raw`^(Sub|Function)\s+(${ID})`, "i");
1249
- var OPERATOR_RE = /^Operator\s+([^\s(]+)\s*\(/i;
1550
+ var OPERATOR_RE2 = /^Operator\s+([^\s(]+)\s*\(/i;
1250
1551
  var EVENT_RE2 = new RegExp(String.raw`^Event\s+(${ID})`, "i");
1251
1552
  var CONST_RE3 = /^Const\s+(\S.*)$/i;
1252
1553
  var DIM_RE = /^Dim\s+(\S.*)$/i;
@@ -1575,7 +1876,7 @@ function extractVb(content, filePath) {
1575
1876
  else open(keyword, name, procedureKind(), stmt);
1576
1877
  continue;
1577
1878
  }
1578
- if ((m = OPERATOR_RE.exec(rest)) !== null) {
1879
+ if ((m = OPERATOR_RE2.exec(rest)) !== null) {
1579
1880
  open("operator", m[1], "method", stmt);
1580
1881
  continue;
1581
1882
  }
@@ -1800,6 +2101,16 @@ function extractVhdl(content, filePath) {
1800
2101
 
1801
2102
  // src/languages/elixir.ts
1802
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
+ }
1803
2114
  function nearestDefName(stack) {
1804
2115
  for (let i = stack.length - 1; i >= 0; i--) {
1805
2116
  const frame = stack[i];
@@ -1819,6 +2130,30 @@ function extractElixir(content, filePath) {
1819
2130
  const lines = content.split(/\r?\n/);
1820
2131
  const moduleStack = [];
1821
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
+ };
1822
2157
  for (let i = 0; i < lines.length; i++) {
1823
2158
  const rawLine = lines[i] ?? "";
1824
2159
  const lineNum = i + 1;
@@ -1826,9 +2161,37 @@ function extractElixir(content, filePath) {
1826
2161
  mlState = nextMlState;
1827
2162
  const line = stripLineComment(masked, ["#"]).trimEnd();
1828
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
+ }
1829
2174
  if (!stripped) {
1830
2175
  continue;
1831
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
+ }
1832
2195
  const opensDoBlock = /\bdo\s*$/.test(stripped);
1833
2196
  const opensFnBlock = /\bfn\b/.test(stripped) && !/\bend\b/.test(stripped) && /(?:fn|->)\s*$/.test(stripped);
1834
2197
  const modM = MODULE_RE.exec(stripped);
@@ -1865,9 +2228,7 @@ function extractElixir(content, filePath) {
1865
2228
  } else {
1866
2229
  symbols.push(makeLineSymbol(filePath, fname, "function", lineNum, stripped.slice(0, 200), void 0, lines, "hash"));
1867
2230
  }
1868
- if (opensDoBlock) {
1869
- moduleStack.push({ name: fname, endKeywordNeeded: true, isBlock: false, symbolIndex: symbols.length - 1 });
1870
- }
2231
+ settleDefHead(fname, stripped);
1871
2232
  continue;
1872
2233
  }
1873
2234
  const pfm = PRIVATE_FUNC_RE.exec(stripped);
@@ -1879,9 +2240,7 @@ function extractElixir(content, filePath) {
1879
2240
  } else {
1880
2241
  symbols.push(makeLineSymbol(filePath, fname, "function", lineNum, stripped.slice(0, 200), void 0, lines, "hash"));
1881
2242
  }
1882
- if (opensDoBlock) {
1883
- moduleStack.push({ name: fname, endKeywordNeeded: true, isBlock: false, symbolIndex: symbols.length - 1 });
1884
- }
2243
+ settleDefHead(fname, stripped);
1885
2244
  continue;
1886
2245
  }
1887
2246
  if (STRUCT_RE.test(stripped)) {
@@ -1912,12 +2271,14 @@ function extractElixir(content, filePath) {
1912
2271
 
1913
2272
  // src/languages/dart.ts
1914
2273
  init_define_import_meta_env();
2274
+ var DART_STRIP = { tripleQuotes: true, singleQuoteHoles: true };
1915
2275
  var CLASS_RE4 = /^(?:(?:abstract|base|interface|final|sealed|mixin)\s+)*class\s+([A-Za-z_][A-Za-z0-9_]*)/;
1916
2276
  var ENUM_RE2 = /^enum\s+([A-Za-z_][A-Za-z0-9_]*)/;
1917
2277
  var MIXIN_RE = /^(?:base\s+)?mixin\s+([A-Za-z_][A-Za-z0-9_]*)/;
1918
2278
  var EXTENSION_RE = new RegExp("^extension\\s+(?:([A-Za-z_][A-Za-z0-9_]*)\\s*(?:" + GENERIC_CLAUSE + ")?\\s+)?on\\s+");
1919
2279
  var EXTENSION_TYPE_RE = /^extension\s+type\s+([A-Za-z_][A-Za-z0-9_]*)/;
1920
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*\(/;
1921
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_]*)/;
1922
2283
  var NAMED_CTOR_RE = /^(?:(?:const|factory|external)\s+)*([A-Za-z_][A-Za-z0-9_]*)\.([A-Za-z_][A-Za-z0-9_]*)\s*\(/;
1923
2284
  var UNNAMED_CTOR_RE = /^(?:(?:const|factory|external)\s+)*([A-Za-z_][A-Za-z0-9_]*)\s*\(/;
@@ -1947,11 +2308,11 @@ function extractDart(content, filePath) {
1947
2308
  const line = stripLineComment(blockStripped).trimEnd();
1948
2309
  const stripped = line.trim();
1949
2310
  if (!stripped) {
1950
- const braceLine2 = stripStringLiterals(line, { tripleQuotes: true });
2311
+ const braceLine2 = stripStringLiterals(line, DART_STRIP);
1951
2312
  braceDepth += (braceLine2.match(/\{/g) ?? []).length - (braceLine2.match(/\}/g) ?? []).length;
1952
2313
  continue;
1953
2314
  }
1954
- const structural = stripStringLiterals(stripped, { tripleQuotes: true });
2315
+ const structural = stripStringLiterals(stripped, DART_STRIP);
1955
2316
  const isIndented = line[0] === " " || line[0] === " ";
1956
2317
  const outerFrame = typeStack.length > 0 ? typeStack[typeStack.length - 1] : null;
1957
2318
  const outerDepthInType = outerFrame !== null ? braceDepth - outerFrame.startDepth : 0;
@@ -2026,6 +2387,11 @@ function extractDart(content, filePath) {
2026
2387
  if (!member && FIELD_START_RE.test(stripped)) {
2027
2388
  member = true;
2028
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
+ }
2029
2395
  const gm = !member ? GETTER_RE.exec(stripped) : null;
2030
2396
  if (gm) {
2031
2397
  symbols.push(makeLineSymbol(filePath, gm[1] ?? "", "function", lineNum, stripped.slice(0, 200), frame.name, lines, "c"));
@@ -2050,7 +2416,7 @@ function extractDart(content, filePath) {
2050
2416
  symbols.push(makeLineSymbol(filePath, fname, "function", lineNum, stripped.slice(0, 200), void 0, lines, "c"));
2051
2417
  }
2052
2418
  }
2053
- const braceLine = stripStringLiterals(line, { tripleQuotes: true });
2419
+ const braceLine = stripStringLiterals(line, DART_STRIP);
2054
2420
  for (const ch of braceLine) {
2055
2421
  if (ch === "{") {
2056
2422
  braceDepth++;
@@ -2467,7 +2833,7 @@ var DOMAIN_RE = makeCreateRe("DOMAIN");
2467
2833
  var AGGREGATE_RE = makeCreateRe("AGGREGATE", OR_REPLACE);
2468
2834
  var POLICY_RE = makeCreateRe("POLICY");
2469
2835
  var RULE_RE = makeCreateRe("RULE", OR_REPLACE);
2470
- var OPERATOR_RE2 = makeCreateRe("OPERATOR(?!\\s+(?:CLASS|FAMILY)\\b)", OR_REPLACE);
2836
+ var OPERATOR_RE4 = makeCreateRe("OPERATOR(?!\\s+(?:CLASS|FAMILY)\\b)", OR_REPLACE);
2471
2837
  var SYNONYM_RE = makeCreateRe("SYNONYM", `${OR_REPLACE}(?:PUBLIC\\s+)?`);
2472
2838
  var DATABASE_LINK_RE = makeCreateRe("DATABASE\\s+LINK", "(?:PUBLIC\\s+)?");
2473
2839
  var CLUSTER_RE = makeCreateRe("CLUSTER");
@@ -2493,7 +2859,7 @@ var PATTERNS = [
2493
2859
  [AGGREGATE_RE, "sql_aggregate"],
2494
2860
  [POLICY_RE, "sql_policy"],
2495
2861
  [RULE_RE, "sql_rule"],
2496
- [OPERATOR_RE2, "sql_operator"],
2862
+ [OPERATOR_RE4, "sql_operator"],
2497
2863
  [SYNONYM_RE, "sql_synonym"],
2498
2864
  [DATABASE_LINK_RE, "sql_database_link"],
2499
2865
  [CLUSTER_RE, "sql_cluster"],
@@ -2785,6 +3151,26 @@ function plsqlStructure(noStrings, lineIndex, units, createStarts, filePath, roo
2785
3151
  }
2786
3152
  return { ends, children };
2787
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
+ }
2788
3174
  function extractSql(content, filePath) {
2789
3175
  const symbols = [];
2790
3176
  const sections = [];
@@ -2806,8 +3192,8 @@ function extractSql(content, filePath) {
2806
3192
  const line = offsetToLine(lineIndex, m.index ?? 0);
2807
3193
  createStarts.push(m.index ?? 0);
2808
3194
  const semiIdx = findStatementTerminator(noStrings, m.index ?? 0);
2809
- if (semiIdx !== -1 && offsetToLine(lineIndex, semiIdx) === line) {
2810
- 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));
2811
3197
  } else if (PLSQL_UNIT_KINDS.has(kind)) {
2812
3198
  units.push({ name, kind, index: m.index ?? 0, matchEnd: (m.index ?? 0) + m[0].length, line });
2813
3199
  }
@@ -2821,10 +3207,13 @@ function extractSql(content, filePath) {
2821
3207
  sections.sort((a, b) => a.line - b.line);
2822
3208
  symbols.sort((a, b) => a.lineStart - b.lineStart);
2823
3209
  assignFlatEndLines(sections, totalLines);
3210
+ const noLines = noStrings.split("\n");
2824
3211
  const pinned = propagateEndLinesToSymbols(symbols, sections).map((sym) => {
2825
3212
  const key = `${sym.name}\0${sym.kind}\0${sym.lineStart}`;
2826
- const pinnedEndLine = singleLineEndLines.get(key) ?? plsql.ends.get(key);
2827
- 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;
2828
3217
  });
2829
3218
  if (plsql.children.length === 0) return pinned;
2830
3219
  return [...pinned, ...plsql.children].sort((a, b) => a.lineStart - b.lineStart);
@@ -3052,6 +3441,103 @@ var FUNC_NAME = "[A-Za-z_][A-Za-z0-9_.+:-]*";
3052
3441
  var FUNC_KEYWORD_RE = new RegExp(`^function\\s+(${FUNC_NAME})\\s*(?:\\(\\s*\\))?`);
3053
3442
  var FUNC_POSIX_RE = new RegExp(`^(${FUNC_NAME})\\s*\\(\\s*\\)`);
3054
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
+ }
3055
3541
  function stripBashComment(line) {
3056
3542
  for (let i = 0; i < line.length; i++) {
3057
3543
  if (line[i] !== "#") continue;
@@ -3110,6 +3596,7 @@ function extractBash(content, filePath) {
3110
3596
  let awaitingFunctionBrace = false;
3111
3597
  let openFunctionIndex = null;
3112
3598
  let openHeadingIndex = null;
3599
+ let skipUntil = 0;
3113
3600
  for (let i = 0; i < lines.length; i++) {
3114
3601
  const rawLine = lines[i] ?? "";
3115
3602
  const lineNum = i + 1;
@@ -3117,7 +3604,7 @@ function extractBash(content, filePath) {
3117
3604
  if (rawLine.trim() === heredocs[0]) heredocs.shift();
3118
3605
  continue;
3119
3606
  }
3120
- if (!inFunction && braceDepth === 0) {
3607
+ if (!inFunction && braceDepth === 0 && lineNum > skipUntil) {
3121
3608
  const banner = extractShellBannerHeading(rawLine);
3122
3609
  if (banner !== null) {
3123
3610
  if (openHeadingIndex !== null) {
@@ -3152,6 +3639,7 @@ function extractBash(content, filePath) {
3152
3639
  const opened = findHeredocOpeners(noComment, arithmeticDepth);
3153
3640
  arithmeticDepth = opened.depth;
3154
3641
  heredocs.push(...opened.terminators);
3642
+ if (lineNum <= skipUntil) continue;
3155
3643
  if (!stripped) continue;
3156
3644
  if (!inFunction && !awaitingFunctionBrace && braceDepth === 0) {
3157
3645
  const kwMatch = FUNC_KEYWORD_RE.exec(stripped);
@@ -3175,7 +3663,18 @@ function extractBash(content, filePath) {
3175
3663
  pushedIndex = symbols.length;
3176
3664
  symbols.push(makeLineSymbol(filePath, fname, "function", lineNum, stripped.slice(0, 200), void 0, lines, "hash"));
3177
3665
  }
3178
- 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) {
3179
3678
  if (stripped.includes("{")) {
3180
3679
  const braceLine2 = stripStringLiterals(stripped);
3181
3680
  const openCount = (braceLine2.match(/\{/g) ?? []).length;
@@ -3289,7 +3788,7 @@ function maskContinuationAndDefines(text) {
3289
3788
  }
3290
3789
  return { noContinuation: contLines.join("\n"), forTargets: targetLines.join("\n") };
3291
3790
  }
3292
- 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;
3293
3792
  var DEFINE_RE2 = /^ *(?:(?:override|export|private)\s+)*define\s+([\w./%$()-]+)/gm;
3294
3793
  var SPECIAL_TARGETS = /* @__PURE__ */ new Set([
3295
3794
  ".PHONY",
@@ -4444,10 +4943,30 @@ function blankJsStringLiterals(content) {
4444
4943
  var FUNC_DECL_RE = /^(?:export\s+)?(?:default\s+)?(?:async\s+)?function\s*\*?\s+([A-Za-z_$][\w$]*)/;
4445
4944
  var CONST_DECL_RE = /^(?:export\s+)?const\s+([A-Za-z_$][\w$]*)\s*[:=]/;
4446
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
+ }
4447
4965
  function extractTopLevelDeclarations(scriptContent, filePath, startLine) {
4448
4966
  const symbols = [];
4449
4967
  const commentFree = stripJsComments(scriptContent);
4450
4968
  const lines = blankJsStringLiterals(commentFree).split("\n");
4969
+ const rawLines = scriptContent.split("\n");
4451
4970
  let depth = 0;
4452
4971
  for (let i = 0; i < lines.length; i++) {
4453
4972
  const rawLine = lines[i] ?? "";
@@ -4455,16 +4974,14 @@ function extractTopLevelDeclarations(scriptContent, filePath, startLine) {
4455
4974
  if (depth === 0 && trimmed) {
4456
4975
  const line = startLine + i;
4457
4976
  const fm = FUNC_DECL_RE.exec(trimmed);
4458
- if (fm?.[1]) {
4459
- symbols.push(makeLineSymbol(filePath, fm[1], "sfc_script_function", line));
4460
- } else {
4461
- const cm = CONST_DECL_RE.exec(trimmed);
4462
- if (cm?.[1]) {
4463
- symbols.push(makeLineSymbol(filePath, cm[1], "sfc_script_const", line));
4464
- } else {
4465
- const clm = CLASS_DECL_RE.exec(trimmed);
4466
- if (clm?.[1]) symbols.push(makeLineSymbol(filePath, clm[1], "sfc_script_class", line));
4467
- }
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);
4468
4985
  }
4469
4986
  }
4470
4987
  depth += (rawLine.match(/\{/g) ?? []).length - (rawLine.match(/\}/g) ?? []).length;
@@ -5398,6 +5915,16 @@ function readToken4(masked, i) {
5398
5915
  if (p === start) return void 0;
5399
5916
  return { word: masked.slice(start, p), start, end: p };
5400
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
+ }
5401
5928
  function extractClojure(content, filePath) {
5402
5929
  if (content.includes("\0")) return { symbols: [], imports: [] };
5403
5930
  const rawLines = content.split(/\r?\n/);
@@ -5418,7 +5945,7 @@ function extractClojure(content, filePath) {
5418
5945
  if (tok !== void 0) {
5419
5946
  const kind = DEFINERS4.get(tok.word.toLowerCase());
5420
5947
  if (kind !== void 0) {
5421
- const nameTok = readToken4(masked, tok.end);
5948
+ const nameTok = readNameToken(masked, tok.end);
5422
5949
  const name = nameTok?.word.replace(/^:+/, "") ?? "";
5423
5950
  const idx = spans.open(name, kind, lineOf(i), owner());
5424
5951
  stack.push({ index: idx, depth });
@@ -5725,7 +6252,7 @@ function afterContext(rest) {
5725
6252
  const arrow = rest.indexOf("=>");
5726
6253
  return (arrow >= 0 ? rest.slice(arrow + 2) : rest).trimStart();
5727
6254
  }
5728
- function classify(line) {
6255
+ function classify(line, continued = false) {
5729
6256
  let m;
5730
6257
  if (m = /^module\s+([A-Za-z_][A-Za-z0-9_.']*)/.exec(line)) return [{ kind: "module", name: m[1] }];
5731
6258
  if (m = /^(?:data|newtype)\s+(?:instance\s+)?([A-Z][A-Za-z0-9_']*)/.exec(line)) return [{ kind: "type", name: m[1] }];
@@ -5745,11 +6272,11 @@ function classify(line) {
5745
6272
  if (m = /^\(([^()]+)\)\s*::/.exec(line)) return [{ kind: "function", name: m[1].trim() }];
5746
6273
  if (m = /^([a-z_][A-Za-z0-9_']*)\b/.exec(line)) {
5747
6274
  const name = m[1];
5748
- if (!RESERVED_TOP.has(name) && hasTopLevelEquals(line)) return [{ kind: "function", name }];
6275
+ if (!RESERVED_TOP.has(name) && (continued || hasTopLevelEquals(line))) return [{ kind: "function", name }];
5749
6276
  return void 0;
5750
6277
  }
5751
6278
  if (m = /^\(([^()]+)\)/.exec(line)) {
5752
- if (hasTopLevelEquals(line)) return [{ kind: "function", name: m[1].trim() }];
6279
+ if (continued || hasTopLevelEquals(line)) return [{ kind: "function", name: m[1].trim() }];
5753
6280
  }
5754
6281
  return void 0;
5755
6282
  }
@@ -5758,7 +6285,15 @@ function extractHaskell(content, filePath) {
5758
6285
  const rawLines = content.split(/\r?\n/);
5759
6286
  const masked = maskHaskell(content);
5760
6287
  const maskedLines = masked.split(/\r?\n/);
5761
- 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
+ };
5762
6297
  const boundaries = [];
5763
6298
  for (let idx = 0; idx < n; idx++) {
5764
6299
  const raw = rawLines[idx] ?? "";
@@ -5766,7 +6301,7 @@ function extractHaskell(content, filePath) {
5766
6301
  const maskedLine = maskedLines[idx] ?? "";
5767
6302
  const trimmed = maskedLine.trim();
5768
6303
  if (trimmed === "") continue;
5769
- const defs = classify(trimmed);
6304
+ const defs = classify(trimmed) ?? classify(trimmed, headContinues(idx));
5770
6305
  if (defs === void 0) {
5771
6306
  boundaries.push({ num: idx + 1, consumed: false });
5772
6307
  continue;
@@ -5783,6 +6318,17 @@ function extractHaskell(content, filePath) {
5783
6318
  boundaries[endIdx + 1].consumed = true;
5784
6319
  endIdx++;
5785
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
+ }
5786
6332
  }
5787
6333
  const next = boundaries[endIdx + 1];
5788
6334
  const lineEnd = Math.max(b.num, next !== void 0 ? next.num - 1 : n);
@@ -5932,7 +6478,7 @@ function extractOcaml(content, filePath) {
5932
6478
  const rawLines = content.split(/\r?\n/);
5933
6479
  const masked = maskOcaml(content);
5934
6480
  const maskedLines = masked.split(/\r?\n/);
5935
- const n = rawLines.length;
6481
+ const n = rawLines.length > 1 && rawLines[rawLines.length - 1] === "" ? rawLines.length - 1 : rawLines.length;
5936
6482
  const boundaries = [];
5937
6483
  for (let idx = 0; idx < n; idx++) {
5938
6484
  const raw = rawLines[idx] ?? "";
@@ -5940,6 +6486,7 @@ function extractOcaml(content, filePath) {
5940
6486
  const maskedLine = maskedLines[idx] ?? "";
5941
6487
  const trimmed = maskedLine.trim();
5942
6488
  if (trimmed === "") continue;
6489
+ if (/^end\b/.test(trimmed)) continue;
5943
6490
  const def = classify2(trimmed);
5944
6491
  boundaries.push(def === void 0 ? { num: idx + 1 } : { num: idx + 1, def });
5945
6492
  }
@@ -6294,7 +6841,7 @@ function sectionsToHeadingSymbols(sections, filePath) {
6294
6841
  }));
6295
6842
  }
6296
6843
  var ADAPTER_EXTRACTORS = {
6297
- 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" }),
6298
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.
6299
6846
  php: (content, filePath) => {
6300
6847
  const code = maskPhpInlineHtml(content);
@@ -6335,13 +6882,13 @@ var ADAPTER_EXTRACTORS = {
6335
6882
  const r = extractTwig(content, filePath);
6336
6883
  return [...r.symbols, ...sectionsToHeadingSymbols(r.sections, filePath)];
6337
6884
  },
6338
- kotlin: (content, filePath) => assignBraceBlockSpans(extractKotlin(content, filePath).symbols, content, { lineComment: "//", nestedBlockComments: true, tripleQuote: true, tripleQuoteRunClose: "last" }),
6339
- swift: (content, filePath) => assignBraceBlockSpans(extractSwift(content, filePath).symbols, content, { lineComment: "//", nestedBlockComments: true, tripleQuote: true, tripleQuoteRunClose: "last", multilineLang: "swift" }),
6340
- 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" }),
6341
6888
  lua: (content, filePath) => extractLua(content, filePath).symbols,
6342
6889
  vb: (content, filePath) => extractVb(content, filePath).symbols,
6343
6890
  elixir: (content, filePath) => extractElixir(content, filePath).symbols,
6344
- 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" }),
6345
6892
  zig: (content, filePath) => assignBraceBlockSpans(extractZig(content, filePath).symbols, content, { lineComment: "//", blockComment: null, lineStringPrefix: "\\\\" }),
6346
6893
  r: (content, filePath) => extractR(content, filePath).symbols,
6347
6894
  graphql: (content, filePath) => extractGraphql(content, filePath).symbols,
@@ -6393,8 +6940,10 @@ var ADAPTER_EXTRACTORS = {
6393
6940
  };
6394
6941
  export {
6395
6942
  ADAPTER_EXTRACTORS,
6943
+ assignBraceBlockSpans,
6396
6944
  extractAstro,
6397
6945
  extractCobol,
6946
+ extractCsharp,
6398
6947
  extractNatural,
6399
6948
  extractSalesforceMetadata,
6400
6949
  extractSvelte,