@rcrsr/rill 0.1.0 → 0.2.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 (260) hide show
  1. package/README.md +16 -8
  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 +427 -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 +373 -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 +106 -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 +133 -0
  35. package/dist/check/rules/formatting.d.ts.map +1 -0
  36. package/dist/check/rules/formatting.js +639 -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 +70 -0
  47. package/dist/check/rules/loops.d.ts.map +1 -0
  48. package/dist/check/rules/loops.js +227 -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 +167 -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 +80 -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 +162 -0
  61. package/dist/check/rules/types.js.map +1 -0
  62. package/dist/check/types.d.ts +106 -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 +88 -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 +243 -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 +356 -0
  77. package/dist/cli-check.js.map +1 -0
  78. package/dist/cli-eval.d.ts +15 -0
  79. package/dist/cli-eval.d.ts.map +1 -0
  80. package/dist/cli-eval.js +120 -0
  81. package/dist/cli-eval.js.map +1 -0
  82. package/dist/cli-exec.d.ts +49 -0
  83. package/dist/cli-exec.d.ts.map +1 -0
  84. package/dist/cli-exec.js +191 -0
  85. package/dist/cli-exec.js.map +1 -0
  86. package/dist/cli-module-loader.d.ts +19 -0
  87. package/dist/cli-module-loader.d.ts.map +1 -0
  88. package/dist/cli-module-loader.js +83 -0
  89. package/dist/cli-module-loader.js.map +1 -0
  90. package/dist/cli-shared.d.ts +36 -0
  91. package/dist/cli-shared.d.ts.map +1 -0
  92. package/dist/cli-shared.js +101 -0
  93. package/dist/cli-shared.js.map +1 -0
  94. package/dist/cli.d.ts +2 -0
  95. package/dist/cli.d.ts.map +1 -1
  96. package/dist/cli.js +4 -11
  97. package/dist/cli.js.map +1 -1
  98. package/dist/index.d.ts +1 -1
  99. package/dist/index.d.ts.map +1 -1
  100. package/dist/index.js +1 -1
  101. package/dist/index.js.map +1 -1
  102. package/dist/lexer/readers.d.ts +1 -1
  103. package/dist/lexer/readers.d.ts.map +1 -1
  104. package/dist/lexer/readers.js +62 -32
  105. package/dist/lexer/readers.js.map +1 -1
  106. package/dist/lexer/tokenizer.d.ts.map +1 -1
  107. package/dist/lexer/tokenizer.js +5 -6
  108. package/dist/lexer/tokenizer.js.map +1 -1
  109. package/dist/parser/index.js +1 -1
  110. package/dist/parser/index.js.map +1 -1
  111. package/dist/parser/parser-expr.js +23 -5
  112. package/dist/parser/parser-expr.js.map +1 -1
  113. package/dist/parser/parser-functions.d.ts +2 -2
  114. package/dist/parser/parser-functions.d.ts.map +1 -1
  115. package/dist/parser/parser-functions.js +2 -1
  116. package/dist/parser/parser-functions.js.map +1 -1
  117. package/dist/parser/parser-literals.js +2 -2
  118. package/dist/parser/parser-literals.js.map +1 -1
  119. package/dist/parser/parser-script.js +9 -7
  120. package/dist/parser/parser-script.js.map +1 -1
  121. package/dist/parser/parser-variables.js +4 -3
  122. package/dist/parser/parser-variables.js.map +1 -1
  123. package/dist/runtime/core/callable.d.ts +5 -6
  124. package/dist/runtime/core/callable.d.ts.map +1 -1
  125. package/dist/runtime/core/callable.js.map +1 -1
  126. package/dist/runtime/core/context.d.ts.map +1 -1
  127. package/dist/runtime/core/context.js +19 -32
  128. package/dist/runtime/core/context.js.map +1 -1
  129. package/dist/runtime/core/equals.js +1 -1
  130. package/dist/runtime/core/equals.js.map +1 -1
  131. package/dist/runtime/core/eval/evaluator.d.ts +78 -0
  132. package/dist/runtime/core/eval/evaluator.d.ts.map +1 -1
  133. package/dist/runtime/core/eval/evaluator.js +78 -0
  134. package/dist/runtime/core/eval/evaluator.js.map +1 -1
  135. package/dist/runtime/core/eval/mixins/closures.d.ts.map +1 -1
  136. package/dist/runtime/core/eval/mixins/closures.js +9 -1
  137. package/dist/runtime/core/eval/mixins/closures.js.map +1 -1
  138. package/dist/runtime/core/eval/mixins/variables.d.ts.map +1 -1
  139. package/dist/runtime/core/eval/mixins/variables.js +143 -2
  140. package/dist/runtime/core/eval/mixins/variables.js.map +1 -1
  141. package/dist/runtime/core/types.d.ts +15 -2
  142. package/dist/runtime/core/types.d.ts.map +1 -1
  143. package/dist/runtime/core/types.js.map +1 -1
  144. package/dist/runtime/ext/extensions.d.ts +51 -0
  145. package/dist/runtime/ext/extensions.d.ts.map +1 -0
  146. package/dist/runtime/ext/extensions.js +67 -0
  147. package/dist/runtime/ext/extensions.js.map +1 -0
  148. package/dist/runtime/index.d.ts +3 -0
  149. package/dist/runtime/index.d.ts.map +1 -1
  150. package/dist/runtime/index.js +1 -0
  151. package/dist/runtime/index.js.map +1 -1
  152. package/dist/types.d.ts +8 -4
  153. package/dist/types.d.ts.map +1 -1
  154. package/dist/types.js +5 -4
  155. package/dist/types.js.map +1 -1
  156. package/docs/00_INDEX.md +1 -0
  157. package/docs/01_guide.md +3 -3
  158. package/docs/02_types.md +8 -10
  159. package/docs/03_variables.md +10 -0
  160. package/docs/04_operators.md +3 -3
  161. package/docs/05_control-flow.md +21 -0
  162. package/docs/07_collections.md +2 -0
  163. package/docs/10_parsing.md +9 -9
  164. package/docs/11_reference.md +1 -1
  165. package/docs/12_examples.md +36 -62
  166. package/docs/14_host-integration.md +116 -111
  167. package/docs/15_grammar.ebnf +1 -5
  168. package/docs/16_conventions.md +3 -4
  169. package/docs/17_cli-tools.md +184 -0
  170. package/docs/99_llm-reference.txt +46 -5
  171. package/package.json +13 -4
  172. package/dist/demo.d.ts +0 -6
  173. package/dist/demo.d.ts.map +0 -1
  174. package/dist/demo.js +0 -121
  175. package/dist/demo.js.map +0 -1
  176. package/dist/lexer.d.ts +0 -19
  177. package/dist/lexer.d.ts.map +0 -1
  178. package/dist/lexer.js +0 -344
  179. package/dist/lexer.js.map +0 -1
  180. package/dist/parser/arithmetic.d.ts +0 -16
  181. package/dist/parser/arithmetic.d.ts.map +0 -1
  182. package/dist/parser/arithmetic.js +0 -128
  183. package/dist/parser/arithmetic.js.map +0 -1
  184. package/dist/parser/boolean.d.ts +0 -15
  185. package/dist/parser/boolean.d.ts.map +0 -1
  186. package/dist/parser/boolean.js +0 -20
  187. package/dist/parser/boolean.js.map +0 -1
  188. package/dist/parser/control-flow.d.ts +0 -56
  189. package/dist/parser/control-flow.d.ts.map +0 -1
  190. package/dist/parser/control-flow.js +0 -167
  191. package/dist/parser/control-flow.js.map +0 -1
  192. package/dist/parser/expressions.d.ts +0 -23
  193. package/dist/parser/expressions.d.ts.map +0 -1
  194. package/dist/parser/expressions.js +0 -950
  195. package/dist/parser/expressions.js.map +0 -1
  196. package/dist/parser/extraction.d.ts +0 -48
  197. package/dist/parser/extraction.d.ts.map +0 -1
  198. package/dist/parser/extraction.js +0 -279
  199. package/dist/parser/extraction.js.map +0 -1
  200. package/dist/parser/functions.d.ts +0 -20
  201. package/dist/parser/functions.d.ts.map +0 -1
  202. package/dist/parser/functions.js +0 -96
  203. package/dist/parser/functions.js.map +0 -1
  204. package/dist/parser/literals.d.ts +0 -37
  205. package/dist/parser/literals.d.ts.map +0 -1
  206. package/dist/parser/literals.js +0 -373
  207. package/dist/parser/literals.js.map +0 -1
  208. package/dist/parser/script.d.ts +0 -14
  209. package/dist/parser/script.d.ts.map +0 -1
  210. package/dist/parser/script.js +0 -196
  211. package/dist/parser/script.js.map +0 -1
  212. package/dist/parser/variables.d.ts +0 -10
  213. package/dist/parser/variables.d.ts.map +0 -1
  214. package/dist/parser/variables.js +0 -215
  215. package/dist/parser/variables.js.map +0 -1
  216. package/dist/runtime/ast-equals.d.ts +0 -13
  217. package/dist/runtime/ast-equals.d.ts.map +0 -1
  218. package/dist/runtime/ast-equals.js +0 -447
  219. package/dist/runtime/ast-equals.js.map +0 -1
  220. package/dist/runtime/builtins.d.ts +0 -13
  221. package/dist/runtime/builtins.d.ts.map +0 -1
  222. package/dist/runtime/builtins.js +0 -180
  223. package/dist/runtime/builtins.js.map +0 -1
  224. package/dist/runtime/callable.d.ts +0 -88
  225. package/dist/runtime/callable.d.ts.map +0 -1
  226. package/dist/runtime/callable.js +0 -98
  227. package/dist/runtime/callable.js.map +0 -1
  228. package/dist/runtime/context.d.ts +0 -13
  229. package/dist/runtime/context.d.ts.map +0 -1
  230. package/dist/runtime/context.js +0 -73
  231. package/dist/runtime/context.js.map +0 -1
  232. package/dist/runtime/core/evaluate.d.ts +0 -42
  233. package/dist/runtime/core/evaluate.d.ts.map +0 -1
  234. package/dist/runtime/core/evaluate.debug.js +0 -1251
  235. package/dist/runtime/core/evaluate.js +0 -1913
  236. package/dist/runtime/core/evaluate.js.map +0 -1
  237. package/dist/runtime/evaluate.d.ts +0 -32
  238. package/dist/runtime/evaluate.d.ts.map +0 -1
  239. package/dist/runtime/evaluate.js +0 -1111
  240. package/dist/runtime/evaluate.js.map +0 -1
  241. package/dist/runtime/execute.d.ts +0 -26
  242. package/dist/runtime/execute.d.ts.map +0 -1
  243. package/dist/runtime/execute.js +0 -121
  244. package/dist/runtime/execute.js.map +0 -1
  245. package/dist/runtime/signals.d.ts +0 -19
  246. package/dist/runtime/signals.d.ts.map +0 -1
  247. package/dist/runtime/signals.js +0 -26
  248. package/dist/runtime/signals.js.map +0 -1
  249. package/dist/runtime/types.d.ts +0 -169
  250. package/dist/runtime/types.d.ts.map +0 -1
  251. package/dist/runtime/types.js +0 -50
  252. package/dist/runtime/types.js.map +0 -1
  253. package/dist/runtime/values.d.ts +0 -50
  254. package/dist/runtime/values.d.ts.map +0 -1
  255. package/dist/runtime/values.js +0 -209
  256. package/dist/runtime/values.js.map +0 -1
  257. package/dist/runtime.d.ts +0 -254
  258. package/dist/runtime.d.ts.map +0 -1
  259. package/dist/runtime.js +0 -2014
  260. package/dist/runtime.js.map +0 -1
@@ -0,0 +1,167 @@
1
+ /**
2
+ * Naming Convention Rules
3
+ * Enforces snake_case naming for variables, parameters, and dict keys.
4
+ */
5
+ import { extractContextLine } from './helpers.js';
6
+ // ============================================================
7
+ // NAMING VALIDATION
8
+ // ============================================================
9
+ /**
10
+ * Check if a name follows snake_case convention.
11
+ * Valid: user_name, item_list, is_valid, x, count
12
+ * Invalid: userName, ItemList, user-name, user.name
13
+ */
14
+ function isSnakeCase(name) {
15
+ // Empty string is invalid
16
+ if (!name)
17
+ return false;
18
+ // Must match: lowercase letters, numbers, underscores only
19
+ // Must start with letter or underscore
20
+ // No consecutive underscores, no trailing underscore
21
+ const snakeCasePattern = /^[a-z_][a-z0-9_]*$/;
22
+ if (!snakeCasePattern.test(name))
23
+ return false;
24
+ // Reject consecutive underscores
25
+ if (name.includes('__'))
26
+ return false;
27
+ // Reject trailing underscore (unless single underscore)
28
+ if (name.length > 1 && name.endsWith('_'))
29
+ return false;
30
+ return true;
31
+ }
32
+ /**
33
+ * Convert a name to snake_case.
34
+ * Handles camelCase, PascalCase, kebab-case, and mixed formats.
35
+ */
36
+ function toSnakeCase(name) {
37
+ return (name
38
+ // Handle consecutive uppercase (XMLParser -> xml_parser)
39
+ .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')
40
+ // Insert underscore before uppercase letters (camelCase -> camel_case)
41
+ .replace(/([a-z0-9])([A-Z])/g, '$1_$2')
42
+ // Replace hyphens and dots with underscores
43
+ .replace(/[-.\s]+/g, '_')
44
+ // Convert to lowercase
45
+ .toLowerCase()
46
+ // Remove consecutive underscores
47
+ .replace(/_+/g, '_')
48
+ // Remove leading/trailing underscores
49
+ .replace(/^_+|_+$/g, ''));
50
+ }
51
+ /**
52
+ * Create a diagnostic for snake_case violation.
53
+ */
54
+ function createNamingDiagnostic(location, name, kind, context, fix) {
55
+ const message = `${kind} '${name}' should use snake_case (e.g., '${toSnakeCase(name)}')`;
56
+ return {
57
+ location,
58
+ severity: 'error',
59
+ code: 'NAMING_SNAKE_CASE',
60
+ message,
61
+ context: extractContextLine(location.line, context.source),
62
+ fix,
63
+ };
64
+ }
65
+ // ============================================================
66
+ // NAMING_SNAKE_CASE RULE
67
+ // ============================================================
68
+ /**
69
+ * Validates that variable definitions, parameters, and dict keys use snake_case.
70
+ *
71
+ * Checks definition sites only (not variable usage):
72
+ * - Captures: :> $user_name, :> $item_list, :> $is_valid
73
+ * - Closure params: |user_name, count| { }
74
+ * - Dict keys: [user_name: "Alice", is_active: true]
75
+ *
76
+ * Exceptions:
77
+ * - Single-letter names are valid (common for loop variables)
78
+ *
79
+ * References:
80
+ * - docs/16_conventions.md:10-53
81
+ */
82
+ export const NAMING_SNAKE_CASE = {
83
+ code: 'NAMING_SNAKE_CASE',
84
+ category: 'naming',
85
+ severity: 'error',
86
+ nodeTypes: ['ClosureParam', 'DictEntry', 'Capture'],
87
+ validate(node, context) {
88
+ switch (node.type) {
89
+ case 'ClosureParam': {
90
+ const paramNode = node;
91
+ const name = paramNode.name;
92
+ if (!isSnakeCase(name)) {
93
+ const fix = this.fix?.(node, context) ?? null;
94
+ return [
95
+ createNamingDiagnostic(paramNode.span.start, name, 'Parameter', context, fix),
96
+ ];
97
+ }
98
+ return [];
99
+ }
100
+ case 'DictEntry': {
101
+ const entryNode = node;
102
+ const key = entryNode.key;
103
+ if (!isSnakeCase(key)) {
104
+ const fix = this.fix?.(node, context) ?? null;
105
+ return [
106
+ createNamingDiagnostic(entryNode.span.start, key, 'Dict key', context, fix),
107
+ ];
108
+ }
109
+ return [];
110
+ }
111
+ case 'Capture': {
112
+ const captureNode = node;
113
+ const name = captureNode.name;
114
+ if (!isSnakeCase(name)) {
115
+ const fix = this.fix?.(node, context) ?? null;
116
+ return [
117
+ createNamingDiagnostic(captureNode.span.start, name, 'Captured variable', context, fix),
118
+ ];
119
+ }
120
+ return [];
121
+ }
122
+ default:
123
+ return [];
124
+ }
125
+ },
126
+ fix(node, context) {
127
+ let name = null;
128
+ let range = node.span;
129
+ // Extract name and determine replacement range
130
+ switch (node.type) {
131
+ case 'ClosureParam': {
132
+ const paramNode = node;
133
+ name = paramNode.name;
134
+ break;
135
+ }
136
+ case 'DictEntry': {
137
+ const entryNode = node;
138
+ name = entryNode.key;
139
+ // For dict entries, replace only the key portion before the colon
140
+ break;
141
+ }
142
+ case 'Capture': {
143
+ const captureNode = node;
144
+ name = captureNode.name;
145
+ break;
146
+ }
147
+ default:
148
+ return null;
149
+ }
150
+ if (!name || isSnakeCase(name)) {
151
+ return null;
152
+ }
153
+ const snakeCaseName = toSnakeCase(name);
154
+ // Get original source text for this node
155
+ const sourceText = context.source.substring(range.start.offset, range.end.offset);
156
+ // Replace the original name with snake_case version
157
+ // This preserves $ prefix for variables and : for dict entries
158
+ const replacement = sourceText.replace(name, snakeCaseName);
159
+ return {
160
+ description: `Rename '${name}' to '${snakeCaseName}'`,
161
+ applicable: true,
162
+ range,
163
+ replacement,
164
+ };
165
+ },
166
+ };
167
+ //# sourceMappingURL=naming.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"naming.js","sourceRoot":"","sources":["../../../src/check/rules/naming.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * String Handling Convention Rules
3
+ * Enforces string handling best practices from docs/16_conventions.md:318-352.
4
+ */
5
+ import type { ValidationRule } from '../types.js';
6
+ /**
7
+ * Enforces .empty method for emptiness checks.
8
+ * Direct string comparison with "" is not idiomatic and may not work
9
+ * correctly in all contexts. Use .empty method instead.
10
+ *
11
+ * Detection:
12
+ * - BinaryExpr with == or != operator
13
+ * - One side is empty string literal ""
14
+ * - Suggests using .empty method
15
+ *
16
+ * Valid patterns:
17
+ * - $str -> .empty (check if empty)
18
+ * - $str -> .empty ? "yes" ! "no" (conditional)
19
+ *
20
+ * Discouraged:
21
+ * - $str == "" (direct comparison)
22
+ * - $str != "" (direct comparison)
23
+ *
24
+ * References:
25
+ * - docs/16_conventions.md:333-345
26
+ */
27
+ export declare const USE_EMPTY_METHOD: ValidationRule;
28
+ //# sourceMappingURL=strings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strings.d.ts","sourceRoot":"","sources":["../../../src/check/rules/strings.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,cAAc,EAGf,MAAM,aAAa,CAAC;AAYrB;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,gBAAgB,EAAE,cA2C9B,CAAC"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * String Handling Convention Rules
3
+ * Enforces string handling best practices from docs/16_conventions.md:318-352.
4
+ */
5
+ import { extractContextLine } from './helpers.js';
6
+ // ============================================================
7
+ // USE_EMPTY_METHOD RULE
8
+ // ============================================================
9
+ /**
10
+ * Enforces .empty method for emptiness checks.
11
+ * Direct string comparison with "" is not idiomatic and may not work
12
+ * correctly in all contexts. Use .empty method instead.
13
+ *
14
+ * Detection:
15
+ * - BinaryExpr with == or != operator
16
+ * - One side is empty string literal ""
17
+ * - Suggests using .empty method
18
+ *
19
+ * Valid patterns:
20
+ * - $str -> .empty (check if empty)
21
+ * - $str -> .empty ? "yes" ! "no" (conditional)
22
+ *
23
+ * Discouraged:
24
+ * - $str == "" (direct comparison)
25
+ * - $str != "" (direct comparison)
26
+ *
27
+ * References:
28
+ * - docs/16_conventions.md:333-345
29
+ */
30
+ export const USE_EMPTY_METHOD = {
31
+ code: 'USE_EMPTY_METHOD',
32
+ category: 'strings',
33
+ severity: 'warning',
34
+ nodeTypes: ['BinaryExpr'],
35
+ validate(node, context) {
36
+ const binaryNode = node;
37
+ // Only check equality operators
38
+ if (binaryNode.op !== '==' && binaryNode.op !== '!=') {
39
+ return [];
40
+ }
41
+ // left and right are PostfixExpr - check their primaries
42
+ const left = binaryNode.left;
43
+ const right = binaryNode.right;
44
+ const leftIsEmpty = left.type === 'PostfixExpr' && isEmptyStringLiteral(left.primary);
45
+ const rightIsEmpty = right.type === 'PostfixExpr' && isEmptyStringLiteral(right.primary);
46
+ if (leftIsEmpty || rightIsEmpty) {
47
+ const suggestedMethod = binaryNode.op === '==' ? '.empty' : '.empty -> !';
48
+ return [
49
+ {
50
+ location: binaryNode.span.start,
51
+ severity: 'warning',
52
+ code: 'USE_EMPTY_METHOD',
53
+ message: `Use ${suggestedMethod} for emptiness checks instead of comparing with ""`,
54
+ context: extractContextLine(binaryNode.span.start.line, context.source),
55
+ fix: null, // Auto-fix would require expression reconstruction
56
+ },
57
+ ];
58
+ }
59
+ return [];
60
+ },
61
+ };
62
+ /**
63
+ * Check if a node is an empty string literal.
64
+ */
65
+ function isEmptyStringLiteral(node) {
66
+ if (node.type !== 'StringLiteral') {
67
+ return false;
68
+ }
69
+ const stringNode = node;
70
+ // Check if all parts are empty strings (no interpolations)
71
+ if (stringNode.parts.length === 0) {
72
+ return true;
73
+ }
74
+ if (stringNode.parts.length === 1) {
75
+ const part = stringNode.parts[0];
76
+ return typeof part === 'string' && part === '';
77
+ }
78
+ return false;
79
+ }
80
+ //# sourceMappingURL=strings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strings.js","sourceRoot":"","sources":["../../../src/check/rules/strings.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAYH,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAElD,+DAA+D;AAC/D,wBAAwB;AACxB,+DAA+D;AAE/D;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAmB;IAC9C,IAAI,EAAE,kBAAkB;IACxB,QAAQ,EAAE,SAAS;IACnB,QAAQ,EAAE,SAAS;IACnB,SAAS,EAAE,CAAC,YAAY,CAAC;IAEzB,QAAQ,CAAC,IAAa,EAAE,OAA0B;QAChD,MAAM,UAAU,GAAG,IAAsB,CAAC;QAE1C,gCAAgC;QAChC,IAAI,UAAU,CAAC,EAAE,KAAK,IAAI,IAAI,UAAU,CAAC,EAAE,KAAK,IAAI,EAAE,CAAC;YACrD,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,yDAAyD;QACzD,MAAM,IAAI,GAAG,UAAU,CAAC,IAAW,CAAC;QACpC,MAAM,KAAK,GAAG,UAAU,CAAC,KAAY,CAAC;QAEtC,MAAM,WAAW,GACf,IAAI,CAAC,IAAI,KAAK,aAAa,IAAI,oBAAoB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACpE,MAAM,YAAY,GAChB,KAAK,CAAC,IAAI,KAAK,aAAa,IAAI,oBAAoB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAEtE,IAAI,WAAW,IAAI,YAAY,EAAE,CAAC;YAChC,MAAM,eAAe,GAAG,UAAU,CAAC,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC;YAE1E,OAAO;gBACL;oBACE,QAAQ,EAAE,UAAU,CAAC,IAAI,CAAC,KAAK;oBAC/B,QAAQ,EAAE,SAAS;oBACnB,IAAI,EAAE,kBAAkB;oBACxB,OAAO,EAAE,OAAO,eAAe,oDAAoD;oBACnF,OAAO,EAAE,kBAAkB,CACzB,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAC1B,OAAO,CAAC,MAAM,CACf;oBACD,GAAG,EAAE,IAAI,EAAE,mDAAmD;iBAC/D;aACF,CAAC;QACJ,CAAC;QAED,OAAO,EAAE,CAAC;IACZ,CAAC;CACF,CAAC;AAEF;;GAEG;AACH,SAAS,oBAAoB,CAAC,IAAa;IACzC,IAAI,IAAI,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;QAClC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,UAAU,GAAG,IAAyB,CAAC;IAE7C,2DAA2D;IAC3D,IAAI,UAAU,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,UAAU,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACjC,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,EAAE,CAAC;IACjD,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Type Safety Convention Rules
3
+ * Enforces type annotation best practices from docs/16_conventions.md:288-316.
4
+ */
5
+ import type { ValidationRule } from '../types.js';
6
+ /**
7
+ * Detects redundant type assertions on literal values.
8
+ * Type assertions are for validation, not conversion. Asserting a literal's
9
+ * type is unnecessary because the type is already known at parse time.
10
+ *
11
+ * Redundant patterns:
12
+ * - 5:number (number literal with number assertion)
13
+ * - "hello":string (string literal with string assertion)
14
+ * - true:bool (bool literal with bool assertion)
15
+ *
16
+ * Valid patterns:
17
+ * - parseJson($input):dict (external input validation)
18
+ * - $userInput:string (runtime validation)
19
+ *
20
+ * References:
21
+ * - docs/16_conventions.md:305-315
22
+ */
23
+ export declare const UNNECESSARY_ASSERTION: ValidationRule;
24
+ /**
25
+ * Recommends type assertions for external input validation.
26
+ * External inputs (from host functions, user input, parsed data) should be
27
+ * validated with type assertions to ensure type safety.
28
+ *
29
+ * Detection heuristics:
30
+ * - Host function calls (HostCall nodes)
31
+ * - Parsing functions (parse_json, parse_xml, etc.)
32
+ * - Variables from external sources ($ARGS, $ENV)
33
+ *
34
+ * This is an informational rule - not all external data needs assertions,
35
+ * but it's a good practice for critical paths.
36
+ *
37
+ * References:
38
+ * - docs/16_conventions.md:307-311
39
+ */
40
+ export declare const VALIDATE_EXTERNAL: ValidationRule;
41
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/check/rules/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,cAAc,EAKf,MAAM,aAAa,CAAC;AAQrB;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,qBAAqB,EAAE,cAwFnC,CAAC;AA4BF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,iBAAiB,EAAE,cAuC/B,CAAC"}
@@ -0,0 +1,162 @@
1
+ /**
2
+ * Type Safety Convention Rules
3
+ * Enforces type annotation best practices from docs/16_conventions.md:288-316.
4
+ */
5
+ import { extractContextLine } from './helpers.js';
6
+ // ============================================================
7
+ // UNNECESSARY_ASSERTION RULE
8
+ // ============================================================
9
+ /**
10
+ * Detects redundant type assertions on literal values.
11
+ * Type assertions are for validation, not conversion. Asserting a literal's
12
+ * type is unnecessary because the type is already known at parse time.
13
+ *
14
+ * Redundant patterns:
15
+ * - 5:number (number literal with number assertion)
16
+ * - "hello":string (string literal with string assertion)
17
+ * - true:bool (bool literal with bool assertion)
18
+ *
19
+ * Valid patterns:
20
+ * - parseJson($input):dict (external input validation)
21
+ * - $userInput:string (runtime validation)
22
+ *
23
+ * References:
24
+ * - docs/16_conventions.md:305-315
25
+ */
26
+ export const UNNECESSARY_ASSERTION = {
27
+ code: 'UNNECESSARY_ASSERTION',
28
+ category: 'types',
29
+ severity: 'info',
30
+ nodeTypes: ['TypeAssertion'],
31
+ validate(node, context) {
32
+ const assertionNode = node;
33
+ const operand = assertionNode.operand;
34
+ // Bare assertions (:type) are valid - they check pipe value
35
+ if (!operand) {
36
+ return [];
37
+ }
38
+ // operand is PostfixExprNode - check the primary
39
+ const primary = operand.primary;
40
+ // Check if primary is a literal
41
+ const isLiteral = primary.type === 'NumberLiteral' ||
42
+ primary.type === 'StringLiteral' ||
43
+ primary.type === 'BoolLiteral';
44
+ if (!isLiteral) {
45
+ return [];
46
+ }
47
+ // Check if the assertion matches the literal type
48
+ const literalType = getLiteralType(primary);
49
+ const assertedType = assertionNode.typeName;
50
+ if (literalType === assertedType) {
51
+ const fix = this.fix?.(node, context) ?? null;
52
+ return [
53
+ {
54
+ location: assertionNode.span.start,
55
+ severity: 'info',
56
+ code: 'UNNECESSARY_ASSERTION',
57
+ message: `Type assertion on ${literalType} literal is unnecessary`,
58
+ context: extractContextLine(assertionNode.span.start.line, context.source),
59
+ fix,
60
+ },
61
+ ];
62
+ }
63
+ return [];
64
+ },
65
+ fix(node, context) {
66
+ const assertionNode = node;
67
+ const operand = assertionNode.operand;
68
+ if (!operand) {
69
+ return null;
70
+ }
71
+ // Find the end of the type assertion (:type part)
72
+ const assertionSource = context.source.substring(assertionNode.span.start.offset, assertionNode.span.end.offset);
73
+ // The type assertion is "literal:type" - we want to keep only "literal"
74
+ // Find the : character position
75
+ const colonIndex = assertionSource.indexOf(':');
76
+ if (colonIndex === -1) {
77
+ return null;
78
+ }
79
+ // Calculate the actual end of ":type" part
80
+ const typeStart = assertionNode.span.start.offset + colonIndex;
81
+ const typeEnd = typeStart + 1 + assertionNode.typeName.length;
82
+ return {
83
+ description: 'Remove unnecessary type assertion',
84
+ applicable: true,
85
+ range: {
86
+ start: { ...assertionNode.span.start, offset: typeStart },
87
+ end: { ...assertionNode.span.start, offset: typeEnd },
88
+ },
89
+ replacement: '',
90
+ };
91
+ },
92
+ };
93
+ /**
94
+ * Get the type name of a literal node.
95
+ */
96
+ function getLiteralType(node) {
97
+ switch (node.type) {
98
+ case 'NumberLiteral':
99
+ return 'number';
100
+ case 'StringLiteral':
101
+ return 'string';
102
+ case 'BoolLiteral':
103
+ return 'bool';
104
+ case 'Tuple':
105
+ return 'list';
106
+ case 'Dict':
107
+ return 'dict';
108
+ default:
109
+ return null;
110
+ }
111
+ }
112
+ // ============================================================
113
+ // VALIDATE_EXTERNAL RULE
114
+ // ============================================================
115
+ /**
116
+ * Recommends type assertions for external input validation.
117
+ * External inputs (from host functions, user input, parsed data) should be
118
+ * validated with type assertions to ensure type safety.
119
+ *
120
+ * Detection heuristics:
121
+ * - Host function calls (HostCall nodes)
122
+ * - Parsing functions (parse_json, parse_xml, etc.)
123
+ * - Variables from external sources ($ARGS, $ENV)
124
+ *
125
+ * This is an informational rule - not all external data needs assertions,
126
+ * but it's a good practice for critical paths.
127
+ *
128
+ * References:
129
+ * - docs/16_conventions.md:307-311
130
+ */
131
+ export const VALIDATE_EXTERNAL = {
132
+ code: 'VALIDATE_EXTERNAL',
133
+ category: 'types',
134
+ severity: 'info',
135
+ nodeTypes: ['HostCall'],
136
+ validate(node, context) {
137
+ const hostCallNode = node;
138
+ const functionName = hostCallNode.name;
139
+ // Check if this is a parsing or external data function
140
+ const isExternalDataFunction = functionName.startsWith('parse_') ||
141
+ functionName.includes('fetch') ||
142
+ functionName.includes('read') ||
143
+ functionName.includes('load');
144
+ if (!isExternalDataFunction) {
145
+ return [];
146
+ }
147
+ // Check if the result is immediately asserted
148
+ // This would require checking the parent node context
149
+ // For now, we'll provide a general recommendation
150
+ return [
151
+ {
152
+ location: hostCallNode.span.start,
153
+ severity: 'info',
154
+ code: 'VALIDATE_EXTERNAL',
155
+ message: `Consider validating external input with type assertion: ${functionName}():type`,
156
+ context: extractContextLine(hostCallNode.span.start.line, context.source),
157
+ fix: null, // Cannot auto-fix - requires developer judgment
158
+ },
159
+ ];
160
+ },
161
+ };
162
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/check/rules/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Check Types
3
+ * Type definitions for the rill-check static analysis tool.
4
+ */
5
+ import type { SourceLocation, SourceSpan, ScriptNode, NodeType, ASTNode } from '../types.js';
6
+ /** Diagnostic severity levels */
7
+ export type Severity = 'error' | 'warning' | 'info';
8
+ /** Rule state configuration */
9
+ export type RuleState = 'on' | 'off' | 'warn';
10
+ /**
11
+ * Fix suggestion for a diagnostic.
12
+ * Provides automated fix information that can be applied to source code.
13
+ */
14
+ export interface Fix {
15
+ /** Human-readable description of what the fix does */
16
+ readonly description: string;
17
+ /** Whether the fix can be safely applied automatically */
18
+ readonly applicable: boolean;
19
+ /** Source range to replace */
20
+ readonly range: SourceSpan;
21
+ /** Replacement text */
22
+ readonly replacement: string;
23
+ }
24
+ /**
25
+ * A single diagnostic issue found during validation.
26
+ * Represents errors, warnings, or informational messages from static analysis.
27
+ */
28
+ export interface Diagnostic {
29
+ /** Location of the issue in source */
30
+ readonly location: SourceLocation;
31
+ /** Severity level */
32
+ readonly severity: Severity;
33
+ /** Rule code (e.g., NAMING_SNAKE_CASE) */
34
+ readonly code: string;
35
+ /** Human-readable description */
36
+ readonly message: string;
37
+ /** Source line containing the issue */
38
+ readonly context: string;
39
+ /** Optional automatic fix */
40
+ readonly fix: Fix | null;
41
+ }
42
+ /**
43
+ * Configuration for check rules and severity overrides.
44
+ * Controls which rules are active and at what severity level.
45
+ */
46
+ export interface CheckConfig {
47
+ /** Per-rule enable/disable/warn state */
48
+ readonly rules: Record<string, RuleState>;
49
+ /** Severity overrides by rule code */
50
+ readonly severity: Record<string, Severity>;
51
+ }
52
+ /**
53
+ * Context for validation passes.
54
+ * Tracks source, AST, configuration, and accumulated diagnostics.
55
+ */
56
+ export interface ValidationContext {
57
+ /** Original source text */
58
+ readonly source: string;
59
+ /** Parsed AST */
60
+ readonly ast: ScriptNode;
61
+ /** Active configuration */
62
+ readonly config: CheckConfig;
63
+ /** Accumulated diagnostics */
64
+ readonly diagnostics: Diagnostic[];
65
+ /** Variable definitions for collision detection */
66
+ readonly variables: Map<string, SourceLocation>;
67
+ }
68
+ /**
69
+ * Context for fix generation.
70
+ * Provides access to source and AST for computing fix replacements.
71
+ */
72
+ export interface FixContext {
73
+ /** Original source text */
74
+ readonly source: string;
75
+ /** Parsed AST */
76
+ readonly ast: ScriptNode;
77
+ }
78
+ /** Rule category for grouping and organization */
79
+ export type RuleCategory = 'naming' | 'flow' | 'collections' | 'loops' | 'conditionals' | 'closures' | 'types' | 'strings' | 'errors' | 'formatting' | 'anti-patterns';
80
+ /**
81
+ * Validation rule interface.
82
+ * Rules are stateless - all context passed via ValidationContext.
83
+ * Rules return diagnostics, never throw.
84
+ * fix() must preserve semantics (no behavior changes).
85
+ */
86
+ export interface ValidationRule {
87
+ /** Unique rule code (e.g., NAMING_SNAKE_CASE) */
88
+ readonly code: string;
89
+ /** Rule category for grouping */
90
+ readonly category: RuleCategory;
91
+ /** Default severity level */
92
+ readonly severity: Severity;
93
+ /** Node types this rule applies to */
94
+ readonly nodeTypes: NodeType[];
95
+ /**
96
+ * Validate a node, returning diagnostics for violations.
97
+ * Called for each node matching nodeTypes.
98
+ */
99
+ validate(node: ASTNode, context: ValidationContext): Diagnostic[];
100
+ /**
101
+ * Optionally generate a fix for a diagnostic.
102
+ * Returns null if fix not applicable.
103
+ */
104
+ fix?(node: ASTNode, context: FixContext): Fix | null;
105
+ }
106
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/check/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Check Types
3
+ * Type definitions for the rill-check static analysis tool.
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/check/types.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Script Validator
3
+ * Orchestrates validation by traversing AST and invoking enabled rules.
4
+ */
5
+ import type { ScriptNode } from '../types.js';
6
+ import type { CheckConfig, Diagnostic } from './types.js';
7
+ /**
8
+ * Validate script AST against all enabled rules.
9
+ * Traverses AST using visitor pattern, invoking enabled rules for matching nodes.
10
+ * Returns diagnostics sorted by line number, then column.
11
+ *
12
+ * @param ast - Parsed script AST to validate
13
+ * @param source - Original source text for context extraction
14
+ * @param config - Configuration determining which rules are active
15
+ * @returns Array of diagnostics sorted by location
16
+ */
17
+ export declare function validateScript(ast: ScriptNode, source: string, config: CheckConfig): Diagnostic[];
18
+ //# sourceMappingURL=validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/check/validator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAW,MAAM,aAAa,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAqB,MAAM,YAAY,CAAC;AAQ7E;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,UAAU,EACf,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,WAAW,GAClB,UAAU,EAAE,CAiDd"}