kopytko-formatter 1.0.9 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/dist/src/config.d.ts +4 -0
  2. package/dist/src/config.d.ts.map +1 -1
  3. package/dist/src/config.js +3 -0
  4. package/dist/src/config.js.map +1 -1
  5. package/dist/src/cst-passes/aaThreshold.d.ts +4 -0
  6. package/dist/src/cst-passes/aaThreshold.d.ts.map +1 -0
  7. package/dist/src/cst-passes/aaThreshold.js +11 -0
  8. package/dist/src/cst-passes/aaThreshold.js.map +1 -0
  9. package/dist/src/cst-passes/alignAssignments.d.ts +4 -0
  10. package/dist/src/cst-passes/alignAssignments.d.ts.map +1 -0
  11. package/dist/src/cst-passes/alignAssignments.js +11 -0
  12. package/dist/src/cst-passes/alignAssignments.js.map +1 -0
  13. package/dist/src/cst-passes/blankLines.d.ts +19 -0
  14. package/dist/src/cst-passes/blankLines.d.ts.map +1 -0
  15. package/dist/src/cst-passes/blankLines.js +40 -0
  16. package/dist/src/cst-passes/blankLines.js.map +1 -0
  17. package/dist/src/cst-passes/casingPass.d.ts +12 -0
  18. package/dist/src/cst-passes/casingPass.d.ts.map +1 -0
  19. package/dist/src/cst-passes/casingPass.js +214 -0
  20. package/dist/src/cst-passes/casingPass.js.map +1 -0
  21. package/dist/src/cst-passes/commentNormalization.d.ts +24 -0
  22. package/dist/src/cst-passes/commentNormalization.d.ts.map +1 -0
  23. package/dist/src/cst-passes/commentNormalization.js +76 -0
  24. package/dist/src/cst-passes/commentNormalization.js.map +1 -0
  25. package/dist/src/cst-passes/commentWidth.d.ts +4 -0
  26. package/dist/src/cst-passes/commentWidth.d.ts.map +1 -0
  27. package/dist/src/cst-passes/commentWidth.js +50 -0
  28. package/dist/src/cst-passes/commentWidth.js.map +1 -0
  29. package/dist/src/cst-passes/elseOnNewLine.d.ts +4 -0
  30. package/dist/src/cst-passes/elseOnNewLine.d.ts.map +1 -0
  31. package/dist/src/cst-passes/elseOnNewLine.js +11 -0
  32. package/dist/src/cst-passes/elseOnNewLine.js.map +1 -0
  33. package/dist/src/cst-passes/emptyLinesBetweenMethods.d.ts +4 -0
  34. package/dist/src/cst-passes/emptyLinesBetweenMethods.d.ts.map +1 -0
  35. package/dist/src/cst-passes/emptyLinesBetweenMethods.js +11 -0
  36. package/dist/src/cst-passes/emptyLinesBetweenMethods.js.map +1 -0
  37. package/dist/src/cst-passes/endKeywordStyle.d.ts +21 -0
  38. package/dist/src/cst-passes/endKeywordStyle.d.ts.map +1 -0
  39. package/dist/src/cst-passes/endKeywordStyle.js +95 -0
  40. package/dist/src/cst-passes/endKeywordStyle.js.map +1 -0
  41. package/dist/src/cst-passes/fieldAccessConsistency.d.ts +4 -0
  42. package/dist/src/cst-passes/fieldAccessConsistency.d.ts.map +1 -0
  43. package/dist/src/cst-passes/fieldAccessConsistency.js +11 -0
  44. package/dist/src/cst-passes/fieldAccessConsistency.js.map +1 -0
  45. package/dist/src/cst-passes/functionVsSub.d.ts +13 -0
  46. package/dist/src/cst-passes/functionVsSub.d.ts.map +1 -0
  47. package/dist/src/cst-passes/functionVsSub.js +112 -0
  48. package/dist/src/cst-passes/functionVsSub.js.map +1 -0
  49. package/dist/src/cst-passes/importSorting.d.ts +25 -0
  50. package/dist/src/cst-passes/importSorting.d.ts.map +1 -0
  51. package/dist/src/cst-passes/importSorting.js +126 -0
  52. package/dist/src/cst-passes/importSorting.js.map +1 -0
  53. package/dist/src/cst-passes/indentation.d.ts +21 -0
  54. package/dist/src/cst-passes/indentation.d.ts.map +1 -0
  55. package/dist/src/cst-passes/indentation.js +115 -0
  56. package/dist/src/cst-passes/indentation.js.map +1 -0
  57. package/dist/src/cst-passes/index.d.ts +45 -0
  58. package/dist/src/cst-passes/index.d.ts.map +1 -0
  59. package/dist/src/cst-passes/index.js +77 -0
  60. package/dist/src/cst-passes/index.js.map +1 -0
  61. package/dist/src/cst-passes/infrastructure.d.ts +39 -0
  62. package/dist/src/cst-passes/infrastructure.d.ts.map +1 -0
  63. package/dist/src/cst-passes/infrastructure.js +63 -0
  64. package/dist/src/cst-passes/infrastructure.js.map +1 -0
  65. package/dist/src/cst-passes/lineCommentPosition.d.ts +4 -0
  66. package/dist/src/cst-passes/lineCommentPosition.d.ts.map +1 -0
  67. package/dist/src/cst-passes/lineCommentPosition.js +42 -0
  68. package/dist/src/cst-passes/lineCommentPosition.js.map +1 -0
  69. package/dist/src/cst-passes/mPrefixStyle.d.ts +4 -0
  70. package/dist/src/cst-passes/mPrefixStyle.d.ts.map +1 -0
  71. package/dist/src/cst-passes/mPrefixStyle.js +11 -0
  72. package/dist/src/cst-passes/mPrefixStyle.js.map +1 -0
  73. package/dist/src/cst-passes/observeFieldStyle.d.ts +6 -0
  74. package/dist/src/cst-passes/observeFieldStyle.d.ts.map +1 -0
  75. package/dist/src/cst-passes/observeFieldStyle.js +21 -0
  76. package/dist/src/cst-passes/observeFieldStyle.js.map +1 -0
  77. package/dist/src/cst-passes/paramAlignment.d.ts +4 -0
  78. package/dist/src/cst-passes/paramAlignment.d.ts.map +1 -0
  79. package/dist/src/cst-passes/paramAlignment.js +11 -0
  80. package/dist/src/cst-passes/paramAlignment.js.map +1 -0
  81. package/dist/src/cst-passes/parenthesisIfCase.d.ts +6 -0
  82. package/dist/src/cst-passes/parenthesisIfCase.d.ts.map +1 -0
  83. package/dist/src/cst-passes/parenthesisIfCase.js +42 -0
  84. package/dist/src/cst-passes/parenthesisIfCase.js.map +1 -0
  85. package/dist/src/cst-passes/printStatementRemoval.d.ts +20 -0
  86. package/dist/src/cst-passes/printStatementRemoval.d.ts.map +1 -0
  87. package/dist/src/cst-passes/printStatementRemoval.js +67 -0
  88. package/dist/src/cst-passes/printStatementRemoval.js.map +1 -0
  89. package/dist/src/cst-passes/spacing.d.ts +19 -0
  90. package/dist/src/cst-passes/spacing.d.ts.map +1 -0
  91. package/dist/src/cst-passes/spacing.js +81 -0
  92. package/dist/src/cst-passes/spacing.js.map +1 -0
  93. package/dist/src/cst-passes/splitArrayOpenBracket.d.ts +4 -0
  94. package/dist/src/cst-passes/splitArrayOpenBracket.d.ts.map +1 -0
  95. package/dist/src/cst-passes/splitArrayOpenBracket.js +11 -0
  96. package/dist/src/cst-passes/splitArrayOpenBracket.js.map +1 -0
  97. package/dist/src/cst-passes/stringConcatStyle.d.ts +4 -0
  98. package/dist/src/cst-passes/stringConcatStyle.d.ts.map +1 -0
  99. package/dist/src/cst-passes/stringConcatStyle.js +11 -0
  100. package/dist/src/cst-passes/stringConcatStyle.js.map +1 -0
  101. package/dist/src/cst-passes/stripCatchParens.d.ts +4 -0
  102. package/dist/src/cst-passes/stripCatchParens.d.ts.map +1 -0
  103. package/dist/src/cst-passes/stripCatchParens.js +29 -0
  104. package/dist/src/cst-passes/stripCatchParens.js.map +1 -0
  105. package/dist/src/cst-passes/thenStyle.d.ts +15 -0
  106. package/dist/src/cst-passes/thenStyle.d.ts.map +1 -0
  107. package/dist/src/cst-passes/thenStyle.js +140 -0
  108. package/dist/src/cst-passes/thenStyle.js.map +1 -0
  109. package/dist/src/cst-passes/trailingCommas.d.ts +13 -0
  110. package/dist/src/cst-passes/trailingCommas.d.ts.map +1 -0
  111. package/dist/src/cst-passes/trailingCommas.js +56 -0
  112. package/dist/src/cst-passes/trailingCommas.js.map +1 -0
  113. package/dist/src/cst-passes/trailingWhitespace.d.ts +13 -0
  114. package/dist/src/cst-passes/trailingWhitespace.d.ts.map +1 -0
  115. package/dist/src/cst-passes/trailingWhitespace.js +26 -0
  116. package/dist/src/cst-passes/trailingWhitespace.js.map +1 -0
  117. package/dist/src/cst-passes/wrapLongStrings.d.ts +4 -0
  118. package/dist/src/cst-passes/wrapLongStrings.d.ts.map +1 -0
  119. package/dist/src/cst-passes/wrapLongStrings.js +11 -0
  120. package/dist/src/cst-passes/wrapLongStrings.js.map +1 -0
  121. package/dist/src/formatter.d.ts +2 -1
  122. package/dist/src/formatter.d.ts.map +1 -1
  123. package/dist/src/formatter.js +74 -333
  124. package/dist/src/formatter.js.map +1 -1
  125. package/dist/src/index.d.ts +3 -2
  126. package/dist/src/index.d.ts.map +1 -1
  127. package/dist/src/index.js +11 -10
  128. package/dist/src/index.js.map +1 -1
  129. package/package.json +5 -2
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.elseOnNewLinePass = elseOnNewLinePass;
4
+ function elseOnNewLinePass(keepOnNewLine) {
5
+ if (keepOnNewLine)
6
+ return () => [];
7
+ return (_root, _source) => {
8
+ return [];
9
+ };
10
+ }
11
+ //# sourceMappingURL=elseOnNewLine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elseOnNewLine.js","sourceRoot":"","sources":["../../../src/cst-passes/elseOnNewLine.ts"],"names":[],"mappings":";;AAGA,8CAKC;AALD,SAAgB,iBAAiB,CAAC,aAAsB;IACtD,IAAI,aAAa;QAAE,OAAO,GAAG,EAAE,CAAC,EAAE,CAAC;IACnC,OAAO,CAAC,KAAiB,EAAE,OAAe,EAAc,EAAE;QACxD,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { SyntaxNode } from 'kopytko-brightscript-parser';
2
+ import { TextEdit } from './infrastructure';
3
+ export declare function emptyLinesBetweenMethodsPass(count: number): (root: SyntaxNode, source: string) => TextEdit[];
4
+ //# sourceMappingURL=emptyLinesBetweenMethods.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emptyLinesBetweenMethods.d.ts","sourceRoot":"","sources":["../../../src/cst-passes/emptyLinesBetweenMethods.ts"],"names":[],"mappings":"AAAsD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACpH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,MAAM,GAAG,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,KAAK,QAAQ,EAAE,CAK5G"}
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.emptyLinesBetweenMethodsPass = emptyLinesBetweenMethodsPass;
4
+ function emptyLinesBetweenMethodsPass(count) {
5
+ if (count <= 0)
6
+ return () => [];
7
+ return (_root, _source) => {
8
+ return [];
9
+ };
10
+ }
11
+ //# sourceMappingURL=emptyLinesBetweenMethods.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emptyLinesBetweenMethods.js","sourceRoot":"","sources":["../../../src/cst-passes/emptyLinesBetweenMethods.ts"],"names":[],"mappings":";;AAGA,oEAKC;AALD,SAAgB,4BAA4B,CAAC,KAAa;IACxD,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,GAAG,EAAE,CAAC,EAAE,CAAC;IAChC,OAAO,CAAC,KAAiB,EAAE,OAAe,EAAc,EAAE;QACxD,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * CST Pass: End keyword style.
3
+ *
4
+ * Converts between compact (`endif`, `endfor`) and spaced (`end if`, `end for`)
5
+ * forms of end keywords. This pass demonstrates the simplest CST transformation:
6
+ * finding specific tokens and replacing their text.
7
+ *
8
+ * Unlike the regex version, this pass:
9
+ * - Cannot accidentally match keywords inside string literals
10
+ * - Works correctly regardless of indentation or surrounding whitespace
11
+ * - Preserves all trivia (comments, whitespace) attached to the token
12
+ */
13
+ import { SyntaxNode } from 'kopytko-brightscript-parser';
14
+ import { TextEdit } from './infrastructure';
15
+ /**
16
+ * Creates an end-keyword-style CST pass.
17
+ *
18
+ * @param style - 'spaced' converts `endif` → `end if`, 'compact' does the reverse.
19
+ */
20
+ export declare function endKeywordStylePass(style: 'spaced' | 'compact'): (root: SyntaxNode, source: string) => TextEdit[];
21
+ //# sourceMappingURL=endKeywordStyle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"endKeywordStyle.d.ts","sourceRoot":"","sources":["../../../src/cst-passes/endKeywordStyle.ts"],"names":[],"mappings":"CAAsD;;;;;;;;;;;GAWnD;AAEH,OAAO,EAAE,UAAU,EAAa,MAAM,6BAA6B,CAAC;AAEpE,OAAO,EAAE,QAAQ,EAAc,MAAM,kBAAkB,CAAC;AAgCxD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,QAAQ,GAAG,SAAS,GAAG,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,KAAK,QAAQ,EAAE,CA2BjH"}
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ /* eslint-disable @typescript-eslint/no-unused-vars */ /**
3
+ * CST Pass: End keyword style.
4
+ *
5
+ * Converts between compact (`endif`, `endfor`) and spaced (`end if`, `end for`)
6
+ * forms of end keywords. This pass demonstrates the simplest CST transformation:
7
+ * finding specific tokens and replacing their text.
8
+ *
9
+ * Unlike the regex version, this pass:
10
+ * - Cannot accidentally match keywords inside string literals
11
+ * - Works correctly regardless of indentation or surrounding whitespace
12
+ * - Preserves all trivia (comments, whitespace) attached to the token
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.endKeywordStylePass = endKeywordStylePass;
16
+ const kopytko_brightscript_parser_1 = require("kopytko-brightscript-parser");
17
+ const infrastructure_1 = require("./infrastructure");
18
+ /** Map from compact form to spaced form. */
19
+ const COMPACT_TO_SPACED = {
20
+ 'endif': 'end if',
21
+ 'endfunction': 'end function',
22
+ 'endsub': 'end sub',
23
+ 'endwhile': 'end while',
24
+ 'endfor': 'end for',
25
+ 'endtry': 'end try',
26
+ };
27
+ /** Map from spaced token text (lowercased) to compact form. */
28
+ const SPACED_TO_COMPACT = {
29
+ 'end if': 'endif',
30
+ 'end function': 'endfunction',
31
+ 'end sub': 'endsub',
32
+ 'end while': 'endwhile',
33
+ 'end for': 'endfor',
34
+ 'end try': 'endtry',
35
+ };
36
+ /** The token kinds that represent end keywords. */
37
+ const END_KEYWORD_KINDS = new Set([
38
+ kopytko_brightscript_parser_1.TokenKind.EndIf,
39
+ kopytko_brightscript_parser_1.TokenKind.EndFunction,
40
+ kopytko_brightscript_parser_1.TokenKind.EndSub,
41
+ kopytko_brightscript_parser_1.TokenKind.EndWhile,
42
+ kopytko_brightscript_parser_1.TokenKind.EndFor,
43
+ kopytko_brightscript_parser_1.TokenKind.EndTry,
44
+ ]);
45
+ /**
46
+ * Creates an end-keyword-style CST pass.
47
+ *
48
+ * @param style - 'spaced' converts `endif` → `end if`, 'compact' does the reverse.
49
+ */
50
+ function endKeywordStylePass(style) {
51
+ return (root, _source) => {
52
+ const edits = [];
53
+ (0, infrastructure_1.walkTokens)(root, (token) => {
54
+ if (!END_KEYWORD_KINDS.has(token.kind))
55
+ return;
56
+ const lower = token.text.toLowerCase();
57
+ if (style === 'spaced') {
58
+ const spaced = COMPACT_TO_SPACED[lower];
59
+ if (spaced) {
60
+ // Preserve original casing pattern: if original was "EndIf", produce "End If"
61
+ const newText = matchCasing(token.text, spaced);
62
+ edits.push({ pos: token.pos, end: token.end, newText });
63
+ }
64
+ }
65
+ else {
66
+ const compact = SPACED_TO_COMPACT[lower];
67
+ if (compact) {
68
+ const newText = matchCasing(token.text, compact);
69
+ edits.push({ pos: token.pos, end: token.end, newText });
70
+ }
71
+ }
72
+ });
73
+ return edits;
74
+ };
75
+ }
76
+ /**
77
+ * Produces the target string with casing that matches the original's pattern.
78
+ * If original is all-lowercase → target lowercase.
79
+ * If original starts with uppercase → capitalize first letter of each word in target.
80
+ * If original is all-uppercase → target uppercase.
81
+ */
82
+ function matchCasing(original, target) {
83
+ if (original === original.toLowerCase())
84
+ return target.toLowerCase();
85
+ if (original === original.toUpperCase())
86
+ return target.toUpperCase();
87
+ // Title case: capitalize first letter of each word
88
+ return target.replace(/\b\w/g, (ch, idx) => {
89
+ // Match the casing of the corresponding position in the original
90
+ if (idx === 0)
91
+ return original[0] === original[0].toUpperCase() ? ch.toUpperCase() : ch.toLowerCase();
92
+ return ch.toUpperCase();
93
+ });
94
+ }
95
+ //# sourceMappingURL=endKeywordStyle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"endKeywordStyle.js","sourceRoot":"","sources":["../../../src/cst-passes/endKeywordStyle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { SyntaxNode } from 'kopytko-brightscript-parser';
2
+ import { TextEdit } from './infrastructure';
3
+ export declare function fieldAccessConsistencyPass(style: string): (root: SyntaxNode, source: string) => TextEdit[];
4
+ //# sourceMappingURL=fieldAccessConsistency.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fieldAccessConsistency.d.ts","sourceRoot":"","sources":["../../../src/cst-passes/fieldAccessConsistency.ts"],"names":[],"mappings":"AAAsD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACpH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,GAAG,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,KAAK,QAAQ,EAAE,CAK1G"}
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fieldAccessConsistencyPass = fieldAccessConsistencyPass;
4
+ function fieldAccessConsistencyPass(style) {
5
+ if (style === 'preserve')
6
+ return () => [];
7
+ return (_root, _source) => {
8
+ return [];
9
+ };
10
+ }
11
+ //# sourceMappingURL=fieldAccessConsistency.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fieldAccessConsistency.js","sourceRoot":"","sources":["../../../src/cst-passes/fieldAccessConsistency.ts"],"names":[],"mappings":";;AAGA,gEAKC;AALD,SAAgB,0BAA0B,CAAC,KAAa;IACtD,IAAI,KAAK,KAAK,UAAU;QAAE,OAAO,GAAG,EAAE,CAAC,EAAE,CAAC;IAC1C,OAAO,CAAC,KAAiB,EAAE,OAAe,EAAc,EAAE;QACxD,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * CST Pass: Function vs Sub for void.
3
+ *
4
+ * Converts between `function`/`sub` for void procedures:
5
+ * - 'sub': converts `function foo() as Void ... end function` to `sub foo() ... end sub`
6
+ * - 'function': converts `sub foo() ... end sub` to `function foo() as Void ... end function`
7
+ */
8
+ import { SyntaxNode } from 'kopytko-brightscript-parser';
9
+ import { TextEdit } from './infrastructure';
10
+ type FuncVsSub = 'function' | 'sub' | 'preserve';
11
+ export declare function functionVsSubPass(style: FuncVsSub): (root: SyntaxNode, source: string) => TextEdit[];
12
+ export {};
13
+ //# sourceMappingURL=functionVsSub.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"functionVsSub.d.ts","sourceRoot":"","sources":["../../../src/cst-passes/functionVsSub.ts"],"names":[],"mappings":"CAAsD;;;;;;GAMnD;AAEH,OAAO,EAAE,UAAU,EAA0C,MAAM,6BAA6B,CAAC;AAEjG,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,KAAK,SAAS,GAAG,UAAU,GAAG,KAAK,GAAG,UAAU,CAAC;AAEjD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,GAAG,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,KAAK,QAAQ,EAAE,CAkBpG"}
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ /* eslint-disable @typescript-eslint/no-unused-vars */ /**
3
+ * CST Pass: Function vs Sub for void.
4
+ *
5
+ * Converts between `function`/`sub` for void procedures:
6
+ * - 'sub': converts `function foo() as Void ... end function` to `sub foo() ... end sub`
7
+ * - 'function': converts `sub foo() ... end sub` to `function foo() as Void ... end function`
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.functionVsSubPass = functionVsSubPass;
11
+ const kopytko_brightscript_parser_1 = require("kopytko-brightscript-parser");
12
+ function functionVsSubPass(style) {
13
+ if (style === 'preserve')
14
+ return () => [];
15
+ return (root, _source) => {
16
+ const edits = [];
17
+ function visit(node) {
18
+ if (node.kind === kopytko_brightscript_parser_1.SyntaxKind.FunctionDeclaration || node.kind === kopytko_brightscript_parser_1.SyntaxKind.FunctionExpression) {
19
+ processFunctionNode(node, edits, style);
20
+ }
21
+ for (const child of node.children) {
22
+ if ((0, kopytko_brightscript_parser_1.isNode)(child))
23
+ visit(child);
24
+ }
25
+ }
26
+ visit(root);
27
+ return edits;
28
+ };
29
+ }
30
+ function processFunctionNode(node, edits, style) {
31
+ const funcToken = node.findToken(kopytko_brightscript_parser_1.TokenKind.Function);
32
+ const subToken = node.findToken(kopytko_brightscript_parser_1.TokenKind.Sub);
33
+ const keyword = funcToken ?? subToken;
34
+ if (!keyword)
35
+ return;
36
+ const isFunc = funcToken !== undefined;
37
+ const isSub = subToken !== undefined;
38
+ // Find end keyword
39
+ const endFuncToken = node.findToken(kopytko_brightscript_parser_1.TokenKind.EndFunction);
40
+ const endSubToken = node.findToken(kopytko_brightscript_parser_1.TokenKind.EndSub);
41
+ const endToken = endFuncToken ?? endSubToken;
42
+ // Check if it has a non-void return type
43
+ const returnTypeClause = node.findChild(kopytko_brightscript_parser_1.SyntaxKind.ReturnTypeClause);
44
+ const hasExplicitReturnType = returnTypeClause !== undefined;
45
+ let returnTypeName = '';
46
+ if (returnTypeClause) {
47
+ const tokens = returnTypeClause.childTokens;
48
+ if (tokens.length >= 2)
49
+ returnTypeName = tokens[1].text.toLowerCase();
50
+ }
51
+ const isVoid = !hasExplicitReturnType || returnTypeName === 'void';
52
+ // Check if body has `return <value>`
53
+ if (!isVoid)
54
+ return; // has explicit non-void return type — don't touch
55
+ const hasReturnValue = checkReturnWithValue(node);
56
+ if (hasReturnValue)
57
+ return; // returns a value — not a void function
58
+ if (style === 'sub' && isFunc && isVoid) {
59
+ // Convert function → sub: replace keyword, remove 'as Void' if present, replace end keyword
60
+ edits.push({ pos: keyword.pos, end: keyword.end, newText: 'sub' });
61
+ if (returnTypeClause) {
62
+ // Remove the return type clause text only (not trailing trivia/newline)
63
+ // Find the actual token end (not including trailing trivia)
64
+ const clauseTokens = returnTypeClause.childTokens;
65
+ const lastClauseToken = clauseTokens[clauseTokens.length - 1];
66
+ const clauseStart = returnTypeClause.pos;
67
+ const clauseEnd = lastClauseToken ? lastClauseToken.end : returnTypeClause.end;
68
+ // Also remove the space before 'as' (between closing paren and 'as')
69
+ const adjustedStart = clauseStart > 0 ? clauseStart - 1 : clauseStart;
70
+ edits.push({ pos: adjustedStart, end: clauseEnd, newText: '' });
71
+ }
72
+ if (endToken) {
73
+ const newEnd = endToken.text.toLowerCase().includes(' ') ? 'end sub' : 'endsub';
74
+ edits.push({ pos: endToken.pos, end: endToken.end, newText: newEnd });
75
+ }
76
+ }
77
+ else if (style === 'function' && isSub) {
78
+ // Convert sub → function: replace keyword, add 'as Void', replace end keyword
79
+ edits.push({ pos: keyword.pos, end: keyword.end, newText: 'function' });
80
+ // Insert ' as Void' after the parameter list closing paren
81
+ const paramList = node.findChild(kopytko_brightscript_parser_1.SyntaxKind.ParameterList);
82
+ if (paramList) {
83
+ const rParen = paramList.findToken(kopytko_brightscript_parser_1.TokenKind.RightParen);
84
+ if (rParen) {
85
+ edits.push({ pos: rParen.end, end: rParen.end, newText: ' as Void' });
86
+ }
87
+ }
88
+ if (endToken) {
89
+ const newEnd = endToken.text.toLowerCase().includes(' ') ? 'end function' : 'endfunction';
90
+ edits.push({ pos: endToken.pos, end: endToken.end, newText: newEnd });
91
+ }
92
+ }
93
+ }
94
+ function checkReturnWithValue(node) {
95
+ for (const child of node.children) {
96
+ if ((0, kopytko_brightscript_parser_1.isNode)(child)) {
97
+ if (child.kind === kopytko_brightscript_parser_1.SyntaxKind.ReturnStatement) {
98
+ // Check if return has a value (more than just the 'return' token)
99
+ const childNodes = child.childNodes;
100
+ if (childNodes.length > 0)
101
+ return true;
102
+ }
103
+ // Don't recurse into nested functions
104
+ if (child.kind === kopytko_brightscript_parser_1.SyntaxKind.FunctionDeclaration || child.kind === kopytko_brightscript_parser_1.SyntaxKind.FunctionExpression)
105
+ continue;
106
+ if (checkReturnWithValue(child))
107
+ return true;
108
+ }
109
+ }
110
+ return false;
111
+ }
112
+ //# sourceMappingURL=functionVsSub.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"functionVsSub.js","sourceRoot":"","sources":["../../../src/cst-passes/functionVsSub.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * CST Pass: Import sorting.
3
+ *
4
+ * Sorts `' @import` and `' @mock` annotations at the top of the file.
5
+ * Groups: module imports (with `from`) first, then local imports.
6
+ * Within each group, sorts alphabetically.
7
+ *
8
+ * Unlike the regex version, this pass:
9
+ * - Uses trivia classification to identify import comments precisely
10
+ * - Works on the actual trivia text, not line-by-line matching
11
+ * - Preserves all non-import content exactly as-is
12
+ */
13
+ import { SyntaxNode } from 'kopytko-brightscript-parser';
14
+ import { TextEdit } from './infrastructure';
15
+ interface ImportSortConfig {
16
+ sortImports: boolean;
17
+ emptyLineAfterImports: boolean;
18
+ }
19
+ /**
20
+ * Creates an import sorting CST pass.
21
+ * Operates on the leading trivia of the first token in the file.
22
+ */
23
+ export declare function importSortingPass(config: ImportSortConfig): (root: SyntaxNode, source: string) => TextEdit[];
24
+ export {};
25
+ //# sourceMappingURL=importSorting.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"importSorting.d.ts","sourceRoot":"","sources":["../../../src/cst-passes/importSorting.ts"],"names":[],"mappings":"CAAsD;;;;;;;;;;;GAWnD;AAEH,OAAO,EAAE,UAAU,EAA+B,MAAM,6BAA6B,CAAC;AAEtF,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,UAAU,gBAAgB;IACxB,WAAW,EAAE,OAAO,CAAC;IACrB,qBAAqB,EAAE,OAAO,CAAC;CAChC;AAOD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,gBAAgB,GAAG,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,KAAK,QAAQ,EAAE,CAgF5G"}
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+ /* eslint-disable @typescript-eslint/no-unused-vars */ /**
3
+ * CST Pass: Import sorting.
4
+ *
5
+ * Sorts `' @import` and `' @mock` annotations at the top of the file.
6
+ * Groups: module imports (with `from`) first, then local imports.
7
+ * Within each group, sorts alphabetically.
8
+ *
9
+ * Unlike the regex version, this pass:
10
+ * - Uses trivia classification to identify import comments precisely
11
+ * - Works on the actual trivia text, not line-by-line matching
12
+ * - Preserves all non-import content exactly as-is
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.importSortingPass = importSortingPass;
16
+ const kopytko_brightscript_parser_1 = require("kopytko-brightscript-parser");
17
+ const IMPORT_RE = /^\s*'\s*@import\s+/;
18
+ const MOCK_RE = /^\s*'\s*@mock\s+/;
19
+ const FROM_IMPORT_RE = /^\s*'\s*@import\s+(.*?)\s+from\s+(\S+)\s*$/;
20
+ const FROM_MOCK_RE = /^\s*'\s*@mock\s+(.*?)\s+from\s+(\S+)\s*$/;
21
+ /**
22
+ * Creates an import sorting CST pass.
23
+ * Operates on the leading trivia of the first token in the file.
24
+ */
25
+ function importSortingPass(config) {
26
+ if (!config.sortImports && !config.emptyLineAfterImports) {
27
+ return () => [];
28
+ }
29
+ return (root, source) => {
30
+ // Find all import/mock comment lines at the top of the file.
31
+ // In our CST, these are trivia attached to the first token.
32
+ const firstToken = findFirstToken(root);
33
+ if (!firstToken)
34
+ return [];
35
+ // Collect consecutive import comments from leading trivia
36
+ const importTrivia = [];
37
+ let lastImportIdx = -1;
38
+ for (let i = 0; i < firstToken.leadingTrivia.length; i++) {
39
+ const t = firstToken.leadingTrivia[i];
40
+ if (t.kind === kopytko_brightscript_parser_1.TriviaKind.Comment) {
41
+ if (IMPORT_RE.test(t.text) || MOCK_RE.test(t.text)) {
42
+ importTrivia.push(t);
43
+ lastImportIdx = i;
44
+ }
45
+ else {
46
+ // Non-import comment encountered — stop
47
+ break;
48
+ }
49
+ }
50
+ // Skip whitespace and line breaks between imports
51
+ }
52
+ if (importTrivia.length === 0)
53
+ return [];
54
+ if (!config.sortImports)
55
+ return []; // Only sorting for now
56
+ // Sort imports
57
+ const moduleImports = [];
58
+ const localImports = [];
59
+ const moduleMocks = [];
60
+ const localMocks = [];
61
+ for (const t of importTrivia) {
62
+ if (MOCK_RE.test(t.text)) {
63
+ if (FROM_MOCK_RE.test(t.text))
64
+ moduleMocks.push(t.text);
65
+ else
66
+ localMocks.push(t.text);
67
+ }
68
+ else {
69
+ if (FROM_IMPORT_RE.test(t.text))
70
+ moduleImports.push(t.text);
71
+ else
72
+ localImports.push(t.text);
73
+ }
74
+ }
75
+ // Sort each group
76
+ moduleImports.sort((a, b) => {
77
+ const am = FROM_IMPORT_RE.exec(a);
78
+ const bm = FROM_IMPORT_RE.exec(b);
79
+ const cmp = am[2].localeCompare(bm[2]);
80
+ return cmp !== 0 ? cmp : am[1].localeCompare(bm[1]);
81
+ });
82
+ localImports.sort();
83
+ moduleMocks.sort((a, b) => {
84
+ const am = FROM_MOCK_RE.exec(a);
85
+ const bm = FROM_MOCK_RE.exec(b);
86
+ const cmp = am[2].localeCompare(bm[2]);
87
+ return cmp !== 0 ? cmp : am[1].localeCompare(bm[1]);
88
+ });
89
+ localMocks.sort();
90
+ const sorted = [...moduleImports, ...localImports, ...moduleMocks, ...localMocks];
91
+ // Check if already sorted
92
+ const original = importTrivia.map(t => t.text);
93
+ if (arraysEqual(original, sorted))
94
+ return [];
95
+ // Build the replacement: sorted imports joined by newlines
96
+ const firstImport = importTrivia[0];
97
+ const lastImport = importTrivia[importTrivia.length - 1];
98
+ // Find the range covering all import trivia (from first import start to last import end)
99
+ const rangeStart = firstImport.pos;
100
+ const rangeEnd = lastImport.end;
101
+ const newText = sorted.join('\n');
102
+ return [{ pos: rangeStart, end: rangeEnd, newText }];
103
+ };
104
+ }
105
+ function findFirstToken(node) {
106
+ for (const child of node.children) {
107
+ if ((0, kopytko_brightscript_parser_1.isToken)(child))
108
+ return child;
109
+ if ((0, kopytko_brightscript_parser_1.isNode)(child)) {
110
+ const found = findFirstToken(child);
111
+ if (found)
112
+ return found;
113
+ }
114
+ }
115
+ return undefined;
116
+ }
117
+ function arraysEqual(a, b) {
118
+ if (a.length !== b.length)
119
+ return false;
120
+ for (let i = 0; i < a.length; i++) {
121
+ if (a[i] !== b[i])
122
+ return false;
123
+ }
124
+ return true;
125
+ }
126
+ //# sourceMappingURL=importSorting.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"importSorting.js","sourceRoot":"","sources":["../../../src/cst-passes/importSorting.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * CST Pass: Indentation.
3
+ *
4
+ * Applies consistent indentation based on nesting depth.
5
+ * Walks the CST structure to determine indent level and sets
6
+ * leading whitespace accordingly.
7
+ */
8
+ import { SyntaxNode } from 'kopytko-brightscript-parser';
9
+ import { TextEdit } from './infrastructure';
10
+ interface IndentConfig {
11
+ indentSize: number;
12
+ useTabs: boolean;
13
+ }
14
+ /**
15
+ * Creates an indentation pass.
16
+ * Calculates depth by counting ancestor INDENT_OPENERS and sets
17
+ * leading whitespace for the first token of each line.
18
+ */
19
+ export declare function indentationPass(config: IndentConfig): (root: SyntaxNode, source: string) => TextEdit[];
20
+ export {};
21
+ //# sourceMappingURL=indentation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indentation.d.ts","sourceRoot":"","sources":["../../../src/cst-passes/indentation.ts"],"names":[],"mappings":"CAAsD;;;;;;GAMnD;AAEH,OAAO,EAAE,UAAU,EAA0C,MAAM,6BAA6B,CAAC;AAEjG,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,UAAU,YAAY;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;CAClB;AAgBD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,YAAY,GAAG,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,KAAK,QAAQ,EAAE,CAiCtG"}
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+ /* eslint-disable @typescript-eslint/no-unused-vars */ /**
3
+ * CST Pass: Indentation.
4
+ *
5
+ * Applies consistent indentation based on nesting depth.
6
+ * Walks the CST structure to determine indent level and sets
7
+ * leading whitespace accordingly.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.indentationPass = indentationPass;
11
+ const kopytko_brightscript_parser_1 = require("kopytko-brightscript-parser");
12
+ const INDENT_OPENERS = new Set([
13
+ kopytko_brightscript_parser_1.SyntaxKind.FunctionDeclaration,
14
+ kopytko_brightscript_parser_1.SyntaxKind.FunctionExpression,
15
+ kopytko_brightscript_parser_1.SyntaxKind.IfStatement,
16
+ kopytko_brightscript_parser_1.SyntaxKind.ElseIfClause,
17
+ kopytko_brightscript_parser_1.SyntaxKind.ElseClause,
18
+ kopytko_brightscript_parser_1.SyntaxKind.ForStatement,
19
+ kopytko_brightscript_parser_1.SyntaxKind.ForEachStatement,
20
+ kopytko_brightscript_parser_1.SyntaxKind.WhileStatement,
21
+ kopytko_brightscript_parser_1.SyntaxKind.TryStatement,
22
+ kopytko_brightscript_parser_1.SyntaxKind.CatchClause,
23
+ kopytko_brightscript_parser_1.SyntaxKind.ConditionalCompilation,
24
+ ]);
25
+ /**
26
+ * Creates an indentation pass.
27
+ * Calculates depth by counting ancestor INDENT_OPENERS and sets
28
+ * leading whitespace for the first token of each line.
29
+ */
30
+ function indentationPass(config) {
31
+ return (root, source) => {
32
+ const edits = [];
33
+ const indentChar = config.useTabs ? '\t' : ' '.repeat(config.indentSize);
34
+ const lines = source.split(/\r?\n/);
35
+ // Build a map: line number → expected indent depth
36
+ const lineDepths = new Map();
37
+ computeDepths(root, 0, lineDepths);
38
+ // For each line, check if the current indentation matches expected
39
+ let offset = 0;
40
+ for (let lineNum = 0; lineNum < lines.length; lineNum++) {
41
+ const line = lines[lineNum];
42
+ const currentIndent = line.match(/^(\s*)/)?.[1] ?? '';
43
+ const expectedDepth = lineDepths.get(lineNum);
44
+ if (expectedDepth !== undefined && expectedDepth >= 0) {
45
+ const expectedIndent = indentChar.repeat(expectedDepth);
46
+ if (currentIndent !== expectedIndent && line.trim() !== '') {
47
+ edits.push({
48
+ pos: offset,
49
+ end: offset + currentIndent.length,
50
+ newText: expectedIndent,
51
+ });
52
+ }
53
+ }
54
+ offset += line.length + 1; // +1 for the newline character
55
+ }
56
+ return edits;
57
+ };
58
+ }
59
+ function computeDepths(node, depth, lineDepths) {
60
+ for (const child of node.children) {
61
+ if ((0, kopytko_brightscript_parser_1.isToken)(child)) {
62
+ // The first token of a line sets that line's depth
63
+ if (!lineDepths.has(child.line)) {
64
+ lineDepths.set(child.line, depth);
65
+ }
66
+ }
67
+ else if ((0, kopytko_brightscript_parser_1.isNode)(child)) {
68
+ const childDepth = INDENT_OPENERS.has(child.kind) ? depth + 1 : depth;
69
+ // For block openers, the first line (the keyword itself) stays at current depth
70
+ if (INDENT_OPENERS.has(child.kind)) {
71
+ // Opening keyword line stays at `depth`
72
+ const firstToken = findFirstToken(child);
73
+ if (firstToken) {
74
+ lineDepths.set(firstToken.line, depth);
75
+ }
76
+ // Closing keyword also stays at `depth`
77
+ const lastToken = findLastToken(child);
78
+ if (lastToken) {
79
+ lineDepths.set(lastToken.line, depth);
80
+ }
81
+ // Body is at depth + 1
82
+ computeDepths(child, depth + 1, lineDepths);
83
+ }
84
+ else {
85
+ computeDepths(child, depth, lineDepths);
86
+ }
87
+ }
88
+ }
89
+ }
90
+ function findFirstToken(node) {
91
+ for (const child of node.children) {
92
+ if ((0, kopytko_brightscript_parser_1.isToken)(child))
93
+ return child;
94
+ if ((0, kopytko_brightscript_parser_1.isNode)(child)) {
95
+ const found = findFirstToken(child);
96
+ if (found)
97
+ return found;
98
+ }
99
+ }
100
+ return undefined;
101
+ }
102
+ function findLastToken(node) {
103
+ for (let i = node.children.length - 1; i >= 0; i--) {
104
+ const child = node.children[i];
105
+ if ((0, kopytko_brightscript_parser_1.isToken)(child))
106
+ return child;
107
+ if ((0, kopytko_brightscript_parser_1.isNode)(child)) {
108
+ const found = findLastToken(child);
109
+ if (found)
110
+ return found;
111
+ }
112
+ }
113
+ return undefined;
114
+ }
115
+ //# sourceMappingURL=indentation.js.map