iobroker.statechart 0.1.1 → 0.3.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 (50) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +59 -438
  3. package/admin/build/tab.js +133 -130
  4. package/admin/statechart.png +0 -0
  5. package/admin/{style.css → tab.css} +0 -2
  6. package/admin/tab_m.html +1 -1
  7. package/build/lib/chart-analysis.js +367 -0
  8. package/build/lib/chart-analysis.js.map +7 -0
  9. package/build/lib/chart-codegen.js +405 -0
  10. package/build/lib/chart-codegen.js.map +7 -0
  11. package/build/lib/chart-helpers.js +102 -0
  12. package/build/lib/chart-helpers.js.map +7 -0
  13. package/build/lib/chart-model.js +477 -0
  14. package/build/lib/chart-model.js.map +7 -0
  15. package/build/lib/chart-runtime.js +1521 -0
  16. package/build/lib/chart-runtime.js.map +7 -0
  17. package/build/lib/chart-structure.js +172 -0
  18. package/build/lib/chart-structure.js.map +7 -0
  19. package/build/lib/chart-validation.js +372 -0
  20. package/build/lib/chart-validation.js.map +7 -0
  21. package/build/main.js +638 -0
  22. package/build/main.js.map +7 -0
  23. package/io-package.json +31 -34
  24. package/package.json +21 -17
  25. package/admin/i18n/de.json +0 -4
  26. package/admin/i18n/en.json +0 -4
  27. package/admin/i18n/es.json +0 -4
  28. package/admin/i18n/fr.json +0 -4
  29. package/admin/i18n/it.json +0 -4
  30. package/admin/i18n/nl.json +0 -4
  31. package/admin/i18n/pl.json +0 -4
  32. package/admin/i18n/pt.json +0 -4
  33. package/admin/i18n/ru.json +0 -4
  34. package/admin/i18n/uk.json +0 -4
  35. package/admin/i18n/zh-cn.json +0 -4
  36. package/admin/jsonConfig.json +0 -19
  37. package/admin/statechart.svg +0 -38
  38. package/lib/adapter-config.d.ts +0 -19
  39. package/lib/chart-codegen.js +0 -436
  40. package/lib/chart-codegen.test.js +0 -132
  41. package/lib/chart-helpers.js +0 -74
  42. package/lib/chart-helpers.test.js +0 -38
  43. package/lib/chart-model.js +0 -577
  44. package/lib/chart-model.test.js +0 -189
  45. package/lib/chart-runtime.js +0 -797
  46. package/lib/chart-runtime.test.js +0 -699
  47. package/lib/chart-structure.js +0 -106
  48. package/lib/chart-validation.js +0 -328
  49. package/lib/chart-validation.test.js +0 -149
  50. package/main.js +0 -279
Binary file
@@ -10,5 +10,3 @@ body,
10
10
  width: 100%;
11
11
  margin: 0;
12
12
  }
13
-
14
- /* Add your styles here */
package/admin/tab_m.html CHANGED
@@ -17,7 +17,7 @@
17
17
  <link
18
18
  rel="stylesheet"
19
19
  type="text/css"
20
- href="style.css"
20
+ href="tab.css"
21
21
  />
22
22
  </head>
23
23
 
@@ -0,0 +1,367 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var chart_analysis_exports = {};
30
+ __export(chart_analysis_exports, {
31
+ analyzeChart: () => analyzeChart
32
+ });
33
+ module.exports = __toCommonJS(chart_analysis_exports);
34
+ var acorn = __toESM(require("acorn"));
35
+ var walk = __toESM(require("acorn-walk"));
36
+ var import_chart_helpers = require("./chart-helpers");
37
+ var import_chart_model = require("./chart-model");
38
+ var import_chart_structure = require("./chart-structure");
39
+ function evaluateConstant(node) {
40
+ switch (node.type) {
41
+ case "Literal":
42
+ return { value: node.value };
43
+ case "Identifier":
44
+ if (node.name === "undefined") {
45
+ return { value: void 0 };
46
+ }
47
+ return node.name === "NaN" || node.name === "Infinity" ? { value: Number(node.name) } : void 0;
48
+ case "TemplateLiteral":
49
+ return node.expressions.length ? void 0 : { value: node.quasis[0]?.value.cooked };
50
+ case "UnaryExpression": {
51
+ const arg = evaluateConstant(node.argument);
52
+ if (!arg) {
53
+ return void 0;
54
+ }
55
+ const value = arg.value;
56
+ const results = {
57
+ "!": () => !value,
58
+ "-": () => -value,
59
+ "+": () => +value
60
+ };
61
+ return node.operator in results ? { value: results[node.operator]() } : void 0;
62
+ }
63
+ case "LogicalExpression": {
64
+ const left = evaluateConstant(node.left);
65
+ if (!left) {
66
+ return void 0;
67
+ }
68
+ if (node.operator === "&&" && !left.value) {
69
+ return left;
70
+ }
71
+ if (node.operator === "||" && left.value) {
72
+ return left;
73
+ }
74
+ if (node.operator === "??" && left.value != null) {
75
+ return left;
76
+ }
77
+ return evaluateConstant(node.right);
78
+ }
79
+ case "BinaryExpression": {
80
+ const left = node.left.type === "PrivateIdentifier" ? void 0 : evaluateConstant(node.left);
81
+ const right = left && evaluateConstant(node.right);
82
+ if (!left || !right) {
83
+ return void 0;
84
+ }
85
+ const [a, b] = [left.value, right.value];
86
+ const results = {
87
+ "==": () => a == b,
88
+ "!=": () => a != b,
89
+ "===": () => a === b,
90
+ "!==": () => a !== b,
91
+ "<": () => a < b,
92
+ "<=": () => a <= b,
93
+ ">": () => a > b,
94
+ ">=": () => a >= b,
95
+ "+": () => a + b,
96
+ "-": () => a - b,
97
+ "*": () => a * b,
98
+ "/": () => a / b,
99
+ "%": () => a % b
100
+ };
101
+ return node.operator in results ? { value: results[node.operator]() } : void 0;
102
+ }
103
+ case "ConditionalExpression": {
104
+ const test = evaluateConstant(node.test);
105
+ if (!test) {
106
+ return void 0;
107
+ }
108
+ return evaluateConstant(test.value ? node.consequent : node.alternate);
109
+ }
110
+ default:
111
+ return void 0;
112
+ }
113
+ }
114
+ function evaluateCondition(code) {
115
+ try {
116
+ const ast = acorn.parseExpressionAt(code, 0, { ecmaVersion: "latest" });
117
+ return code.substring(ast.end).trim() ? void 0 : evaluateConstant(ast);
118
+ } catch {
119
+ return void 0;
120
+ }
121
+ }
122
+ class Usage {
123
+ read = /* @__PURE__ */ new Set();
124
+ written = /* @__PURE__ */ new Set();
125
+ /**
126
+ * Adds the variables used by a condition or action
127
+ *
128
+ * @param code The code, ignored if it has syntax errors
129
+ * @param kind Condition (expression) or action (statements)
130
+ */
131
+ add(code, kind) {
132
+ if (!code?.trim()) {
133
+ return;
134
+ }
135
+ let ast;
136
+ try {
137
+ ast = kind === "statements" ? acorn.parse(code, { ecmaVersion: "latest", sourceType: "script" }) : acorn.parseExpressionAt(code, 0, { ecmaVersion: "latest" });
138
+ } catch {
139
+ return;
140
+ }
141
+ const declared = /* @__PURE__ */ new Set();
142
+ const references = [];
143
+ walk.fullAncestor(ast, (node, _state, ancestors, type) => {
144
+ if (node.type !== "Identifier") {
145
+ return;
146
+ }
147
+ const parent = ancestors[ancestors.length - 2];
148
+ if (type === "VariablePattern") {
149
+ if (parent?.type === "AssignmentExpression" && parent.left === node) {
150
+ references.push({ name: node.name, write: true });
151
+ } else {
152
+ declared.add(node.name);
153
+ }
154
+ } else {
155
+ references.push({ name: node.name, write: parent?.type === "UpdateExpression" });
156
+ }
157
+ });
158
+ walk.simple(ast, {
159
+ CallExpression: (node) => {
160
+ const arg = node.arguments[0];
161
+ if (node.callee.type === "Identifier" && import_chart_helpers.CHANGE_HELPERS.has(node.callee.name) && arg?.type === "Literal" && typeof arg.value === "string") {
162
+ this.read.add(arg.value);
163
+ }
164
+ }
165
+ });
166
+ for (const { name, write } of references) {
167
+ if (!declared.has(name)) {
168
+ (write ? this.written : this.read).add(name);
169
+ }
170
+ }
171
+ }
172
+ }
173
+ function analyzeChart(chart) {
174
+ const structure = new import_chart_structure.ChartStructure(chart);
175
+ const findings = [];
176
+ const add = (kind, id, severity, key, args = []) => {
177
+ findings.push({ kind, id, severity, key, args });
178
+ };
179
+ const stateName = (id) => structure.statesById.get(id)?.name ?? id;
180
+ const usage = new Usage();
181
+ const validBySource = /* @__PURE__ */ new Map();
182
+ for (const state of chart.states) {
183
+ for (const transition of structure.getTransitions(state.id)) {
184
+ let label;
185
+ try {
186
+ label = (0, import_chart_model.parseTransitionLabel)(transition.label);
187
+ } catch {
188
+ continue;
189
+ }
190
+ usage.add(label.condition, "expression");
191
+ usage.add(label.temporal?.condition, "expression");
192
+ usage.add(label.action, "statements");
193
+ for (const event of [label.event, label.temporal?.event]) {
194
+ if (event) {
195
+ usage.read.add(event);
196
+ }
197
+ }
198
+ if (!structure.statesById.has(transition.target) || structure.getCrossedParallel(transition) !== void 0) {
199
+ continue;
200
+ }
201
+ const condition = label.condition ? evaluateCondition(label.condition) : { value: true };
202
+ const temporalCondition = label.temporal?.condition && evaluateCondition(label.temporal.condition);
203
+ if (condition && !condition.value) {
204
+ add(
205
+ "transition",
206
+ transition.id,
207
+ "warning",
208
+ "The condition is never true, the transition is never taken"
209
+ );
210
+ continue;
211
+ }
212
+ if (temporalCondition && !temporalCondition.value) {
213
+ add(
214
+ "transition",
215
+ transition.id,
216
+ "warning",
217
+ "The condition is never true, the transition is never taken"
218
+ );
219
+ continue;
220
+ }
221
+ if (label.condition && condition) {
222
+ add("transition", transition.id, "info", "The condition is always true");
223
+ }
224
+ const valid = { transition, label, alwaysTrue: !!condition };
225
+ validBySource.set(state.id, [...validBySource.get(state.id) || [], valid]);
226
+ }
227
+ }
228
+ findUnreachable(structure, validBySource, add);
229
+ findShadowed(structure, validBySource, add, stateName);
230
+ for (const state of chart.states) {
231
+ if (structure.getChildren(state.id).length || state.during?.trim()) {
232
+ continue;
233
+ }
234
+ if (structure.getPath(state.id).every((id) => !validBySource.get(id)?.length)) {
235
+ add(
236
+ "state",
237
+ state.id,
238
+ "info",
239
+ "The chart stays in this state: neither it nor a state containing it has an outgoing transition"
240
+ );
241
+ }
242
+ }
243
+ for (const state of chart.states) {
244
+ usage.add(state.entry, "statements");
245
+ usage.add(state.during, "statements");
246
+ usage.add(state.exit, "statements");
247
+ }
248
+ for (const fn of chart.functions || []) {
249
+ usage.add(fn.code, "statements");
250
+ }
251
+ for (const symbol of chart.symbols) {
252
+ const { read, written } = { read: usage.read.has(symbol.name), written: usage.written.has(symbol.name) };
253
+ if (symbol.scope === "input" && !read && !written) {
254
+ add("symbol", symbol.name, "info", "The input is not used, it only wakes up the chart");
255
+ } else if (symbol.scope === "output" && !written) {
256
+ add("symbol", symbol.name, "warning", "The output is never written");
257
+ } else if (symbol.scope === "local" && !read) {
258
+ add(
259
+ "symbol",
260
+ symbol.name,
261
+ "info",
262
+ written ? "The variable is written but never read" : "The variable is not used"
263
+ );
264
+ }
265
+ }
266
+ return findings;
267
+ }
268
+ function findUnreachable(structure, validBySource, add) {
269
+ const reachable = /* @__PURE__ */ new Set();
270
+ const enterDefault = (id) => {
271
+ if (reachable.has(id)) {
272
+ return;
273
+ }
274
+ reachable.add(id);
275
+ const children = structure.getChildren(id);
276
+ const initial2 = structure.getInitialChild(id);
277
+ for (const child of structure.isParallel(id) ? children : children.filter((c) => c.id === initial2)) {
278
+ enterDefault(child.id);
279
+ }
280
+ };
281
+ const enter = (target) => {
282
+ for (const id of structure.getPath(target)) {
283
+ reachable.add(id);
284
+ const parent = structure.statesById.get(id)?.parent || null;
285
+ if (structure.isParallel(parent)) {
286
+ for (const sibling of structure.getChildren(parent)) {
287
+ if (sibling.id !== id) {
288
+ enterDefault(sibling.id);
289
+ }
290
+ }
291
+ }
292
+ }
293
+ reachable.delete(target);
294
+ enterDefault(target);
295
+ };
296
+ const topLevel = structure.getChildren(null);
297
+ const initial = structure.getInitialChild(null);
298
+ for (const state of structure.isParallel(null) ? topLevel : topLevel.filter((s) => s.id === initial)) {
299
+ enterDefault(state.id);
300
+ }
301
+ for (let changed = true; changed; ) {
302
+ changed = false;
303
+ for (const [source, transitions] of validBySource) {
304
+ if (!reachable.has(source)) {
305
+ continue;
306
+ }
307
+ for (const { transition } of transitions) {
308
+ const before = reachable.size;
309
+ enter(transition.target);
310
+ changed ||= reachable.size !== before;
311
+ }
312
+ }
313
+ }
314
+ for (const state of structure.chart.states) {
315
+ const parent = state.parent && structure.statesById.has(state.parent) ? state.parent : null;
316
+ if (!reachable.has(state.id) && (!parent || reachable.has(parent))) {
317
+ add("state", state.id, "warning", "The state never becomes active: no transition leads to it");
318
+ }
319
+ }
320
+ }
321
+ function findShadowed(structure, validBySource, add, stateName) {
322
+ for (const transitions of validBySource.values()) {
323
+ let always;
324
+ const byEvent = /* @__PURE__ */ new Map();
325
+ const byTrigger = /* @__PURE__ */ new Map();
326
+ const outer = transitions.filter((t) => !structure.getTransitionKind(t.transition).inner);
327
+ const inner = transitions.filter((t) => structure.getTransitionKind(t.transition).inner);
328
+ for (const { transition, label, alwaysTrue } of [...outer, ...inner]) {
329
+ const trigger = JSON.stringify([label.event, label.temporal, label.condition?.replace(/\s+/g, "")]);
330
+ const before = always ?? (label.event ? byEvent.get(label.event) : void 0);
331
+ if (before) {
332
+ add(
333
+ "transition",
334
+ transition.id,
335
+ "warning",
336
+ 'Never taken: the transition to "%s" before it is always valid',
337
+ [stateName(before.target)]
338
+ );
339
+ continue;
340
+ }
341
+ const same = byTrigger.get(trigger);
342
+ if (same) {
343
+ add(
344
+ "transition",
345
+ transition.id,
346
+ "warning",
347
+ 'Never taken: the transition to "%s" before it has the same event and condition',
348
+ [stateName(same.target)]
349
+ );
350
+ continue;
351
+ }
352
+ byTrigger.set(trigger, transition);
353
+ if (alwaysTrue && !label.temporal) {
354
+ if (label.event) {
355
+ byEvent.set(label.event, transition);
356
+ } else {
357
+ always = transition;
358
+ }
359
+ }
360
+ }
361
+ }
362
+ }
363
+ // Annotate the CommonJS export names for ESM import in node:
364
+ 0 && (module.exports = {
365
+ analyzeChart
366
+ });
367
+ //# sourceMappingURL=chart-analysis.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/lib/chart-analysis.ts"],
4
+ "sourcesContent": ["/*\n * Static analysis of a chart: finds logical problems without running it, e.g. states which can never become\n * active, transitions which are never taken or variables which are not used. Syntax errors and unknown names are\n * found by the validation, the analysis ignores the code and labels with errors.\n */\n\nimport * as acorn from \"acorn\";\nimport * as walk from \"acorn-walk\";\nimport { CHANGE_HELPERS } from \"./chart-helpers\";\nimport { parseTransitionLabel } from \"./chart-model\";\nimport type { Chart, ChartTransition, TransitionLabel } from \"./chart-model\";\nimport { ChartStructure } from \"./chart-structure\";\n\nexport type Severity = \"error\" | \"warning\" | \"info\";\n\n/** A problem of the chart as a whole, not at a position in a text */\nexport interface Finding {\n /** What the problem is about */\n kind: \"state\" | \"transition\" | \"symbol\";\n /** ID of the state or transition, name of the variable */\n id: string;\n /** How severe the problem is */\n severity: Severity;\n /** English message with %s placeholders, used to translate it */\n key: string;\n /** Values for the %s placeholders of the message */\n args: string[];\n}\n\n/** A transition the runtime executes, with its parsed label */\ninterface ValidTransition {\n transition: ChartTransition;\n label: TransitionLabel;\n /** The condition is always true or there is none */\n alwaysTrue: boolean;\n}\n\ntype Constant = { value: unknown } | undefined;\n\n/**\n * Evaluates an expression which only consists of literals and operators, e.g. `true` or `1 > 2`\n *\n * @param node The expression\n * @returns undefined if the value depends on variables or function calls\n */\nfunction evaluateConstant(node: acorn.AnyNode): Constant {\n switch (node.type) {\n case \"Literal\":\n return { value: node.value };\n case \"Identifier\":\n if (node.name === \"undefined\") {\n return { value: undefined };\n }\n return node.name === \"NaN\" || node.name === \"Infinity\" ? { value: Number(node.name) } : undefined;\n case \"TemplateLiteral\":\n return node.expressions.length ? undefined : { value: node.quasis[0]?.value.cooked };\n case \"UnaryExpression\": {\n const arg = evaluateConstant(node.argument);\n if (!arg) {\n return undefined;\n }\n const value = arg.value as any;\n const results: Record<string, () => unknown> = {\n \"!\": () => !value,\n \"-\": () => -value,\n \"+\": () => +value,\n };\n return node.operator in results ? { value: results[node.operator]() } : undefined;\n }\n case \"LogicalExpression\": {\n const left = evaluateConstant(node.left);\n if (!left) {\n return undefined;\n }\n // a constant left side may decide the result on its own\n if (node.operator === \"&&\" && !left.value) {\n return left;\n }\n if (node.operator === \"||\" && left.value) {\n return left;\n }\n if (node.operator === \"??\" && left.value != null) {\n return left;\n }\n return evaluateConstant(node.right);\n }\n case \"BinaryExpression\": {\n const left = node.left.type === \"PrivateIdentifier\" ? undefined : evaluateConstant(node.left);\n const right = left && evaluateConstant(node.right);\n if (!left || !right) {\n return undefined;\n }\n const [a, b] = [left.value as any, right.value as any];\n const results: Record<string, () => unknown> = {\n \"==\": () => a == b,\n \"!=\": () => a != b,\n \"===\": () => a === b,\n \"!==\": () => a !== b,\n \"<\": () => a < b,\n \"<=\": () => a <= b,\n \">\": () => a > b,\n \">=\": () => a >= b,\n \"+\": () => a + b,\n \"-\": () => a - b,\n \"*\": () => a * b,\n \"/\": () => a / b,\n \"%\": () => a % b,\n };\n return node.operator in results ? { value: results[node.operator]() } : undefined;\n }\n case \"ConditionalExpression\": {\n const test = evaluateConstant(node.test);\n if (!test) {\n return undefined;\n }\n return evaluateConstant(test.value ? node.consequent : node.alternate);\n }\n default:\n return undefined;\n }\n}\n\n/**\n * @param code A condition\n * @returns its value if it does not depend on anything, undefined otherwise or if it has syntax errors\n */\nfunction evaluateCondition(code: string): Constant {\n try {\n const ast = acorn.parseExpressionAt(code, 0, { ecmaVersion: \"latest\" });\n return code.substring(ast.end).trim() ? undefined : evaluateConstant(ast);\n } catch {\n return undefined;\n }\n}\n\n/** Which variables are read and written */\nclass Usage {\n readonly read = new Set<string>();\n readonly written = new Set<string>();\n\n /**\n * Adds the variables used by a condition or action\n *\n * @param code The code, ignored if it has syntax errors\n * @param kind Condition (expression) or action (statements)\n */\n add(code: string | undefined, kind: \"expression\" | \"statements\"): void {\n if (!code?.trim()) {\n return;\n }\n let ast;\n try {\n ast =\n kind === \"statements\"\n ? acorn.parse(code, { ecmaVersion: \"latest\", sourceType: \"script\" })\n : acorn.parseExpressionAt(code, 0, { ecmaVersion: \"latest\" });\n } catch {\n return;\n }\n // names declared in the code itself (let, const, function parameters, ...) hide the variables\n const declared = new Set<string>();\n const references: { name: string; write: boolean }[] = [];\n walk.fullAncestor(ast, (node, _state, ancestors, type) => {\n if (node.type !== \"Identifier\") {\n return;\n }\n const parent = ancestors[ancestors.length - 2] as acorn.AnyNode | undefined;\n if (type === \"VariablePattern\") {\n // acorn-walk uses \"VariablePattern\" for declarations and for assignment targets\n if (parent?.type === \"AssignmentExpression\" && parent.left === node) {\n references.push({ name: node.name, write: true });\n } else {\n declared.add(node.name);\n }\n } else {\n // count++ only changes the variable, its value is not used\n references.push({ name: node.name, write: parent?.type === \"UpdateExpression\" });\n }\n });\n walk.simple(ast, {\n CallExpression: node => {\n const arg = node.arguments[0];\n // the variable of hasChanged(\"name\")\n if (\n node.callee.type === \"Identifier\" &&\n CHANGE_HELPERS.has(node.callee.name) &&\n arg?.type === \"Literal\" &&\n typeof arg.value === \"string\"\n ) {\n this.read.add(arg.value);\n }\n },\n });\n for (const { name, write } of references) {\n if (!declared.has(name)) {\n (write ? this.written : this.read).add(name);\n }\n }\n }\n}\n\n/**\n * Finds the logical problems of a chart\n *\n * @param chart The chart\n */\nexport function analyzeChart(chart: Chart): Finding[] {\n const structure = new ChartStructure(chart);\n const findings: Finding[] = [];\n const add = (kind: Finding[\"kind\"], id: string, severity: Severity, key: string, args: string[] = []): void => {\n findings.push({ kind, id, severity, key, args });\n };\n const stateName = (id: string): string => structure.statesById.get(id)?.name ?? id;\n\n // the transitions the runtime executes, by source\n const usage = new Usage();\n const validBySource = new Map<string, ValidTransition[]>();\n for (const state of chart.states) {\n for (const transition of structure.getTransitions(state.id)) {\n let label;\n try {\n label = parseTransitionLabel(transition.label);\n } catch {\n continue;\n }\n usage.add(label.condition, \"expression\");\n usage.add(label.temporal?.condition, \"expression\");\n usage.add(label.action, \"statements\");\n for (const event of [label.event, label.temporal?.event]) {\n if (event) {\n usage.read.add(event);\n }\n }\n if (\n !structure.statesById.has(transition.target) ||\n structure.getCrossedParallel(transition) !== undefined\n ) {\n continue;\n }\n const condition = label.condition ? evaluateCondition(label.condition) : { value: true };\n const temporalCondition = label.temporal?.condition && evaluateCondition(label.temporal.condition);\n if (condition && !condition.value) {\n add(\n \"transition\",\n transition.id,\n \"warning\",\n \"The condition is never true, the transition is never taken\",\n );\n continue;\n }\n if (temporalCondition && !temporalCondition.value) {\n add(\n \"transition\",\n transition.id,\n \"warning\",\n \"The condition is never true, the transition is never taken\",\n );\n continue;\n }\n if (label.condition && condition) {\n add(\"transition\", transition.id, \"info\", \"The condition is always true\");\n }\n const valid = { transition, label, alwaysTrue: !!condition };\n validBySource.set(state.id, [...(validBySource.get(state.id) || []), valid]);\n }\n }\n\n findUnreachable(structure, validBySource, add);\n findShadowed(structure, validBySource, add, stateName);\n\n // leaf states which are never left\n for (const state of chart.states) {\n if (structure.getChildren(state.id).length || state.during?.trim()) {\n // a state with a during action may do its work as long as it is active\n continue;\n }\n if (structure.getPath(state.id).every(id => !validBySource.get(id)?.length)) {\n add(\n \"state\",\n state.id,\n \"info\",\n \"The chart stays in this state: neither it nor a state containing it has an outgoing transition\",\n );\n }\n }\n\n // variables which are not used\n for (const state of chart.states) {\n usage.add(state.entry, \"statements\");\n usage.add(state.during, \"statements\");\n usage.add(state.exit, \"statements\");\n }\n for (const fn of chart.functions || []) {\n usage.add(fn.code, \"statements\");\n }\n for (const symbol of chart.symbols) {\n const { read, written } = { read: usage.read.has(symbol.name), written: usage.written.has(symbol.name) };\n if (symbol.scope === \"input\" && !read && !written) {\n add(\"symbol\", symbol.name, \"info\", \"The input is not used, it only wakes up the chart\");\n } else if (symbol.scope === \"output\" && !written) {\n add(\"symbol\", symbol.name, \"warning\", \"The output is never written\");\n } else if (symbol.scope === \"local\" && !read) {\n add(\n \"symbol\",\n symbol.name,\n \"info\",\n written ? \"The variable is written but never read\" : \"The variable is not used\",\n );\n }\n }\n return findings;\n}\n\n/**\n * Finds the states which can never become active: the topmost ones, their sub states are not reported\n *\n * @param structure The structure of the chart\n * @param validBySource The transitions the runtime executes, by source\n * @param add Adds a finding\n */\nfunction findUnreachable(\n structure: ChartStructure,\n validBySource: Map<string, ValidTransition[]>,\n add: (kind: Finding[\"kind\"], id: string, severity: Severity, key: string) => void,\n): void {\n const reachable = new Set<string>();\n // enters a state like the runtime: with its initial sub state, or all of them if they are parallel\n const enterDefault = (id: string): void => {\n if (reachable.has(id)) {\n return;\n }\n reachable.add(id);\n const children = structure.getChildren(id);\n const initial = structure.getInitialChild(id);\n for (const child of structure.isParallel(id) ? children : children.filter(c => c.id === initial)) {\n enterDefault(child.id);\n }\n };\n // enters the target of a transition with its parents, and their parallel siblings\n const enter = (target: string): void => {\n for (const id of structure.getPath(target)) {\n reachable.add(id);\n const parent = structure.statesById.get(id)?.parent || null;\n if (structure.isParallel(parent)) {\n for (const sibling of structure.getChildren(parent)) {\n if (sibling.id !== id) {\n enterDefault(sibling.id);\n }\n }\n }\n }\n // the history is only set by sub states which were active before, so they are reachable anyway\n reachable.delete(target);\n enterDefault(target);\n };\n\n const topLevel = structure.getChildren(null);\n const initial = structure.getInitialChild(null);\n for (const state of structure.isParallel(null) ? topLevel : topLevel.filter(s => s.id === initial)) {\n enterDefault(state.id);\n }\n for (let changed = true; changed;) {\n changed = false;\n for (const [source, transitions] of validBySource) {\n if (!reachable.has(source)) {\n continue;\n }\n for (const { transition } of transitions) {\n const before = reachable.size;\n enter(transition.target);\n changed ||= reachable.size !== before;\n }\n }\n }\n\n for (const state of structure.chart.states) {\n const parent = state.parent && structure.statesById.has(state.parent) ? state.parent : null;\n if (!reachable.has(state.id) && (!parent || reachable.has(parent))) {\n add(\"state\", state.id, \"warning\", \"The state never becomes active: no transition leads to it\");\n }\n }\n}\n\n/**\n * Finds the transitions which are never taken because one before them is always valid: it has no condition (or one\n * which is always true) and no temporal logic, and no event or the same event. Like in the runtime, the transitions\n * leaving a state are checked before its inner transitions.\n *\n * @param structure The structure of the chart\n * @param validBySource The transitions the runtime executes, by source\n * @param add Adds a finding\n * @param stateName Returns the name of a state\n */\nfunction findShadowed(\n structure: ChartStructure,\n validBySource: Map<string, ValidTransition[]>,\n add: (kind: Finding[\"kind\"], id: string, severity: Severity, key: string, args: string[]) => void,\n stateName: (id: string) => string,\n): void {\n for (const transitions of validBySource.values()) {\n /** the transition which is always valid, for all wakeups */\n let always: ChartTransition | undefined;\n /** the transitions which are always valid, by event */\n const byEvent = new Map<string, ChartTransition>();\n /** the transitions by event, temporal logic and condition */\n const byTrigger = new Map<string, ChartTransition>();\n const outer = transitions.filter(t => !structure.getTransitionKind(t.transition).inner);\n const inner = transitions.filter(t => structure.getTransitionKind(t.transition).inner);\n for (const { transition, label, alwaysTrue } of [...outer, ...inner]) {\n const trigger = JSON.stringify([label.event, label.temporal, label.condition?.replace(/\\s+/g, \"\")]);\n const before = always ?? (label.event ? byEvent.get(label.event) : undefined);\n if (before) {\n add(\n \"transition\",\n transition.id,\n \"warning\",\n 'Never taken: the transition to \"%s\" before it is always valid',\n [stateName(before.target)],\n );\n continue;\n }\n const same = byTrigger.get(trigger);\n if (same) {\n add(\n \"transition\",\n transition.id,\n \"warning\",\n 'Never taken: the transition to \"%s\" before it has the same event and condition',\n [stateName(same.target)],\n );\n continue;\n }\n byTrigger.set(trigger, transition);\n if (alwaysTrue && !label.temporal) {\n if (label.event) {\n byEvent.set(label.event, transition);\n } else {\n always = transition;\n }\n }\n }\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["initial"]
7
+ }