@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.
- package/LICENSE +21 -0
- package/dist/check/config.d.ts +20 -0
- package/dist/check/config.d.ts.map +1 -0
- package/dist/check/config.js +151 -0
- package/dist/check/config.js.map +1 -0
- package/dist/check/fixer.d.ts +39 -0
- package/dist/check/fixer.d.ts.map +1 -0
- package/dist/check/fixer.js +119 -0
- package/dist/check/fixer.js.map +1 -0
- package/dist/check/index.d.ts +10 -0
- package/dist/check/index.d.ts.map +1 -0
- package/dist/check/index.js +21 -0
- package/dist/check/index.js.map +1 -0
- package/dist/check/rules/anti-patterns.d.ts +65 -0
- package/dist/check/rules/anti-patterns.d.ts.map +1 -0
- package/dist/check/rules/anti-patterns.js +481 -0
- package/dist/check/rules/anti-patterns.js.map +1 -0
- package/dist/check/rules/closures.d.ts +66 -0
- package/dist/check/rules/closures.d.ts.map +1 -0
- package/dist/check/rules/closures.js +370 -0
- package/dist/check/rules/closures.js.map +1 -0
- package/dist/check/rules/collections.d.ts +90 -0
- package/dist/check/rules/collections.d.ts.map +1 -0
- package/dist/check/rules/collections.js +373 -0
- package/dist/check/rules/collections.js.map +1 -0
- package/dist/check/rules/conditionals.d.ts +41 -0
- package/dist/check/rules/conditionals.d.ts.map +1 -0
- package/dist/check/rules/conditionals.js +134 -0
- package/dist/check/rules/conditionals.js.map +1 -0
- package/dist/check/rules/flow.d.ts +46 -0
- package/dist/check/rules/flow.d.ts.map +1 -0
- package/dist/check/rules/flow.js +206 -0
- package/dist/check/rules/flow.js.map +1 -0
- package/dist/check/rules/formatting.d.ts +143 -0
- package/dist/check/rules/formatting.d.ts.map +1 -0
- package/dist/check/rules/formatting.js +656 -0
- package/dist/check/rules/formatting.js.map +1 -0
- package/dist/check/rules/helpers.d.ts +26 -0
- package/dist/check/rules/helpers.d.ts.map +1 -0
- package/dist/check/rules/helpers.js +66 -0
- package/dist/check/rules/helpers.js.map +1 -0
- package/dist/check/rules/index.d.ts +21 -0
- package/dist/check/rules/index.d.ts.map +1 -0
- package/dist/check/rules/index.js +78 -0
- package/dist/check/rules/index.js.map +1 -0
- package/dist/check/rules/loops.d.ts +77 -0
- package/dist/check/rules/loops.d.ts.map +1 -0
- package/dist/check/rules/loops.js +310 -0
- package/dist/check/rules/loops.js.map +1 -0
- package/dist/check/rules/naming.d.ts +21 -0
- package/dist/check/rules/naming.d.ts.map +1 -0
- package/dist/check/rules/naming.js +174 -0
- package/dist/check/rules/naming.js.map +1 -0
- package/dist/check/rules/strings.d.ts +28 -0
- package/dist/check/rules/strings.d.ts.map +1 -0
- package/dist/check/rules/strings.js +79 -0
- package/dist/check/rules/strings.js.map +1 -0
- package/dist/check/rules/types.d.ts +41 -0
- package/dist/check/rules/types.d.ts.map +1 -0
- package/dist/check/rules/types.js +167 -0
- package/dist/check/rules/types.js.map +1 -0
- package/dist/check/types.d.ts +112 -0
- package/dist/check/types.d.ts.map +1 -0
- package/dist/check/types.js +6 -0
- package/dist/check/types.js.map +1 -0
- package/dist/check/validator.d.ts +18 -0
- package/dist/check/validator.d.ts.map +1 -0
- package/dist/check/validator.js +110 -0
- package/dist/check/validator.js.map +1 -0
- package/dist/check/visitor.d.ts +33 -0
- package/dist/check/visitor.d.ts.map +1 -0
- package/dist/check/visitor.js +259 -0
- package/dist/check/visitor.js.map +1 -0
- package/dist/cli-check.d.ts +43 -0
- package/dist/cli-check.d.ts.map +1 -0
- package/dist/cli-check.js +366 -0
- package/dist/cli-check.js.map +1 -0
- package/dist/cli-error-enrichment.d.ts +73 -0
- package/dist/cli-error-enrichment.d.ts.map +1 -0
- package/dist/cli-error-enrichment.js +205 -0
- package/dist/cli-error-enrichment.js.map +1 -0
- package/dist/cli-error-formatter.d.ts +45 -0
- package/dist/cli-error-formatter.d.ts.map +1 -0
- package/dist/cli-error-formatter.js +218 -0
- package/dist/cli-error-formatter.js.map +1 -0
- package/dist/cli-eval.d.ts +15 -0
- package/dist/cli-eval.d.ts.map +1 -0
- package/dist/cli-eval.js +116 -0
- package/dist/cli-eval.js.map +1 -0
- package/dist/cli-exec.d.ts +58 -0
- package/dist/cli-exec.d.ts.map +1 -0
- package/dist/cli-exec.js +326 -0
- package/dist/cli-exec.js.map +1 -0
- package/dist/cli-explain.d.ts +24 -0
- package/dist/cli-explain.d.ts.map +1 -0
- package/dist/cli-explain.js +68 -0
- package/dist/cli-explain.js.map +1 -0
- package/dist/cli-lsp-diagnostic.d.ts +35 -0
- package/dist/cli-lsp-diagnostic.d.ts.map +1 -0
- package/dist/cli-lsp-diagnostic.js +98 -0
- package/dist/cli-lsp-diagnostic.js.map +1 -0
- package/dist/cli-module-loader.d.ts +19 -0
- package/dist/cli-module-loader.d.ts.map +1 -0
- package/dist/cli-module-loader.js +83 -0
- package/dist/cli-module-loader.js.map +1 -0
- package/dist/cli-shared.d.ts +62 -0
- package/dist/cli-shared.d.ts.map +1 -0
- package/dist/cli-shared.js +158 -0
- package/dist/cli-shared.js.map +1 -0
- package/dist/cli.d.ts +13 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +62 -0
- package/dist/cli.js.map +1 -0
- package/dist/test-internal-import.d.ts +2 -0
- package/dist/test-internal-import.d.ts.map +1 -0
- package/dist/test-internal-import.js +7 -0
- package/dist/test-internal-import.js.map +1 -0
- package/package.json +24 -0
- package/src/check/config.ts +202 -0
- package/src/check/fixer.ts +174 -0
- package/src/check/index.ts +39 -0
- package/src/check/rules/anti-patterns.ts +585 -0
- package/src/check/rules/closures.ts +445 -0
- package/src/check/rules/collections.ts +437 -0
- package/src/check/rules/conditionals.ts +155 -0
- package/src/check/rules/flow.ts +262 -0
- package/src/check/rules/formatting.ts +811 -0
- package/src/check/rules/helpers.ts +89 -0
- package/src/check/rules/index.ts +140 -0
- package/src/check/rules/loops.ts +372 -0
- package/src/check/rules/naming.ts +242 -0
- package/src/check/rules/strings.ts +104 -0
- package/src/check/rules/types.ts +214 -0
- package/src/check/types.ts +163 -0
- package/src/check/validator.ts +136 -0
- package/src/check/visitor.ts +338 -0
- package/src/cli-check.ts +456 -0
- package/src/cli-error-enrichment.ts +274 -0
- package/src/cli-error-formatter.ts +313 -0
- package/src/cli-eval.ts +145 -0
- package/src/cli-exec.ts +408 -0
- package/src/cli-explain.ts +76 -0
- package/src/cli-lsp-diagnostic.ts +132 -0
- package/src/cli-module-loader.ts +101 -0
- package/src/cli-shared.ts +187 -0
- package/tests/check/cli-check.test.ts +189 -0
- package/tests/check/config.test.ts +350 -0
- package/tests/check/fixer.test.ts +373 -0
- package/tests/check/format-diagnostics.test.ts +327 -0
- package/tests/check/rules/anti-patterns.test.ts +467 -0
- package/tests/check/rules/closures.test.ts +192 -0
- package/tests/check/rules/collections.test.ts +380 -0
- package/tests/check/rules/conditionals.test.ts +185 -0
- package/tests/check/rules/flow.test.ts +250 -0
- package/tests/check/rules/formatting.test.ts +755 -0
- package/tests/check/rules/loops.test.ts +334 -0
- package/tests/check/rules/naming.test.ts +336 -0
- package/tests/check/rules/strings.test.ts +129 -0
- package/tests/check/rules/types.test.ts +257 -0
- package/tests/check/validator.test.ts +444 -0
- package/tests/check/visitor.test.ts +171 -0
- package/tests/cli/check.test.ts +801 -0
- package/tests/cli/error-enrichment.test.ts +510 -0
- package/tests/cli/error-formatter.test.ts +631 -0
- package/tests/cli/eval.test.ts +85 -0
- package/tests/cli/exec.test.ts +537 -0
- package/tests/cli-explain.test.ts +249 -0
- package/tests/cli-lsp-diagnostic.test.ts +202 -0
- package/tests/cli-shared.test.ts +439 -0
- package/tsconfig.json +9 -0
- 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';
|