@rcrsr/rill-cli 0.6.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 (171) hide show
  1. package/LICENSE +21 -0
  2. package/dist/check/config.d.ts +20 -0
  3. package/dist/check/config.d.ts.map +1 -0
  4. package/dist/check/config.js +151 -0
  5. package/dist/check/config.js.map +1 -0
  6. package/dist/check/fixer.d.ts +39 -0
  7. package/dist/check/fixer.d.ts.map +1 -0
  8. package/dist/check/fixer.js +119 -0
  9. package/dist/check/fixer.js.map +1 -0
  10. package/dist/check/index.d.ts +10 -0
  11. package/dist/check/index.d.ts.map +1 -0
  12. package/dist/check/index.js +21 -0
  13. package/dist/check/index.js.map +1 -0
  14. package/dist/check/rules/anti-patterns.d.ts +65 -0
  15. package/dist/check/rules/anti-patterns.d.ts.map +1 -0
  16. package/dist/check/rules/anti-patterns.js +481 -0
  17. package/dist/check/rules/anti-patterns.js.map +1 -0
  18. package/dist/check/rules/closures.d.ts +66 -0
  19. package/dist/check/rules/closures.d.ts.map +1 -0
  20. package/dist/check/rules/closures.js +370 -0
  21. package/dist/check/rules/closures.js.map +1 -0
  22. package/dist/check/rules/collections.d.ts +90 -0
  23. package/dist/check/rules/collections.d.ts.map +1 -0
  24. package/dist/check/rules/collections.js +373 -0
  25. package/dist/check/rules/collections.js.map +1 -0
  26. package/dist/check/rules/conditionals.d.ts +41 -0
  27. package/dist/check/rules/conditionals.d.ts.map +1 -0
  28. package/dist/check/rules/conditionals.js +134 -0
  29. package/dist/check/rules/conditionals.js.map +1 -0
  30. package/dist/check/rules/flow.d.ts +46 -0
  31. package/dist/check/rules/flow.d.ts.map +1 -0
  32. package/dist/check/rules/flow.js +206 -0
  33. package/dist/check/rules/flow.js.map +1 -0
  34. package/dist/check/rules/formatting.d.ts +143 -0
  35. package/dist/check/rules/formatting.d.ts.map +1 -0
  36. package/dist/check/rules/formatting.js +656 -0
  37. package/dist/check/rules/formatting.js.map +1 -0
  38. package/dist/check/rules/helpers.d.ts +26 -0
  39. package/dist/check/rules/helpers.d.ts.map +1 -0
  40. package/dist/check/rules/helpers.js +66 -0
  41. package/dist/check/rules/helpers.js.map +1 -0
  42. package/dist/check/rules/index.d.ts +21 -0
  43. package/dist/check/rules/index.d.ts.map +1 -0
  44. package/dist/check/rules/index.js +78 -0
  45. package/dist/check/rules/index.js.map +1 -0
  46. package/dist/check/rules/loops.d.ts +77 -0
  47. package/dist/check/rules/loops.d.ts.map +1 -0
  48. package/dist/check/rules/loops.js +310 -0
  49. package/dist/check/rules/loops.js.map +1 -0
  50. package/dist/check/rules/naming.d.ts +21 -0
  51. package/dist/check/rules/naming.d.ts.map +1 -0
  52. package/dist/check/rules/naming.js +174 -0
  53. package/dist/check/rules/naming.js.map +1 -0
  54. package/dist/check/rules/strings.d.ts +28 -0
  55. package/dist/check/rules/strings.d.ts.map +1 -0
  56. package/dist/check/rules/strings.js +79 -0
  57. package/dist/check/rules/strings.js.map +1 -0
  58. package/dist/check/rules/types.d.ts +41 -0
  59. package/dist/check/rules/types.d.ts.map +1 -0
  60. package/dist/check/rules/types.js +167 -0
  61. package/dist/check/rules/types.js.map +1 -0
  62. package/dist/check/types.d.ts +112 -0
  63. package/dist/check/types.d.ts.map +1 -0
  64. package/dist/check/types.js +6 -0
  65. package/dist/check/types.js.map +1 -0
  66. package/dist/check/validator.d.ts +18 -0
  67. package/dist/check/validator.d.ts.map +1 -0
  68. package/dist/check/validator.js +110 -0
  69. package/dist/check/validator.js.map +1 -0
  70. package/dist/check/visitor.d.ts +33 -0
  71. package/dist/check/visitor.d.ts.map +1 -0
  72. package/dist/check/visitor.js +259 -0
  73. package/dist/check/visitor.js.map +1 -0
  74. package/dist/cli-check.d.ts +43 -0
  75. package/dist/cli-check.d.ts.map +1 -0
  76. package/dist/cli-check.js +366 -0
  77. package/dist/cli-check.js.map +1 -0
  78. package/dist/cli-error-enrichment.d.ts +73 -0
  79. package/dist/cli-error-enrichment.d.ts.map +1 -0
  80. package/dist/cli-error-enrichment.js +205 -0
  81. package/dist/cli-error-enrichment.js.map +1 -0
  82. package/dist/cli-error-formatter.d.ts +45 -0
  83. package/dist/cli-error-formatter.d.ts.map +1 -0
  84. package/dist/cli-error-formatter.js +218 -0
  85. package/dist/cli-error-formatter.js.map +1 -0
  86. package/dist/cli-eval.d.ts +15 -0
  87. package/dist/cli-eval.d.ts.map +1 -0
  88. package/dist/cli-eval.js +116 -0
  89. package/dist/cli-eval.js.map +1 -0
  90. package/dist/cli-exec.d.ts +58 -0
  91. package/dist/cli-exec.d.ts.map +1 -0
  92. package/dist/cli-exec.js +326 -0
  93. package/dist/cli-exec.js.map +1 -0
  94. package/dist/cli-explain.d.ts +24 -0
  95. package/dist/cli-explain.d.ts.map +1 -0
  96. package/dist/cli-explain.js +68 -0
  97. package/dist/cli-explain.js.map +1 -0
  98. package/dist/cli-lsp-diagnostic.d.ts +35 -0
  99. package/dist/cli-lsp-diagnostic.d.ts.map +1 -0
  100. package/dist/cli-lsp-diagnostic.js +98 -0
  101. package/dist/cli-lsp-diagnostic.js.map +1 -0
  102. package/dist/cli-module-loader.d.ts +19 -0
  103. package/dist/cli-module-loader.d.ts.map +1 -0
  104. package/dist/cli-module-loader.js +83 -0
  105. package/dist/cli-module-loader.js.map +1 -0
  106. package/dist/cli-shared.d.ts +62 -0
  107. package/dist/cli-shared.d.ts.map +1 -0
  108. package/dist/cli-shared.js +158 -0
  109. package/dist/cli-shared.js.map +1 -0
  110. package/dist/cli.d.ts +13 -0
  111. package/dist/cli.d.ts.map +1 -0
  112. package/dist/cli.js +62 -0
  113. package/dist/cli.js.map +1 -0
  114. package/dist/test-internal-import.d.ts +2 -0
  115. package/dist/test-internal-import.d.ts.map +1 -0
  116. package/dist/test-internal-import.js +7 -0
  117. package/dist/test-internal-import.js.map +1 -0
  118. package/package.json +24 -0
  119. package/src/check/config.ts +202 -0
  120. package/src/check/fixer.ts +174 -0
  121. package/src/check/index.ts +39 -0
  122. package/src/check/rules/anti-patterns.ts +585 -0
  123. package/src/check/rules/closures.ts +445 -0
  124. package/src/check/rules/collections.ts +437 -0
  125. package/src/check/rules/conditionals.ts +155 -0
  126. package/src/check/rules/flow.ts +262 -0
  127. package/src/check/rules/formatting.ts +811 -0
  128. package/src/check/rules/helpers.ts +89 -0
  129. package/src/check/rules/index.ts +140 -0
  130. package/src/check/rules/loops.ts +372 -0
  131. package/src/check/rules/naming.ts +242 -0
  132. package/src/check/rules/strings.ts +104 -0
  133. package/src/check/rules/types.ts +214 -0
  134. package/src/check/types.ts +163 -0
  135. package/src/check/validator.ts +136 -0
  136. package/src/check/visitor.ts +338 -0
  137. package/src/cli-check.ts +456 -0
  138. package/src/cli-error-enrichment.ts +274 -0
  139. package/src/cli-error-formatter.ts +313 -0
  140. package/src/cli-eval.ts +145 -0
  141. package/src/cli-exec.ts +408 -0
  142. package/src/cli-explain.ts +76 -0
  143. package/src/cli-lsp-diagnostic.ts +132 -0
  144. package/src/cli-module-loader.ts +101 -0
  145. package/src/cli-shared.ts +187 -0
  146. package/tests/check/cli-check.test.ts +189 -0
  147. package/tests/check/config.test.ts +350 -0
  148. package/tests/check/fixer.test.ts +373 -0
  149. package/tests/check/format-diagnostics.test.ts +327 -0
  150. package/tests/check/rules/anti-patterns.test.ts +467 -0
  151. package/tests/check/rules/closures.test.ts +192 -0
  152. package/tests/check/rules/collections.test.ts +380 -0
  153. package/tests/check/rules/conditionals.test.ts +185 -0
  154. package/tests/check/rules/flow.test.ts +250 -0
  155. package/tests/check/rules/formatting.test.ts +755 -0
  156. package/tests/check/rules/loops.test.ts +334 -0
  157. package/tests/check/rules/naming.test.ts +336 -0
  158. package/tests/check/rules/strings.test.ts +129 -0
  159. package/tests/check/rules/types.test.ts +257 -0
  160. package/tests/check/validator.test.ts +444 -0
  161. package/tests/check/visitor.test.ts +171 -0
  162. package/tests/cli/check.test.ts +801 -0
  163. package/tests/cli/error-enrichment.test.ts +510 -0
  164. package/tests/cli/error-formatter.test.ts +631 -0
  165. package/tests/cli/eval.test.ts +85 -0
  166. package/tests/cli/exec.test.ts +537 -0
  167. package/tests/cli-explain.test.ts +249 -0
  168. package/tests/cli-lsp-diagnostic.test.ts +202 -0
  169. package/tests/cli-shared.test.ts +439 -0
  170. package/tsconfig.json +9 -0
  171. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,174 @@
1
+ /**
2
+ * Fix Applier
3
+ * Apply automatic fixes to source code with collision detection.
4
+ */
5
+
6
+ import { parse } from '@rcrsr/rill';
7
+ import type { Diagnostic, ValidationContext } from './types.js';
8
+
9
+ // ============================================================
10
+ // TYPES
11
+ // ============================================================
12
+
13
+ /**
14
+ * Result of applying fixes to source code.
15
+ */
16
+ export interface ApplyResult {
17
+ /** Modified source code with fixes applied */
18
+ readonly modified: string;
19
+ /** Number of fixes successfully applied */
20
+ readonly applied: number;
21
+ /** Number of fixes skipped */
22
+ readonly skipped: number;
23
+ /** Reasons for skipped fixes */
24
+ readonly skippedReasons: Array<{ code: string; reason: string }>;
25
+ }
26
+
27
+ /**
28
+ * Internal representation of a fix to apply.
29
+ */
30
+ interface ApplicableFix {
31
+ readonly code: string;
32
+ readonly start: number;
33
+ readonly end: number;
34
+ readonly replacement: string;
35
+ }
36
+
37
+ // ============================================================
38
+ // FIX APPLICATION
39
+ // ============================================================
40
+
41
+ /**
42
+ * Apply automatic fixes to source code.
43
+ *
44
+ * Constraints:
45
+ * - Applies fixes in reverse position order (end to start) to avoid offset shifts
46
+ * - Skips fixes where applicable === false
47
+ * - Detects collisions (overlapping ranges) and skips with reason
48
+ * - Verifies modified source parses successfully
49
+ * - Throws if any applied fix creates invalid syntax
50
+ *
51
+ * @param source - Original source code
52
+ * @param diagnostics - Diagnostics with potential fixes
53
+ * @param context - Validation context (unused but required by spec)
54
+ * @returns ApplyResult with modified source and counts
55
+ * @throws Error if applied fixes create invalid syntax [EC-6]
56
+ */
57
+ export function applyFixes(
58
+ source: string,
59
+ diagnostics: Diagnostic[],
60
+ _context: ValidationContext
61
+ ): ApplyResult {
62
+ // Filter to diagnostics with fixes
63
+ const fixableDiagnostics = diagnostics.filter(
64
+ (d) => d.fix !== null && d.fix.applicable
65
+ );
66
+
67
+ // If no applicable fixes, return original
68
+ if (fixableDiagnostics.length === 0) {
69
+ return {
70
+ modified: source,
71
+ applied: 0,
72
+ skipped: 0,
73
+ skippedReasons: [],
74
+ };
75
+ }
76
+
77
+ // Convert to ApplicableFix with positions
78
+ const fixes: ApplicableFix[] = fixableDiagnostics.map((d) => ({
79
+ code: d.code,
80
+ start: d.fix!.range.start.offset,
81
+ end: d.fix!.range.end.offset,
82
+ replacement: d.fix!.replacement,
83
+ }));
84
+
85
+ // Sort fixes by end position (descending) to apply from end to start
86
+ // This avoids offset shifts when applying multiple fixes
87
+ const sortedFixes = fixes.slice().sort((a, b) => b.end - a.end);
88
+
89
+ // Detect collisions and filter to non-overlapping fixes
90
+ const { validFixes, skippedReasons } = filterCollisions(sortedFixes);
91
+
92
+ // Apply fixes to source
93
+ let modified = source;
94
+ for (const fix of validFixes) {
95
+ const before = modified.slice(0, fix.start);
96
+ const after = modified.slice(fix.end);
97
+ modified = before + fix.replacement + after;
98
+ }
99
+
100
+ // Verify modified source parses successfully [EC-6]
101
+ try {
102
+ parse(modified);
103
+ } catch {
104
+ throw new Error('Fix would create invalid syntax');
105
+ }
106
+
107
+ const applied = validFixes.length;
108
+ const skipped = sortedFixes.length - applied;
109
+
110
+ return {
111
+ modified,
112
+ applied,
113
+ skipped,
114
+ skippedReasons,
115
+ };
116
+ }
117
+
118
+ // ============================================================
119
+ // COLLISION DETECTION
120
+ // ============================================================
121
+
122
+ /**
123
+ * Filter fixes to remove overlapping ranges.
124
+ * Detects collisions where fix ranges overlap [EC-5].
125
+ *
126
+ * Strategy: Keep first fix in sorted order (end to start),
127
+ * skip subsequent fixes that overlap with any kept fix.
128
+ *
129
+ * @param sortedFixes - Fixes sorted by end position (descending)
130
+ * @returns Valid fixes and reasons for skipped fixes
131
+ */
132
+ function filterCollisions(sortedFixes: ApplicableFix[]): {
133
+ validFixes: ApplicableFix[];
134
+ skippedReasons: Array<{ code: string; reason: string }>;
135
+ } {
136
+ const validFixes: ApplicableFix[] = [];
137
+ const skippedReasons: Array<{ code: string; reason: string }> = [];
138
+
139
+ for (const fix of sortedFixes) {
140
+ // Check if this fix overlaps with any already-kept fix
141
+ const hasCollision = validFixes.some((kept) => rangesOverlap(fix, kept));
142
+
143
+ if (hasCollision) {
144
+ // Skip this fix due to collision [EC-5]
145
+ skippedReasons.push({
146
+ code: fix.code,
147
+ reason: 'Fix range overlaps with another fix',
148
+ });
149
+ } else {
150
+ // No collision, keep this fix
151
+ validFixes.push(fix);
152
+ }
153
+ }
154
+
155
+ return { validFixes, skippedReasons };
156
+ }
157
+
158
+ /**
159
+ * Check if two fix ranges overlap.
160
+ *
161
+ * Ranges overlap if:
162
+ * - One starts before the other ends, AND
163
+ * - One ends after the other starts
164
+ *
165
+ * @param a - First fix range
166
+ * @param b - Second fix range
167
+ * @returns true if ranges overlap
168
+ */
169
+ function rangesOverlap(
170
+ a: { start: number; end: number },
171
+ b: { start: number; end: number }
172
+ ): boolean {
173
+ return a.start < b.end && a.end > b.start;
174
+ }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Check Module - Static Analysis for rill
3
+ * Public API for rill-check tool.
4
+ */
5
+
6
+ // ============================================================
7
+ // PUBLIC TYPES
8
+ // ============================================================
9
+ export type {
10
+ ValidationRule,
11
+ RuleCategory,
12
+ Severity,
13
+ RuleState,
14
+ Diagnostic,
15
+ Fix,
16
+ CheckConfig,
17
+ ValidationContext,
18
+ FixContext,
19
+ } from './types.js';
20
+
21
+ // ============================================================
22
+ // RULE REGISTRY
23
+ // ============================================================
24
+ export { VALIDATION_RULES } from './rules/index.js';
25
+
26
+ // ============================================================
27
+ // CONFIGURATION
28
+ // ============================================================
29
+ export { loadConfig, createDefaultConfig } from './config.js';
30
+
31
+ // ============================================================
32
+ // VALIDATION
33
+ // ============================================================
34
+ export { validateScript } from './validator.js';
35
+
36
+ // ============================================================
37
+ // FIX APPLICATION
38
+ // ============================================================
39
+ export { applyFixes, type ApplyResult } from './fixer.js';