@elaraai/east-diagnostics 1.0.13 → 1.0.15

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 (51) hide show
  1. package/README.md +21 -4
  2. package/dist/src/east-ir.d.ts +23 -0
  3. package/dist/src/east-ir.d.ts.map +1 -0
  4. package/dist/src/east-ir.js +55 -0
  5. package/dist/src/east-ir.js.map +1 -0
  6. package/dist/src/east-source.d.ts +18 -0
  7. package/dist/src/east-source.d.ts.map +1 -0
  8. package/dist/src/east-source.js +68 -0
  9. package/dist/src/east-source.js.map +1 -0
  10. package/dist/src/rules/index.d.ts +4 -1
  11. package/dist/src/rules/index.d.ts.map +1 -1
  12. package/dist/src/rules/index.js +16 -3
  13. package/dist/src/rules/index.js.map +1 -1
  14. package/dist/src/rules/no-compile-time-data-injection.d.ts +3 -0
  15. package/dist/src/rules/no-compile-time-data-injection.d.ts.map +1 -0
  16. package/dist/src/rules/no-compile-time-data-injection.js +107 -0
  17. package/dist/src/rules/no-compile-time-data-injection.js.map +1 -0
  18. package/dist/src/rules/no-compile-time-seed-data.d.ts +3 -0
  19. package/dist/src/rules/no-compile-time-seed-data.d.ts.map +1 -0
  20. package/dist/src/rules/no-compile-time-seed-data.js +209 -0
  21. package/dist/src/rules/no-compile-time-seed-data.js.map +1 -0
  22. package/dist/src/rules/no-host-in-east-block.d.ts +3 -0
  23. package/dist/src/rules/no-host-in-east-block.d.ts.map +1 -0
  24. package/dist/src/rules/no-host-in-east-block.js +266 -0
  25. package/dist/src/rules/no-host-in-east-block.js.map +1 -0
  26. package/dist/src/rules/no-let-const-in-expression.d.ts.map +1 -1
  27. package/dist/src/rules/no-let-const-in-expression.js +11 -10
  28. package/dist/src/rules/no-let-const-in-expression.js.map +1 -1
  29. package/dist/src/rules/no-module-scope-east-macro.d.ts +3 -0
  30. package/dist/src/rules/no-module-scope-east-macro.d.ts.map +1 -0
  31. package/dist/src/rules/no-module-scope-east-macro.js +150 -0
  32. package/dist/src/rules/no-module-scope-east-macro.js.map +1 -0
  33. package/dist/src/rules/no-redundant-east-cast.d.ts.map +1 -1
  34. package/dist/src/rules/no-redundant-east-cast.js +62 -24
  35. package/dist/src/rules/no-redundant-east-cast.js.map +1 -1
  36. package/dist/src/rules/no-relative-src-import.d.ts.map +1 -1
  37. package/dist/src/rules/no-relative-src-import.js +9 -2
  38. package/dist/src/rules/no-relative-src-import.js.map +1 -1
  39. package/dist/src/rules/no-unexecuted-east-expression.d.ts +4 -0
  40. package/dist/src/rules/no-unexecuted-east-expression.d.ts.map +1 -1
  41. package/dist/src/rules/no-unexecuted-east-expression.js +2 -12
  42. package/dist/src/rules/no-unexecuted-east-expression.js.map +1 -1
  43. package/dist/src/tsserver-plugin.d.ts +4 -0
  44. package/dist/src/tsserver-plugin.d.ts.map +1 -1
  45. package/dist/src/tsserver-plugin.js +15 -42
  46. package/dist/src/tsserver-plugin.js.map +1 -1
  47. package/package.json +3 -2
  48. package/dist/src/rules/no-east-data-builder-helper.d.ts +0 -3
  49. package/dist/src/rules/no-east-data-builder-helper.d.ts.map +0 -1
  50. package/dist/src/rules/no-east-data-builder-helper.js +0 -90
  51. package/dist/src/rules/no-east-data-builder-helper.js.map +0 -1
@@ -0,0 +1,209 @@
1
+ import { insideBlockScope } from "../block-scope.js";
2
+ const NAME = "no-compile-time-seed-data";
3
+ const CODE = 990021;
4
+ function fire(ctx, target, messageText) {
5
+ const sf = ctx.sourceFile;
6
+ const start = target.getStart(sf);
7
+ ctx.report({ ruleName: NAME, code: CODE, start, length: target.getEnd() - start, messageText, category: "warning" });
8
+ }
9
+ /** The `ImportDeclaration` a symbol's (local, un-aliased) declaration belongs to. */
10
+ function importDeclOfSymbol(sym, t) {
11
+ for (const d of sym?.declarations ?? []) {
12
+ let n = d;
13
+ // ImportSpecifier -> NamedImports -> ImportClause -> ImportDeclaration; a
14
+ // NamespaceImport sits one level higher; a DEFAULT import binds the
15
+ // ImportClause itself (`import e3 from "@elaraai/e3"`).
16
+ if (t.isImportSpecifier(n))
17
+ n = n.parent.parent.parent;
18
+ else if (t.isNamespaceImport(n))
19
+ n = n.parent.parent;
20
+ else if (t.isImportClause(n))
21
+ n = n.parent;
22
+ else
23
+ continue;
24
+ if (t.isImportDeclaration(n))
25
+ return n;
26
+ }
27
+ return undefined;
28
+ }
29
+ /** Does `id` resolve to a binding imported from any `@elaraai/*` package? (Keyed by
30
+ * SYMBOL → import specifier, like the other host-vs-East rules — never the text.) */
31
+ function resolvesToEastImport(id, ctx) {
32
+ const t = ctx.ts;
33
+ const imp = importDeclOfSymbol(ctx.checker.getSymbolAtLocation(id), t);
34
+ return imp !== undefined && t.isStringLiteral(imp.moduleSpecifier) && imp.moduleSpecifier.text.startsWith("@elaraai/");
35
+ }
36
+ /** Is `node` a call `<e3>.input(...)` where `<e3>` is the DEFAULT import of `@elaraai/e3`? */
37
+ function isE3InputCall(node, ctx) {
38
+ const t = ctx.ts;
39
+ const callee = node.expression;
40
+ if (!t.isPropertyAccessExpression(callee) || callee.name.text !== "input")
41
+ return false;
42
+ if (!t.isIdentifier(callee.expression))
43
+ return false;
44
+ const imp = importDeclOfSymbol(ctx.checker.getSymbolAtLocation(callee.expression), t);
45
+ return imp !== undefined && t.isStringLiteral(imp.moduleSpecifier) && imp.moduleSpecifier.text === "@elaraai/e3";
46
+ }
47
+ /** The root identifier a call/member chain is rooted on (`a.b.c(...)` -> `a`). */
48
+ function rootIdentifier(node, t) {
49
+ let cur = node;
50
+ for (;;) {
51
+ if (t.isPropertyAccessExpression(cur) || t.isElementAccessExpression(cur))
52
+ cur = cur.expression;
53
+ else if (t.isCallExpression(cur))
54
+ cur = cur.expression;
55
+ else
56
+ break;
57
+ }
58
+ return t.isIdentifier(cur) ? cur : undefined;
59
+ }
60
+ // The host constructors that REPRESENT a constant East value (per east's
61
+ // `ValueTypeOf`): `Map` (DictType), `Set` (SetType), `Date` (DateTimeType), the
62
+ // typed arrays + `ArrayBuffer` (BlobType / VectorType). Constructing one is
63
+ // authoring a constant value, not computing data — its arguments are still walked,
64
+ // so `new Map(readCsv(...))` still fires on the inner host call.
65
+ const VALUE_CTORS = new Set([
66
+ "Map", "Set", "Date", "ArrayBuffer",
67
+ "Uint8Array", "Int8Array", "Uint8ClampedArray", "Int16Array", "Uint16Array",
68
+ "Int32Array", "Uint32Array", "Float32Array", "Float64Array", "BigInt64Array", "BigUint64Array",
69
+ ]);
70
+ /**
71
+ * Does `expr` embed HOST COMPUTATION — a call to a non-`@elaraai` function (`num`,
72
+ * `BigInt`, `Number`, `readCsv`, a JS Array method, …), or a `new` of something
73
+ * other than a value-representation constructor (`Map`/`Set`/`Date`) or an
74
+ * `@elaraai` one? East value constructors (`variant`/`some`/`none`/`East.value`),
75
+ * primitive literals, `Map`/`Set`/array/object literals, constant concatenation and
76
+ * template labels are NOT host computation — they author a constant East value.
77
+ */
78
+ function embedsHostComputation(expr, ctx) {
79
+ const t = ctx.ts;
80
+ let bad = false;
81
+ const visit = (n) => {
82
+ if (bad)
83
+ return;
84
+ if (t.isCallExpression(n)) {
85
+ const root = rootIdentifier(n.expression, t);
86
+ if (root === undefined || !resolvesToEastImport(root, ctx)) {
87
+ bad = true;
88
+ return;
89
+ }
90
+ }
91
+ else if (t.isNewExpression(n)) {
92
+ const ctor = n.expression;
93
+ const ok = t.isIdentifier(ctor) && (VALUE_CTORS.has(ctor.text) || resolvesToEastImport(ctor, ctx));
94
+ if (!ok) {
95
+ bad = true;
96
+ return;
97
+ }
98
+ }
99
+ t.forEachChild(n, visit);
100
+ };
101
+ visit(expr);
102
+ return bad;
103
+ }
104
+ const MUTATORS = new Set(["set", "add", "push", "unshift", "splice", "delete", "clear", "fill", "sort", "copyWithin", "pop", "shift"]);
105
+ function isAssignmentOp(kind, t) {
106
+ const k = t.SyntaxKind;
107
+ return (kind === k.EqualsToken || kind === k.PlusEqualsToken || kind === k.MinusEqualsToken ||
108
+ kind === k.AsteriskEqualsToken || kind === k.SlashEqualsToken || kind === k.PercentEqualsToken ||
109
+ kind === k.AmpersandEqualsToken || kind === k.BarEqualsToken || kind === k.CaretEqualsToken ||
110
+ kind === k.LessThanLessThanEqualsToken || kind === k.GreaterThanGreaterThanEqualsToken ||
111
+ kind === k.GreaterThanGreaterThanGreaterThanEqualsToken || kind === k.AsteriskAsteriskEqualsToken ||
112
+ kind === k.QuestionQuestionEqualsToken || kind === k.BarBarEqualsToken || kind === k.AmpersandAmpersandEqualsToken);
113
+ }
114
+ /** Is `node` lexically inside a host loop (`for`/`for-of`/`for-in`/`while`/`do`)? */
115
+ function insideLoop(node, t) {
116
+ let cur = node.parent;
117
+ while (cur !== undefined) {
118
+ if (t.isForStatement(cur) || t.isForOfStatement(cur) || t.isForInStatement(cur) || t.isWhileStatement(cur) || t.isDoStatement(cur)) {
119
+ return true;
120
+ }
121
+ cur = cur.parent;
122
+ }
123
+ return false;
124
+ }
125
+ /** Is the binding `sym` HOST-FILLED anywhere in the file — mutated in place
126
+ * (`sym.set(...)` / `.push(...)` / `sym[k] = …`) EITHER inside a host loop (the
127
+ * Cartesian-product / CSV-overlay fill pattern) OR from a host-computed value? A
128
+ * handful of literal `.set("a", 1n)` calls outside any loop is just an imperatively
129
+ * authored constant and is NOT flagged. */
130
+ function isHostFilled(sym, ctx) {
131
+ const t = ctx.ts;
132
+ let filled = false;
133
+ const isSym = (n) => t.isIdentifier(n) && ctx.checker.getSymbolAtLocation(n) === sym;
134
+ const visit = (n) => {
135
+ if (filled)
136
+ return;
137
+ if (t.isCallExpression(n) &&
138
+ t.isPropertyAccessExpression(n.expression) &&
139
+ MUTATORS.has(n.expression.name.text) &&
140
+ isSym(n.expression.expression)) {
141
+ if (insideLoop(n, t) || n.arguments.some((a) => embedsHostComputation(a, ctx))) {
142
+ filled = true;
143
+ return;
144
+ }
145
+ }
146
+ if (t.isBinaryExpression(n) && isAssignmentOp(n.operatorToken.kind, t)) {
147
+ const root = rootIdentifier(n.left, t);
148
+ if (root !== undefined && isSym(root) && (insideLoop(n, t) || embedsHostComputation(n.right, ctx))) {
149
+ filled = true;
150
+ return;
151
+ }
152
+ }
153
+ t.forEachChild(n, visit);
154
+ };
155
+ visit(ctx.sourceFile);
156
+ return filled;
157
+ }
158
+ // `e3.input(name, type, seed?)` declares a WRITABLE dataset; the optional 3rd arg
159
+ // is only a default/genesis value, overwritten the moment anything writes to the
160
+ // dataset. It must therefore be a small AUTHORED CONSTANT — a literal, an
161
+ // empty/literal Map/Set/array/struct, or an East value (`variant`/`some`/`none`/
162
+ // `East.value`) — or omitted. Computing it from build-time data (a `new Map()`
163
+ // filled by host `for`-loops over parsed CSV, or an object literal of `num(cfg.x)`
164
+ // calls) bakes a non-portable, non-reactive snapshot into the deployed program.
165
+ // Real/bulk data belongs at RUNTIME: a `BlobType` input parsed with
166
+ // `blob.decodeCsv(...)` inside an `e3.task`, a platform `FileSystem.readFile` in a
167
+ // task, or `e3.record(...)` + `e3.mutation` for set-once root state.
168
+ export const noCompileTimeSeedData = {
169
+ name: NAME,
170
+ code: CODE,
171
+ description: "Flag host-computed data passed as the seed (3rd arg) of e3.input — the default must be a small authored constant; load real data at runtime.",
172
+ check(node, ctx) {
173
+ const t = ctx.ts;
174
+ if (!t.isCallExpression(node) || !isE3InputCall(node, ctx))
175
+ return;
176
+ if (insideBlockScope(node, ctx))
177
+ return; // e3.input only legitimately appears at module scope
178
+ const seedArg = node.arguments[2];
179
+ if (seedArg === undefined)
180
+ return; // no default — value arrives at runtime (correct)
181
+ // Resolve an identifier seed to its initializer; keep the symbol so we can see
182
+ // whether an authored-empty collection is then host-filled. An opaque seed
183
+ // (imported const, parameter, no initializer) is left silent — we only judge
184
+ // what we can see.
185
+ let expr = seedArg;
186
+ let sym;
187
+ if (t.isIdentifier(seedArg)) {
188
+ sym = ctx.checker.getSymbolAtLocation(seedArg);
189
+ const decl = sym?.valueDeclaration;
190
+ if (decl === undefined || !t.isVariableDeclaration(decl) || decl.initializer === undefined)
191
+ return;
192
+ expr = decl.initializer;
193
+ }
194
+ while (t.isAsExpression(expr) || t.isSatisfiesExpression(expr) || t.isParenthesizedExpression(expr)) {
195
+ expr = expr.expression;
196
+ }
197
+ const hostComputed = embedsHostComputation(expr, ctx);
198
+ const hostFilled = sym !== undefined && isHostFilled(sym, ctx);
199
+ if (!hostComputed && !hostFilled)
200
+ return;
201
+ const nameArg = node.arguments[0];
202
+ const name = nameArg !== undefined && t.isStringLiteralLike(nameArg) ? nameArg.text : "…";
203
+ const reason = hostFilled
204
+ ? "this seed is an authored-empty collection then filled in place by host code (a `for`-loop / `.set(...)`)"
205
+ : "this seed is assembled by host calls (`num(...)`, `BigInt(...)`, parsed config) at module-evaluation time";
206
+ fire(ctx, seedArg, `Host-computed data passed as the \`e3.input("${name}", …)\` seed bakes a build-time snapshot into the deployed program — ${reason}. The default (3rd arg) must be a small AUTHORED CONSTANT (a literal, an empty/literal Map/Set/array/struct, or an East value \`variant\`/\`some\`/\`none\`/\`East.value\`) or omitted. Load real/bulk data at RUNTIME: put the bytes in a \`BlobType\` input and parse with \`blob.decodeCsv(...)\` inside an \`e3.task\`, read files in a task via a platform \`FileSystem.readFile\`, or use \`e3.record(...)\` + \`e3.mutation\` for set-once root state.`);
207
+ },
208
+ };
209
+ //# sourceMappingURL=no-compile-time-seed-data.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-compile-time-seed-data.js","sourceRoot":"","sources":["../../../src/rules/no-compile-time-seed-data.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { EastRule } from "../types.js";
2
+ export declare const noHostInEastBlock: EastRule;
3
+ //# sourceMappingURL=no-host-in-east-block.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-host-in-east-block.d.ts","sourceRoot":"","sources":["../../../src/rules/no-host-in-east-block.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAyB,MAAM,aAAa,CAAC;AAyJnE,eAAO,MAAM,iBAAiB,EAAE,QAuH/B,CAAC"}
@@ -0,0 +1,266 @@
1
+ import { isEastExprType, isBlockBuilderType } from "../east-type.js";
2
+ import { insideBlockScope } from "../block-scope.js";
3
+ import { chainRootReceiver, bodyBuildsEastIr } from "../east-ir.js";
4
+ const NAME = "no-host-in-east-block";
5
+ const CODE = 990020;
6
+ // ── East-vs-host classification ─────────────────────────────────────────────
7
+ /** Does `id` resolve to a binding imported from an `@elaraai/*` package? (The
8
+ * whole East ecosystem API — `East`, `Expr`, `variant`/`some`, `ArrayType`/
9
+ * `StructType`/`DictType`, `GoogleOr`, `Data`, … — is recognised by SYMBOL, not a
10
+ * brittle name list.) */
11
+ function resolvesToEastImport(id, ctx) {
12
+ const t = ctx.ts;
13
+ // Use the LOCAL import symbol (its declaration is the ImportSpecifier/clause) —
14
+ // do NOT resolve the alias, which would jump to the declaration inside
15
+ // @elaraai/east and lose the import-specifier we key on.
16
+ const sym = ctx.checker.getSymbolAtLocation(id);
17
+ for (const d of sym?.declarations ?? []) {
18
+ let n = d;
19
+ if (t.isImportSpecifier(n))
20
+ n = n.parent.parent.parent;
21
+ else if (t.isNamespaceImport(n))
22
+ n = n.parent.parent;
23
+ else if (t.isImportClause(n))
24
+ n = n.parent;
25
+ else
26
+ continue;
27
+ if (t.isImportDeclaration(n) && t.isStringLiteral(n.moduleSpecifier) && n.moduleSpecifier.text.startsWith("@elaraai/")) {
28
+ return true;
29
+ }
30
+ }
31
+ return false;
32
+ }
33
+ /**
34
+ * Does `id` resolve to a binding LOCAL to an East block whose runtime value is an
35
+ * East `Expr` typed loosely as `any` — an in-block TS macro (`g`/`sdiv`/`roundI`/…,
36
+ * itself reported by clause E) or one of its loosely-typed parameters? East methods
37
+ * chained off such a receiver (`sdiv(a, b).multiply(…)`, or `a.divide(b)` inside the
38
+ * macro body) are East methods, not separate host calls: the macro is already
39
+ * flagged, so re-reporting the East ops on its result/operands is a false positive.
40
+ * (We must NOT exempt all `any` receivers — only these block-local East bindings.)
41
+ */
42
+ function resolvesToInBlockEastBinding(id, ctx) {
43
+ const t = ctx.ts;
44
+ const sym = ctx.checker.getSymbolAtLocation(id);
45
+ for (const d of sym?.declarations ?? []) {
46
+ // An in-block TS macro: `const f = (…) => …` / `function f(…) {…}`.
47
+ if (t.isFunctionDeclaration(d) && d.body !== undefined && insideBlockScope(d, ctx))
48
+ return true;
49
+ if (t.isVariableDeclaration(d) &&
50
+ d.initializer !== undefined &&
51
+ (t.isArrowFunction(d.initializer) || t.isFunctionExpression(d.initializer)) &&
52
+ insideBlockScope(d, ctx)) {
53
+ return true;
54
+ }
55
+ // A parameter of an in-block TS macro (its loosely-typed East operands). A
56
+ // `$`-callback's params are already East-typed (clause A2 handles them), so
57
+ // only non-`$` macro params reach here.
58
+ if (t.isParameter(d)) {
59
+ const fn = d.parent;
60
+ if ((t.isArrowFunction(fn) || t.isFunctionExpression(fn) || t.isFunctionDeclaration(fn)) &&
61
+ insideBlockScope(fn, ctx)) {
62
+ const first = fn.parameters[0];
63
+ if (first === undefined || !isBlockBuilderType(ctx.checker.getTypeAtLocation(first.name)))
64
+ return true;
65
+ }
66
+ }
67
+ }
68
+ return false;
69
+ }
70
+ /** Is a CallExpression an EAST call (allowed), vs a HOST call (the violation)? */
71
+ function isEastCall(call, ctx) {
72
+ const t = ctx.ts;
73
+ const f = call.expression;
74
+ // A0 — the callee is itself an East value (a bound `East.function`, a
75
+ // function-typed param, a curried/higher-order East fn).
76
+ if (isEastExprType(ctx.checker.getTypeAtLocation(f)))
77
+ return true;
78
+ const root = chainRootReceiver(f, ctx);
79
+ // A1 — rooted on the block builder `$` (`$.let`/`$.const`/`$(…)`/`$.if`/…).
80
+ if (isBlockBuilderType(ctx.checker.getTypeAtLocation(root)))
81
+ return true;
82
+ // A2 — a method on an East `Expr` receiver (`.add`/`.get`/`.map`/`.match`/…).
83
+ // Read the immediate receiver's own type (survives an `: any` return).
84
+ if (t.isPropertyAccessExpression(f) && isEastExprType(ctx.checker.getTypeAtLocation(f.expression)))
85
+ return true;
86
+ // A5 — rooted on an `@elaraai/*` import (`East.*`, `Expr.*`, `variant`/`some`,
87
+ // `ArrayType`/`StructType`/`DictType`, `GoogleOr.*`, …).
88
+ if (t.isIdentifier(root) && resolvesToEastImport(root, ctx))
89
+ return true;
90
+ // A6 — a method chained off an in-block TS macro or its loosely-typed (`any`)
91
+ // operand, whose type-info is lost as `any`. The macro is reported elsewhere
92
+ // (clause E / its bare call); the East methods on its East-`Expr` result are
93
+ // East, not additional host calls.
94
+ if (t.isPropertyAccessExpression(f) && t.isIdentifier(root) && resolvesToInBlockEastBinding(root, ctx))
95
+ return true;
96
+ return false;
97
+ }
98
+ function isEast(expr, ctx) {
99
+ return isEastExprType(ctx.checker.getTypeAtLocation(expr));
100
+ }
101
+ /** Is `node` inside JSX (UI composition is out of scope — `prefer-jsx-…` owns it)? */
102
+ function insideJsx(node, t) {
103
+ let cur = node.parent;
104
+ while (cur !== undefined) {
105
+ if (t.isJsxElement(cur) || t.isJsxSelfClosingElement(cur) || t.isJsxFragment(cur) || t.isJsxExpression(cur) || t.isJsxAttribute(cur)) {
106
+ return true;
107
+ }
108
+ cur = cur.parent;
109
+ }
110
+ return false;
111
+ }
112
+ function isJsx(node, t) {
113
+ return t.isJsxElement(node) || t.isJsxFragment(node) || t.isJsxSelfClosingElement(node) || (t.isParenthesizedExpression(node) && isJsx(node.expression, t));
114
+ }
115
+ /** The expressions a function/arrow returns, not descending into nested functions. */
116
+ function returnExpressions(fn, t) {
117
+ if (fn.body === undefined)
118
+ return [];
119
+ if (!t.isBlock(fn.body))
120
+ return [fn.body];
121
+ const out = [];
122
+ const visit = (n) => {
123
+ if (t.isFunctionDeclaration(n) || t.isFunctionExpression(n) || t.isArrowFunction(n))
124
+ return;
125
+ if (t.isReturnStatement(n) && n.expression !== undefined)
126
+ out.push(n.expression);
127
+ t.forEachChild(n, visit);
128
+ };
129
+ t.forEachChild(fn.body, visit);
130
+ return out;
131
+ }
132
+ const REPORT = (ctx, target, messageText, fix) => {
133
+ const sf = ctx.sourceFile;
134
+ const start = target.getStart(sf);
135
+ const length = target.getEnd() - start;
136
+ ctx.report({
137
+ ruleName: NAME,
138
+ code: CODE,
139
+ start,
140
+ length,
141
+ messageText,
142
+ category: "warning",
143
+ ...(fix !== undefined ? { fix: { description: fix.description, changes: [{ start, length, newText: fix.newText }] } } : {}),
144
+ });
145
+ };
146
+ // Inside an East block the code must be East all the way down — only East
147
+ // expressions and East statements (`$.let`/`$.const`/`$(…)`/`$.if`/`$.for`/`$.assign`,
148
+ // East `Expr` method chains, `East.*`/`Expr.*`/`variant`/`some`/`none`, `East.str`,
149
+ // and `return <East expr>`). ANY host-language construct is an authoring-time macro
150
+ // over East: a call to a host function (a local TS helper, a JS builtin, a JS Array
151
+ // method), a host operator on East operands, a host `for`/`while`/`if` that emits
152
+ // IR, or host string interpolation. Express it in East instead.
153
+ export const noHostInEastBlock = {
154
+ name: NAME,
155
+ code: CODE,
156
+ description: "Flag host-language constructs (host calls, operators on East operands, JS control-flow, host string interpolation) inside an East block — express them in East.",
157
+ check(node, ctx) {
158
+ const t = ctx.ts;
159
+ if (!insideBlockScope(node, ctx))
160
+ return;
161
+ if (insideJsx(node, t))
162
+ return;
163
+ // Clause E — a TS closure/function DECLARED inside an East block (a `const`
164
+ // arrow, a function-expression, or a `function` declaration). It is an
165
+ // authoring-time macro: it can't be serialized/recursed and expands inline at
166
+ // each call. `$`-callbacks (`($, x) => …`) and JSX/UI helpers are excluded.
167
+ {
168
+ let fn;
169
+ let reportNode;
170
+ if (t.isFunctionDeclaration(node) && node.body !== undefined) {
171
+ fn = node;
172
+ reportNode = node.name ?? node;
173
+ }
174
+ else if (t.isVariableDeclaration(node) &&
175
+ node.initializer !== undefined &&
176
+ (t.isArrowFunction(node.initializer) || t.isFunctionExpression(node.initializer))) {
177
+ fn = node.initializer;
178
+ reportNode = node.name;
179
+ }
180
+ if (fn !== undefined && reportNode !== undefined) {
181
+ const first = fn.parameters[0];
182
+ if (first !== undefined && isBlockBuilderType(ctx.checker.getTypeAtLocation(first.name)))
183
+ return; // East `$`-callback
184
+ if (returnExpressions(fn, t).some((r) => isJsx(r, t)))
185
+ return; // UI-composition helper
186
+ REPORT(ctx, reportNode, "TS closure/function declared inside an East block — an authoring-time macro (it can't be serialized or recursed and expands inline at each call). Make it a real `East.function` (`$.const(East.function(...))`) or inline it.");
187
+ return;
188
+ }
189
+ }
190
+ // Clause C — host control-flow statements that emit East IR.
191
+ if (t.isForStatement(node) || t.isWhileStatement(node) || t.isForOfStatement(node)) {
192
+ if (t.isForOfStatement(node) && isEast(node.expression, ctx))
193
+ return; // for-of over an East Expr is fine
194
+ if (!bodyBuildsEastIr(node.statement, ctx))
195
+ return;
196
+ REPORT(ctx, node.getChildAt(0, ctx.sourceFile), "Host loop building East IR — bind the data with `$.const([...], ArrayType(...))` and use an East collection op (`data.map(($, x) => …)`) or `$.for(data, ($, x) => …)`.");
197
+ return;
198
+ }
199
+ if (t.isIfStatement(node)) {
200
+ const emits = bodyBuildsEastIr(node.thenStatement, ctx) || (node.elseStatement !== undefined && bodyBuildsEastIr(node.elseStatement, ctx));
201
+ if (!emits)
202
+ return;
203
+ REPORT(ctx, node.getChildAt(0, ctx.sourceFile), "Host `if` building East IR — use East's `$.if(cond, …)` so the branch is chosen at East runtime.");
204
+ return;
205
+ }
206
+ // Clause B — host operators on East operands.
207
+ if (t.isConditionalExpression(node)) {
208
+ if (isEast(node.condition, ctx) && isEast(node.whenTrue, ctx) && isEast(node.whenFalse, ctx)) {
209
+ const sf = ctx.sourceFile;
210
+ REPORT(ctx, node, "Host `?:` selecting between East values — use `cond.ifElse(() => a, () => b)`.", {
211
+ description: "Rewrite as cond.ifElse(...)",
212
+ newText: `(${node.condition.getText(sf)}).ifElse(() => ${node.whenTrue.getText(sf)}, () => ${node.whenFalse.getText(sf)})`,
213
+ });
214
+ }
215
+ return;
216
+ }
217
+ if (t.isBinaryExpression(node)) {
218
+ const op = node.operatorToken.kind;
219
+ const k = t.SyntaxKind;
220
+ const logical = op === k.AmpersandAmpersandToken || op === k.BarBarToken;
221
+ const arith = op === k.PlusToken || op === k.MinusToken || op === k.AsteriskToken || op === k.SlashToken ||
222
+ op === k.PercentToken || op === k.EqualsEqualsEqualsToken || op === k.ExclamationEqualsEqualsToken ||
223
+ op === k.EqualsEqualsToken || op === k.LessThanToken || op === k.LessThanEqualsToken ||
224
+ op === k.GreaterThanToken || op === k.GreaterThanEqualsToken;
225
+ if (logical && isEast(node.left, ctx) && isEast(node.right, ctx)) {
226
+ REPORT(ctx, node, "Host `&&`/`||` on East booleans — use East's `.and(() => …)` / `.or(() => …)`.");
227
+ }
228
+ else if (arith && (isEast(node.left, ctx) || isEast(node.right, ctx))) {
229
+ REPORT(ctx, node, "Host operator on an East value — use the East method (`.add`/`.subtract`/`.multiply`/`.divide`) or `East.equal`/`East.less`/`East.greater`.");
230
+ }
231
+ return;
232
+ }
233
+ if (t.isPrefixUnaryExpression(node) && (node.operator === t.SyntaxKind.MinusToken || node.operator === t.SyntaxKind.ExclamationToken)) {
234
+ if (isEast(node.operand, ctx)) {
235
+ REPORT(ctx, node, "Host unary operator on an East value — use `.negate()` / `East.not`.");
236
+ }
237
+ return;
238
+ }
239
+ // Clause F — host index access `x[i]` on a JS value (an East collection is
240
+ // read with `.get(...)`, never `[i]`, so a non-`Expr` receiver here is a host
241
+ // array/object being indexed — `adopt[ti]`, `BUSINESS_UNITS[oi]`).
242
+ if (t.isElementAccessExpression(node)) {
243
+ if (isEast(node.expression, ctx))
244
+ return; // (an Expr has no index signature anyway)
245
+ REPORT(ctx, node, "Host index access on a JS value inside an East block — model the data as an East collection and read it with `.get(...)` / East ops, not `[i]`.");
246
+ return;
247
+ }
248
+ // Clause D — host string interpolation (not an `East.str`/`str` tagged template).
249
+ if (t.isTemplateExpression(node) && !(node.parent !== undefined && t.isTaggedTemplateExpression(node.parent))) {
250
+ REPORT(ctx, node, "Host string interpolation inside an East block — build the string in East with `East.str`…`` (or `str`…``).");
251
+ return;
252
+ }
253
+ // Clause A — host call.
254
+ if (t.isCallExpression(node)) {
255
+ if (isEastCall(node, ctx))
256
+ return;
257
+ // Specialised message for the host-key-into-East-collection sub-case.
258
+ const callee = node.expression;
259
+ const KEY_ACCESSORS = new Set(["get", "tryGet", "has", "insert", "insertOrUpdate", "update", "remove"]);
260
+ REPORT(ctx, node, t.isPropertyAccessExpression(callee) && KEY_ACCESSORS.has(callee.name.text)
261
+ ? "Host call inside an East block — make it a real `East.function` (`$.const(East.function(...))`) or inline it as East."
262
+ : "Host call inside an East block — this is an authoring-time macro over East. Make it a real `East.function` (`$.const(East.function(...))`), inline it as East, or use the East stdlib.");
263
+ }
264
+ },
265
+ };
266
+ //# sourceMappingURL=no-host-in-east-block.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-host-in-east-block.js","sourceRoot":"","sources":["../../../src/rules/no-host-in-east-block.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"no-let-const-in-expression.d.ts","sourceRoot":"","sources":["../../../src/rules/no-let-const-in-expression.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAW5C,eAAO,MAAM,sBAAsB,EAAE,QA4CpC,CAAC"}
1
+ {"version":3,"file":"no-let-const-in-expression.d.ts","sourceRoot":"","sources":["../../../src/rules/no-let-const-in-expression.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAW5C,eAAO,MAAM,sBAAsB,EAAE,QA6CpC,CAAC"}
@@ -25,16 +25,17 @@ export const noLetConstInExpression = {
25
25
  }
26
26
  if (parent === undefined)
27
27
  return;
28
- // Flag only when the result is consumed inline: a chain target
29
- // (`$.let(...).add(1n)`), an index target, an operator operand, or an
30
- // argument to another call (`$.if($.let(...))`). A const/let initializer,
31
- // a bare statement, `return $.const(...)`, and a concise arrow body are all
32
- // valid and stay silent.
33
- const usedInExpression = (t.isPropertyAccessExpression(parent) && parent.expression === current) ||
34
- (t.isElementAccessExpression(parent) && parent.expression === current) ||
35
- (t.isBinaryExpression(parent) && (parent.left === current || parent.right === current)) ||
36
- (t.isCallExpression(parent) && parent.arguments.some((arg) => arg === current));
37
- if (!usedInExpression)
28
+ // Allow-list: `$.let`/`$.const` is only valid as a JS `const`/`let`
29
+ // initializer, a bare statement, a `return`, or a concise arrow body. ANY
30
+ // other position buries the declaration in an expression — a struct-field
31
+ // value (`field: $.let(...)`), an array element, a call argument
32
+ // (`$.if($.let(...))`), a chain target (`$.let(...).add(1n)`), an operator
33
+ // operand, a ternary branch, etc. Flag everything that is not allowed.
34
+ const allowed = (t.isVariableDeclaration(parent) && parent.initializer === current) ||
35
+ (t.isExpressionStatement(parent) && parent.expression === current) ||
36
+ (t.isReturnStatement(parent) && parent.expression === current) ||
37
+ (t.isArrowFunction(parent) && parent.body === current);
38
+ if (allowed)
38
39
  return;
39
40
  const sf = ctx.sourceFile;
40
41
  const start = call.getStart(sf);
@@ -1 +1 @@
1
- {"version":3,"file":"no-let-const-in-expression.js","sourceRoot":"","sources":["../../../src/rules/no-let-const-in-expression.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAE5D,MAAM,IAAI,GAAG,4BAA4B,CAAC;AAC1C,MAAM,IAAI,GAAG,MAAM,CAAC;AAEpB,gFAAgF;AAChF,iFAAiF;AACjF,mFAAmF;AACnF,iFAAiF;AACjF,yEAAyE;AACzE,MAAM,CAAC,MAAM,sBAAsB,GAAa;IAC9C,IAAI,EAAE,IAAI;IACV,IAAI,EAAE,IAAI;IACV,WAAW,EACT,kGAAkG;IACpG,KAAK,CAAC,IAAI,EAAE,GAAG;QACb,MAAM,KAAK,GAAG,qBAAqB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAC/C,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO;QAEhC,MAAM,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QAExB,oCAAoC;QACpC,IAAI,OAAO,GAAY,IAAI,CAAC;QAC5B,IAAI,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC5B,OAAO,MAAM,KAAK,SAAS,IAAI,CAAC,CAAC,yBAAyB,CAAC,MAAM,CAAC,EAAE,CAAC;YACnE,OAAO,GAAG,MAAM,CAAC;YACjB,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QACzB,CAAC;QACD,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO;QAEjC,+DAA+D;QAC/D,sEAAsE;QACtE,0EAA0E;QAC1E,4EAA4E;QAC5E,yBAAyB;QACzB,MAAM,gBAAgB,GACpB,CAAC,CAAC,CAAC,0BAA0B,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,UAAU,KAAK,OAAO,CAAC;YACvE,CAAC,CAAC,CAAC,yBAAyB,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,UAAU,KAAK,OAAO,CAAC;YACtE,CAAC,CAAC,CAAC,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,OAAO,IAAI,MAAM,CAAC,KAAK,KAAK,OAAO,CAAC,CAAC;YACvF,CAAC,CAAC,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC;QAClF,IAAI,CAAC,gBAAgB;YAAE,OAAO;QAE9B,MAAM,EAAE,GAAG,GAAG,CAAC,UAAU,CAAC;QAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAChC,GAAG,CAAC,MAAM,CAAC;YACT,QAAQ,EAAE,IAAI;YACd,IAAI,EAAE,IAAI;YACV,KAAK;YACL,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,KAAK;YAC7B,WAAW,EAAE,OAAO,KAAK,CAAC,MAAM,wEAAwE,KAAK,CAAC,MAAM,uGAAuG;YAC3N,QAAQ,EAAE,SAAS;SACpB,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"no-let-const-in-expression.js","sourceRoot":"","sources":["../../../src/rules/no-let-const-in-expression.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAE5D,MAAM,IAAI,GAAG,4BAA4B,CAAC;AAC1C,MAAM,IAAI,GAAG,MAAM,CAAC;AAEpB,gFAAgF;AAChF,iFAAiF;AACjF,mFAAmF;AACnF,iFAAiF;AACjF,yEAAyE;AACzE,MAAM,CAAC,MAAM,sBAAsB,GAAa;IAC9C,IAAI,EAAE,IAAI;IACV,IAAI,EAAE,IAAI;IACV,WAAW,EACT,kGAAkG;IACpG,KAAK,CAAC,IAAI,EAAE,GAAG;QACb,MAAM,KAAK,GAAG,qBAAqB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAC/C,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO;QAEhC,MAAM,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QAExB,oCAAoC;QACpC,IAAI,OAAO,GAAY,IAAI,CAAC;QAC5B,IAAI,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC5B,OAAO,MAAM,KAAK,SAAS,IAAI,CAAC,CAAC,yBAAyB,CAAC,MAAM,CAAC,EAAE,CAAC;YACnE,OAAO,GAAG,MAAM,CAAC;YACjB,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QACzB,CAAC;QACD,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO;QAEjC,oEAAoE;QACpE,0EAA0E;QAC1E,0EAA0E;QAC1E,iEAAiE;QACjE,2EAA2E;QAC3E,uEAAuE;QACvE,MAAM,OAAO,GACX,CAAC,CAAC,CAAC,qBAAqB,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,WAAW,KAAK,OAAO,CAAC;YACnE,CAAC,CAAC,CAAC,qBAAqB,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,UAAU,KAAK,OAAO,CAAC;YAClE,CAAC,CAAC,CAAC,iBAAiB,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,UAAU,KAAK,OAAO,CAAC;YAC9D,CAAC,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;QACzD,IAAI,OAAO;YAAE,OAAO;QAEpB,MAAM,EAAE,GAAG,GAAG,CAAC,UAAU,CAAC;QAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAChC,GAAG,CAAC,MAAM,CAAC;YACT,QAAQ,EAAE,IAAI;YACd,IAAI,EAAE,IAAI;YACV,KAAK;YACL,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,KAAK;YAC7B,WAAW,EAAE,OAAO,KAAK,CAAC,MAAM,wEAAwE,KAAK,CAAC,MAAM,uGAAuG;YAC3N,QAAQ,EAAE,SAAS;SACpB,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { EastRule } from "../types.js";
2
+ export declare const noModuleScopeEastMacro: EastRule;
3
+ //# sourceMappingURL=no-module-scope-east-macro.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-module-scope-east-macro.d.ts","sourceRoot":"","sources":["../../../src/rules/no-module-scope-east-macro.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAyB,MAAM,aAAa,CAAC;AA+FnE,eAAO,MAAM,sBAAsB,EAAE,QAwDpC,CAAC"}