@rcrsr/rill-cli 0.18.0 → 0.18.1
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.
|
@@ -168,11 +168,15 @@ export const CLOSURE_LATE_BINDING = {
|
|
|
168
168
|
validate(node, context) {
|
|
169
169
|
const eachNode = node;
|
|
170
170
|
const body = eachNode.body;
|
|
171
|
+
// For named parameter closures (|entry| { ... }), the body itself is a
|
|
172
|
+
// Closure. Look inside the inner block for nested closure creations,
|
|
173
|
+
// not the body closure itself.
|
|
174
|
+
const innerBody = body.type === 'Closure' ? body.body : body;
|
|
171
175
|
// Check if body contains a closure creation
|
|
172
|
-
const hasClosureCreation = containsClosureCreation(
|
|
176
|
+
const hasClosureCreation = containsClosureCreation(innerBody);
|
|
173
177
|
if (hasClosureCreation) {
|
|
174
178
|
// Check if there's an explicit capture before the closure
|
|
175
|
-
const hasExplicitCapture = containsExplicitCapture(
|
|
179
|
+
const hasExplicitCapture = containsExplicitCapture(innerBody);
|
|
176
180
|
if (!hasExplicitCapture) {
|
|
177
181
|
return [
|
|
178
182
|
{
|
|
@@ -24,6 +24,23 @@ function containsBreak(node) {
|
|
|
24
24
|
});
|
|
25
25
|
return found;
|
|
26
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Check if an AST subtree contains side-effecting operations.
|
|
29
|
+
* Detects HostCall (log, host functions) and ClosureCall ($fn(), $obj.method()).
|
|
30
|
+
*/
|
|
31
|
+
function containsSideEffects(node) {
|
|
32
|
+
let found = false;
|
|
33
|
+
const ctx = {};
|
|
34
|
+
visitNode(node, ctx, {
|
|
35
|
+
enter(n) {
|
|
36
|
+
if (n.type === 'HostCall' || n.type === 'ClosureCall') {
|
|
37
|
+
found = true;
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
exit() { },
|
|
41
|
+
});
|
|
42
|
+
return found;
|
|
43
|
+
}
|
|
27
44
|
/**
|
|
28
45
|
* Check if a body is a simple method shorthand.
|
|
29
46
|
* Body structure for .method shorthand is PostfixExpr with MethodCall as primary.
|
|
@@ -179,9 +196,13 @@ export const PREFER_MAP = {
|
|
|
179
196
|
return [];
|
|
180
197
|
}
|
|
181
198
|
}
|
|
182
|
-
//
|
|
183
|
-
|
|
184
|
-
|
|
199
|
+
// Check for side effects: host calls (log, etc.) and closure calls ($fn())
|
|
200
|
+
const innerBody = eachExpr.body.type === 'Closure'
|
|
201
|
+
? eachExpr.body.body
|
|
202
|
+
: eachExpr.body;
|
|
203
|
+
if (containsSideEffects(innerBody)) {
|
|
204
|
+
return [];
|
|
205
|
+
}
|
|
185
206
|
return [
|
|
186
207
|
{
|
|
187
208
|
location: node.span.start,
|
|
@@ -189,7 +210,7 @@ export const PREFER_MAP = {
|
|
|
189
210
|
code: 'PREFER_MAP',
|
|
190
211
|
message: "Consider using 'map' instead of 'each' for pure transformations (no side effects)",
|
|
191
212
|
context: extractContextLine(node.span.start.line, context.source),
|
|
192
|
-
fix: null,
|
|
213
|
+
fix: null,
|
|
193
214
|
},
|
|
194
215
|
];
|
|
195
216
|
},
|
|
@@ -125,7 +125,6 @@ export const SPACING_BRACES = {
|
|
|
125
125
|
const span = node.span;
|
|
126
126
|
const lines = context.source.split('\n');
|
|
127
127
|
const openLine = lines[span.start.line - 1] ?? '';
|
|
128
|
-
const closeLine = lines[span.end.line - 1] ?? '';
|
|
129
128
|
// Check for opening brace without space after
|
|
130
129
|
// Only examine the opening line (from the { onward)
|
|
131
130
|
// Use ^ anchor to only check the block's opening brace, not string interpolation
|
|
@@ -141,11 +140,16 @@ export const SPACING_BRACES = {
|
|
|
141
140
|
});
|
|
142
141
|
}
|
|
143
142
|
// Check for closing brace without space before
|
|
144
|
-
//
|
|
145
|
-
//
|
|
146
|
-
|
|
147
|
-
const
|
|
148
|
-
const
|
|
143
|
+
// For Closure nodes with return type annotations, span.end extends past }
|
|
144
|
+
// to include the type annotation. Use body.span.end to find the actual }.
|
|
145
|
+
const closeSpan = node.type === 'Closure' ? node.body.span : span;
|
|
146
|
+
const closeEnd = closeSpan.end;
|
|
147
|
+
const closeLineActual = lines[closeEnd.line - 1] ?? '';
|
|
148
|
+
// closeEnd.column is 1-indexed and points AFTER the }, so:
|
|
149
|
+
// - } is at 0-index: closeEnd.column - 2
|
|
150
|
+
// - Character before } is at 0-index: closeEnd.column - 3
|
|
151
|
+
const charBeforeClose = closeLineActual[closeEnd.column - 3];
|
|
152
|
+
const isCloseOnOwnLine = /^\s*$/.test(closeLineActual.substring(0, closeEnd.column - 2));
|
|
149
153
|
if (charBeforeClose && !/\s/.test(charBeforeClose) && !isCloseOnOwnLine) {
|
|
150
154
|
diagnostics.push({
|
|
151
155
|
location: span.end,
|
package/dist/cli-run.js
CHANGED
|
@@ -11,7 +11,7 @@ import { parse, execute, createRuntimeContext, invokeCallable, isScriptCallable,
|
|
|
11
11
|
import { resolveConfigPath, loadProject, parseMainField, introspectHandler, marshalCliArgs, ConfigError, } from '@rcrsr/rill-config';
|
|
12
12
|
import { CLI_VERSION } from './cli-shared.js';
|
|
13
13
|
import { explainError } from './cli-explain.js';
|
|
14
|
-
import { runScript } from './run/runner.js';
|
|
14
|
+
import { formatOutput, runScript } from './run/runner.js';
|
|
15
15
|
// ============================================================
|
|
16
16
|
// HELP TEXT
|
|
17
17
|
// ============================================================
|
|
@@ -288,10 +288,13 @@ export async function main() {
|
|
|
288
288
|
}
|
|
289
289
|
}
|
|
290
290
|
}
|
|
291
|
-
if (
|
|
292
|
-
|
|
291
|
+
if (handlerResult !== false &&
|
|
292
|
+
handlerResult !== '' &&
|
|
293
|
+
handlerResult !== undefined) {
|
|
294
|
+
const output = formatOutput(handlerResult, opts.format);
|
|
295
|
+
process.stdout.write(output + '\n');
|
|
293
296
|
}
|
|
294
|
-
process.exit(0);
|
|
297
|
+
process.exit(handlerResult === false || handlerResult === '' ? 1 : 0);
|
|
295
298
|
}
|
|
296
299
|
// Module mode: main field in config is required
|
|
297
300
|
if (mainField === undefined) {
|
package/dist/run/runner.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export interface RunResult {
|
|
|
17
17
|
* - `module:alias` → `{dir}/index.rill`
|
|
18
18
|
*/
|
|
19
19
|
export declare function buildModuleResolver(modulesConfig: Record<string, string>, configDir: string): SchemeResolver;
|
|
20
|
+
export declare function formatOutput(value: RillValue, format: RunCliOptions['format']): string;
|
|
20
21
|
/**
|
|
21
22
|
* Run a rill script file with the given extension tree and config.
|
|
22
23
|
*/
|
package/dist/run/runner.js
CHANGED
|
@@ -59,7 +59,7 @@ function mapResultToRunResult(result, format) {
|
|
|
59
59
|
const formatted = formatOutput(result, format);
|
|
60
60
|
return { exitCode: 0, output: formatted };
|
|
61
61
|
}
|
|
62
|
-
function formatOutput(value, format) {
|
|
62
|
+
export function formatOutput(value, format) {
|
|
63
63
|
const native = toNative(value);
|
|
64
64
|
if (format === 'json' || format === 'compact') {
|
|
65
65
|
return JSON.stringify(native.value);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rcrsr/rill-cli",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.1",
|
|
4
4
|
"description": "CLI tools for the rill scripting language",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Andre Bremer",
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"dotenv": "^16.0.0",
|
|
23
23
|
"yaml": "^2.8.2",
|
|
24
|
-
"@rcrsr/rill": "^0.18.
|
|
25
|
-
"@rcrsr/rill
|
|
24
|
+
"@rcrsr/rill-config": "^0.18.1",
|
|
25
|
+
"@rcrsr/rill": "^0.18.0"
|
|
26
26
|
},
|
|
27
27
|
"files": [
|
|
28
28
|
"dist"
|