token-goat 2.9.13 → 2.9.15

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 (52) hide show
  1. package/README.md +28 -1
  2. package/dist/token-goat-chunk-2X2EBBC6.mjs +277 -0
  3. package/dist/token-goat-chunk-3BTK54F3.mjs +1733 -0
  4. package/dist/token-goat-chunk-3NSDDTGL.mjs +34 -0
  5. package/dist/token-goat-chunk-4EXFN2AW.mjs +29 -0
  6. package/dist/token-goat-chunk-5V7DAC7V.mjs +123 -0
  7. package/dist/token-goat-chunk-6DLVZDB6.mjs +34 -0
  8. package/dist/token-goat-chunk-7ZYK25AO.mjs +24 -0
  9. package/dist/token-goat-chunk-A4JYKD5H.mjs +144 -0
  10. package/dist/token-goat-chunk-AH6QILZM.mjs +26 -0
  11. package/dist/token-goat-chunk-ASYEPR3S.mjs +212 -0
  12. package/dist/{token-goat-chunk-RDITECDL.mjs → token-goat-chunk-ATIFTMRC.mjs} +31 -13
  13. package/dist/{token-goat-chunk-ZZI3IDQZ.mjs → token-goat-chunk-BL5LNGBG.mjs} +3935 -11949
  14. package/dist/{token-goat-chunk-4NXUKV7D.mjs → token-goat-chunk-C5JIO6HK.mjs} +8 -4
  15. package/dist/{token-goat-chunk-FZU7GMUS.mjs → token-goat-chunk-DQ4J5AFF.mjs} +50 -18
  16. package/dist/token-goat-chunk-ERTXEKB6.mjs +228 -0
  17. package/dist/{token-goat-chunk-6B44WLIF.mjs → token-goat-chunk-GIIHUSZX.mjs} +142 -21
  18. package/dist/token-goat-chunk-GMOUBOX4.mjs +386 -0
  19. package/dist/{token-goat-chunk-3ESRORNM.mjs → token-goat-chunk-GMQQA7E4.mjs} +12576 -12326
  20. package/dist/token-goat-chunk-IVUQLQWN.mjs +2046 -0
  21. package/dist/token-goat-chunk-K7F2BFIK.mjs +2430 -0
  22. package/dist/{token-goat-chunk-U7X6LQD2.mjs → token-goat-chunk-LCZBPOIN.mjs} +10197 -9717
  23. package/dist/token-goat-chunk-LMFO66YD.mjs +331 -0
  24. package/dist/token-goat-chunk-LT7JRU6K.mjs +22 -0
  25. package/dist/token-goat-chunk-MZDIJJ3R.mjs +420 -0
  26. package/dist/token-goat-chunk-NDPO7GAH.mjs +177 -0
  27. package/dist/token-goat-chunk-NDRP4KJQ.mjs +4371 -0
  28. package/dist/token-goat-chunk-NEI4NC54.mjs +424 -0
  29. package/dist/token-goat-chunk-NU7TLMQK.mjs +585 -0
  30. package/dist/token-goat-chunk-OSUFN2FV.mjs +326 -0
  31. package/dist/token-goat-chunk-OUGNPMDA.mjs +959 -0
  32. package/dist/token-goat-chunk-PM76YS22.mjs +1341 -0
  33. package/dist/token-goat-chunk-S4XRY446.mjs +2637 -0
  34. package/dist/{token-goat-chunk-YOA4N6WA.mjs → token-goat-chunk-SFAS46RE.mjs} +5 -3
  35. package/dist/{token-goat-chunk-QWSUZWFP.mjs → token-goat-chunk-SZWYESBS.mjs} +793 -650
  36. package/dist/{token-goat-chunk-B3CTCQTH.mjs → token-goat-chunk-XEPXYDPI.mjs} +3 -2
  37. package/dist/token-goat-chunk-XTQAOTSO.mjs +89 -0
  38. package/dist/token-goat-chunk-Y4AFKTHK.mjs +22 -0
  39. package/dist/token-goat-chunk-YKG35VHC.mjs +228 -0
  40. package/dist/{token-goat-chunk-JOXLE672.mjs → token-goat-chunk-YQ7WI2CO.mjs} +990 -106
  41. package/dist/{token-goat-chunk-2WC4ZUXN.mjs → token-goat-chunk-YZX7EFG4.mjs} +1 -1
  42. package/dist/token-goat-chunk-Z6UXPYJA.mjs +62 -0
  43. package/dist/token-goat-hook.mjs +16 -8
  44. package/dist/token-goat.core.mjs +27 -10
  45. package/docs/cli.md +9 -6
  46. package/package.json +4 -2
  47. package/dist/token-goat-chunk-FQCNJV4V.mjs +0 -693
  48. package/dist/token-goat-chunk-JVNPCQB7.mjs +0 -31
  49. package/dist/token-goat-chunk-P2PU4CR5.mjs +0 -26
  50. package/dist/token-goat-chunk-QKXBGBQR.mjs +0 -3653
  51. package/dist/token-goat-chunk-UM47DRD3.mjs +0 -242
  52. package/dist/token-goat-chunk-UMXJN7DI.mjs +0 -5521
@@ -25,13 +25,17 @@ import {
25
25
  extractSwift,
26
26
  extractThrift,
27
27
  extractWgsl
28
- } from "./token-goat-chunk-B3CTCQTH.mjs";
28
+ } from "./token-goat-chunk-XEPXYDPI.mjs";
29
29
  import {
30
+ extractShellBannerHeading
31
+ } from "./token-goat-chunk-NDRP4KJQ.mjs";
32
+ import "./token-goat-chunk-2X2EBBC6.mjs";
33
+ import "./token-goat-chunk-Y4AFKTHK.mjs";
34
+ import {
35
+ GENERIC_CLAUSE,
30
36
  assignBraceBlockSpans,
31
37
  assignFlatEndLines,
32
38
  buildLineIndex,
33
- countContentLines,
34
- escapeRegExp,
35
39
  extractEnv,
36
40
  extractIni,
37
41
  findHtmlHeadingMatches,
@@ -46,7 +50,6 @@ import {
46
50
  offsetToLine,
47
51
  precedingDocComment,
48
52
  propagateEndLinesToSymbols,
49
- pushAll,
50
53
  scanQuotedStringEnd,
51
54
  stripBlockCommentSpan,
52
55
  stripCstyleComments,
@@ -56,7 +59,17 @@ import {
56
59
  stripMultilineStringSpan,
57
60
  stripStringLiterals,
58
61
  stripXmlComments
59
- } from "./token-goat-chunk-QKXBGBQR.mjs";
62
+ } from "./token-goat-chunk-K7F2BFIK.mjs";
63
+ import "./token-goat-chunk-S4XRY446.mjs";
64
+ import "./token-goat-chunk-EEIDFMEM.mjs";
65
+ import "./token-goat-chunk-OSUFN2FV.mjs";
66
+ import {
67
+ countContentLines,
68
+ escapeRegExp,
69
+ pushAll
70
+ } from "./token-goat-chunk-PM76YS22.mjs";
71
+ import "./token-goat-chunk-ERTXEKB6.mjs";
72
+ import "./token-goat-chunk-GMOUBOX4.mjs";
60
73
  import {
61
74
  init_define_import_meta_env
62
75
  } from "./token-goat-chunk-A37V4PBF.mjs";
@@ -306,6 +319,7 @@ function extractPhp(content, filePath) {
306
319
  const lines = maskPhpInlineHtml(content).split(/\r?\n/);
307
320
  const contextStack = [];
308
321
  let braceDepth = 0;
322
+ let parenDepth = 0;
309
323
  let inComment = false;
310
324
  let mlState = null;
311
325
  for (let i = 0; i < lines.length; i++) {
@@ -321,11 +335,17 @@ function extractPhp(content, filePath) {
321
335
  inComment = nextInComment;
322
336
  const line = codeLine.trimEnd();
323
337
  const stripped = line.trimStart();
324
- if (!stripped || stripped.startsWith("//") || stripped.startsWith("#")) continue;
325
- const braceLine = stripStringLiterals(stripLineComment(line, ["//", "#"]));
338
+ const attrOpen = stripped.startsWith("#[");
339
+ if (!stripped || stripped.startsWith("//") || stripped.startsWith("#") && !attrOpen) continue;
340
+ const commentFrom = attrOpen ? line.indexOf("#[") + 2 : 0;
341
+ const braceLine = stripStringLiterals(line.slice(0, commentFrom) + stripLineComment(line.slice(commentFrom), ["//", "#"]));
326
342
  const openB = (braceLine.match(/\{/g) ?? []).length;
327
343
  const closeB = (braceLine.match(/\}/g) ?? []).length;
328
344
  braceDepth += openB - closeB;
345
+ const preLineParenDepth = parenDepth;
346
+ const openP = (braceLine.match(/\(/g) ?? []).length;
347
+ const closeP = (braceLine.match(/\)/g) ?? []).length;
348
+ parenDepth = Math.max(0, parenDepth + openP - closeP);
329
349
  const topFrame = contextStack.length > 0 ? contextStack[contextStack.length - 1] : void 0;
330
350
  if (topFrame !== void 0 && braceDepth > topFrame[1]) {
331
351
  topFrame[2] = true;
@@ -408,7 +428,7 @@ function extractPhp(content, filePath) {
408
428
  const name = propM[1] ?? "";
409
429
  const preLineDepth = braceDepth - openB + closeB;
410
430
  const topFrame2 = contextStack.length > 0 ? contextStack[contextStack.length - 1] : void 0;
411
- if (topFrame2 !== void 0 && preLineDepth === topFrame2[1] + 1) {
431
+ if (topFrame2 !== void 0 && preLineDepth === topFrame2[1] + 1 && preLineParenDepth === 0) {
412
432
  symbols.push(makeLineSymbol(filePath, name, "var", lineNum, stripped.slice(0, 200), topFrame2[0], lines, "c"));
413
433
  }
414
434
  continue;
@@ -631,7 +651,7 @@ function unquoteName(name) {
631
651
  return name.length >= 2 && name.startsWith("`") && name.endsWith("`") ? name.slice(1, -1) : name;
632
652
  }
633
653
  var FUN_RE = new RegExp(
634
- "^\\s*(?:(?:public|internal|protected|private|open|override|abstract|suspend|inline|infix|operator|external|actual|expect|final|sealed|tailrec)\\s+)*fun\\s+(?:<[^>]*>\\s*)?" + RECEIVER_RE + "(" + NAME_RE + ")\\s*[(<]"
654
+ "^\\s*(?:(?:public|internal|protected|private|open|override|abstract|suspend|inline|infix|operator|external|actual|expect|final|sealed|tailrec)\\s+)*fun\\s+(?:" + GENERIC_CLAUSE + "\\s*)?" + RECEIVER_RE + "(" + NAME_RE + ")\\s*[(<]"
635
655
  );
636
656
  var CONST_RE2 = new RegExp(
637
657
  "^\\s*(?:(?:public|internal|protected|private|open|override|abstract|final|actual|expect|const|lateinit|companion|external|inline)\\s+)*(?:const\\s+)?val\\s+([A-Z_][A-Z0-9_]*)\\s*(?::|=)"
@@ -643,10 +663,10 @@ var COMPANION_RE = new RegExp(
643
663
  "^(?:(?:public|internal|protected|private)\\s+)*companion\\s+object\\b(?:\\s+(" + NAME_RE + "))?"
644
664
  );
645
665
  var TYPEALIAS_RE = new RegExp(
646
- "^(?:(?:public|internal|private|actual|expect)\\s+)*typealias\\s+(" + NAME_RE + ")(?:\\s*<[^>]*>)?\\s*="
666
+ "^(?:(?:public|internal|private|actual|expect)\\s+)*typealias\\s+(" + NAME_RE + ")(?:\\s*" + GENERIC_CLAUSE + ")?\\s*="
647
667
  );
648
668
  var TOP_FUN_RE = new RegExp(
649
- "^(?:(?:public|internal|private|suspend|inline|infix|operator|external|actual|expect|tailrec)\\s+)*fun\\s+(?:<[^>]*>\\s*)?" + RECEIVER_RE + "(" + NAME_RE + ")\\s*[(<]"
669
+ "^(?:(?:public|internal|private|suspend|inline|infix|operator|external|actual|expect|tailrec)\\s+)*fun\\s+(?:" + GENERIC_CLAUSE + "\\s*)?" + RECEIVER_RE + "(" + NAME_RE + ")\\s*[(<]"
650
670
  );
651
671
  function extractKotlin(content, filePath) {
652
672
  const symbols = [];
@@ -1812,16 +1832,16 @@ init_define_import_meta_env();
1812
1832
  var CLASS_RE4 = /^(?:(?:abstract|base|interface|final|sealed|mixin)\s+)*class\s+([A-Za-z_][A-Za-z0-9_]*)/;
1813
1833
  var ENUM_RE2 = /^enum\s+([A-Za-z_][A-Za-z0-9_]*)/;
1814
1834
  var MIXIN_RE = /^(?:base\s+)?mixin\s+([A-Za-z_][A-Za-z0-9_]*)/;
1815
- var EXTENSION_RE = /^extension\s+(?:([A-Za-z_][A-Za-z0-9_]*)\s*(?:<[^>]*>)?\s+)?on\s+/;
1835
+ var EXTENSION_RE = new RegExp("^extension\\s+(?:([A-Za-z_][A-Za-z0-9_]*)\\s*(?:" + GENERIC_CLAUSE + ")?\\s+)?on\\s+");
1816
1836
  var EXTENSION_TYPE_RE = /^extension\s+type\s+([A-Za-z_][A-Za-z0-9_]*)/;
1817
- var FUNC_RE5 = /(?:^|\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*(?:<[^>]*>)?\s*\(/;
1818
- 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_]*)/;
1837
+ 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*\\(");
1838
+ 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_]*)/;
1819
1839
  var NAMED_CTOR_RE = /^(?:(?:const|factory|external)\s+)*([A-Za-z_][A-Za-z0-9_]*)\.([A-Za-z_][A-Za-z0-9_]*)\s*\(/;
1820
1840
  var UNNAMED_CTOR_RE = /^(?:(?:const|factory|external)\s+)*([A-Za-z_][A-Za-z0-9_]*)\s*\(/;
1821
1841
  var FIELD_START_RE = /^(?:(?:static|covariant|late|external)\s+)*(?:final|var|const)\s/;
1822
- var CLASS_ALIAS_RE = /^(?:(?:abstract|base|interface|final|sealed|mixin)\s+)*class\s+[A-Za-z_][A-Za-z0-9_]*(?:<[^>]*>)?\s*=/;
1823
- var TYPEDEF_RE = /^typedef\s+([A-Za-z_][A-Za-z0-9_]*)(?:\s*<[^>]*>)?\s*=/;
1824
- var TYPEDEF_LEGACY_RE = /^typedef\s+[A-Za-z_][A-Za-z0-9_<>,?]*\s+([A-Za-z_][A-Za-z0-9_]*)(?:\s*<[^>]*>)?\s*\(/;
1842
+ var CLASS_ALIAS_RE = new RegExp("^(?:(?:abstract|base|interface|final|sealed|mixin)\\s+)*class\\s+[A-Za-z_][A-Za-z0-9_]*(?:" + GENERIC_CLAUSE + ")?\\s*=");
1843
+ var TYPEDEF_RE = new RegExp("^typedef\\s+([A-Za-z_][A-Za-z0-9_]*)(?:\\s*" + GENERIC_CLAUSE + ")?\\s*=");
1844
+ var TYPEDEF_LEGACY_RE = new RegExp("^typedef\\s+[A-Za-z_][A-Za-z0-9_<>,?]*\\s+([A-Za-z_][A-Za-z0-9_]*)(?:\\s*" + GENERIC_CLAUSE + ")?\\s*\\(");
1825
1845
  function extractDart(content, filePath) {
1826
1846
  const symbols = [];
1827
1847
  const imports = [];
@@ -1848,6 +1868,7 @@ function extractDart(content, filePath) {
1848
1868
  braceDepth += (braceLine2.match(/\{/g) ?? []).length - (braceLine2.match(/\}/g) ?? []).length;
1849
1869
  continue;
1850
1870
  }
1871
+ const structural = stripStringLiterals(stripped, { tripleQuotes: true });
1851
1872
  const isIndented = line[0] === " " || line[0] === " ";
1852
1873
  const outerFrame = typeStack.length > 0 ? typeStack[typeStack.length - 1] : null;
1853
1874
  const outerDepthInType = outerFrame !== null ? braceDepth - outerFrame.startDepth : 0;
@@ -1859,7 +1880,8 @@ function extractDart(content, filePath) {
1859
1880
  const cname = cm[1] ?? "";
1860
1881
  const parent = typeStack.length > 0 ? typeStack[typeStack.length - 1].name : void 0;
1861
1882
  symbols.push(makeLineSymbol(filePath, cname, "class", lineNum, stripped.slice(0, 200), parent, lines, "c"));
1862
- if (!CLASS_ALIAS_RE.test(stripped)) {
1883
+ const bracelessDeclaration = !structural.includes("{") && structural.includes(";");
1884
+ if (!CLASS_ALIAS_RE.test(stripped) && !bracelessDeclaration) {
1863
1885
  typeStack.push({ name: cname, startDepth: braceDepth, bodyEntered: false });
1864
1886
  }
1865
1887
  matched = true;
@@ -1926,7 +1948,7 @@ function extractDart(content, filePath) {
1926
1948
  symbols.push(makeLineSymbol(filePath, gm[1] ?? "", "function", lineNum, stripped.slice(0, 200), frame.name, lines, "c"));
1927
1949
  member = true;
1928
1950
  }
1929
- const fm = !member ? FUNC_RE5.exec(stripped) : null;
1951
+ const fm = !member ? FUNC_RE5.exec(structural) : null;
1930
1952
  if (fm) {
1931
1953
  let fname = fm[1] ?? "";
1932
1954
  fname = fname.replace(/^operator\s+/, "");
@@ -1938,7 +1960,7 @@ function extractDart(content, filePath) {
1938
1960
  if (gm) {
1939
1961
  symbols.push(makeLineSymbol(filePath, gm[1] ?? "", "function", lineNum, stripped.slice(0, 200), void 0, lines, "c"));
1940
1962
  }
1941
- const fm = !gm ? FUNC_RE5.exec(stripped) : null;
1963
+ const fm = !gm ? FUNC_RE5.exec(structural) : null;
1942
1964
  if (fm) {
1943
1965
  let fname = fm[1] ?? "";
1944
1966
  fname = fname.replace(/^operator\s+/, "");
@@ -2765,6 +2787,7 @@ function extractBash(content, filePath) {
2765
2787
  let functionBraceDepth = 0;
2766
2788
  let awaitingFunctionBrace = false;
2767
2789
  let openFunctionIndex = null;
2790
+ let openHeadingIndex = null;
2768
2791
  for (let i = 0; i < lines.length; i++) {
2769
2792
  const rawLine = lines[i] ?? "";
2770
2793
  const lineNum = i + 1;
@@ -2772,6 +2795,36 @@ function extractBash(content, filePath) {
2772
2795
  if (rawLine.trim() === heredocs[0]) heredocs.shift();
2773
2796
  continue;
2774
2797
  }
2798
+ if (!inFunction && braceDepth === 0) {
2799
+ const banner = extractShellBannerHeading(rawLine);
2800
+ if (banner !== null) {
2801
+ if (openHeadingIndex !== null) {
2802
+ const prev = symbols[openHeadingIndex];
2803
+ if (prev !== void 0 && lineNum > prev.lineStart) {
2804
+ symbols[openHeadingIndex] = {
2805
+ ...prev,
2806
+ lineEnd: lineNum - 1,
2807
+ body: lines.slice(prev.lineStart - 1, lineNum - 1).join("\n")
2808
+ };
2809
+ }
2810
+ openHeadingIndex = null;
2811
+ }
2812
+ if (symbols.length < MAX_SYMBOLS5) {
2813
+ const pushIdx = symbols.length;
2814
+ symbols.push({
2815
+ filePath,
2816
+ name: banner.heading,
2817
+ kind: "heading",
2818
+ lineStart: lineNum,
2819
+ lineEnd: lineNum,
2820
+ body: rawLine.trim(),
2821
+ docstring: "",
2822
+ parent: ""
2823
+ });
2824
+ openHeadingIndex = pushIdx;
2825
+ }
2826
+ }
2827
+ }
2775
2828
  const noComment = stripBashComment(rawLine);
2776
2829
  const stripped = noComment.trim();
2777
2830
  const opened = findHeredocOpeners(noComment, arithmeticDepth);
@@ -2783,6 +2836,17 @@ function extractBash(content, filePath) {
2783
2836
  const posixMatch = kwMatch === null ? FUNC_POSIX_RE.exec(stripped) : null;
2784
2837
  const funcMatch = kwMatch ?? posixMatch;
2785
2838
  if (funcMatch) {
2839
+ if (openHeadingIndex !== null) {
2840
+ const prev = symbols[openHeadingIndex];
2841
+ if (prev !== void 0 && lineNum > prev.lineStart) {
2842
+ symbols[openHeadingIndex] = {
2843
+ ...prev,
2844
+ lineEnd: lineNum - 1,
2845
+ body: lines.slice(prev.lineStart - 1, lineNum - 1).join("\n")
2846
+ };
2847
+ }
2848
+ openHeadingIndex = null;
2849
+ }
2786
2850
  const fname = funcMatch[1] ?? "";
2787
2851
  let pushedIndex = null;
2788
2852
  if (fname && symbols.length < MAX_SYMBOLS5) {
@@ -2832,6 +2896,16 @@ function extractBash(content, filePath) {
2832
2896
  }
2833
2897
  }
2834
2898
  }
2899
+ if (openHeadingIndex !== null && lines.length > 0) {
2900
+ const prev = symbols[openHeadingIndex];
2901
+ if (prev !== void 0 && lines.length >= prev.lineStart) {
2902
+ symbols[openHeadingIndex] = {
2903
+ ...prev,
2904
+ lineEnd: lines.length,
2905
+ body: lines.slice(prev.lineStart - 1, lines.length).join("\n")
2906
+ };
2907
+ }
2908
+ }
2835
2909
  return symbols;
2836
2910
  }
2837
2911
 
@@ -3307,6 +3381,7 @@ function stripLeadingAttributes2(text) {
3307
3381
  }
3308
3382
  var FUNC_RE7 = new RegExp(`^(?:function|filter|workflow|configuration)\\s+(?:(?:global|local|script|private):)?(${FUNC_IDENT})`, "i");
3309
3383
  var CLASS_RE5 = new RegExp(`^(class|enum)\\s+(${IDENT2})`, "i");
3384
+ var PESTER_RE = /^(Describe|Context|It)\b(?:\s+-[A-Za-z0-9_-]+(?:\s+(?:'[^']*'|"[^"]*"|[^\s{]+))?)*\s*(?:'([^']*)'|"([^"]*)"|([A-Za-z0-9_.-]+))/i;
3310
3385
  var METHOD_NAME_RE = new RegExp(
3311
3386
  `^(?!(?:if|elseif|else|while|for|foreach|do|switch|return|throw|try|catch|finally|param|begin|process|end)\\b)(${IDENT2})\\s*\\(`,
3312
3387
  "i"
@@ -3333,6 +3408,7 @@ function extractPowershell(content, filePath) {
3333
3408
  let inBlockComment = false;
3334
3409
  let mlState = null;
3335
3410
  let openQuote = null;
3411
+ const openBlocks = [];
3336
3412
  const pushInlineMethods = (body, className, lineNum) => {
3337
3413
  for (const piece of body.split(/(?<=[{}])/)) {
3338
3414
  const mname = matchMethodName(piece.replace(/^[{}\s]+/, ""));
@@ -3380,7 +3456,28 @@ function extractPowershell(content, filePath) {
3380
3456
  if (funcMatch) {
3381
3457
  const fname = funcMatch[1] ?? "";
3382
3458
  if (symbols.length < MAX_SYMBOLS9) {
3459
+ const pushIdx = symbols.length;
3383
3460
  symbols.push(makeLineSymbol(filePath, fname, "function", lineNum, line.trimEnd().slice(0, 200), void 0, lines, "hash"));
3461
+ openBlocks.push({ symbolIndex: pushIdx, kind: "function", braceDepth, entered: false });
3462
+ }
3463
+ }
3464
+ }
3465
+ if (currentClass === null) {
3466
+ const pesterTrigger = /^(?:Describe|Context|It)\b/i.exec(stripped);
3467
+ if (pesterTrigger) {
3468
+ const rawLine = sourceLine.trimStart();
3469
+ const pesterMatch = PESTER_RE.exec(rawLine);
3470
+ if (pesterMatch) {
3471
+ const blockType = (pesterMatch[1] ?? "").toLowerCase();
3472
+ const testName = (pesterMatch[2] ?? pesterMatch[3] ?? pesterMatch[4] ?? "").trim();
3473
+ if (testName && symbols.length < MAX_SYMBOLS9) {
3474
+ const kind = blockType === "context" ? "context" : "test";
3475
+ const parentBlock = [...openBlocks].reverse().find((b) => b.kind === "test" || b.kind === "context");
3476
+ const parentName = parentBlock !== void 0 ? symbols[parentBlock.symbolIndex]?.name : void 0;
3477
+ const pushIdx = symbols.length;
3478
+ symbols.push(makeLineSymbol(filePath, testName, kind, lineNum, sourceLine.trimEnd().slice(0, 200), parentName, lines, "hash"));
3479
+ openBlocks.push({ symbolIndex: pushIdx, kind, braceDepth, entered: false });
3480
+ }
3384
3481
  }
3385
3482
  }
3386
3483
  }
@@ -3403,6 +3500,7 @@ function extractPowershell(content, filePath) {
3403
3500
  currentClass = cname;
3404
3501
  classBraceDepth = braceDepth;
3405
3502
  classBodyEntered = false;
3503
+ openBlocks.push({ symbolIndex: symbols.length - 1, kind: "class", braceDepth, entered: false });
3406
3504
  }
3407
3505
  }
3408
3506
  }
@@ -3412,10 +3510,33 @@ function extractPowershell(content, filePath) {
3412
3510
  if (mname !== null && symbols.length < MAX_SYMBOLS9) {
3413
3511
  const sigEnd = line.indexOf("{");
3414
3512
  const sig = sigEnd >= 0 ? line.slice(0, sigEnd).trimEnd() : line.trimEnd();
3513
+ const pushIdx = symbols.length;
3415
3514
  symbols.push(makeLineSymbol(filePath, mname, "method", lineNum, sig.slice(0, 200), currentClass, lines, "hash"));
3515
+ openBlocks.push({ symbolIndex: pushIdx, kind: "method", braceDepth, entered: false });
3516
+ }
3517
+ }
3518
+ const openBraces = (line.match(/\{/g) ?? []).length;
3519
+ const closeBraces = (line.match(/\}/g) ?? []).length;
3520
+ for (const block of openBlocks) {
3521
+ if (braceDepth + openBraces > block.braceDepth) {
3522
+ block.entered = true;
3523
+ }
3524
+ }
3525
+ braceDepth += openBraces - closeBraces;
3526
+ for (let b = openBlocks.length - 1; b >= 0; b--) {
3527
+ const block = openBlocks[b];
3528
+ if (block !== void 0 && block.entered && braceDepth <= block.braceDepth) {
3529
+ openBlocks.splice(b, 1);
3530
+ const sym = symbols[block.symbolIndex];
3531
+ if (sym !== void 0 && lineNum > sym.lineStart) {
3532
+ symbols[block.symbolIndex] = {
3533
+ ...sym,
3534
+ lineEnd: lineNum,
3535
+ body: lines.slice(sym.lineStart - 1, lineNum).join("\n")
3536
+ };
3537
+ }
3416
3538
  }
3417
3539
  }
3418
- braceDepth += (line.match(/\{/g) ?? []).length - (line.match(/\}/g) ?? []).length;
3419
3540
  if (currentClass !== null && braceDepth > classBraceDepth) {
3420
3541
  classBodyEntered = true;
3421
3542
  }