@rcrsr/rill-cli 0.7.1 → 0.8.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 (57) hide show
  1. package/dist/cli-shared.d.ts.map +1 -1
  2. package/dist/cli-shared.js +3 -1
  3. package/dist/cli-shared.js.map +1 -1
  4. package/package.json +16 -1
  5. package/src/check/config.ts +0 -202
  6. package/src/check/fixer.ts +0 -174
  7. package/src/check/index.ts +0 -39
  8. package/src/check/rules/anti-patterns.ts +0 -585
  9. package/src/check/rules/closures.ts +0 -445
  10. package/src/check/rules/collections.ts +0 -437
  11. package/src/check/rules/conditionals.ts +0 -155
  12. package/src/check/rules/flow.ts +0 -262
  13. package/src/check/rules/formatting.ts +0 -811
  14. package/src/check/rules/helpers.ts +0 -89
  15. package/src/check/rules/index.ts +0 -140
  16. package/src/check/rules/loops.ts +0 -372
  17. package/src/check/rules/naming.ts +0 -242
  18. package/src/check/rules/strings.ts +0 -104
  19. package/src/check/rules/types.ts +0 -213
  20. package/src/check/types.ts +0 -163
  21. package/src/check/validator.ts +0 -136
  22. package/src/check/visitor.ts +0 -338
  23. package/src/cli-check.ts +0 -456
  24. package/src/cli-error-enrichment.ts +0 -274
  25. package/src/cli-error-formatter.ts +0 -313
  26. package/src/cli-eval.ts +0 -145
  27. package/src/cli-exec.ts +0 -408
  28. package/src/cli-explain.ts +0 -76
  29. package/src/cli-lsp-diagnostic.ts +0 -132
  30. package/src/cli-module-loader.ts +0 -101
  31. package/src/cli-shared.ts +0 -187
  32. package/tests/check/cli-check.test.ts +0 -189
  33. package/tests/check/config.test.ts +0 -350
  34. package/tests/check/fixer.test.ts +0 -373
  35. package/tests/check/format-diagnostics.test.ts +0 -327
  36. package/tests/check/rules/anti-patterns.test.ts +0 -467
  37. package/tests/check/rules/closures.test.ts +0 -192
  38. package/tests/check/rules/collections.test.ts +0 -380
  39. package/tests/check/rules/conditionals.test.ts +0 -185
  40. package/tests/check/rules/flow.test.ts +0 -250
  41. package/tests/check/rules/formatting.test.ts +0 -755
  42. package/tests/check/rules/loops.test.ts +0 -334
  43. package/tests/check/rules/naming.test.ts +0 -336
  44. package/tests/check/rules/strings.test.ts +0 -129
  45. package/tests/check/rules/types.test.ts +0 -233
  46. package/tests/check/validator.test.ts +0 -444
  47. package/tests/check/visitor.test.ts +0 -171
  48. package/tests/cli/check.test.ts +0 -801
  49. package/tests/cli/error-enrichment.test.ts +0 -510
  50. package/tests/cli/error-formatter.test.ts +0 -631
  51. package/tests/cli/eval.test.ts +0 -85
  52. package/tests/cli/exec.test.ts +0 -537
  53. package/tests/cli-explain.test.ts +0 -249
  54. package/tests/cli-lsp-diagnostic.test.ts +0 -202
  55. package/tests/cli-shared.test.ts +0 -439
  56. package/tsconfig.json +0 -9
  57. package/tsconfig.tsbuildinfo +0 -1
@@ -1,129 +0,0 @@
1
- /**
2
- * String Handling Convention Rules Tests
3
- * Verify string handling convention enforcement.
4
- */
5
-
6
- import { describe, it, expect } from 'vitest';
7
- import { parse } from '@rcrsr/rill';
8
- import { validateScript } from '../../../src/check/validator.js';
9
- import type { CheckConfig } from '../../../src/check/types.js';
10
-
11
- // ============================================================
12
- // TEST HELPERS
13
- // ============================================================
14
-
15
- /**
16
- * Create a config with string rules enabled.
17
- */
18
- function createConfig(rules: Record<string, 'on' | 'off'> = {}): CheckConfig {
19
- return {
20
- rules: {
21
- USE_EMPTY_METHOD: 'on',
22
- ...rules,
23
- },
24
- severity: {},
25
- };
26
- }
27
-
28
- /**
29
- * Validate source and extract diagnostic messages.
30
- */
31
- function getDiagnostics(source: string, config?: CheckConfig): string[] {
32
- const ast = parse(source);
33
- const diagnostics = validateScript(ast, source, config ?? createConfig());
34
- return diagnostics.map((d) => d.message);
35
- }
36
-
37
- /**
38
- * Validate source and check for violations.
39
- */
40
- function hasViolations(source: string, config?: CheckConfig): boolean {
41
- const ast = parse(source);
42
- const diagnostics = validateScript(ast, source, config ?? createConfig());
43
- return diagnostics.length > 0;
44
- }
45
-
46
- /**
47
- * Validate source and get diagnostic codes.
48
- */
49
- function getCodes(source: string, config?: CheckConfig): string[] {
50
- const ast = parse(source);
51
- const diagnostics = validateScript(ast, source, config ?? createConfig());
52
- return diagnostics.map((d) => d.code);
53
- }
54
-
55
- // ============================================================
56
- // USE_EMPTY_METHOD TESTS
57
- // ============================================================
58
-
59
- describe('USE_EMPTY_METHOD', () => {
60
- const config = createConfig();
61
-
62
- it('accepts .empty method usage', () => {
63
- expect(hasViolations('$str -> .empty', config)).toBe(false);
64
- });
65
-
66
- it('accepts comparisons not involving empty strings', () => {
67
- expect(hasViolations('$str == "hello"', config)).toBe(false);
68
- });
69
-
70
- it('warns on equality comparison with empty string', () => {
71
- const source = '$str == ""';
72
-
73
- const messages = getDiagnostics(source, config);
74
- expect(messages.length).toBeGreaterThan(0);
75
- expect(messages[0]).toContain('Use .empty');
76
- expect(messages[0]).toContain('comparing with ""');
77
- });
78
-
79
- it('warns on inequality comparison with empty string', () => {
80
- const source = '$str != ""';
81
-
82
- const messages = getDiagnostics(source, config);
83
- expect(messages.length).toBeGreaterThan(0);
84
- expect(messages[0]).toContain('Use .empty');
85
- });
86
-
87
- it('suggests correct method for equality', () => {
88
- const source = '$str == ""';
89
-
90
- const messages = getDiagnostics(source, config);
91
- expect(messages.length).toBeGreaterThan(0);
92
- expect(messages[0]).toContain('.empty');
93
- });
94
-
95
- it('suggests correct method for inequality', () => {
96
- const source = '$str != ""';
97
-
98
- const messages = getDiagnostics(source, config);
99
- expect(messages.length).toBeGreaterThan(0);
100
- expect(messages[0]).toContain('.empty -> !');
101
- });
102
-
103
- it('detects empty string on left side', () => {
104
- const source = '"" == $str';
105
-
106
- const messages = getDiagnostics(source, config);
107
- expect(messages.length).toBeGreaterThan(0);
108
- expect(messages[0]).toContain('Use .empty');
109
- });
110
-
111
- it('has correct severity and code', () => {
112
- const source = '$str == ""';
113
- const ast = parse(source);
114
- const diagnostics = validateScript(ast, source, config);
115
-
116
- expect(diagnostics.length).toBeGreaterThan(0);
117
- expect(diagnostics[0]?.code).toBe('USE_EMPTY_METHOD');
118
- expect(diagnostics[0]?.severity).toBe('warning');
119
- });
120
-
121
- it('does not provide auto-fix', () => {
122
- const source = '$str == ""';
123
- const ast = parse(source);
124
- const diagnostics = validateScript(ast, source, config);
125
-
126
- expect(diagnostics.length).toBeGreaterThan(0);
127
- expect(diagnostics[0]?.fix).toBeNull();
128
- });
129
- });
@@ -1,233 +0,0 @@
1
- /**
2
- * Type Safety Convention Rules Tests
3
- * Verify type safety convention enforcement.
4
- */
5
-
6
- import { describe, it, expect } from 'vitest';
7
- import { parse } from '@rcrsr/rill';
8
- import { validateScript } from '../../../src/check/validator.js';
9
- import type { CheckConfig, Fix } from '../../../src/check/types.js';
10
-
11
- /**
12
- * Apply a single fix to source code.
13
- */
14
- function applyFix(source: string, fix: Fix): string {
15
- const before = source.slice(0, fix.range.start.offset);
16
- const after = source.slice(fix.range.end.offset);
17
- return before + fix.replacement + after;
18
- }
19
-
20
- // ============================================================
21
- // TEST HELPERS
22
- // ============================================================
23
-
24
- /**
25
- * Create a config with type rules enabled.
26
- */
27
- function createConfig(rules: Record<string, 'on' | 'off'> = {}): CheckConfig {
28
- return {
29
- rules: {
30
- UNNECESSARY_ASSERTION: 'on',
31
- VALIDATE_EXTERNAL: 'on',
32
- ...rules,
33
- },
34
- severity: {},
35
- };
36
- }
37
-
38
- /**
39
- * Validate source and extract diagnostic messages.
40
- */
41
- function getDiagnostics(source: string, config?: CheckConfig): string[] {
42
- const ast = parse(source);
43
- const diagnostics = validateScript(ast, source, config ?? createConfig());
44
- return diagnostics.map((d) => d.message);
45
- }
46
-
47
- /**
48
- * Validate source and check for violations.
49
- */
50
- function hasViolations(source: string, config?: CheckConfig): boolean {
51
- const ast = parse(source);
52
- const diagnostics = validateScript(ast, source, config ?? createConfig());
53
- return diagnostics.length > 0;
54
- }
55
-
56
- // ============================================================
57
- // UNNECESSARY_ASSERTION TESTS
58
- // ============================================================
59
-
60
- describe('UNNECESSARY_ASSERTION', () => {
61
- const config = createConfig({ VALIDATE_EXTERNAL: 'off' });
62
-
63
- it('accepts assertions on variables', () => {
64
- expect(hasViolations('$val:number', config)).toBe(false);
65
- });
66
-
67
- it('accepts assertions on function results', () => {
68
- expect(hasViolations('getData():dict', config)).toBe(false);
69
- });
70
-
71
- it('accepts bare type assertions', () => {
72
- expect(hasViolations('$ -> :string', config)).toBe(false);
73
- });
74
-
75
- it('detects unnecessary number assertion', () => {
76
- const source = '5:number => $n';
77
-
78
- const messages = getDiagnostics(source, config);
79
- expect(messages.length).toBeGreaterThan(0);
80
- expect(messages[0]).toContain('unnecessary');
81
- expect(messages[0]).toContain('number literal');
82
- });
83
-
84
- it('detects unnecessary string assertion', () => {
85
- const source = '"hello":string => $s';
86
-
87
- const messages = getDiagnostics(source, config);
88
- expect(messages.length).toBeGreaterThan(0);
89
- expect(messages[0]).toContain('unnecessary');
90
- expect(messages[0]).toContain('string literal');
91
- });
92
-
93
- it('detects unnecessary bool assertion', () => {
94
- const source = 'true:bool => $b';
95
-
96
- const messages = getDiagnostics(source, config);
97
- expect(messages.length).toBeGreaterThan(0);
98
- expect(messages[0]).toContain('unnecessary');
99
- expect(messages[0]).toContain('bool literal');
100
- });
101
-
102
- it('has correct severity and code', () => {
103
- const source = '42:number';
104
- const ast = parse(source);
105
- const diagnostics = validateScript(ast, source, config);
106
-
107
- expect(diagnostics.length).toBeGreaterThan(0);
108
- expect(diagnostics[0]?.code).toBe('UNNECESSARY_ASSERTION');
109
- expect(diagnostics[0]?.severity).toBe('info');
110
- });
111
-
112
- it('provides fix to remove assertion', () => {
113
- const source = '5:number => $n';
114
- const ast = parse(source);
115
- const diagnostics = validateScript(ast, source, config);
116
-
117
- expect(diagnostics.length).toBeGreaterThan(0);
118
- const diagnostic = diagnostics[0];
119
- expect(diagnostic?.fix).toBeDefined();
120
- expect(diagnostic?.fix?.applicable).toBe(true);
121
- expect(diagnostic?.fix?.description).toContain('Remove unnecessary');
122
- });
123
-
124
- it('fix removes assertion correctly', () => {
125
- const source = '5:number => $n';
126
- const ast = parse(source);
127
- const diagnostics = validateScript(ast, source, config);
128
-
129
- expect(diagnostics.length).toBeGreaterThan(0);
130
- const diagnostic = diagnostics[0];
131
- if (diagnostic?.fix) {
132
- const fixed = applyFix(source, diagnostic.fix);
133
- expect(fixed).toBe('5 => $n');
134
- }
135
- });
136
-
137
- it('fix handles string assertions', () => {
138
- const source = '"test":string => $s';
139
- const ast = parse(source);
140
- const diagnostics = validateScript(ast, source, config);
141
-
142
- expect(diagnostics.length).toBeGreaterThan(0);
143
- const diagnostic = diagnostics[0];
144
- if (diagnostic?.fix) {
145
- const fixed = applyFix(source, diagnostic.fix);
146
- expect(fixed).toBe('"test" => $s');
147
- }
148
- });
149
- });
150
-
151
- // ============================================================
152
- // VALIDATE_EXTERNAL TESTS
153
- // ============================================================
154
-
155
- describe('VALIDATE_EXTERNAL', () => {
156
- const config = createConfig({ UNNECESSARY_ASSERTION: 'off' });
157
-
158
- it('recommends validation for fetch functions', () => {
159
- const source = 'fetch_data($url)';
160
-
161
- const messages = getDiagnostics(source, config);
162
- expect(messages.length).toBeGreaterThan(0);
163
- expect(messages[0]).toContain('external input');
164
- });
165
-
166
- it('recommends validation for read functions', () => {
167
- const source = 'read_file($path)';
168
-
169
- const messages = getDiagnostics(source, config);
170
- expect(messages.length).toBeGreaterThan(0);
171
- expect(messages[0]).toContain('external input');
172
- });
173
-
174
- it('does not warn on non-external functions', () => {
175
- expect(hasViolations('compute($x)', config)).toBe(false);
176
- });
177
-
178
- it('has correct severity and code', () => {
179
- const source = 'fetch_data($url)';
180
- const ast = parse(source);
181
- const diagnostics = validateScript(ast, source, config);
182
-
183
- expect(diagnostics.length).toBeGreaterThan(0);
184
- expect(diagnostics[0]?.code).toBe('VALIDATE_EXTERNAL');
185
- expect(diagnostics[0]?.severity).toBe('info');
186
- });
187
-
188
- it('does not provide auto-fix', () => {
189
- const source = 'fetch_data($url)';
190
- const ast = parse(source);
191
- const diagnostics = validateScript(ast, source, config);
192
-
193
- expect(diagnostics.length).toBeGreaterThan(0);
194
- expect(diagnostics[0]?.fix).toBeNull();
195
- });
196
-
197
- it('does not warn when already type-asserted (simple case)', () => {
198
- const source = 'fetch_data($url):dict';
199
-
200
- const violations = hasViolations(source, config);
201
- expect(violations).toBe(false);
202
- });
203
-
204
- it('does not warn when already type-asserted (with property access)', () => {
205
- const source = 'ccr::read_frontmatter($path, [status: ""]):dict.status';
206
-
207
- const violations = hasViolations(source, config);
208
- expect(violations).toBe(false);
209
- });
210
-
211
- it('does not warn when already type-asserted (namespaced function)', () => {
212
- const source = 'io::read_file($path):string';
213
-
214
- const violations = hasViolations(source, config);
215
- expect(violations).toBe(false);
216
- });
217
-
218
- it('does not warn for namespaced functions (trusted host APIs)', () => {
219
- // Namespaced functions like ccr::read_frontmatter are trusted host APIs
220
- const source = 'ccr::read_frontmatter($path)';
221
-
222
- const violations = hasViolations(source, config);
223
- expect(violations).toBe(false);
224
- });
225
-
226
- it('does not warn for parse_ prefix functions (transformations, not external data)', () => {
227
- // parse_* functions are transformations, not external data sources
228
- const source = 'parse_something($text)';
229
-
230
- const violations = hasViolations(source, config);
231
- expect(violations).toBe(false);
232
- });
233
- });